Imported Upstream version 0.1.7
This commit is contained in:
parent
de4e9a8439
commit
add65b5191
77 changed files with 23649 additions and 7918 deletions
7
AUTHORS
7
AUTHORS
|
@ -15,6 +15,8 @@ Contributors:
|
|||
Nick Schermer <nick@xfce.org>
|
||||
Matthias Kruk <mkruk@matthiaskruk.de>
|
||||
Johannes Reinhardt <jreinhardt@ist-dein-freund.de>
|
||||
Jean-François Guchens <zcx000@gmail.com>
|
||||
Jérôme Geulfucci <jeromeg@xfce.org>
|
||||
|
||||
Graphics:
|
||||
extension: Nancy Runge <nancy@twotoasts.de>
|
||||
|
@ -23,6 +25,7 @@ Graphics:
|
|||
logo-shade: Nancy Runge <nancy@twotoasts.de>
|
||||
|
||||
Translations:
|
||||
cs: David Stancl <dstancl@dstancl.cz>
|
||||
da: Per Kongstad <p_kongstad@op.pl>
|
||||
de: Enrico Tröger <enrico.troeger@uvena.de>
|
||||
de: Christian Dywan <christian@twotoasts.de>
|
||||
|
@ -39,6 +42,7 @@ Translations:
|
|||
fr: Adrien Nader <camaradetux@gmail.com>
|
||||
fr: Robert-André Mauchin <zebob.m@pengzone.org>
|
||||
fr: Pascal Gervais <pggervais@yahoo.ca>
|
||||
fr: Jérôme Geulfucci <jeromeg@xfce.org>
|
||||
gl: Miguel Anxo Bouzada <mbouzada@gmail.com>
|
||||
he: Shlomi Israel <sijproject@gmail.com>
|
||||
hu: SZERVÁC Attila <sas@321.hu>
|
||||
|
@ -49,8 +53,11 @@ Translations:
|
|||
pl: Przemysław Sitek <el.pescado@gazeta.pl>
|
||||
pl: Lukasz Romanowicz <romanowicz88@gmail.com>
|
||||
pt_PT: Sérgio Marques <smarquespt@gmail.com>
|
||||
ro: Igor Știrbu <igor.stirbu@gmail.com>
|
||||
ro: Mișu Moldovan <dumol@gnome.ro>
|
||||
ru: Troitskiy Nikita <niktr@mail.ru>
|
||||
ru: Anton Shestakov <engored@ya.ru>
|
||||
sk: Robert Hartl <hartl.robert@gmail.com>
|
||||
sv: Mikael Magnusson <mikachu@comhem.se>
|
||||
tr: Mirat Can Bayrak <MiratCanBayrak@gmail.com>
|
||||
uk: Dmitry Nikitin <luckas_fb@mail.ru>
|
||||
|
|
18
ChangeLog
18
ChangeLog
|
@ -1,5 +1,23 @@
|
|||
This file is licensed under the terms of the expat license, see the file EXPAT.
|
||||
|
||||
v0.1.7:
|
||||
+ Save the activation status of extensions
|
||||
+ Catch and ignore mouse buttons meant for horizontal scrolling
|
||||
+ Improve panel detaching and how panels handle it
|
||||
+ Add a Feed Panel extension
|
||||
+ Add a Fixed-width Font Family preference
|
||||
+ Support spell checking
|
||||
+ Implement (optional) Speed dial feature
|
||||
+ Support nicer error pages with WebKitGTK+ 1.1.6
|
||||
+ Implement middle click to open menu items in tabs
|
||||
+ Implement -s, --snapshot command line switch
|
||||
+ Use libnotify (runtime dependency) for finished transfers
|
||||
+ Add a Go button to the address entry
|
||||
+ Always append tabs opened via middle/ double click on the tab bar
|
||||
+ Implement Open new pages in: New window preference
|
||||
+ Implement inline find with direct '.' and '/' hotkeys
|
||||
+ Add basic support for @-moz-document in user styles
|
||||
|
||||
v0.1.6:
|
||||
+ Add Delete All to transferbar
|
||||
+ Show search in context menu
|
||||
|
|
2
README
2
README
|
@ -13,7 +13,7 @@ Midori is a lightweight web browser.
|
|||
|
||||
Requirements: GTK+ 2.10, WebkitGTK+ 1.1.1, libXML2, libsoup 2.25.2
|
||||
|
||||
Optional: Unique 0.9, libidn, sqlite 3.0, docutils
|
||||
Optional: Unique 0.9, libidn, sqlite 3.0, docutils, libnotify
|
||||
|
||||
For installation instructions read INSTALL.
|
||||
|
||||
|
|
81
data/error.html
Normal file
81
data/error.html
Normal file
|
@ -0,0 +1,81 @@
|
|||
<!--
|
||||
Error page template for Midori.
|
||||
This file is licensed under the terms of the expat license, see the file EXPAT.
|
||||
-->
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>{title}</title>
|
||||
<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;
|
||||
}
|
||||
|
||||
#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">
|
||||
<img id="logo" src="{res}/logo-shade.png" />
|
||||
<img id="icon" src="{stock}/gtk-dialog-error" />
|
||||
<div id="main">
|
||||
<h1>{title}</h1>
|
||||
<p id="message">{message}</p>
|
||||
<p id="description">{description}</p>
|
||||
<form onsubmit="location.reload()">
|
||||
<button>
|
||||
<img src="{stock}/gtk-refresh"/>
|
||||
<span>{tryagain}</span>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
<br style="clear: both;"/>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
313
data/mootools.js
Normal file
313
data/mootools.js
Normal file
|
@ -0,0 +1,313 @@
|
|||
//MooTools, <http://mootools.net>, My Object Oriented (JavaScript) Tools. Copyright (c) 2006-2009 Valerio Proietti, <http://mad4milk.net>, MIT Style License.
|
||||
|
||||
var MooTools={version:"1.2.2",build:"f0491d62fbb7e906789aa3733d6a67d43e5af7c9"};var Native=function(k){k=k||{};var a=k.name;var i=k.legacy;var b=k.protect;
|
||||
var c=k.implement;var h=k.generics;var f=k.initialize;var g=k.afterImplement||function(){};var d=f||i;h=h!==false;d.constructor=Native;d.$family={name:"native"};
|
||||
if(i&&f){d.prototype=i.prototype;}d.prototype.constructor=d;if(a){var e=a.toLowerCase();d.prototype.$family={name:e};Native.typize(d,e);}var j=function(n,l,o,m){if(!b||m||!n.prototype[l]){n.prototype[l]=o;
|
||||
}if(h){Native.genericize(n,l,b);}g.call(n,l,o);return n;};d.alias=function(n,l,o){if(typeof n=="string"){if((n=this.prototype[n])){return j(this,l,n,o);
|
||||
}}for(var m in n){this.alias(m,n[m],l);}return this;};d.implement=function(m,l,o){if(typeof m=="string"){return j(this,m,l,o);}for(var n in m){j(this,n,m[n],l);
|
||||
}return this;};if(c){d.implement(c);}return d;};Native.genericize=function(b,c,a){if((!a||!b[c])&&typeof b.prototype[c]=="function"){b[c]=function(){var d=Array.prototype.slice.call(arguments);
|
||||
return b.prototype[c].apply(d.shift(),d);};}};Native.implement=function(d,c){for(var b=0,a=d.length;b<a;b++){d[b].implement(c);}};Native.typize=function(a,b){if(!a.type){a.type=function(c){return($type(c)===b);
|
||||
};}};(function(){var a={Array:Array,Date:Date,Function:Function,Number:Number,RegExp:RegExp,String:String};for(var h in a){new Native({name:h,initialize:a[h],protect:true});
|
||||
}var d={"boolean":Boolean,"native":Native,object:Object};for(var c in d){Native.typize(d[c],c);}var f={Array:["concat","indexOf","join","lastIndexOf","pop","push","reverse","shift","slice","sort","splice","toString","unshift","valueOf"],String:["charAt","charCodeAt","concat","indexOf","lastIndexOf","match","replace","search","slice","split","substr","substring","toLowerCase","toUpperCase","valueOf"]};
|
||||
for(var e in f){for(var b=f[e].length;b--;){Native.genericize(window[e],f[e][b],true);}}})();var Hash=new Native({name:"Hash",initialize:function(a){if($type(a)=="hash"){a=$unlink(a.getClean());
|
||||
}for(var b in a){this[b]=a[b];}return this;}});Hash.implement({forEach:function(b,c){for(var a in this){if(this.hasOwnProperty(a)){b.call(c,this[a],a,this);
|
||||
}}},getClean:function(){var b={};for(var a in this){if(this.hasOwnProperty(a)){b[a]=this[a];}}return b;},getLength:function(){var b=0;for(var a in this){if(this.hasOwnProperty(a)){b++;
|
||||
}}return b;}});Hash.alias("forEach","each");Array.implement({forEach:function(c,d){for(var b=0,a=this.length;b<a;b++){c.call(d,this[b],b,this);}}});Array.alias("forEach","each");
|
||||
function $A(b){if(b.item){var a=b.length,c=new Array(a);while(a--){c[a]=b[a];}return c;}return Array.prototype.slice.call(b);}function $arguments(a){return function(){return arguments[a];
|
||||
};}function $chk(a){return !!(a||a===0);}function $clear(a){clearTimeout(a);clearInterval(a);return null;}function $defined(a){return(a!=undefined);}function $each(c,b,d){var a=$type(c);
|
||||
((a=="arguments"||a=="collection"||a=="array")?Array:Hash).each(c,b,d);}function $empty(){}function $extend(c,a){for(var b in (a||{})){c[b]=a[b];}return c;
|
||||
}function $H(a){return new Hash(a);}function $lambda(a){return(typeof a=="function")?a:function(){return a;};}function $merge(){var a=Array.slice(arguments);
|
||||
a.unshift({});return $mixin.apply(null,a);}function $mixin(e){for(var d=1,a=arguments.length;d<a;d++){var b=arguments[d];if($type(b)!="object"){continue;
|
||||
}for(var c in b){var g=b[c],f=e[c];e[c]=(f&&$type(g)=="object"&&$type(f)=="object")?$mixin(f,g):$unlink(g);}}return e;}function $pick(){for(var b=0,a=arguments.length;
|
||||
b<a;b++){if(arguments[b]!=undefined){return arguments[b];}}return null;}function $random(b,a){return Math.floor(Math.random()*(a-b+1)+b);}function $splat(b){var a=$type(b);
|
||||
return(a)?((a!="array"&&a!="arguments")?[b]:b):[];}var $time=Date.now||function(){return +new Date;};function $try(){for(var b=0,a=arguments.length;b<a;
|
||||
b++){try{return arguments[b]();}catch(c){}}return null;}function $type(a){if(a==undefined){return false;}if(a.$family){return(a.$family.name=="number"&&!isFinite(a))?false:a.$family.name;
|
||||
}if(a.nodeName){switch(a.nodeType){case 1:return"element";case 3:return(/\S/).test(a.nodeValue)?"textnode":"whitespace";}}else{if(typeof a.length=="number"){if(a.callee){return"arguments";
|
||||
}else{if(a.item){return"collection";}}}}return typeof a;}function $unlink(c){var b;switch($type(c)){case"object":b={};for(var e in c){b[e]=$unlink(c[e]);
|
||||
}break;case"hash":b=new Hash(c);break;case"array":b=[];for(var d=0,a=c.length;d<a;d++){b[d]=$unlink(c[d]);}break;default:return c;}return b;}var Browser=$merge({Engine:{name:"unknown",version:0},Platform:{name:(window.orientation!=undefined)?"ipod":(navigator.platform.match(/mac|win|linux/i)||["other"])[0].toLowerCase()},Features:{xpath:!!(document.evaluate),air:!!(window.runtime),query:!!(document.querySelector)},Plugins:{},Engines:{presto:function(){return(!window.opera)?false:((arguments.callee.caller)?960:((document.getElementsByClassName)?950:925));
|
||||
},trident:function(){return(!window.ActiveXObject)?false:((window.XMLHttpRequest)?5:4);},webkit:function(){return(navigator.taintEnabled)?false:((Browser.Features.xpath)?((Browser.Features.query)?525:420):419);
|
||||
},gecko:function(){return(document.getBoxObjectFor==undefined)?false:((document.getElementsByClassName)?19:18);}}},Browser||{});Browser.Platform[Browser.Platform.name]=true;
|
||||
Browser.detect=function(){for(var b in this.Engines){var a=this.Engines[b]();if(a){this.Engine={name:b,version:a};this.Engine[b]=this.Engine[b+a]=true;
|
||||
break;}}return{name:b,version:a};};Browser.detect();Browser.Request=function(){return $try(function(){return new XMLHttpRequest();},function(){return new ActiveXObject("MSXML2.XMLHTTP");
|
||||
});};Browser.Features.xhr=!!(Browser.Request());Browser.Plugins.Flash=(function(){var a=($try(function(){return navigator.plugins["Shockwave Flash"].description;
|
||||
},function(){return new ActiveXObject("ShockwaveFlash.ShockwaveFlash").GetVariable("$version");})||"0 r0").match(/\d+/g);return{version:parseInt(a[0]||0+"."+a[1],10)||0,build:parseInt(a[2],10)||0};
|
||||
})();function $exec(b){if(!b){return b;}if(window.execScript){window.execScript(b);}else{var a=document.createElement("script");a.setAttribute("type","text/javascript");
|
||||
a[(Browser.Engine.webkit&&Browser.Engine.version<420)?"innerText":"text"]=b;document.head.appendChild(a);document.head.removeChild(a);}return b;}Native.UID=1;
|
||||
var $uid=(Browser.Engine.trident)?function(a){return(a.uid||(a.uid=[Native.UID++]))[0];}:function(a){return a.uid||(a.uid=Native.UID++);};var Window=new Native({name:"Window",legacy:(Browser.Engine.trident)?null:window.Window,initialize:function(a){$uid(a);
|
||||
if(!a.Element){a.Element=$empty;if(Browser.Engine.webkit){a.document.createElement("iframe");}a.Element.prototype=(Browser.Engine.webkit)?window["[[DOMElement.prototype]]"]:{};
|
||||
}a.document.window=a;return $extend(a,Window.Prototype);},afterImplement:function(b,a){window[b]=Window.Prototype[b]=a;}});Window.Prototype={$family:{name:"window"}};
|
||||
new Window(window);var Document=new Native({name:"Document",legacy:(Browser.Engine.trident)?null:window.Document,initialize:function(a){$uid(a);a.head=a.getElementsByTagName("head")[0];
|
||||
a.html=a.getElementsByTagName("html")[0];if(Browser.Engine.trident&&Browser.Engine.version<=4){$try(function(){a.execCommand("BackgroundImageCache",false,true);
|
||||
});}if(Browser.Engine.trident){a.window.attachEvent("onunload",function(){a.window.detachEvent("onunload",arguments.callee);a.head=a.html=a.window=null;
|
||||
});}return $extend(a,Document.Prototype);},afterImplement:function(b,a){document[b]=Document.Prototype[b]=a;}});Document.Prototype={$family:{name:"document"}};
|
||||
new Document(document);Array.implement({every:function(c,d){for(var b=0,a=this.length;b<a;b++){if(!c.call(d,this[b],b,this)){return false;}}return true;
|
||||
},filter:function(d,e){var c=[];for(var b=0,a=this.length;b<a;b++){if(d.call(e,this[b],b,this)){c.push(this[b]);}}return c;},clean:function(){return this.filter($defined);
|
||||
},indexOf:function(c,d){var a=this.length;for(var b=(d<0)?Math.max(0,a+d):d||0;b<a;b++){if(this[b]===c){return b;}}return -1;},map:function(d,e){var c=[];
|
||||
for(var b=0,a=this.length;b<a;b++){c[b]=d.call(e,this[b],b,this);}return c;},some:function(c,d){for(var b=0,a=this.length;b<a;b++){if(c.call(d,this[b],b,this)){return true;
|
||||
}}return false;},associate:function(c){var d={},b=Math.min(this.length,c.length);for(var a=0;a<b;a++){d[c[a]]=this[a];}return d;},link:function(c){var a={};
|
||||
for(var e=0,b=this.length;e<b;e++){for(var d in c){if(c[d](this[e])){a[d]=this[e];delete c[d];break;}}}return a;},contains:function(a,b){return this.indexOf(a,b)!=-1;
|
||||
},extend:function(c){for(var b=0,a=c.length;b<a;b++){this.push(c[b]);}return this;},getLast:function(){return(this.length)?this[this.length-1]:null;},getRandom:function(){return(this.length)?this[$random(0,this.length-1)]:null;
|
||||
},include:function(a){if(!this.contains(a)){this.push(a);}return this;},combine:function(c){for(var b=0,a=c.length;b<a;b++){this.include(c[b]);}return this;
|
||||
},erase:function(b){for(var a=this.length;a--;a){if(this[a]===b){this.splice(a,1);}}return this;},empty:function(){this.length=0;return this;},flatten:function(){var d=[];
|
||||
for(var b=0,a=this.length;b<a;b++){var c=$type(this[b]);if(!c){continue;}d=d.concat((c=="array"||c=="collection"||c=="arguments")?Array.flatten(this[b]):this[b]);
|
||||
}return d;},hexToRgb:function(b){if(this.length!=3){return null;}var a=this.map(function(c){if(c.length==1){c+=c;}return c.toInt(16);});return(b)?a:"rgb("+a+")";
|
||||
},rgbToHex:function(d){if(this.length<3){return null;}if(this.length==4&&this[3]==0&&!d){return"transparent";}var b=[];for(var a=0;a<3;a++){var c=(this[a]-0).toString(16);
|
||||
b.push((c.length==1)?"0"+c:c);}return(d)?b:"#"+b.join("");}});Function.implement({extend:function(a){for(var b in a){this[b]=a[b];}return this;},create:function(b){var a=this;
|
||||
b=b||{};return function(d){var c=b.arguments;c=(c!=undefined)?$splat(c):Array.slice(arguments,(b.event)?1:0);if(b.event){c=[d||window.event].extend(c);
|
||||
}var e=function(){return a.apply(b.bind||null,c);};if(b.delay){return setTimeout(e,b.delay);}if(b.periodical){return setInterval(e,b.periodical);}if(b.attempt){return $try(e);
|
||||
}return e();};},run:function(a,b){return this.apply(b,$splat(a));},pass:function(a,b){return this.create({bind:b,arguments:a});},bind:function(b,a){return this.create({bind:b,arguments:a});
|
||||
},bindWithEvent:function(b,a){return this.create({bind:b,arguments:a,event:true});},attempt:function(a,b){return this.create({bind:b,arguments:a,attempt:true})();
|
||||
},delay:function(b,c,a){return this.create({bind:c,arguments:a,delay:b})();},periodical:function(c,b,a){return this.create({bind:b,arguments:a,periodical:c})();
|
||||
}});Number.implement({limit:function(b,a){return Math.min(a,Math.max(b,this));},round:function(a){a=Math.pow(10,a||0);return Math.round(this*a)/a;},times:function(b,c){for(var a=0;
|
||||
a<this;a++){b.call(c,a,this);}},toFloat:function(){return parseFloat(this);},toInt:function(a){return parseInt(this,a||10);}});Number.alias("times","each");
|
||||
(function(b){var a={};b.each(function(c){if(!Number[c]){a[c]=function(){return Math[c].apply(null,[this].concat($A(arguments)));};}});Number.implement(a);
|
||||
})(["abs","acos","asin","atan","atan2","ceil","cos","exp","floor","log","max","min","pow","sin","sqrt","tan"]);String.implement({test:function(a,b){return((typeof a=="string")?new RegExp(a,b):a).test(this);
|
||||
},contains:function(a,b){return(b)?(b+this+b).indexOf(b+a+b)>-1:this.indexOf(a)>-1;},trim:function(){return this.replace(/^\s+|\s+$/g,"");},clean:function(){return this.replace(/\s+/g," ").trim();
|
||||
},camelCase:function(){return this.replace(/-\D/g,function(a){return a.charAt(1).toUpperCase();});},hyphenate:function(){return this.replace(/[A-Z]/g,function(a){return("-"+a.charAt(0).toLowerCase());
|
||||
});},capitalize:function(){return this.replace(/\b[a-z]/g,function(a){return a.toUpperCase();});},escapeRegExp:function(){return this.replace(/([-.*+?^${}()|[\]\/\\])/g,"\\$1");
|
||||
},toInt:function(a){return parseInt(this,a||10);},toFloat:function(){return parseFloat(this);},hexToRgb:function(b){var a=this.match(/^#?(\w{1,2})(\w{1,2})(\w{1,2})$/);
|
||||
return(a)?a.slice(1).hexToRgb(b):null;},rgbToHex:function(b){var a=this.match(/\d{1,3}/g);return(a)?a.rgbToHex(b):null;},stripScripts:function(b){var a="";
|
||||
var c=this.replace(/<script[^>]*>([\s\S]*?)<\/script>/gi,function(){a+=arguments[1]+"\n";return"";});if(b===true){$exec(a);}else{if($type(b)=="function"){b(a,c);
|
||||
}}return c;},substitute:function(a,b){return this.replace(b||(/\\?\{([^{}]+)\}/g),function(d,c){if(d.charAt(0)=="\\"){return d.slice(1);}return(a[c]!=undefined)?a[c]:"";
|
||||
});}});Hash.implement({has:Object.prototype.hasOwnProperty,keyOf:function(b){for(var a in this){if(this.hasOwnProperty(a)&&this[a]===b){return a;}}return null;
|
||||
},hasValue:function(a){return(Hash.keyOf(this,a)!==null);},extend:function(a){Hash.each(a,function(c,b){Hash.set(this,b,c);},this);return this;},combine:function(a){Hash.each(a,function(c,b){Hash.include(this,b,c);
|
||||
},this);return this;},erase:function(a){if(this.hasOwnProperty(a)){delete this[a];}return this;},get:function(a){return(this.hasOwnProperty(a))?this[a]:null;
|
||||
},set:function(a,b){if(!this[a]||this.hasOwnProperty(a)){this[a]=b;}return this;},empty:function(){Hash.each(this,function(b,a){delete this[a];},this);
|
||||
return this;},include:function(a,b){if(this[a]==undefined){this[a]=b;}return this;},map:function(b,c){var a=new Hash;Hash.each(this,function(e,d){a.set(d,b.call(c,e,d,this));
|
||||
},this);return a;},filter:function(b,c){var a=new Hash;Hash.each(this,function(e,d){if(b.call(c,e,d,this)){a.set(d,e);}},this);return a;},every:function(b,c){for(var a in this){if(this.hasOwnProperty(a)&&!b.call(c,this[a],a)){return false;
|
||||
}}return true;},some:function(b,c){for(var a in this){if(this.hasOwnProperty(a)&&b.call(c,this[a],a)){return true;}}return false;},getKeys:function(){var a=[];
|
||||
Hash.each(this,function(c,b){a.push(b);});return a;},getValues:function(){var a=[];Hash.each(this,function(b){a.push(b);});return a;},toQueryString:function(a){var b=[];
|
||||
Hash.each(this,function(f,e){if(a){e=a+"["+e+"]";}var d;switch($type(f)){case"object":d=Hash.toQueryString(f,e);break;case"array":var c={};f.each(function(h,g){c[g]=h;
|
||||
});d=Hash.toQueryString(c,e);break;default:d=e+"="+encodeURIComponent(f);}if(f!=undefined){b.push(d);}});return b.join("&");}});Hash.alias({keyOf:"indexOf",hasValue:"contains"});
|
||||
var Event=new Native({name:"Event",initialize:function(a,f){f=f||window;var k=f.document;a=a||f.event;if(a.$extended){return a;}this.$extended=true;var j=a.type;
|
||||
var g=a.target||a.srcElement;while(g&&g.nodeType==3){g=g.parentNode;}if(j.test(/key/)){var b=a.which||a.keyCode;var m=Event.Keys.keyOf(b);if(j=="keydown"){var d=b-111;
|
||||
if(d>0&&d<13){m="f"+d;}}m=m||String.fromCharCode(b).toLowerCase();}else{if(j.match(/(click|mouse|menu)/i)){k=(!k.compatMode||k.compatMode=="CSS1Compat")?k.html:k.body;
|
||||
var i={x:a.pageX||a.clientX+k.scrollLeft,y:a.pageY||a.clientY+k.scrollTop};var c={x:(a.pageX)?a.pageX-f.pageXOffset:a.clientX,y:(a.pageY)?a.pageY-f.pageYOffset:a.clientY};
|
||||
if(j.match(/DOMMouseScroll|mousewheel/)){var h=(a.wheelDelta)?a.wheelDelta/120:-(a.detail||0)/3;}var e=(a.which==3)||(a.button==2);var l=null;if(j.match(/over|out/)){switch(j){case"mouseover":l=a.relatedTarget||a.fromElement;
|
||||
break;case"mouseout":l=a.relatedTarget||a.toElement;}if(!(function(){while(l&&l.nodeType==3){l=l.parentNode;}return true;}).create({attempt:Browser.Engine.gecko})()){l=false;
|
||||
}}}}return $extend(this,{event:a,type:j,page:i,client:c,rightClick:e,wheel:h,relatedTarget:l,target:g,code:b,key:m,shift:a.shiftKey,control:a.ctrlKey,alt:a.altKey,meta:a.metaKey});
|
||||
}});Event.Keys=new Hash({enter:13,up:38,down:40,left:37,right:39,esc:27,space:32,backspace:8,tab:9,"delete":46});Event.implement({stop:function(){return this.stopPropagation().preventDefault();
|
||||
},stopPropagation:function(){if(this.event.stopPropagation){this.event.stopPropagation();}else{this.event.cancelBubble=true;}return this;},preventDefault:function(){if(this.event.preventDefault){this.event.preventDefault();
|
||||
}else{this.event.returnValue=false;}return this;}});function Class(b){if(b instanceof Function){b={initialize:b};}var a=function(){Object.reset(this);if(a._prototyping){return this;
|
||||
}this._current=$empty;var c=(this.initialize)?this.initialize.apply(this,arguments):this;delete this._current;delete this.caller;return c;}.extend(this);
|
||||
a.implement(b);a.constructor=Class;a.prototype.constructor=a;return a;}Function.prototype.protect=function(){this._protected=true;return this;};Object.reset=function(a,c){if(c==null){for(var e in a){Object.reset(a,e);
|
||||
}return a;}delete a[c];switch($type(a[c])){case"object":var d=function(){};d.prototype=a[c];var b=new d;a[c]=Object.reset(b);break;case"array":a[c]=$unlink(a[c]);
|
||||
break;}return a;};new Native({name:"Class",initialize:Class}).extend({instantiate:function(b){b._prototyping=true;var a=new b;delete b._prototyping;return a;
|
||||
},wrap:function(a,b,c){if(c._origin){c=c._origin;}return function(){if(c._protected&&this._current==null){throw new Error('The method "'+b+'" cannot be called.');
|
||||
}var e=this.caller,f=this._current;this.caller=f;this._current=arguments.callee;var d=c.apply(this,arguments);this._current=f;this.caller=e;return d;}.extend({_owner:a,_origin:c,_name:b});
|
||||
}});Class.implement({implement:function(a,d){if($type(a)=="object"){for(var e in a){this.implement(e,a[e]);}return this;}var f=Class.Mutators[a];if(f){d=f.call(this,d);
|
||||
if(d==null){return this;}}var c=this.prototype;switch($type(d)){case"function":if(d._hidden){return this;}c[a]=Class.wrap(this,a,d);break;case"object":var b=c[a];
|
||||
if($type(b)=="object"){$mixin(b,d);}else{c[a]=$unlink(d);}break;case"array":c[a]=$unlink(d);break;default:c[a]=d;}return this;}});Class.Mutators={Extends:function(a){this.parent=a;
|
||||
this.prototype=Class.instantiate(a);this.implement("parent",function(){var b=this.caller._name,c=this.caller._owner.parent.prototype[b];if(!c){throw new Error('The method "'+b+'" has no parent.');
|
||||
}return c.apply(this,arguments);}.protect());},Implements:function(a){$splat(a).each(function(b){if(b instanceof Function){b=Class.instantiate(b);}this.implement(b);
|
||||
},this);}};var Chain=new Class({$chain:[],chain:function(){this.$chain.extend(Array.flatten(arguments));return this;},callChain:function(){return(this.$chain.length)?this.$chain.shift().apply(this,arguments):false;
|
||||
},clearChain:function(){this.$chain.empty();return this;}});var Events=new Class({$events:{},addEvent:function(c,b,a){c=Events.removeOn(c);if(b!=$empty){this.$events[c]=this.$events[c]||[];
|
||||
this.$events[c].include(b);if(a){b.internal=true;}}return this;},addEvents:function(a){for(var b in a){this.addEvent(b,a[b]);}return this;},fireEvent:function(c,b,a){c=Events.removeOn(c);
|
||||
if(!this.$events||!this.$events[c]){return this;}this.$events[c].each(function(d){d.create({bind:this,delay:a,"arguments":b})();},this);return this;},removeEvent:function(b,a){b=Events.removeOn(b);
|
||||
if(!this.$events[b]){return this;}if(!a.internal){this.$events[b].erase(a);}return this;},removeEvents:function(c){var d;if($type(c)=="object"){for(d in c){this.removeEvent(d,c[d]);
|
||||
}return this;}if(c){c=Events.removeOn(c);}for(d in this.$events){if(c&&c!=d){continue;}var b=this.$events[d];for(var a=b.length;a--;a){this.removeEvent(d,b[a]);
|
||||
}}return this;}});Events.removeOn=function(a){return a.replace(/^on([A-Z])/,function(b,c){return c.toLowerCase();});};var Options=new Class({setOptions:function(){this.options=$merge.run([this.options].extend(arguments));
|
||||
if(!this.addEvent){return this;}for(var a in this.options){if($type(this.options[a])!="function"||!(/^on[A-Z]/).test(a)){continue;}this.addEvent(a,this.options[a]);
|
||||
delete this.options[a];}return this;}});var Element=new Native({name:"Element",legacy:window.Element,initialize:function(a,b){var c=Element.Constructors.get(a);
|
||||
if(c){return c(b);}if(typeof a=="string"){return document.newElement(a,b);}return $(a).set(b);},afterImplement:function(a,b){Element.Prototype[a]=b;if(Array[a]){return;
|
||||
}Elements.implement(a,function(){var c=[],g=true;for(var e=0,d=this.length;e<d;e++){var f=this[e][a].apply(this[e],arguments);c.push(f);if(g){g=($type(f)=="element");
|
||||
}}return(g)?new Elements(c):c;});}});Element.Prototype={$family:{name:"element"}};Element.Constructors=new Hash;var IFrame=new Native({name:"IFrame",generics:false,initialize:function(){var e=Array.link(arguments,{properties:Object.type,iframe:$defined});
|
||||
var c=e.properties||{};var b=$(e.iframe)||false;var d=c.onload||$empty;delete c.onload;c.id=c.name=$pick(c.id,c.name,b.id,b.name,"IFrame_"+$time());b=new Element(b||"iframe",c);
|
||||
var a=function(){var f=$try(function(){return b.contentWindow.location.host;});if(f&&f==window.location.host){var g=new Window(b.contentWindow);new Document(b.contentWindow.document);
|
||||
$extend(g.Element.prototype,Element.Prototype);}d.call(b.contentWindow,b.contentWindow.document);};(window.frames[c.id])?a():b.addListener("load",a);return b;
|
||||
}});var Elements=new Native({initialize:function(f,b){b=$extend({ddup:true,cash:true},b);f=f||[];if(b.ddup||b.cash){var g={},e=[];for(var c=0,a=f.length;
|
||||
c<a;c++){var d=$.element(f[c],!b.cash);if(b.ddup){if(g[d.uid]){continue;}g[d.uid]=true;}e.push(d);}f=e;}return(b.cash)?$extend(f,this):f;}});Elements.implement({filter:function(a,b){if(!a){return this;
|
||||
}return new Elements(Array.filter(this,(typeof a=="string")?function(c){return c.match(a);}:a,b));}});Document.implement({newElement:function(a,b){if(Browser.Engine.trident&&b){["name","type","checked"].each(function(c){if(!b[c]){return;
|
||||
}a+=" "+c+'="'+b[c]+'"';if(c!="checked"){delete b[c];}});a="<"+a+">";}return $.element(this.createElement(a)).set(b);},newTextNode:function(a){return this.createTextNode(a);
|
||||
},getDocument:function(){return this;},getWindow:function(){return this.window;}});Window.implement({$:function(b,c){if(b&&b.$family&&b.uid){return b;}var a=$type(b);
|
||||
return($[a])?$[a](b,c,this.document):null;},$$:function(a){if(arguments.length==1&&typeof a=="string"){return this.document.getElements(a);}var f=[];var c=Array.flatten(arguments);
|
||||
for(var d=0,b=c.length;d<b;d++){var e=c[d];switch($type(e)){case"element":f.push(e);break;case"string":f.extend(this.document.getElements(e,true));}}return new Elements(f);
|
||||
},getDocument:function(){return this.document;},getWindow:function(){return this;}});$.string=function(c,b,a){c=a.getElementById(c);return(c)?$.element(c,b):null;
|
||||
};$.element=function(a,d){$uid(a);if(!d&&!a.$family&&!(/^object|embed$/i).test(a.tagName)){var b=Element.Prototype;for(var c in b){a[c]=b[c];}}return a;
|
||||
};$.object=function(b,c,a){if(b.toElement){return $.element(b.toElement(a),c);}return null;};$.textnode=$.whitespace=$.window=$.document=$arguments(0);
|
||||
Native.implement([Element,Document],{getElement:function(a,b){return $(this.getElements(a,true)[0]||null,b);},getElements:function(a,d){a=a.split(",");
|
||||
var c=[];var b=(a.length>1);a.each(function(e){var f=this.getElementsByTagName(e.trim());(b)?c.extend(f):c=f;},this);return new Elements(c,{ddup:b,cash:!d});
|
||||
}});(function(){var h={},f={};var i={input:"checked",option:"selected",textarea:(Browser.Engine.webkit&&Browser.Engine.version<420)?"innerHTML":"value"};
|
||||
var c=function(l){return(f[l]||(f[l]={}));};var g=function(n,l){if(!n){return;}var m=n.uid;if(Browser.Engine.trident){if(n.clearAttributes){var q=l&&n.cloneNode(false);
|
||||
n.clearAttributes();if(q){n.mergeAttributes(q);}}else{if(n.removeEvents){n.removeEvents();}}if((/object/i).test(n.tagName)){for(var o in n){if(typeof n[o]=="function"){n[o]=$empty;
|
||||
}}Element.dispose(n);}}if(!m){return;}h[m]=f[m]=null;};var d=function(){Hash.each(h,g);if(Browser.Engine.trident){$A(document.getElementsByTagName("object")).each(g);
|
||||
}if(window.CollectGarbage){CollectGarbage();}h=f=null;};var j=function(n,l,s,m,p,r){var o=n[s||l];var q=[];while(o){if(o.nodeType==1&&(!m||Element.match(o,m))){if(!p){return $(o,r);
|
||||
}q.push(o);}o=o[l];}return(p)?new Elements(q,{ddup:false,cash:!r}):null;};var e={html:"innerHTML","class":"className","for":"htmlFor",text:(Browser.Engine.trident||(Browser.Engine.webkit&&Browser.Engine.version<420))?"innerText":"textContent"};
|
||||
var b=["compact","nowrap","ismap","declare","noshade","checked","disabled","readonly","multiple","selected","noresize","defer"];var k=["value","accessKey","cellPadding","cellSpacing","colSpan","frameBorder","maxLength","readOnly","rowSpan","tabIndex","useMap"];
|
||||
b=b.associate(b);Hash.extend(e,b);Hash.extend(e,k.associate(k.map(String.toLowerCase)));var a={before:function(m,l){if(l.parentNode){l.parentNode.insertBefore(m,l);
|
||||
}},after:function(m,l){if(!l.parentNode){return;}var n=l.nextSibling;(n)?l.parentNode.insertBefore(m,n):l.parentNode.appendChild(m);},bottom:function(m,l){l.appendChild(m);
|
||||
},top:function(m,l){var n=l.firstChild;(n)?l.insertBefore(m,n):l.appendChild(m);}};a.inside=a.bottom;Hash.each(a,function(l,m){m=m.capitalize();Element.implement("inject"+m,function(n){l(this,$(n,true));
|
||||
return this;});Element.implement("grab"+m,function(n){l($(n,true),this);return this;});});Element.implement({set:function(o,m){switch($type(o)){case"object":for(var n in o){this.set(n,o[n]);
|
||||
}break;case"string":var l=Element.Properties.get(o);(l&&l.set)?l.set.apply(this,Array.slice(arguments,1)):this.setProperty(o,m);}return this;},get:function(m){var l=Element.Properties.get(m);
|
||||
return(l&&l.get)?l.get.apply(this,Array.slice(arguments,1)):this.getProperty(m);},erase:function(m){var l=Element.Properties.get(m);(l&&l.erase)?l.erase.apply(this):this.removeProperty(m);
|
||||
return this;},setProperty:function(m,n){var l=e[m];if(n==undefined){return this.removeProperty(m);}if(l&&b[m]){n=!!n;}(l)?this[l]=n:this.setAttribute(m,""+n);
|
||||
return this;},setProperties:function(l){for(var m in l){this.setProperty(m,l[m]);}return this;},getProperty:function(m){var l=e[m];var n=(l)?this[l]:this.getAttribute(m,2);
|
||||
return(b[m])?!!n:(l)?n:n||null;},getProperties:function(){var l=$A(arguments);return l.map(this.getProperty,this).associate(l);},removeProperty:function(m){var l=e[m];
|
||||
(l)?this[l]=(l&&b[m])?false:"":this.removeAttribute(m);return this;},removeProperties:function(){Array.each(arguments,this.removeProperty,this);return this;
|
||||
},hasClass:function(l){return this.className.contains(l," ");},addClass:function(l){if(!this.hasClass(l)){this.className=(this.className+" "+l).clean();
|
||||
}return this;},removeClass:function(l){this.className=this.className.replace(new RegExp("(^|\\s)"+l+"(?:\\s|$)"),"$1");return this;},toggleClass:function(l){return this.hasClass(l)?this.removeClass(l):this.addClass(l);
|
||||
},adopt:function(){Array.flatten(arguments).each(function(l){l=$(l,true);if(l){this.appendChild(l);}},this);return this;},appendText:function(m,l){return this.grab(this.getDocument().newTextNode(m),l);
|
||||
},grab:function(m,l){a[l||"bottom"]($(m,true),this);return this;},inject:function(m,l){a[l||"bottom"](this,$(m,true));return this;},replaces:function(l){l=$(l,true);
|
||||
l.parentNode.replaceChild(this,l);return this;},wraps:function(m,l){m=$(m,true);return this.replaces(m).grab(m,l);},getPrevious:function(l,m){return j(this,"previousSibling",null,l,false,m);
|
||||
},getAllPrevious:function(l,m){return j(this,"previousSibling",null,l,true,m);},getNext:function(l,m){return j(this,"nextSibling",null,l,false,m);},getAllNext:function(l,m){return j(this,"nextSibling",null,l,true,m);
|
||||
},getFirst:function(l,m){return j(this,"nextSibling","firstChild",l,false,m);},getLast:function(l,m){return j(this,"previousSibling","lastChild",l,false,m);
|
||||
},getParent:function(l,m){return j(this,"parentNode",null,l,false,m);},getParents:function(l,m){return j(this,"parentNode",null,l,true,m);},getSiblings:function(l,m){return this.getParent().getChildren(l,m).erase(this);
|
||||
},getChildren:function(l,m){return j(this,"nextSibling","firstChild",l,true,m);},getWindow:function(){return this.ownerDocument.window;},getDocument:function(){return this.ownerDocument;
|
||||
},getElementById:function(o,n){var m=this.ownerDocument.getElementById(o);if(!m){return null;}for(var l=m.parentNode;l!=this;l=l.parentNode){if(!l){return null;
|
||||
}}return $.element(m,n);},getSelected:function(){return new Elements($A(this.options).filter(function(l){return l.selected;}));},getComputedStyle:function(m){if(this.currentStyle){return this.currentStyle[m.camelCase()];
|
||||
}var l=this.getDocument().defaultView.getComputedStyle(this,null);return(l)?l.getPropertyValue([m.hyphenate()]):null;},toQueryString:function(){var l=[];
|
||||
this.getElements("input, select, textarea",true).each(function(m){if(!m.name||m.disabled){return;}var n=(m.tagName.toLowerCase()=="select")?Element.getSelected(m).map(function(o){return o.value;
|
||||
}):((m.type=="radio"||m.type=="checkbox")&&!m.checked)?null:m.value;$splat(n).each(function(o){if(typeof o!="undefined"){l.push(m.name+"="+encodeURIComponent(o));
|
||||
}});});return l.join("&");},clone:function(o,l){o=o!==false;var r=this.cloneNode(o);var n=function(v,u){if(!l){v.removeAttribute("id");}if(Browser.Engine.trident){v.clearAttributes();
|
||||
v.mergeAttributes(u);v.removeAttribute("uid");if(v.options){var w=v.options,s=u.options;for(var t=w.length;t--;){w[t].selected=s[t].selected;}}}var x=i[u.tagName.toLowerCase()];
|
||||
if(x&&u[x]){v[x]=u[x];}};if(o){var p=r.getElementsByTagName("*"),q=this.getElementsByTagName("*");for(var m=p.length;m--;){n(p[m],q[m]);}}n(r,this);return $(r);
|
||||
},destroy:function(){Element.empty(this);Element.dispose(this);g(this,true);return null;},empty:function(){$A(this.childNodes).each(function(l){Element.destroy(l);
|
||||
});return this;},dispose:function(){return(this.parentNode)?this.parentNode.removeChild(this):this;},hasChild:function(l){l=$(l,true);if(!l){return false;
|
||||
}if(Browser.Engine.webkit&&Browser.Engine.version<420){return $A(this.getElementsByTagName(l.tagName)).contains(l);}return(this.contains)?(this!=l&&this.contains(l)):!!(this.compareDocumentPosition(l)&16);
|
||||
},match:function(l){return(!l||(l==this)||(Element.get(this,"tag")==l));}});Native.implement([Element,Window,Document],{addListener:function(o,n){if(o=="unload"){var l=n,m=this;
|
||||
n=function(){m.removeListener("unload",n);l();};}else{h[this.uid]=this;}if(this.addEventListener){this.addEventListener(o,n,false);}else{this.attachEvent("on"+o,n);
|
||||
}return this;},removeListener:function(m,l){if(this.removeEventListener){this.removeEventListener(m,l,false);}else{this.detachEvent("on"+m,l);}return this;
|
||||
},retrieve:function(m,l){var o=c(this.uid),n=o[m];if(l!=undefined&&n==undefined){n=o[m]=l;}return $pick(n);},store:function(m,l){var n=c(this.uid);n[m]=l;
|
||||
return this;},eliminate:function(l){var m=c(this.uid);delete m[l];return this;}});window.addListener("unload",d);})();Element.Properties=new Hash;Element.Properties.style={set:function(a){this.style.cssText=a;
|
||||
},get:function(){return this.style.cssText;},erase:function(){this.style.cssText="";}};Element.Properties.tag={get:function(){return this.tagName.toLowerCase();
|
||||
}};Element.Properties.html=(function(){var c=document.createElement("div");var a={table:[1,"<table>","</table>"],select:[1,"<select>","</select>"],tbody:[2,"<table><tbody>","</tbody></table>"],tr:[3,"<table><tbody><tr>","</tr></tbody></table>"]};
|
||||
a.thead=a.tfoot=a.tbody;var b={set:function(){var e=Array.flatten(arguments).join("");var f=Browser.Engine.trident&&a[this.get("tag")];if(f){var g=c;g.innerHTML=f[1]+e+f[2];
|
||||
for(var d=f[0];d--;){g=g.firstChild;}this.empty().adopt(g.childNodes);}else{this.innerHTML=e;}}};b.erase=b.set;return b;})();if(Browser.Engine.webkit&&Browser.Engine.version<420){Element.Properties.text={get:function(){if(this.innerText){return this.innerText;
|
||||
}var a=this.ownerDocument.newElement("div",{html:this.innerHTML}).inject(this.ownerDocument.body);var b=a.innerText;a.destroy();return b;}};}Element.Properties.events={set:function(a){this.addEvents(a);
|
||||
}};Native.implement([Element,Window,Document],{addEvent:function(e,g){var h=this.retrieve("events",{});h[e]=h[e]||{keys:[],values:[]};if(h[e].keys.contains(g)){return this;
|
||||
}h[e].keys.push(g);var f=e,a=Element.Events.get(e),c=g,i=this;if(a){if(a.onAdd){a.onAdd.call(this,g);}if(a.condition){c=function(j){if(a.condition.call(this,j)){return g.call(this,j);
|
||||
}return true;};}f=a.base||f;}var d=function(){return g.call(i);};var b=Element.NativeEvents[f];if(b){if(b==2){d=function(j){j=new Event(j,i.getWindow());
|
||||
if(c.call(i,j)===false){j.stop();}};}this.addListener(f,d);}h[e].values.push(d);return this;},removeEvent:function(c,b){var a=this.retrieve("events");if(!a||!a[c]){return this;
|
||||
}var f=a[c].keys.indexOf(b);if(f==-1){return this;}a[c].keys.splice(f,1);var e=a[c].values.splice(f,1)[0];var d=Element.Events.get(c);if(d){if(d.onRemove){d.onRemove.call(this,b);
|
||||
}c=d.base||c;}return(Element.NativeEvents[c])?this.removeListener(c,e):this;},addEvents:function(a){for(var b in a){this.addEvent(b,a[b]);}return this;
|
||||
},removeEvents:function(a){var c;if($type(a)=="object"){for(c in a){this.removeEvent(c,a[c]);}return this;}var b=this.retrieve("events");if(!b){return this;
|
||||
}if(!a){for(c in b){this.removeEvents(c);}this.eliminate("events");}else{if(b[a]){while(b[a].keys[0]){this.removeEvent(a,b[a].keys[0]);}b[a]=null;}}return this;
|
||||
},fireEvent:function(d,b,a){var c=this.retrieve("events");if(!c||!c[d]){return this;}c[d].keys.each(function(e){e.create({bind:this,delay:a,"arguments":b})();
|
||||
},this);return this;},cloneEvents:function(d,a){d=$(d);var c=d.retrieve("events");if(!c){return this;}if(!a){for(var b in c){this.cloneEvents(d,b);}}else{if(c[a]){c[a].keys.each(function(e){this.addEvent(a,e);
|
||||
},this);}}return this;}});Element.NativeEvents={click:2,dblclick:2,mouseup:2,mousedown:2,contextmenu:2,mousewheel:2,DOMMouseScroll:2,mouseover:2,mouseout:2,mousemove:2,selectstart:2,selectend:2,keydown:2,keypress:2,keyup:2,focus:2,blur:2,change:2,reset:2,select:2,submit:2,load:1,unload:1,beforeunload:2,resize:1,move:1,DOMContentLoaded:1,readystatechange:1,error:1,abort:1,scroll:1};
|
||||
(function(){var a=function(b){var c=b.relatedTarget;if(c==undefined){return true;}if(c===false){return false;}return($type(this)!="document"&&c!=this&&c.prefix!="xul"&&!this.hasChild(c));
|
||||
};Element.Events=new Hash({mouseenter:{base:"mouseover",condition:a},mouseleave:{base:"mouseout",condition:a},mousewheel:{base:(Browser.Engine.gecko)?"DOMMouseScroll":"mousewheel"}});
|
||||
})();Element.Properties.styles={set:function(a){this.setStyles(a);}};Element.Properties.opacity={set:function(a,b){if(!b){if(a==0){if(this.style.visibility!="hidden"){this.style.visibility="hidden";
|
||||
}}else{if(this.style.visibility!="visible"){this.style.visibility="visible";}}}if(!this.currentStyle||!this.currentStyle.hasLayout){this.style.zoom=1;}if(Browser.Engine.trident){this.style.filter=(a==1)?"":"alpha(opacity="+a*100+")";
|
||||
}this.style.opacity=a;this.store("opacity",a);},get:function(){return this.retrieve("opacity",1);}};Element.implement({setOpacity:function(a){return this.set("opacity",a,true);
|
||||
},getOpacity:function(){return this.get("opacity");},setStyle:function(b,a){switch(b){case"opacity":return this.set("opacity",parseFloat(a));case"float":b=(Browser.Engine.trident)?"styleFloat":"cssFloat";
|
||||
}b=b.camelCase();if($type(a)!="string"){var c=(Element.Styles.get(b)||"@").split(" ");a=$splat(a).map(function(e,d){if(!c[d]){return"";}return($type(e)=="number")?c[d].replace("@",Math.round(e)):e;
|
||||
}).join(" ");}else{if(a==String(Number(a))){a=Math.round(a);}}this.style[b]=a;return this;},getStyle:function(g){switch(g){case"opacity":return this.get("opacity");
|
||||
case"float":g=(Browser.Engine.trident)?"styleFloat":"cssFloat";}g=g.camelCase();var a=this.style[g];if(!$chk(a)){a=[];for(var f in Element.ShortStyles){if(g!=f){continue;
|
||||
}for(var e in Element.ShortStyles[f]){a.push(this.getStyle(e));}return a.join(" ");}a=this.getComputedStyle(g);}if(a){a=String(a);var c=a.match(/rgba?\([\d\s,]+\)/);
|
||||
if(c){a=a.replace(c[0],c[0].rgbToHex());}}if(Browser.Engine.presto||(Browser.Engine.trident&&!$chk(parseInt(a,10)))){if(g.test(/^(height|width)$/)){var b=(g=="width")?["left","right"]:["top","bottom"],d=0;
|
||||
b.each(function(h){d+=this.getStyle("border-"+h+"-width").toInt()+this.getStyle("padding-"+h).toInt();},this);return this["offset"+g.capitalize()]-d+"px";
|
||||
}if((Browser.Engine.presto)&&String(a).test("px")){return a;}if(g.test(/(border(.+)Width|margin|padding)/)){return"0px";}}return a;},setStyles:function(b){for(var a in b){this.setStyle(a,b[a]);
|
||||
}return this;},getStyles:function(){var a={};Array.each(arguments,function(b){a[b]=this.getStyle(b);},this);return a;}});Element.Styles=new Hash({left:"@px",top:"@px",bottom:"@px",right:"@px",width:"@px",height:"@px",maxWidth:"@px",maxHeight:"@px",minWidth:"@px",minHeight:"@px",backgroundColor:"rgb(@, @, @)",backgroundPosition:"@px @px",color:"rgb(@, @, @)",fontSize:"@px",letterSpacing:"@px",lineHeight:"@px",clip:"rect(@px @px @px @px)",margin:"@px @px @px @px",padding:"@px @px @px @px",border:"@px @ rgb(@, @, @) @px @ rgb(@, @, @) @px @ rgb(@, @, @)",borderWidth:"@px @px @px @px",borderStyle:"@ @ @ @",borderColor:"rgb(@, @, @) rgb(@, @, @) rgb(@, @, @) rgb(@, @, @)",zIndex:"@",zoom:"@",fontWeight:"@",textIndent:"@px",opacity:"@"});
|
||||
Element.ShortStyles={margin:{},padding:{},border:{},borderWidth:{},borderStyle:{},borderColor:{}};["Top","Right","Bottom","Left"].each(function(g){var f=Element.ShortStyles;
|
||||
var b=Element.Styles;["margin","padding"].each(function(h){var i=h+g;f[h][i]=b[i]="@px";});var e="border"+g;f.border[e]=b[e]="@px @ rgb(@, @, @)";var d=e+"Width",a=e+"Style",c=e+"Color";
|
||||
f[e]={};f.borderWidth[d]=f[e][d]=b[d]="@px";f.borderStyle[a]=f[e][a]=b[a]="@";f.borderColor[c]=f[e][c]=b[c]="rgb(@, @, @)";});Native.implement([Document,Element],{getElements:function(h,g){h=h.split(",");
|
||||
var c,e={};for(var d=0,b=h.length;d<b;d++){var a=h[d],f=Selectors.Utils.search(this,a,e);if(d!=0&&f.item){f=$A(f);}c=(d==0)?f:(c.item)?$A(c).concat(f):c.concat(f);
|
||||
}return new Elements(c,{ddup:(h.length>1),cash:!g});}});Element.implement({match:function(b){if(!b||(b==this)){return true;}var d=Selectors.Utils.parseTagAndID(b);
|
||||
var a=d[0],e=d[1];if(!Selectors.Filters.byID(this,e)||!Selectors.Filters.byTag(this,a)){return false;}var c=Selectors.Utils.parseSelector(b);return(c)?Selectors.Utils.filter(this,c,{}):true;
|
||||
}});var Selectors={Cache:{nth:{},parsed:{}}};Selectors.RegExps={id:(/#([\w-]+)/),tag:(/^(\w+|\*)/),quick:(/^(\w+|\*)$/),splitter:(/\s*([+>~\s])\s*([a-zA-Z#.*:\[])/g),combined:(/\.([\w-]+)|\[(\w+)(?:([!*^$~|]?=)(["']?)([^\4]*?)\4)?\]|:([\w-]+)(?:\(["']?(.*?)?["']?\)|$)/g)};
|
||||
Selectors.Utils={chk:function(b,c){if(!c){return true;}var a=$uid(b);if(!c[a]){return c[a]=true;}return false;},parseNthArgument:function(h){if(Selectors.Cache.nth[h]){return Selectors.Cache.nth[h];
|
||||
}var e=h.match(/^([+-]?\d*)?([a-z]+)?([+-]?\d*)?$/);if(!e){return false;}var g=parseInt(e[1],10);var d=(g||g===0)?g:1;var f=e[2]||false;var c=parseInt(e[3],10)||0;
|
||||
if(d!=0){c--;while(c<1){c+=d;}while(c>=d){c-=d;}}else{d=c;f="index";}switch(f){case"n":e={a:d,b:c,special:"n"};break;case"odd":e={a:2,b:0,special:"n"};
|
||||
break;case"even":e={a:2,b:1,special:"n"};break;case"first":e={a:0,special:"index"};break;case"last":e={special:"last-child"};break;case"only":e={special:"only-child"};
|
||||
break;default:e={a:(d-1),special:"index"};}return Selectors.Cache.nth[h]=e;},parseSelector:function(e){if(Selectors.Cache.parsed[e]){return Selectors.Cache.parsed[e];
|
||||
}var d,h={classes:[],pseudos:[],attributes:[]};while((d=Selectors.RegExps.combined.exec(e))){var i=d[1],g=d[2],f=d[3],b=d[5],c=d[6],j=d[7];if(i){h.classes.push(i);
|
||||
}else{if(c){var a=Selectors.Pseudo.get(c);if(a){h.pseudos.push({parser:a,argument:j});}else{h.attributes.push({name:c,operator:"=",value:j});}}else{if(g){h.attributes.push({name:g,operator:f,value:b});
|
||||
}}}}if(!h.classes.length){delete h.classes;}if(!h.attributes.length){delete h.attributes;}if(!h.pseudos.length){delete h.pseudos;}if(!h.classes&&!h.attributes&&!h.pseudos){h=null;
|
||||
}return Selectors.Cache.parsed[e]=h;},parseTagAndID:function(b){var a=b.match(Selectors.RegExps.tag);var c=b.match(Selectors.RegExps.id);return[(a)?a[1]:"*",(c)?c[1]:false];
|
||||
},filter:function(f,c,e){var d;if(c.classes){for(d=c.classes.length;d--;d){var g=c.classes[d];if(!Selectors.Filters.byClass(f,g)){return false;}}}if(c.attributes){for(d=c.attributes.length;
|
||||
d--;d){var b=c.attributes[d];if(!Selectors.Filters.byAttribute(f,b.name,b.operator,b.value)){return false;}}}if(c.pseudos){for(d=c.pseudos.length;d--;d){var a=c.pseudos[d];
|
||||
if(!Selectors.Filters.byPseudo(f,a.parser,a.argument,e)){return false;}}}return true;},getByTagAndID:function(b,a,d){if(d){var c=(b.getElementById)?b.getElementById(d,true):Element.getElementById(b,d,true);
|
||||
return(c&&Selectors.Filters.byTag(c,a))?[c]:[];}else{return b.getElementsByTagName(a);}},search:function(o,h,t){var b=[];var c=h.trim().replace(Selectors.RegExps.splitter,function(k,j,i){b.push(j);
|
||||
return":)"+i;}).split(":)");var p,e,A;for(var z=0,v=c.length;z<v;z++){var y=c[z];if(z==0&&Selectors.RegExps.quick.test(y)){p=o.getElementsByTagName(y);
|
||||
continue;}var a=b[z-1];var q=Selectors.Utils.parseTagAndID(y);var B=q[0],r=q[1];if(z==0){p=Selectors.Utils.getByTagAndID(o,B,r);}else{var d={},g=[];for(var x=0,w=p.length;
|
||||
x<w;x++){g=Selectors.Getters[a](g,p[x],B,r,d);}p=g;}var f=Selectors.Utils.parseSelector(y);if(f){e=[];for(var u=0,s=p.length;u<s;u++){A=p[u];if(Selectors.Utils.filter(A,f,t)){e.push(A);
|
||||
}}p=e;}}return p;}};Selectors.Getters={" ":function(h,g,j,a,e){var d=Selectors.Utils.getByTagAndID(g,j,a);for(var c=0,b=d.length;c<b;c++){var f=d[c];if(Selectors.Utils.chk(f,e)){h.push(f);
|
||||
}}return h;},">":function(h,g,j,a,f){var c=Selectors.Utils.getByTagAndID(g,j,a);for(var e=0,d=c.length;e<d;e++){var b=c[e];if(b.parentNode==g&&Selectors.Utils.chk(b,f)){h.push(b);
|
||||
}}return h;},"+":function(c,b,a,e,d){while((b=b.nextSibling)){if(b.nodeType==1){if(Selectors.Utils.chk(b,d)&&Selectors.Filters.byTag(b,a)&&Selectors.Filters.byID(b,e)){c.push(b);
|
||||
}break;}}return c;},"~":function(c,b,a,e,d){while((b=b.nextSibling)){if(b.nodeType==1){if(!Selectors.Utils.chk(b,d)){break;}if(Selectors.Filters.byTag(b,a)&&Selectors.Filters.byID(b,e)){c.push(b);
|
||||
}}}return c;}};Selectors.Filters={byTag:function(b,a){return(a=="*"||(b.tagName&&b.tagName.toLowerCase()==a));},byID:function(a,b){return(!b||(a.id&&a.id==b));
|
||||
},byClass:function(b,a){return(b.className&&b.className.contains(a," "));},byPseudo:function(a,d,c,b){return d.call(a,c,b);},byAttribute:function(c,d,b,e){var a=Element.prototype.getProperty.call(c,d);
|
||||
if(!a){return(b=="!=");}if(!b||e==undefined){return true;}switch(b){case"=":return(a==e);case"*=":return(a.contains(e));case"^=":return(a.substr(0,e.length)==e);
|
||||
case"$=":return(a.substr(a.length-e.length)==e);case"!=":return(a!=e);case"~=":return a.contains(e," ");case"|=":return a.contains(e,"-");}return false;
|
||||
}};Selectors.Pseudo=new Hash({checked:function(){return this.checked;},empty:function(){return !(this.innerText||this.textContent||"").length;},not:function(a){return !Element.match(this,a);
|
||||
},contains:function(a){return(this.innerText||this.textContent||"").contains(a);},"first-child":function(){return Selectors.Pseudo.index.call(this,0);},"last-child":function(){var a=this;
|
||||
while((a=a.nextSibling)){if(a.nodeType==1){return false;}}return true;},"only-child":function(){var b=this;while((b=b.previousSibling)){if(b.nodeType==1){return false;
|
||||
}}var a=this;while((a=a.nextSibling)){if(a.nodeType==1){return false;}}return true;},"nth-child":function(g,e){g=(g==undefined)?"n":g;var c=Selectors.Utils.parseNthArgument(g);
|
||||
if(c.special!="n"){return Selectors.Pseudo[c.special].call(this,c.a,e);}var f=0;e.positions=e.positions||{};var d=$uid(this);if(!e.positions[d]){var b=this;
|
||||
while((b=b.previousSibling)){if(b.nodeType!=1){continue;}f++;var a=e.positions[$uid(b)];if(a!=undefined){f=a+f;break;}}e.positions[d]=f;}return(e.positions[d]%c.a==c.b);
|
||||
},index:function(a){var b=this,c=0;while((b=b.previousSibling)){if(b.nodeType==1&&++c>a){return false;}}return(c==a);},even:function(b,a){return Selectors.Pseudo["nth-child"].call(this,"2n+1",a);
|
||||
},odd:function(b,a){return Selectors.Pseudo["nth-child"].call(this,"2n",a);},selected:function(){return this.selected;}});Element.Events.domready={onAdd:function(a){if(Browser.loaded){a.call(this);
|
||||
}}};(function(){var b=function(){if(Browser.loaded){return;}Browser.loaded=true;window.fireEvent("domready");document.fireEvent("domready");};if(Browser.Engine.trident){var a=document.createElement("div");
|
||||
(function(){($try(function(){a.doScroll("left");return $(a).inject(document.body).set("html","temp").dispose();}))?b():arguments.callee.delay(50);})();
|
||||
}else{if(Browser.Engine.webkit&&Browser.Engine.version<525){(function(){(["loaded","complete"].contains(document.readyState))?b():arguments.callee.delay(50);
|
||||
})();}else{window.addEvent("load",b);document.addEvent("DOMContentLoaded",b);}}})();var JSON=new Hash({$specialChars:{"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},$replaceChars:function(a){return JSON.$specialChars[a]||"\\u00"+Math.floor(a.charCodeAt()/16).toString(16)+(a.charCodeAt()%16).toString(16);
|
||||
},encode:function(b){switch($type(b)){case"string":return'"'+b.replace(/[\x00-\x1f\\"]/g,JSON.$replaceChars)+'"';case"array":return"["+String(b.map(JSON.encode).filter($defined))+"]";
|
||||
case"object":case"hash":var a=[];Hash.each(b,function(e,d){var c=JSON.encode(e);if(c){a.push(JSON.encode(d)+":"+c);}});return"{"+a+"}";case"number":case"boolean":return String(b);
|
||||
case false:return"null";}return null;},decode:function(string,secure){if($type(string)!="string"||!string.length){return null;}if(secure&&!(/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(string.replace(/\\./g,"@").replace(/"[^"\\\n\r]*"/g,""))){return null;
|
||||
}return eval("("+string+")");}});Native.implement([Hash,Array,String,Number],{toJSON:function(){return JSON.encode(this);}});var Cookie=new Class({Implements:Options,options:{path:false,domain:false,duration:false,secure:false,document:document},initialize:function(b,a){this.key=b;
|
||||
this.setOptions(a);},write:function(b){b=encodeURIComponent(b);if(this.options.domain){b+="; domain="+this.options.domain;}if(this.options.path){b+="; path="+this.options.path;
|
||||
}if(this.options.duration){var a=new Date();a.setTime(a.getTime()+this.options.duration*24*60*60*1000);b+="; expires="+a.toGMTString();}if(this.options.secure){b+="; secure";
|
||||
}this.options.document.cookie=this.key+"="+b;return this;},read:function(){var a=this.options.document.cookie.match("(?:^|;)\\s*"+this.key.escapeRegExp()+"=([^;]*)");
|
||||
return(a)?decodeURIComponent(a[1]):null;},dispose:function(){new Cookie(this.key,$merge(this.options,{duration:-1})).write("");return this;}});Cookie.write=function(b,c,a){return new Cookie(b,a).write(c);
|
||||
};Cookie.read=function(a){return new Cookie(a).read();};Cookie.dispose=function(b,a){return new Cookie(b,a).dispose();};var Fx=new Class({Implements:[Chain,Events,Options],options:{fps:50,unit:false,duration:500,link:"ignore"},initialize:function(a){this.subject=this.subject||this;
|
||||
this.setOptions(a);this.options.duration=Fx.Durations[this.options.duration]||this.options.duration.toInt();var b=this.options.wait;if(b===false){this.options.link="cancel";
|
||||
}},getTransition:function(){return function(a){return -(Math.cos(Math.PI*a)-1)/2;};},step:function(){var a=$time();if(a<this.time+this.options.duration){var b=this.transition((a-this.time)/this.options.duration);
|
||||
this.set(this.compute(this.from,this.to,b));}else{this.set(this.compute(this.from,this.to,1));this.complete();}},set:function(a){return a;},compute:function(c,b,a){return Fx.compute(c,b,a);
|
||||
},check:function(){if(!this.timer){return true;}switch(this.options.link){case"cancel":this.cancel();return true;case"chain":this.chain(this.caller.bind(this,arguments));
|
||||
return false;}return false;},start:function(b,a){if(!this.check(b,a)){return this;}this.from=b;this.to=a;this.time=0;this.transition=this.getTransition();
|
||||
this.startTimer();this.onStart();return this;},complete:function(){if(this.stopTimer()){this.onComplete();}return this;},cancel:function(){if(this.stopTimer()){this.onCancel();
|
||||
}return this;},onStart:function(){this.fireEvent("start",this.subject);},onComplete:function(){this.fireEvent("complete",this.subject);if(!this.callChain()){this.fireEvent("chainComplete",this.subject);
|
||||
}},onCancel:function(){this.fireEvent("cancel",this.subject).clearChain();},pause:function(){this.stopTimer();return this;},resume:function(){this.startTimer();
|
||||
return this;},stopTimer:function(){if(!this.timer){return false;}this.time=$time()-this.time;this.timer=$clear(this.timer);return true;},startTimer:function(){if(this.timer){return false;
|
||||
}this.time=$time()-this.time;this.timer=this.step.periodical(Math.round(1000/this.options.fps),this);return true;}});Fx.compute=function(c,b,a){return(b-c)*a+c;
|
||||
};Fx.Durations={"short":250,normal:500,"long":1000};Fx.CSS=new Class({Extends:Fx,prepare:function(d,e,b){b=$splat(b);var c=b[1];if(!$chk(c)){b[1]=b[0];
|
||||
b[0]=d.getStyle(e);}var a=b.map(this.parse);return{from:a[0],to:a[1]};},parse:function(a){a=$lambda(a)();a=(typeof a=="string")?a.split(" "):$splat(a);
|
||||
return a.map(function(c){c=String(c);var b=false;Fx.CSS.Parsers.each(function(f,e){if(b){return;}var d=f.parse(c);if($chk(d)){b={value:d,parser:f};}});
|
||||
b=b||{value:c,parser:Fx.CSS.Parsers.String};return b;});},compute:function(d,c,b){var a=[];(Math.min(d.length,c.length)).times(function(e){a.push({value:d[e].parser.compute(d[e].value,c[e].value,b),parser:d[e].parser});
|
||||
});a.$family={name:"fx:css:value"};return a;},serve:function(c,b){if($type(c)!="fx:css:value"){c=this.parse(c);}var a=[];c.each(function(d){a=a.concat(d.parser.serve(d.value,b));
|
||||
});return a;},render:function(a,d,c,b){a.setStyle(d,this.serve(c,b));},search:function(a){if(Fx.CSS.Cache[a]){return Fx.CSS.Cache[a];}var b={};Array.each(document.styleSheets,function(e,d){var c=e.href;
|
||||
if(c&&c.contains("://")&&!c.contains(document.domain)){return;}var f=e.rules||e.cssRules;Array.each(f,function(j,g){if(!j.style){return;}var h=(j.selectorText)?j.selectorText.replace(/^\w+/,function(i){return i.toLowerCase();
|
||||
}):null;if(!h||!h.test("^"+a+"$")){return;}Element.Styles.each(function(k,i){if(!j.style[i]||Element.ShortStyles[i]){return;}k=String(j.style[i]);b[i]=(k.test(/^rgb/))?k.rgbToHex():k;
|
||||
});});});return Fx.CSS.Cache[a]=b;}});Fx.CSS.Cache={};Fx.CSS.Parsers=new Hash({Color:{parse:function(a){if(a.match(/^#[0-9a-f]{3,6}$/i)){return a.hexToRgb(true);
|
||||
}return((a=a.match(/(\d+),\s*(\d+),\s*(\d+)/)))?[a[1],a[2],a[3]]:false;},compute:function(c,b,a){return c.map(function(e,d){return Math.round(Fx.compute(c[d],b[d],a));
|
||||
});},serve:function(a){return a.map(Number);}},Number:{parse:parseFloat,compute:Fx.compute,serve:function(b,a){return(a)?b+a:b;}},String:{parse:$lambda(false),compute:$arguments(1),serve:$arguments(0)}});
|
||||
Fx.Tween=new Class({Extends:Fx.CSS,initialize:function(b,a){this.element=this.subject=$(b);this.parent(a);},set:function(b,a){if(arguments.length==1){a=b;
|
||||
b=this.property||this.options.property;}this.render(this.element,b,a,this.options.unit);return this;},start:function(c,e,d){if(!this.check(c,e,d)){return this;
|
||||
}var b=Array.flatten(arguments);this.property=this.options.property||b.shift();var a=this.prepare(this.element,this.property,b);return this.parent(a.from,a.to);
|
||||
}});Element.Properties.tween={set:function(a){var b=this.retrieve("tween");if(b){b.cancel();}return this.eliminate("tween").store("tween:options",$extend({link:"cancel"},a));
|
||||
},get:function(a){if(a||!this.retrieve("tween")){if(a||!this.retrieve("tween:options")){this.set("tween",a);}this.store("tween",new Fx.Tween(this,this.retrieve("tween:options")));
|
||||
}return this.retrieve("tween");}};Element.implement({tween:function(a,c,b){this.get("tween").start(arguments);return this;},fade:function(c){var e=this.get("tween"),d="opacity",a;
|
||||
c=$pick(c,"toggle");switch(c){case"in":e.start(d,1);break;case"out":e.start(d,0);break;case"show":e.set(d,1);break;case"hide":e.set(d,0);break;case"toggle":var b=this.retrieve("fade:flag",this.get("opacity")==1);
|
||||
e.start(d,(b)?0:1);this.store("fade:flag",!b);a=true;break;default:e.start(d,arguments);}if(!a){this.eliminate("fade:flag");}return this;},highlight:function(c,a){if(!a){a=this.retrieve("highlight:original",this.getStyle("background-color"));
|
||||
a=(a=="transparent")?"#fff":a;}var b=this.get("tween");b.start("background-color",c||"#ffff88",a).chain(function(){this.setStyle("background-color",this.retrieve("highlight:original"));
|
||||
b.callChain();}.bind(this));return this;}});Fx.Morph=new Class({Extends:Fx.CSS,initialize:function(b,a){this.element=this.subject=$(b);this.parent(a);},set:function(a){if(typeof a=="string"){a=this.search(a);
|
||||
}for(var b in a){this.render(this.element,b,a[b],this.options.unit);}return this;},compute:function(e,d,c){var a={};for(var b in e){a[b]=this.parent(e[b],d[b],c);
|
||||
}return a;},start:function(b){if(!this.check(b)){return this;}if(typeof b=="string"){b=this.search(b);}var e={},d={};for(var c in b){var a=this.prepare(this.element,c,b[c]);
|
||||
e[c]=a.from;d[c]=a.to;}return this.parent(e,d);}});Element.Properties.morph={set:function(a){var b=this.retrieve("morph");if(b){b.cancel();}return this.eliminate("morph").store("morph:options",$extend({link:"cancel"},a));
|
||||
},get:function(a){if(a||!this.retrieve("morph")){if(a||!this.retrieve("morph:options")){this.set("morph",a);}this.store("morph",new Fx.Morph(this,this.retrieve("morph:options")));
|
||||
}return this.retrieve("morph");}};Element.implement({morph:function(a){this.get("morph").start(a);return this;}});Fx.implement({getTransition:function(){var a=this.options.transition||Fx.Transitions.Sine.easeInOut;
|
||||
if(typeof a=="string"){var b=a.split(":");a=Fx.Transitions;a=a[b[0]]||a[b[0].capitalize()];if(b[1]){a=a["ease"+b[1].capitalize()+(b[2]?b[2].capitalize():"")];
|
||||
}}return a;}});Fx.Transition=function(b,a){a=$splat(a);return $extend(b,{easeIn:function(c){return b(c,a);},easeOut:function(c){return 1-b(1-c,a);},easeInOut:function(c){return(c<=0.5)?b(2*c,a)/2:(2-b(2*(1-c),a))/2;
|
||||
}});};Fx.Transitions=new Hash({linear:$arguments(0)});Fx.Transitions.extend=function(a){for(var b in a){Fx.Transitions[b]=new Fx.Transition(a[b]);}};Fx.Transitions.extend({Pow:function(b,a){return Math.pow(b,a[0]||6);
|
||||
},Expo:function(a){return Math.pow(2,8*(a-1));},Circ:function(a){return 1-Math.sin(Math.acos(a));},Sine:function(a){return 1-Math.sin((1-a)*Math.PI/2);
|
||||
},Back:function(b,a){a=a[0]||1.618;return Math.pow(b,2)*((a+1)*b-a);},Bounce:function(f){var e;for(var d=0,c=1;1;d+=c,c/=2){if(f>=(7-4*d)/11){e=c*c-Math.pow((11-6*d-11*f)/4,2);
|
||||
break;}}return e;},Elastic:function(b,a){return Math.pow(2,10*--b)*Math.cos(20*b*Math.PI*(a[0]||1)/3);}});["Quad","Cubic","Quart","Quint"].each(function(b,a){Fx.Transitions[b]=new Fx.Transition(function(c){return Math.pow(c,[a+2]);
|
||||
});});var Request=new Class({Implements:[Chain,Events,Options],options:{url:"",data:"",headers:{"X-Requested-With":"XMLHttpRequest",Accept:"text/javascript, text/html, application/xml, text/xml, */*"},async:true,format:false,method:"post",link:"ignore",isSuccess:null,emulation:true,urlEncoded:true,encoding:"utf-8",evalScripts:false,evalResponse:false,noCache:false},initialize:function(a){this.xhr=new Browser.Request();
|
||||
this.setOptions(a);this.options.isSuccess=this.options.isSuccess||this.isSuccess;this.headers=new Hash(this.options.headers);},onStateChange:function(){if(this.xhr.readyState!=4||!this.running){return;
|
||||
}this.running=false;this.status=0;$try(function(){this.status=this.xhr.status;}.bind(this));if(this.options.isSuccess.call(this,this.status)){this.response={text:this.xhr.responseText,xml:this.xhr.responseXML};
|
||||
this.success(this.response.text,this.response.xml);}else{this.response={text:null,xml:null};this.failure();}this.xhr.onreadystatechange=$empty;},isSuccess:function(){return((this.status>=200)&&(this.status<300));
|
||||
},processScripts:function(a){if(this.options.evalResponse||(/(ecma|java)script/).test(this.getHeader("Content-type"))){return $exec(a);}return a.stripScripts(this.options.evalScripts);
|
||||
},success:function(b,a){this.onSuccess(this.processScripts(b),a);},onSuccess:function(){this.fireEvent("complete",arguments).fireEvent("success",arguments).callChain();
|
||||
},failure:function(){this.onFailure();},onFailure:function(){this.fireEvent("complete").fireEvent("failure",this.xhr);},setHeader:function(a,b){this.headers.set(a,b);
|
||||
return this;},getHeader:function(a){return $try(function(){return this.xhr.getResponseHeader(a);}.bind(this));},check:function(){if(!this.running){return true;
|
||||
}switch(this.options.link){case"cancel":this.cancel();return true;case"chain":this.chain(this.caller.bind(this,arguments));return false;}return false;},send:function(j){if(!this.check(j)){return this;
|
||||
}this.running=true;var h=$type(j);if(h=="string"||h=="element"){j={data:j};}var d=this.options;j=$extend({data:d.data,url:d.url,method:d.method},j);var f=j.data,b=j.url,a=j.method;
|
||||
switch($type(f)){case"element":f=$(f).toQueryString();break;case"object":case"hash":f=Hash.toQueryString(f);}if(this.options.format){var i="format="+this.options.format;
|
||||
f=(f)?i+"&"+f:i;}if(this.options.emulation&&["put","delete"].contains(a)){var g="_method="+a;f=(f)?g+"&"+f:g;a="post";}if(this.options.urlEncoded&&a=="post"){var c=(this.options.encoding)?"; charset="+this.options.encoding:"";
|
||||
this.headers.set("Content-type","application/x-www-form-urlencoded"+c);}if(this.options.noCache){var e="noCache="+new Date().getTime();f=(f)?e+"&"+f:e;
|
||||
}if(f&&a=="get"){b=b+(b.contains("?")?"&":"?")+f;f=null;}this.xhr.open(a.toUpperCase(),b,this.options.async);this.xhr.onreadystatechange=this.onStateChange.bind(this);
|
||||
this.headers.each(function(l,k){try{this.xhr.setRequestHeader(k,l);}catch(m){this.fireEvent("exception",[k,l]);}},this);this.fireEvent("request");this.xhr.send(f);
|
||||
if(!this.options.async){this.onStateChange();}return this;},cancel:function(){if(!this.running){return this;}this.running=false;this.xhr.abort();this.xhr.onreadystatechange=$empty;
|
||||
this.xhr=new Browser.Request();this.fireEvent("cancel");return this;}});(function(){var a={};["get","post","put","delete","GET","POST","PUT","DELETE"].each(function(b){a[b]=function(){var c=Array.link(arguments,{url:String.type,data:$defined});
|
||||
return this.send($extend(c,{method:b.toLowerCase()}));};});Request.implement(a);})();
|
317
data/speeddial-head.html
Normal file
317
data/speeddial-head.html
Normal file
|
@ -0,0 +1,317 @@
|
|||
<!--
|
||||
Speed Dial head template for Midori.
|
||||
Copyright (C) 2009 Jean-François Guchens <zcx000@gmail.com>
|
||||
This file is licensed under the terms of the expat license, see the file EXPAT.
|
||||
-->
|
||||
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>{title}</title>
|
||||
<script type="text/javascript" src="{res}/mootools.js"></script>
|
||||
|
||||
<style>
|
||||
html, body, #content {
|
||||
margin: 0px;
|
||||
padding: 0px
|
||||
}
|
||||
|
||||
body {
|
||||
text-align: center;
|
||||
background-color: #fefefe;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
#wrap {
|
||||
width: 660px;
|
||||
height: 500px;
|
||||
margin: 0px auto;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#content {
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
div.shortcut {
|
||||
float: left;
|
||||
border: 1px solid #ccc;
|
||||
position: relative;
|
||||
width: 200px;
|
||||
height: 150px;
|
||||
margin: 20px 20px 0px 0px;
|
||||
background-color: #fff;
|
||||
-webkit-border-radius: 10px;
|
||||
}
|
||||
|
||||
div.right {
|
||||
margin-right: 0px;
|
||||
margin-left: 0px;
|
||||
}
|
||||
|
||||
div.top {
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 50px;
|
||||
font-weight: bold;
|
||||
margin: 0px;
|
||||
height: 30px;
|
||||
padding: 10px 0px 0px 0px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 11px;
|
||||
font-weight: bold
|
||||
margin: 10px 0px 0px 0px;
|
||||
padding: 10px 5px 0px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
h4 span:before {
|
||||
content: "{click_to_add}";
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
h4 span {
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
div.shortcut a {
|
||||
border: 1px solid #ccc;
|
||||
display: block;
|
||||
width: 160px;
|
||||
height: 107px;
|
||||
margin: 15px auto 0px;
|
||||
background-color: #fafafa;
|
||||
color: #aaa;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.waiter img {
|
||||
margin-top: 38px;
|
||||
}
|
||||
|
||||
div.shortcut a:hover {
|
||||
border: 1px solid #999;
|
||||
}
|
||||
|
||||
div.shortcut p {
|
||||
font-size: 12px;
|
||||
margin: 0px;
|
||||
padding: 5px 0px 0px;
|
||||
color: #222;
|
||||
}
|
||||
|
||||
div.clear {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
div.activated {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
.cross {
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
margin-bottom: -17px;
|
||||
margin-left: 180px;
|
||||
margin-top: 2px;
|
||||
background: url({stock}/16/gtk-close) 98% 70% no-repeat;
|
||||
cursor: pointer;
|
||||
z-index: -4;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.cross:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.activated p {
|
||||
cursor: text;
|
||||
background: url({stock}/16/gtk-edit) 98% 70% no-repeat;
|
||||
opacity: 0.6;
|
||||
color: rgba(0,0,0,1);
|
||||
}
|
||||
|
||||
.activated p:hover {
|
||||
opacity: 1;
|
||||
color: rgba(0,0,0,0.5);
|
||||
}
|
||||
</style>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
sc = JSON.decode ({json_data});
|
||||
|
||||
var encodeSafe = function (obj) {
|
||||
var str = JSON.encode (obj);
|
||||
str = str.replace (/\'/g, '\\\'');
|
||||
return str;
|
||||
}
|
||||
|
||||
var getAction = function (id)
|
||||
{
|
||||
var a = $(id).getFirst ();
|
||||
if (a.getProperty ('href') != "#" )
|
||||
return true;
|
||||
|
||||
var url = prompt ("{enter_shortcut_address}", "http://");
|
||||
if (!url) return false;
|
||||
|
||||
var name = prompt ("{enter_shortcut_name}", "");
|
||||
if (!name) name = "";
|
||||
|
||||
a.setProperty('href', url);
|
||||
a.getNext().set('text', name);
|
||||
|
||||
var num = id.charAt (1) - 1;
|
||||
sc.shortcuts[num].title = name;
|
||||
|
||||
a.empty();
|
||||
var im = new Element('img', { src: '{stock}/image-loading' });
|
||||
|
||||
a.addClass ('waiter');
|
||||
a.grab (im);
|
||||
|
||||
getThumbnail (id, url);
|
||||
return false;
|
||||
}
|
||||
|
||||
var getThumbnail = function (id, url)
|
||||
{
|
||||
console.log ("speed_dial-get-thumbnail " + id + " " + url);
|
||||
return false;
|
||||
}
|
||||
|
||||
var setThumbnail = function (id, data, href)
|
||||
{
|
||||
var a = $(id).getFirst ();
|
||||
var im = new Element ('img', { src: 'data:image/png;base64,' + data });
|
||||
|
||||
a.empty ().removeClass ('waiter').grab (im);
|
||||
a.setProperty ('href', href);
|
||||
|
||||
var cross = new Element ('div', { 'html': '' });
|
||||
cross.setProperty ('onclick', 'clearShortcut("' + id + '");');
|
||||
cross.addClass ('cross');
|
||||
cross.inject ($(id), 'top');
|
||||
|
||||
$(id).addClass ('activated');
|
||||
|
||||
var p = a.getNext ();
|
||||
p.setProperty('onclick', 'javascript:renameShortcut("' + id + '");');
|
||||
|
||||
var num = id.charAt (1) - 1;
|
||||
sc.shortcuts[num].href = href;
|
||||
sc.shortcuts[num].img = data;
|
||||
|
||||
console.log ("speed_dial-save '" + encodeSafe (sc) + "'");
|
||||
}
|
||||
|
||||
var renameShortcut = function (id)
|
||||
{
|
||||
var name = prompt ("{enter_shortcut_name}", "");
|
||||
if (!name) return;
|
||||
|
||||
var num = id.charAt (1) - 1;
|
||||
|
||||
$(id).getLast ().set ('html', name);
|
||||
sc.shortcuts[num].title = name;
|
||||
|
||||
console.log ("speed_dial-save '" + encodeSafe (sc) + "'");
|
||||
}
|
||||
|
||||
var clearShortcut = function (id)
|
||||
{
|
||||
if(!confirm("{are_you_sure}"))
|
||||
return;
|
||||
|
||||
var num = id.charAt (1);
|
||||
var div = $(id);
|
||||
var cross = div.getFirst ();
|
||||
var a = cross.getNext ();
|
||||
var p = a.getNext ();
|
||||
|
||||
cross.dispose ();
|
||||
div.removeClass ('activated');
|
||||
a.empty ();
|
||||
|
||||
cross.dispose ();
|
||||
div.removeClass ('activated');
|
||||
a.empty ().set ('html', '<h1>' + num + '</h1><h4><span/></h4>');
|
||||
a.setProperty ('href', '#');
|
||||
p.empty ().removeProperty ('onclick');
|
||||
|
||||
num -= 1;
|
||||
sc.shortcuts[num].href = "#";
|
||||
sc.shortcuts[num].title = "";
|
||||
sc.shortcuts[num].img = "";
|
||||
|
||||
console.log ("speed_dial-save '" + encodeSafe (sc) + "'");
|
||||
}
|
||||
|
||||
var buildSpeeddial = function ()
|
||||
{
|
||||
sc.shortcuts.each (function (item, index, sc)
|
||||
{
|
||||
var cl = "shortcut";
|
||||
|
||||
if (index == 0 || index == 1 || index == 2)
|
||||
cl += " top";
|
||||
if (index == 2 || index == 5 || index == 8)
|
||||
cl += " right";
|
||||
|
||||
var div = new Element ('div', {
|
||||
'class': cl,
|
||||
'id': item.id
|
||||
});
|
||||
|
||||
var a = new Element ('a', {
|
||||
'href': item.href,
|
||||
'events': {
|
||||
'click': function () {
|
||||
return getAction (item.id);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var p = new Element ('p', {
|
||||
'text': item.title
|
||||
});
|
||||
|
||||
if (item.href == "#")
|
||||
a.set ('html', '<h1>' + item.id.charAt (1) + '</h1><h4><span/></h4>');
|
||||
else
|
||||
{
|
||||
div.addClass ('activated');
|
||||
var im = new Element ('img', { src: 'data:image/png;base64,' + item.img });
|
||||
var cross = new Element ('div', { 'html': '' });
|
||||
cross.setProperty ('onclick', 'clearShortcut("' + item.id + '");');
|
||||
cross.addClass ('cross');
|
||||
cross.inject (div, 'top');
|
||||
a.grab (im);
|
||||
p.setProperty('onclick', 'javascript:renameShortcut("' + item.id + '");');
|
||||
}
|
||||
|
||||
div.grab (a);
|
||||
div.grab (p);
|
||||
$('content').grab (div);
|
||||
});
|
||||
}
|
||||
|
||||
window.addEvent ('domready', function () {
|
||||
buildSpeeddial ();
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="wrap">
|
||||
<div id="content">
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
1
data/speeddial.json
Normal file
1
data/speeddial.json
Normal file
|
@ -0,0 +1 @@
|
|||
'{"shortcuts":[{"id":"s1","href":"#","title":"","img":""},{"id":"s2","href":"#","title":"","img":""},{"id":"s3","href":"#","title":"","img":""},{"id":"s4","href":"#","title":"","img":""},{"id":"s5","href":"#","title":"","img":""},{"id":"s6","href":"#","title":"","img":""},{"id":"s7","href":"#","title":"","img":""},{"id":"s8","href":"#","title":"","img":""},{"id":"s9","href":"#","title":"","img":""}]}'
|
385
extensions/adblock.c
Normal file
385
extensions/adblock.c
Normal file
|
@ -0,0 +1,385 @@
|
|||
/*
|
||||
Copyright (C) 2009 Christian Dywan <christian@twotoasts.de>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
See the file COPYING for the full license text.
|
||||
*/
|
||||
|
||||
#include <midori/midori.h>
|
||||
|
||||
#include <midori/sokoke.h>
|
||||
#include "config.h"
|
||||
|
||||
#include <glib/gstdio.h>
|
||||
|
||||
static void
|
||||
adblock_app_add_browser_cb (MidoriApp* app,
|
||||
MidoriBrowser* browser,
|
||||
MidoriExtension* extension);
|
||||
|
||||
static void
|
||||
adblock_deactivate_cb (MidoriExtension* extension,
|
||||
GtkWidget* menuitem)
|
||||
{
|
||||
MidoriApp* app = midori_extension_get_app (extension);
|
||||
|
||||
gtk_widget_destroy (menuitem);
|
||||
g_signal_handlers_disconnect_by_func (
|
||||
extension, adblock_deactivate_cb, menuitem);
|
||||
g_signal_handlers_disconnect_by_func (
|
||||
app, adblock_app_add_browser_cb, extension);
|
||||
/* FIXME: Disconnect session callbacks */
|
||||
}
|
||||
|
||||
static void
|
||||
adblock_preferences_render_text (GtkTreeViewColumn* column,
|
||||
GtkCellRenderer* renderer,
|
||||
GtkTreeModel* model,
|
||||
GtkTreeIter* iter,
|
||||
MidoriExtension* extension)
|
||||
{
|
||||
gchar* uri;
|
||||
|
||||
gtk_tree_model_get (model, iter, 0, &uri, -1);
|
||||
g_object_set (renderer, "text", uri, NULL);
|
||||
g_free (uri);
|
||||
}
|
||||
|
||||
static GtkWidget*
|
||||
adblock_get_preferences_dialog (MidoriExtension* extension)
|
||||
{
|
||||
MidoriApp* app;
|
||||
GtkWidget* browser;
|
||||
const gchar* dialog_title;
|
||||
GtkWidget* dialog;
|
||||
gint width, height;
|
||||
GtkWidget* xfce_heading;
|
||||
GtkWidget* hbox;
|
||||
GtkListStore* liststore;
|
||||
GtkWidget* treeview;
|
||||
GtkTreeViewColumn* column;
|
||||
GtkCellRenderer* renderer_text;
|
||||
GtkCellRenderer* renderer_pixbuf;
|
||||
GtkWidget* scrolled;
|
||||
gchar** filters;
|
||||
GtkWidget* vbox;
|
||||
GtkWidget* button;
|
||||
#if HAVE_OSX
|
||||
GtkWidget* icon;
|
||||
#endif
|
||||
|
||||
app = midori_extension_get_app (extension);
|
||||
browser = katze_object_get_object (app, "browser");
|
||||
|
||||
dialog_title = _("Configure Advertisement filters");
|
||||
dialog = gtk_dialog_new_with_buttons (dialog_title, GTK_WINDOW (browser),
|
||||
GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR,
|
||||
#if !HAVE_OSX
|
||||
GTK_STOCK_HELP, GTK_RESPONSE_HELP,
|
||||
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);
|
||||
/* TODO: Implement some kind of help function */
|
||||
gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog),
|
||||
GTK_RESPONSE_HELP, FALSE);
|
||||
sokoke_widget_get_text_size (dialog, "M", &width, &height);
|
||||
gtk_window_set_default_size (GTK_WINDOW (dialog), width * 52, -1);
|
||||
g_signal_connect (dialog, "response",
|
||||
G_CALLBACK (gtk_widget_destroy), dialog);
|
||||
/* TODO: We need mnemonics */
|
||||
if ((xfce_heading = sokoke_xfce_header_new (
|
||||
gtk_window_get_icon_name (GTK_WINDOW (dialog)), dialog_title)))
|
||||
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox),
|
||||
xfce_heading, FALSE, FALSE, 0);
|
||||
hbox = gtk_hbox_new (FALSE, 0);
|
||||
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), hbox,
|
||||
TRUE, TRUE, 12);
|
||||
liststore = gtk_list_store_new (1, G_TYPE_STRING);
|
||||
treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (liststore));
|
||||
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
|
||||
column = gtk_tree_view_column_new ();
|
||||
renderer_pixbuf = gtk_cell_renderer_pixbuf_new ();
|
||||
gtk_tree_view_column_pack_start (column, renderer_pixbuf, FALSE);
|
||||
/* gtk_tree_view_column_set_cell_data_func (column, renderer_pixbuf,
|
||||
(GtkTreeCellDataFunc)adblock_preferences_render_icon_cb,
|
||||
treeview, NULL); */
|
||||
renderer_text = gtk_cell_renderer_text_new ();
|
||||
gtk_tree_view_column_pack_start (column, renderer_text, TRUE);
|
||||
gtk_tree_view_column_set_cell_data_func (column, renderer_text,
|
||||
(GtkTreeCellDataFunc)adblock_preferences_render_text,
|
||||
extension, NULL);
|
||||
gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
|
||||
scrolled = gtk_scrolled_window_new (NULL, NULL);
|
||||
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled),
|
||||
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
|
||||
gtk_container_add (GTK_CONTAINER (scrolled), treeview);
|
||||
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled),
|
||||
GTK_SHADOW_IN);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), scrolled, TRUE, TRUE, 5);
|
||||
|
||||
filters = midori_extension_get_string_list (extension, "filters", NULL);
|
||||
if (filters != NULL)
|
||||
{
|
||||
gsize i = 0;
|
||||
while (filters[i++] != NULL)
|
||||
gtk_list_store_insert_with_values (GTK_LIST_STORE (liststore),
|
||||
NULL, i - 1, 0, filters[i -1], -1);
|
||||
}
|
||||
g_strfreev (filters);
|
||||
|
||||
g_object_unref (liststore);
|
||||
vbox = gtk_vbox_new (FALSE, 4);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 4);
|
||||
button = gtk_button_new_from_stock (GTK_STOCK_ADD);
|
||||
/* g_signal_connect (button, "clicked",
|
||||
G_CALLBACK (adblock_preferences_add_cb), extension); */
|
||||
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
|
||||
gtk_widget_set_sensitive (button, FALSE);
|
||||
button = gtk_button_new_from_stock (GTK_STOCK_EDIT);
|
||||
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
|
||||
gtk_widget_set_sensitive (button, FALSE);
|
||||
button = gtk_button_new_from_stock (GTK_STOCK_REMOVE);
|
||||
/* g_signal_connect (button, "clicked",
|
||||
G_CALLBACK (adblock_preferences_remove_cb), extension); */
|
||||
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
|
||||
gtk_widget_set_sensitive (button, FALSE);
|
||||
button = gtk_label_new (""); /* This is an invisible separator */
|
||||
gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 8);
|
||||
gtk_widget_set_sensitive (button, FALSE);
|
||||
button = gtk_label_new (""); /* This is an invisible separator */
|
||||
gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 12);
|
||||
button = gtk_button_new_from_stock (GTK_STOCK_GO_DOWN);
|
||||
gtk_widget_set_sensitive (button, FALSE);
|
||||
gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
|
||||
button = gtk_button_new_from_stock (GTK_STOCK_GO_UP);
|
||||
gtk_widget_set_sensitive (button, FALSE);
|
||||
gtk_box_pack_end (GTK_BOX (vbox), button, FALSE, FALSE, 0);
|
||||
|
||||
#if HAVE_OSX
|
||||
hbox = gtk_hbox_new (FALSE, 0);
|
||||
button = gtk_button_new ();
|
||||
icon = gtk_image_new_from_stock (GTK_STOCK_HELP, GTK_ICON_SIZE_BUTTON);
|
||||
gtk_button_set_image (GTK_BUTTON (button), icon);
|
||||
/* TODO: Implement some kind of help function */
|
||||
gtk_widget_set_sensitive (button, FALSE);
|
||||
/* g_signal_connect (button, "clicked",
|
||||
G_CALLBACK (adblock_preferences_help_clicked_cb), dialog); */
|
||||
gtk_box_pack_end (GTK_BOX (hbox),
|
||||
button, FALSE, FALSE, 4);
|
||||
gtk_box_pack_end (GTK_BOX (GTK_DIALOG (dialog)->vbox),
|
||||
hbox, FALSE, FALSE, 0);
|
||||
#endif
|
||||
gtk_widget_show_all (GTK_DIALOG (dialog)->vbox);
|
||||
|
||||
g_object_unref (browser);
|
||||
|
||||
return dialog;
|
||||
}
|
||||
|
||||
static void
|
||||
adblock_menu_configure_filters_activate_cb (GtkWidget* menuitem,
|
||||
MidoriExtension* extension)
|
||||
{
|
||||
static GtkWidget* dialog = NULL;
|
||||
|
||||
if (!dialog)
|
||||
{
|
||||
dialog = adblock_get_preferences_dialog (extension);
|
||||
g_signal_connect (dialog, "destroy",
|
||||
G_CALLBACK (gtk_widget_destroyed), &dialog);
|
||||
gtk_widget_show (dialog);
|
||||
}
|
||||
else
|
||||
gtk_window_present (GTK_WINDOW (dialog));
|
||||
}
|
||||
|
||||
static void
|
||||
adblock_app_add_browser_cb (MidoriApp* app,
|
||||
MidoriBrowser* browser,
|
||||
MidoriExtension* extension)
|
||||
{
|
||||
GtkWidget* panel;
|
||||
GtkWidget* menu;
|
||||
GtkWidget* menuitem;
|
||||
|
||||
panel = katze_object_get_object (browser, "panel");
|
||||
menu = katze_object_get_object (panel, "menu");
|
||||
menuitem = gtk_menu_item_new_with_mnemonic (_("Configure _Advertisement filters..."));
|
||||
g_signal_connect (menuitem, "activate",
|
||||
G_CALLBACK (adblock_menu_configure_filters_activate_cb), extension);
|
||||
gtk_widget_show (menuitem);
|
||||
gtk_menu_shell_insert (GTK_MENU_SHELL (menu), menuitem, 3);
|
||||
g_object_unref (menu);
|
||||
g_object_unref (panel);
|
||||
|
||||
g_signal_connect (extension, "deactivate",
|
||||
G_CALLBACK (adblock_deactivate_cb), menuitem);
|
||||
}
|
||||
|
||||
static void
|
||||
adblock_session_request_queued_cb (SoupSession* session,
|
||||
SoupMessage* msg,
|
||||
GRegex* regex)
|
||||
{
|
||||
SoupURI* soup_uri = soup_message_get_uri (msg);
|
||||
gchar* uri = soup_uri ? soup_uri_to_string (soup_uri, FALSE) : g_strdup ("");
|
||||
if (g_regex_match_full (regex, uri, -1, 0, 0, NULL, NULL))
|
||||
{
|
||||
/* g_debug ("match! '%s'", uri); */
|
||||
/* FIXME: This leads to funny error pages if frames are blocked */
|
||||
soup_message_set_response (msg, "text/plain", SOUP_MEMORY_STATIC, "adblock", 7);
|
||||
}
|
||||
g_free (uri);
|
||||
}
|
||||
|
||||
static void
|
||||
adblock_session_add_filter (SoupSession* session,
|
||||
gchar* path)
|
||||
{
|
||||
FILE* file;
|
||||
|
||||
if ((file = g_fopen (path, "r")))
|
||||
{
|
||||
/* We assume filter lists found on the web are commonly very long */
|
||||
GString* pattern = g_string_sized_new (1000 * 200);
|
||||
gchar line[255];
|
||||
GRegex* regex;
|
||||
GError* error;
|
||||
|
||||
while (fgets (line, 255, file))
|
||||
{
|
||||
/* Ignore comments and new lines */
|
||||
if (line[0] == '!')
|
||||
continue;
|
||||
/* FIXME: No support for whitelisting */
|
||||
if (line[0] == '@' && line[1] == '@')
|
||||
continue;
|
||||
/* FIXME: Differentiate # comments from element hiding */
|
||||
/* FIXME: No support for element hiding */
|
||||
if (line[0] == '#' && line[1] == '#')
|
||||
continue;
|
||||
/* FIXME: No support for [include] and [exclude] tags */
|
||||
if (line[0] == '[')
|
||||
continue;
|
||||
g_strchomp (line);
|
||||
g_string_append (pattern, line);
|
||||
g_string_append_c (pattern, '|');
|
||||
}
|
||||
|
||||
error = NULL;
|
||||
if (pattern->len > 2 &&
|
||||
(regex = g_regex_new (pattern->str, G_REGEX_OPTIMIZE,
|
||||
G_REGEX_MATCH_NOTEMPTY, &error)))
|
||||
{
|
||||
/* g_debug ("%s: '%s'", G_STRFUNC, pattern->str); */
|
||||
g_signal_connect_data (session, "request-queued",
|
||||
G_CALLBACK (adblock_session_request_queued_cb),
|
||||
regex, (GClosureNotify)g_regex_unref, 0);
|
||||
}
|
||||
else if (error)
|
||||
{
|
||||
/* g_warning ("%s: %s", G_STRFUNC, error->message); */
|
||||
g_error_free (error);
|
||||
}
|
||||
g_string_free (pattern, TRUE);
|
||||
fclose (file);
|
||||
}
|
||||
/* FIXME: This should presumably be freed, but there's a possible crash
|
||||
g_free (path); */
|
||||
}
|
||||
|
||||
#if WEBKIT_CHECK_VERSION (1, 1, 3)
|
||||
static void
|
||||
adblock_download_notify_status_cb (WebKitDownload* download,
|
||||
GParamSpec* pspec,
|
||||
gchar* path)
|
||||
{
|
||||
SoupSession* session = webkit_get_default_session ();
|
||||
adblock_session_add_filter (session, path);
|
||||
/* g_object_unref (download); */
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
adblock_activate_cb (MidoriExtension* extension,
|
||||
MidoriApp* app)
|
||||
{
|
||||
KatzeArray* browsers;
|
||||
MidoriBrowser* browser;
|
||||
guint i;
|
||||
gchar* folder;
|
||||
gchar** filters;
|
||||
SoupSession* session;
|
||||
|
||||
browsers = katze_object_get_object (app, "browsers");
|
||||
i = 0;
|
||||
while ((browser = katze_array_get_nth_item (browsers, i++)))
|
||||
adblock_app_add_browser_cb (app, browser, extension);
|
||||
g_signal_connect (app, "add-browser",
|
||||
G_CALLBACK (adblock_app_add_browser_cb), extension);
|
||||
g_object_unref (browsers);
|
||||
|
||||
session = webkit_get_default_session ();
|
||||
folder = g_build_filename (g_get_user_cache_dir (), PACKAGE_NAME,
|
||||
"adblock", NULL);
|
||||
g_mkdir_with_parents (folder, 0700);
|
||||
filters = midori_extension_get_string_list (extension, "filters", NULL);
|
||||
if (filters != NULL)
|
||||
{
|
||||
i = 0;
|
||||
while (filters[i++] != NULL)
|
||||
{
|
||||
gchar* filename = g_compute_checksum_for_string (G_CHECKSUM_MD5,
|
||||
filters[i - 1], -1);
|
||||
gchar* path = g_build_filename (folder, filename, NULL);
|
||||
if (!g_file_test (path, G_FILE_TEST_EXISTS))
|
||||
{
|
||||
#if WEBKIT_CHECK_VERSION (1, 1, 3)
|
||||
WebKitNetworkRequest* request;
|
||||
WebKitDownload* download;
|
||||
gchar* destination = g_filename_to_uri (path, NULL, NULL);
|
||||
|
||||
request = webkit_network_request_new (filters[i -1]);
|
||||
download = webkit_download_new (request);
|
||||
g_object_unref (request);
|
||||
webkit_download_set_destination_uri (download, destination);
|
||||
g_free (destination);
|
||||
g_signal_connect (download, "notify::status",
|
||||
G_CALLBACK (adblock_download_notify_status_cb), path);
|
||||
webkit_download_start (download);
|
||||
#else
|
||||
/* FIXME: Is it worth to rewrite this without WebKitDownload? */
|
||||
#endif
|
||||
}
|
||||
else
|
||||
adblock_session_add_filter (session, path);
|
||||
g_free (filename);
|
||||
}
|
||||
}
|
||||
g_strfreev (filters);
|
||||
g_free (folder);
|
||||
}
|
||||
|
||||
MidoriExtension*
|
||||
extension_init (void)
|
||||
{
|
||||
MidoriExtension* extension = g_object_new (MIDORI_TYPE_EXTENSION,
|
||||
"name", _("Advertisement blocker"),
|
||||
"description", _("Block advertisements according to a filter list"),
|
||||
"version", "0.1",
|
||||
"authors", "Christian Dywan <christian@twotoasts.de>",
|
||||
NULL);
|
||||
midori_extension_install_string_list (extension, "filters", NULL, G_MAXSIZE);
|
||||
|
||||
g_signal_connect (extension, "activate",
|
||||
G_CALLBACK (adblock_activate_cb), NULL);
|
||||
|
||||
return extension;
|
||||
}
|
|
@ -11,15 +11,6 @@
|
|||
|
||||
#include <midori/midori.h>
|
||||
|
||||
static void
|
||||
colorful_tabs_button_toggled_cb (GtkWidget* button,
|
||||
MidoriExtension* extension)
|
||||
{
|
||||
midori_extension_set_boolean (extension, "tint",
|
||||
!midori_extension_get_boolean (extension, "tint"));
|
||||
/* FIXME: Update all tab colors */
|
||||
}
|
||||
|
||||
static void
|
||||
colorful_tabs_view_notify_uri_cb (MidoriView* view,
|
||||
GParamSpec* pspec,
|
||||
|
@ -70,6 +61,25 @@ colorful_tabs_view_notify_uri_cb (MidoriView* view,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
colorful_tabs_browser_foreach_cb (GtkWidget* view,
|
||||
MidoriExtension* extension)
|
||||
{
|
||||
colorful_tabs_view_notify_uri_cb (MIDORI_VIEW (view), NULL, extension);
|
||||
}
|
||||
|
||||
static void
|
||||
colorful_tabs_button_toggled_cb (GtkWidget* button,
|
||||
MidoriExtension* extension)
|
||||
{
|
||||
MidoriBrowser* browser = MIDORI_BROWSER (gtk_widget_get_toplevel (button));
|
||||
|
||||
midori_extension_set_boolean (extension, "tint",
|
||||
!midori_extension_get_boolean (extension, "tint"));
|
||||
midori_browser_foreach (browser,
|
||||
(GtkCallback)colorful_tabs_browser_foreach_cb, extension);
|
||||
}
|
||||
|
||||
static void
|
||||
colorful_tabs_browser_add_tab_cb (MidoriBrowser* browser,
|
||||
MidoriView* view,
|
||||
|
@ -83,11 +93,12 @@ static void
|
|||
colorful_tabs_deactivate_cb (MidoriExtension* extension,
|
||||
GtkWidget* bbox)
|
||||
{
|
||||
gtk_widget_destroy (bbox);
|
||||
g_signal_handlers_disconnect_by_func (
|
||||
extension, colorful_tabs_deactivate_cb, bbox);
|
||||
/* FIXME: Disconnect signals */
|
||||
/* FIXME: Reset all tab colors */
|
||||
midori_browser_foreach (MIDORI_BROWSER (gtk_widget_get_toplevel (bbox)),
|
||||
(GtkCallback)colorful_tabs_browser_foreach_cb, extension);
|
||||
gtk_widget_destroy (bbox);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
File diff suppressed because it is too large
Load diff
45
extensions/cookie-manager/cookie-manager-page.h
Normal file
45
extensions/cookie-manager/cookie-manager-page.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
Copyright (C) 2009 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
See the file COPYING for the full license text.
|
||||
*/
|
||||
|
||||
#ifndef __COOKIE_MANAGER_PAGE_H__
|
||||
#define __COOKIE_MANAGER_PAGE_H__
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define COOKIE_MANAGER_PAGE_TYPE (cookie_manager_page_get_type())
|
||||
#define COOKIE_MANAGER_PAGE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),\
|
||||
COOKIE_MANAGER_PAGE_TYPE, CookieManagerPage))
|
||||
#define COOKIE_MANAGER_PAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),\
|
||||
COOKIE_MANAGER_PAGE_TYPE, CookieManagerPageClass))
|
||||
#define IS_COOKIE_MANAGER_PAGE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),\
|
||||
COOKIE_MANAGER_PAGE_TYPE))
|
||||
#define IS_COOKIE_MANAGER_PAGE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),\
|
||||
COOKIE_MANAGER_PAGE_TYPE))
|
||||
|
||||
typedef struct _CookieManagerPage CookieManagerPage;
|
||||
typedef struct _CookieManagerPageClass CookieManagerPageClass;
|
||||
|
||||
struct _CookieManagerPage
|
||||
{
|
||||
GtkVBox parent;
|
||||
};
|
||||
|
||||
struct _CookieManagerPageClass
|
||||
{
|
||||
GtkVBoxClass parent_class;
|
||||
};
|
||||
|
||||
GType cookie_manager_page_get_type (void);
|
||||
GtkWidget* cookie_manager_page_new (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __COOKIE_MANAGER_PAGE_H__ */
|
130
extensions/cookie-manager/cookie-manager.c
Normal file
130
extensions/cookie-manager/cookie-manager.c
Normal file
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
Copyright (C) 2009 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
See the file COPYING for the full license text.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <midori/midori.h>
|
||||
#include <webkit/webkit.h>
|
||||
|
||||
#include "cookie-manager.h"
|
||||
#include "cookie-manager-page.h"
|
||||
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
MidoriApp *app;
|
||||
MidoriBrowser *browser;
|
||||
MidoriExtension *extension;
|
||||
GtkWidget *panel_page;
|
||||
} CMData;
|
||||
|
||||
static void cm_app_add_browser_cb(MidoriApp *app, MidoriBrowser *browser, MidoriExtension *ext);
|
||||
static void cm_deactivate_cb(MidoriExtension *extension, CMData *cmdata);
|
||||
|
||||
|
||||
|
||||
static void cm_browser_close_cb(GtkObject *browser, CMData *cmdata)
|
||||
{
|
||||
g_signal_handlers_disconnect_by_func(cmdata->extension, cm_deactivate_cb, cmdata);
|
||||
g_signal_handlers_disconnect_by_func(cmdata->browser, cm_browser_close_cb, cmdata);
|
||||
|
||||
/* the panel_page widget gets destroyed automatically when a browser is closed but not
|
||||
* when the extension is deactivated */
|
||||
if (cmdata->panel_page != NULL && IS_COOKIE_MANAGER_PAGE(cmdata->panel_page))
|
||||
gtk_widget_destroy(cmdata->panel_page);
|
||||
|
||||
g_free(cmdata);
|
||||
}
|
||||
|
||||
|
||||
static void cm_deactivate_cb(MidoriExtension *extension, CMData *cmdata)
|
||||
{
|
||||
g_signal_handlers_disconnect_by_func(cmdata->app, cm_app_add_browser_cb, extension);
|
||||
cm_browser_close_cb(NULL, cmdata);
|
||||
}
|
||||
|
||||
|
||||
static void cm_app_add_browser_cb(MidoriApp *app, MidoriBrowser *browser, MidoriExtension *ext)
|
||||
{
|
||||
GtkWidget *panel;
|
||||
GtkWidget *page;
|
||||
CMData *cmdata;
|
||||
|
||||
panel = katze_object_get_object(browser, "panel");
|
||||
|
||||
page = cookie_manager_page_new();
|
||||
gtk_widget_show(page);
|
||||
midori_panel_append_page(MIDORI_PANEL(panel), MIDORI_VIEWABLE(page));
|
||||
|
||||
cmdata = g_new0(CMData, 1);
|
||||
cmdata->app = app;
|
||||
cmdata->browser = browser;
|
||||
cmdata->extension = ext;
|
||||
cmdata->panel_page = page;
|
||||
|
||||
g_signal_connect(browser, "destroy", G_CALLBACK(cm_browser_close_cb), cmdata);
|
||||
g_signal_connect(ext, "deactivate", G_CALLBACK(cm_deactivate_cb), cmdata);
|
||||
|
||||
g_object_unref(panel);
|
||||
}
|
||||
|
||||
|
||||
static void cm_activate_cb(MidoriExtension *extension, MidoriApp *app, gpointer data)
|
||||
{
|
||||
guint i;
|
||||
KatzeArray *browsers;
|
||||
MidoriBrowser *browser;
|
||||
|
||||
/* add the cookie manager panel page to existing browsers */
|
||||
browsers = katze_object_get_object(app, "browsers");
|
||||
i = 0;
|
||||
while ((browser = katze_array_get_nth_item(browsers, i++)))
|
||||
cm_app_add_browser_cb(app, browser, extension);
|
||||
g_object_unref(browsers);
|
||||
|
||||
g_signal_connect(app, "add-browser", G_CALLBACK(cm_app_add_browser_cb), extension);
|
||||
}
|
||||
|
||||
|
||||
MidoriExtension *extension_init(void)
|
||||
{
|
||||
MidoriExtension *extension;
|
||||
GtkIconFactory *factory;
|
||||
GtkIconSource *icon_source;
|
||||
GtkIconSet *icon_set;
|
||||
static GtkStockItem items[] =
|
||||
{
|
||||
{ STOCK_COOKIE_MANAGER, N_("_Cookie Manager"), 0, 0, NULL }
|
||||
};
|
||||
|
||||
factory = gtk_icon_factory_new();
|
||||
gtk_stock_add(items, G_N_ELEMENTS(items));
|
||||
icon_set = gtk_icon_set_new();
|
||||
icon_source = gtk_icon_source_new();
|
||||
gtk_icon_source_set_icon_name(icon_source, GTK_STOCK_DIALOG_AUTHENTICATION);
|
||||
gtk_icon_set_add_source(icon_set, icon_source);
|
||||
gtk_icon_source_free(icon_source);
|
||||
gtk_icon_factory_add(factory, STOCK_COOKIE_MANAGER, icon_set);
|
||||
gtk_icon_set_unref(icon_set);
|
||||
gtk_icon_factory_add_default(factory);
|
||||
g_object_unref(factory);
|
||||
|
||||
extension = g_object_new(MIDORI_TYPE_EXTENSION,
|
||||
"name", _("Cookie Manager"),
|
||||
"description", _("List, view and delete cookies"),
|
||||
"version", "0.2",
|
||||
"authors", "Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>",
|
||||
NULL);
|
||||
|
||||
g_signal_connect(extension, "activate", G_CALLBACK(cm_activate_cb), NULL);
|
||||
|
||||
return extension;
|
||||
}
|
20
extensions/cookie-manager/cookie-manager.h
Normal file
20
extensions/cookie-manager/cookie-manager.h
Normal file
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
Copyright (C) 2009 Enrico Tröger <enrico(dot)troeger(at)uvena(dot)de>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
See the file COPYING for the full license text.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __COOKIE_MANAGER_H__
|
||||
#define __COOKIE_MANAGER_H__
|
||||
|
||||
|
||||
#define STOCK_COOKIE_MANAGER "cookie-manager"
|
||||
|
||||
|
||||
#endif /* __COOKIE_MANAGER_H__ */
|
368
extensions/feed-panel/feed-atom.c
Normal file
368
extensions/feed-panel/feed-atom.c
Normal file
|
@ -0,0 +1,368 @@
|
|||
/*
|
||||
Copyright (C) 2009 Dale Whittaker <dayul@users.sf.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
See the file COPYING for the full license text.
|
||||
*/
|
||||
|
||||
#include "feed-atom.h"
|
||||
|
||||
#define atom_get_link_attribute(item, attribute) \
|
||||
(gchar*)g_object_get_data (G_OBJECT (item), attribute)
|
||||
|
||||
#define atom_set_link_attribute(item, attribute, value) \
|
||||
g_object_set_data (G_OBJECT (item), attribute, value)
|
||||
|
||||
static gboolean
|
||||
atom_is_valid (FeedParser* fparser)
|
||||
{
|
||||
xmlNodePtr node;
|
||||
|
||||
node = fparser->node;
|
||||
|
||||
if (!(xmlStrcmp (node->name, BAD_CAST "feed")) &&
|
||||
!(xmlStrcmp (node->ns->href, BAD_CAST "http://www.w3.org/2005/Atom"))
|
||||
)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
atom_update (FeedParser* fparser)
|
||||
{
|
||||
xmlNodePtr node;
|
||||
xmlNodePtr child;
|
||||
gint64 date;
|
||||
gint64 newdate;
|
||||
|
||||
date = katze_item_get_added (fparser->item);
|
||||
|
||||
node = fparser->node;
|
||||
child = node->children;
|
||||
while (child)
|
||||
{
|
||||
if (child->type == XML_ELEMENT_NODE)
|
||||
{
|
||||
if (!(xmlStrcmp (child->name, BAD_CAST "updated")))
|
||||
{
|
||||
fparser->node = child;
|
||||
newdate = feed_get_element_date (fparser);
|
||||
fparser->node = node;
|
||||
return (date != newdate);
|
||||
}
|
||||
}
|
||||
child = child->next;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
atom_preferred_link (const gchar* old,
|
||||
const gchar* new)
|
||||
{
|
||||
guint i;
|
||||
gint iold;
|
||||
gint inew;
|
||||
gchar* rels[5] =
|
||||
{
|
||||
"enclosure",
|
||||
"via",
|
||||
"related",
|
||||
"alternate",
|
||||
"self",
|
||||
};
|
||||
|
||||
iold = inew = -1;
|
||||
for (i = 0; i < 5; i++)
|
||||
{
|
||||
if (old && g_str_equal (old, rels[i]))
|
||||
iold = i;
|
||||
if (new && g_str_equal (new, rels[i]))
|
||||
inew = i;
|
||||
}
|
||||
return (inew > iold);
|
||||
}
|
||||
|
||||
static void
|
||||
atom_get_link (KatzeItem* item,
|
||||
xmlNodePtr node)
|
||||
{
|
||||
gchar* oldtype;
|
||||
gchar* newtype;
|
||||
gchar* oldrel;
|
||||
gchar* newrel;
|
||||
gchar* href;
|
||||
gboolean oldishtml;
|
||||
gboolean newishtml;
|
||||
gboolean newlink;
|
||||
|
||||
newlink = FALSE;
|
||||
oldtype = atom_get_link_attribute (item, "linktype");
|
||||
oldrel = atom_get_link_attribute (item, "linkrel");
|
||||
|
||||
newtype = (gchar*)xmlGetProp (node, BAD_CAST "type");
|
||||
newrel = (gchar*)xmlGetProp (node, BAD_CAST "rel");
|
||||
href = (gchar*)xmlGetProp (node, BAD_CAST "href");
|
||||
|
||||
if (!newrel)
|
||||
newrel = g_strdup ("alternate");
|
||||
|
||||
oldishtml = (oldtype && g_str_equal (oldtype, "text/html"));
|
||||
newishtml = (newtype && g_str_equal (newtype, "text/html"));
|
||||
|
||||
/* prefer HTML links over anything else.
|
||||
* if the previous link was already HTML, decide which link
|
||||
* we prefer.
|
||||
*/
|
||||
if ((newishtml && oldishtml) || (!newishtml && !oldishtml))
|
||||
newlink = atom_preferred_link (oldrel, newrel);
|
||||
else
|
||||
newlink = newishtml;
|
||||
|
||||
if (newlink)
|
||||
{
|
||||
katze_item_set_uri (item, href);
|
||||
atom_set_link_attribute (item, "linkrel", newrel);
|
||||
atom_set_link_attribute (item, "linktype", newrel);
|
||||
}
|
||||
else
|
||||
{
|
||||
xmlFree (href);
|
||||
xmlFree (newrel);
|
||||
xmlFree (newtype);
|
||||
}
|
||||
}
|
||||
|
||||
static gchar*
|
||||
atom_get_title (FeedParser* fparser)
|
||||
{
|
||||
if (!katze_item_get_name (fparser->item))
|
||||
{
|
||||
gchar* type;
|
||||
|
||||
type = (gchar*)xmlGetProp (fparser->node, BAD_CAST "type");
|
||||
if (type)
|
||||
{
|
||||
gchar* content = NULL;
|
||||
|
||||
if (g_str_equal (type, "html") ||
|
||||
g_str_equal (type, "xhtml"))
|
||||
content = feed_get_element_markup (fparser);
|
||||
|
||||
xmlFree (type);
|
||||
|
||||
if (content)
|
||||
return content;
|
||||
}
|
||||
}
|
||||
return feed_get_element_string (fparser);
|
||||
}
|
||||
|
||||
static void
|
||||
atom_preparse_entry (FeedParser* fparser)
|
||||
{
|
||||
fparser->item = katze_item_new ();
|
||||
}
|
||||
|
||||
static void
|
||||
atom_parse_entry (FeedParser* fparser)
|
||||
{
|
||||
xmlNodePtr node;
|
||||
gchar* content;
|
||||
gint64 date;
|
||||
|
||||
node = fparser->node;
|
||||
content = NULL;
|
||||
|
||||
if (!xmlStrcmp (node->name, BAD_CAST "id"))
|
||||
{
|
||||
content = feed_get_element_string (fparser);
|
||||
katze_item_set_token (fparser->item, content);
|
||||
}
|
||||
else if (!xmlStrcmp (node->name, BAD_CAST "title"))
|
||||
{
|
||||
content = atom_get_title (fparser);
|
||||
katze_item_set_name (fparser->item, content);
|
||||
}
|
||||
else if (!xmlStrcmp (node->name, BAD_CAST "summary"))
|
||||
{
|
||||
content = feed_get_element_string (fparser);
|
||||
katze_item_set_text (fparser->item, content);
|
||||
}
|
||||
else if (!xmlStrcmp (node->name, BAD_CAST "updated"))
|
||||
{
|
||||
date = feed_get_element_date (fparser);
|
||||
katze_item_set_added (fparser->item, date);
|
||||
}
|
||||
else if (!xmlStrcmp (node->name, BAD_CAST "icon"))
|
||||
{
|
||||
content = feed_get_element_string (fparser);
|
||||
katze_item_set_icon (fparser->item, content);
|
||||
}
|
||||
/* FIXME content can be used in some cases where there
|
||||
* is no summary, but it needs additional work,
|
||||
* as it can be HTML, or base64 encoded.
|
||||
* see the spec.
|
||||
*/
|
||||
else if (!xmlStrcmp (node->name, BAD_CAST "content"))
|
||||
{
|
||||
/* Only retrieve content if there is no summary */
|
||||
if (!katze_item_get_text (fparser->item))
|
||||
{
|
||||
content = feed_get_element_string (fparser);
|
||||
katze_item_set_text (fparser->item, content);
|
||||
}
|
||||
}
|
||||
else if (!(xmlStrcmp (node->name, BAD_CAST "link")))
|
||||
atom_get_link (fparser->item, node);
|
||||
|
||||
g_free (content);
|
||||
}
|
||||
|
||||
static void
|
||||
atom_postparse_entry (FeedParser* fparser)
|
||||
{
|
||||
if (!*fparser->error)
|
||||
{
|
||||
/*
|
||||
* Verify that the required Atom elements are added
|
||||
* (as per the spec)
|
||||
*/
|
||||
if (!katze_item_get_token (fparser->item) ||
|
||||
!katze_item_get_name (fparser->item) ||
|
||||
!katze_item_get_uri (fparser->item) ||
|
||||
!katze_item_get_added (fparser->item))
|
||||
{
|
||||
feed_parser_set_error (fparser, FEED_PARSE_ERROR_MISSING_ELEMENT,
|
||||
_("Failed to find required Atom \"entry\" elements in XML data."));
|
||||
}
|
||||
}
|
||||
|
||||
if (KATZE_IS_ITEM (fparser->item))
|
||||
{
|
||||
atom_set_link_attribute (fparser->item, "linkrel", NULL);
|
||||
atom_set_link_attribute (fparser->item, "linktype", NULL);
|
||||
|
||||
if (*fparser->error)
|
||||
{
|
||||
g_object_unref (fparser->item);
|
||||
fparser->item = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
atom_parse_feed (FeedParser* fparser)
|
||||
{
|
||||
FeedParser* eparser;
|
||||
xmlNodePtr node;
|
||||
gchar* content;
|
||||
gint64 date;
|
||||
|
||||
node = fparser->node;
|
||||
content = NULL;
|
||||
|
||||
if (!xmlStrcmp (node->name, BAD_CAST "id"))
|
||||
{
|
||||
content = feed_get_element_string (fparser);
|
||||
katze_item_set_token (fparser->item, content);
|
||||
}
|
||||
else if (!xmlStrcmp (node->name, BAD_CAST "title"))
|
||||
{
|
||||
content = atom_get_title (fparser);
|
||||
katze_item_set_name (fparser->item, content);
|
||||
}
|
||||
else if (!xmlStrcmp (node->name, BAD_CAST "subtitle"))
|
||||
{
|
||||
content = feed_get_element_string (fparser);
|
||||
katze_item_set_text (fparser->item, content);
|
||||
}
|
||||
else if (!xmlStrcmp (node->name, BAD_CAST "updated"))
|
||||
{
|
||||
date = feed_get_element_date (fparser);
|
||||
katze_item_set_added (fparser->item, date);
|
||||
}
|
||||
else if (!xmlStrcmp (node->name, BAD_CAST "icon"))
|
||||
{
|
||||
content = feed_get_element_string (fparser);
|
||||
katze_item_set_icon (fparser->item, content);
|
||||
}
|
||||
else if (!(xmlStrcmp (node->name, BAD_CAST "link")))
|
||||
{
|
||||
atom_get_link (fparser->item, node);
|
||||
}
|
||||
else if (!xmlStrcmp (node->name, BAD_CAST "entry"))
|
||||
{
|
||||
eparser = g_new0 (FeedParser, 1);
|
||||
eparser->doc = fparser->doc;
|
||||
eparser->node = fparser->node;
|
||||
eparser->error = fparser->error;
|
||||
eparser->preparse = atom_preparse_entry;
|
||||
eparser->parse = atom_parse_entry;
|
||||
eparser->postparse = atom_postparse_entry;
|
||||
|
||||
feed_parse_node (eparser);
|
||||
|
||||
if (KATZE_IS_ITEM (eparser->item))
|
||||
{
|
||||
KatzeItem* item;
|
||||
if (!(item = feed_item_exists (KATZE_ARRAY (fparser->item), eparser->item)))
|
||||
katze_array_add_item (KATZE_ARRAY (fparser->item), eparser->item);
|
||||
else
|
||||
{
|
||||
g_object_unref (eparser->item);
|
||||
katze_array_move_item (KATZE_ARRAY (fparser->item), item, 0);
|
||||
}
|
||||
}
|
||||
g_free (eparser);
|
||||
|
||||
}
|
||||
g_free (content);
|
||||
}
|
||||
|
||||
static void
|
||||
atom_postparse_feed (FeedParser* fparser)
|
||||
{
|
||||
if (KATZE_IS_ARRAY (fparser->item))
|
||||
{
|
||||
atom_set_link_attribute (fparser->item, "linkrel", NULL);
|
||||
atom_set_link_attribute (fparser->item, "linktype", NULL);
|
||||
}
|
||||
|
||||
if (!*fparser->error)
|
||||
{
|
||||
/*
|
||||
* Verify that the required Atom elements are added
|
||||
* (as per the spec)
|
||||
*/
|
||||
if (!katze_item_get_token (fparser->item) ||
|
||||
!katze_item_get_name (fparser->item) ||
|
||||
!katze_item_get_added (fparser->item))
|
||||
{
|
||||
feed_parser_set_error (fparser, FEED_PARSE_ERROR_MISSING_ELEMENT,
|
||||
_("Failed to find required Atom \"feed\" elements in XML data."));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FeedParser*
|
||||
atom_init_parser (void)
|
||||
{
|
||||
FeedParser* fparser;
|
||||
|
||||
fparser = g_new0 (FeedParser, 1);
|
||||
g_return_val_if_fail (fparser, NULL);
|
||||
|
||||
fparser->isvalid = atom_is_valid;
|
||||
fparser->update = atom_update;
|
||||
fparser->parse = atom_parse_feed;
|
||||
fparser->postparse = atom_postparse_feed;
|
||||
|
||||
return fparser;
|
||||
}
|
||||
|
25
extensions/feed-panel/feed-atom.h
Normal file
25
extensions/feed-panel/feed-atom.h
Normal file
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
Copyright (C) 2009 Dale Whittaker <dayul@users.sf.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
See the file COPYING for the full license text.
|
||||
*/
|
||||
|
||||
#ifndef __FEED_ATOM_H__
|
||||
#define __FEED_ATOM_H__
|
||||
|
||||
#include "feed-parse.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
FeedParser*
|
||||
atom_init_parser (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __FEED_ATOM_H__ */
|
||||
|
900
extensions/feed-panel/feed-panel.c
Normal file
900
extensions/feed-panel/feed-panel.c
Normal file
|
@ -0,0 +1,900 @@
|
|||
/*
|
||||
Copyright (C) 2009 Dale Whittaker <dayul@users.sf.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
See the file COPYING for the full license text.
|
||||
*/
|
||||
|
||||
#include "feed-panel.h"
|
||||
|
||||
#include <midori/midori.h>
|
||||
#include <midori/sokoke.h>
|
||||
#include <time.h>
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#define STOCK_FEED_PANEL "feed-panel"
|
||||
|
||||
struct _FeedPanel
|
||||
{
|
||||
GtkVBox parent_instance;
|
||||
|
||||
GtkWidget* toolbar;
|
||||
GtkWidget* treeview;
|
||||
GtkWidget* webview;
|
||||
GtkWidget* delete;
|
||||
GdkPixbuf* pixbuf;
|
||||
KatzeNet* net;
|
||||
};
|
||||
|
||||
struct _FeedPanelClass
|
||||
{
|
||||
GtkVBoxClass parent_class;
|
||||
};
|
||||
|
||||
static void
|
||||
feed_panel_viewable_iface_init (MidoriViewableIface* iface);
|
||||
|
||||
static void
|
||||
feed_panel_insert_item (FeedPanel* panel,
|
||||
GtkTreeStore* treestore,
|
||||
GtkTreeIter* parent,
|
||||
KatzeItem* item);
|
||||
|
||||
static void
|
||||
feed_panel_disconnect_feed (FeedPanel* panel,
|
||||
KatzeArray* feed);
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (FeedPanel, feed_panel, GTK_TYPE_VBOX,
|
||||
G_IMPLEMENT_INTERFACE (MIDORI_TYPE_VIEWABLE,
|
||||
feed_panel_viewable_iface_init));
|
||||
|
||||
enum
|
||||
{
|
||||
ADD_FEED,
|
||||
REMOVE_FEED,
|
||||
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
static guint signals[LAST_SIGNAL];
|
||||
|
||||
static void
|
||||
feed_panel_treeview_render_icon_cb (GtkTreeViewColumn* column,
|
||||
GtkCellRenderer* renderer,
|
||||
GtkTreeModel* model,
|
||||
GtkTreeIter* iter,
|
||||
FeedPanel* panel)
|
||||
{
|
||||
GdkPixbuf* pixbuf;
|
||||
KatzeItem* item;
|
||||
KatzeItem* pitem;
|
||||
const gchar* uri;
|
||||
|
||||
gtk_tree_model_get (model, iter, 0, &item, -1);
|
||||
g_assert (KATZE_IS_ITEM (item));
|
||||
|
||||
if (!KATZE_IS_ARRAY (item))
|
||||
{
|
||||
pitem = katze_item_get_parent (item);
|
||||
g_assert (KATZE_IS_ITEM (pitem));
|
||||
}
|
||||
else
|
||||
pitem = item;
|
||||
|
||||
uri = katze_item_get_uri (pitem);
|
||||
if (uri)
|
||||
{
|
||||
pixbuf = katze_net_load_icon (panel->net, uri, NULL, NULL, NULL);
|
||||
if (!pixbuf)
|
||||
pixbuf = panel->pixbuf;
|
||||
}
|
||||
else
|
||||
{
|
||||
pixbuf = gtk_widget_render_icon (panel->treeview,
|
||||
GTK_STOCK_DIALOG_ERROR, GTK_ICON_SIZE_MENU, NULL);
|
||||
}
|
||||
|
||||
g_object_set (renderer, "pixbuf", pixbuf, NULL);
|
||||
|
||||
if (pixbuf != panel->pixbuf)
|
||||
g_object_unref (pixbuf);
|
||||
}
|
||||
|
||||
static void
|
||||
feed_panel_treeview_render_text_cb (GtkTreeViewColumn* column,
|
||||
GtkCellRenderer* renderer,
|
||||
GtkTreeModel* model,
|
||||
GtkTreeIter* iter,
|
||||
GtkWidget* treeview)
|
||||
{
|
||||
KatzeItem* item;
|
||||
const gchar* title;
|
||||
|
||||
gtk_tree_model_get (model, iter, 0, &item, -1);
|
||||
g_assert (KATZE_IS_ITEM (item));
|
||||
|
||||
title = katze_item_get_name (item);
|
||||
if (!title || !*title || g_str_equal (title, " "))
|
||||
title = katze_item_get_text (item);
|
||||
if (!title || !*title || g_str_equal (title, " "))
|
||||
title = katze_item_get_uri (item);
|
||||
|
||||
g_object_set (renderer, "text", title, NULL);
|
||||
g_object_unref (item);
|
||||
}
|
||||
|
||||
static void
|
||||
feed_panel_add_item_cb (KatzeArray* parent,
|
||||
KatzeItem* child,
|
||||
FeedPanel* panel)
|
||||
{
|
||||
GtkTreeModel* model;
|
||||
GtkTreeIter iter;
|
||||
GtkTreeIter child_iter;
|
||||
KatzeItem* item;
|
||||
gint i;
|
||||
|
||||
g_return_if_fail (FEED_IS_PANEL (panel));
|
||||
g_return_if_fail (KATZE_IS_ARRAY (parent));
|
||||
g_return_if_fail (KATZE_IS_ITEM (child));
|
||||
|
||||
model = gtk_tree_view_get_model (GTK_TREE_VIEW (panel->treeview));
|
||||
|
||||
if (katze_item_get_parent (KATZE_ITEM (parent)))
|
||||
{
|
||||
if (KATZE_IS_ARRAY (child))
|
||||
{
|
||||
gtk_tree_store_insert_with_values (GTK_TREE_STORE (model), &child_iter,
|
||||
NULL, G_MAXINT, 0, child, -1);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
i = 0;
|
||||
while (gtk_tree_model_iter_nth_child (model, &iter, NULL, i++))
|
||||
{
|
||||
gtk_tree_model_get (model, &iter, 0, &item, -1);
|
||||
if (item == KATZE_ITEM (parent))
|
||||
{
|
||||
gtk_tree_store_insert_with_values (GTK_TREE_STORE (model), &child_iter,
|
||||
&iter, 0, 0, child, -1);
|
||||
|
||||
g_object_unref (child);
|
||||
g_object_unref (item);
|
||||
break;
|
||||
}
|
||||
g_object_unref (item);
|
||||
}
|
||||
}
|
||||
}
|
||||
feed_panel_insert_item (panel, GTK_TREE_STORE (model), &child_iter, child);
|
||||
}
|
||||
|
||||
static void
|
||||
feed_panel_remove_iter (GtkTreeModel* model,
|
||||
KatzeItem* removed_item)
|
||||
{
|
||||
guint i;
|
||||
GtkTreeIter iter;
|
||||
|
||||
i = 0;
|
||||
while (gtk_tree_model_iter_nth_child (model, &iter, NULL, i))
|
||||
{
|
||||
KatzeItem* item;
|
||||
|
||||
gtk_tree_model_get (model, &iter, 0, &item, -1);
|
||||
|
||||
if (item == removed_item)
|
||||
{
|
||||
gtk_tree_store_remove (GTK_TREE_STORE (model), &iter);
|
||||
g_object_unref (item);
|
||||
break;
|
||||
}
|
||||
g_object_unref (item);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
feed_panel_remove_item_cb (KatzeArray* item,
|
||||
KatzeItem* child,
|
||||
FeedPanel* panel)
|
||||
{
|
||||
GtkTreeModel* model;
|
||||
KatzeItem* pitem;
|
||||
|
||||
g_return_if_fail (FEED_IS_PANEL (panel));
|
||||
g_return_if_fail (KATZE_IS_ARRAY (item));
|
||||
g_return_if_fail (KATZE_IS_ITEM (child));
|
||||
|
||||
if (KATZE_IS_ARRAY (child))
|
||||
feed_panel_disconnect_feed (panel, KATZE_ARRAY (child));
|
||||
|
||||
if (!katze_item_get_parent (KATZE_ITEM (item)))
|
||||
{
|
||||
gint n;
|
||||
|
||||
n = katze_array_get_length (KATZE_ARRAY (child));
|
||||
g_assert (n == 1);
|
||||
pitem = katze_array_get_nth_item (KATZE_ARRAY (child), 0);
|
||||
}
|
||||
else
|
||||
pitem = child;
|
||||
|
||||
model = gtk_tree_view_get_model (GTK_TREE_VIEW (panel->treeview));
|
||||
feed_panel_remove_iter (model, pitem);
|
||||
g_object_unref (pitem);
|
||||
}
|
||||
|
||||
static void
|
||||
feed_panel_move_item_cb (KatzeArray* feed,
|
||||
KatzeItem* child,
|
||||
gint position,
|
||||
FeedPanel* panel)
|
||||
{
|
||||
GtkTreeModel* model;
|
||||
GtkTreeIter iter;
|
||||
guint i;
|
||||
|
||||
g_return_if_fail (FEED_IS_PANEL (panel));
|
||||
g_return_if_fail (KATZE_IS_ARRAY (feed));
|
||||
g_return_if_fail (KATZE_IS_ITEM (child));
|
||||
|
||||
model = gtk_tree_view_get_model (GTK_TREE_VIEW (panel->treeview));
|
||||
|
||||
i = 0;
|
||||
while (gtk_tree_model_iter_nth_child (model, &iter, NULL, i))
|
||||
{
|
||||
KatzeItem* item;
|
||||
|
||||
gtk_tree_model_get (model, &iter, 0, &item, -1);
|
||||
|
||||
if (item == child)
|
||||
{
|
||||
gtk_tree_store_move_after (GTK_TREE_STORE (model), &iter, NULL);
|
||||
g_object_unref (item);
|
||||
break;
|
||||
}
|
||||
g_object_unref (item);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
feed_panel_disconnect_feed (FeedPanel* panel,
|
||||
KatzeArray* feed)
|
||||
{
|
||||
KatzeItem* item;
|
||||
guint i;
|
||||
|
||||
g_return_if_fail (KATZE_IS_ARRAY (feed));
|
||||
|
||||
g_signal_handlers_disconnect_by_func (feed,
|
||||
feed_panel_add_item_cb, panel);
|
||||
g_signal_handlers_disconnect_by_func (feed,
|
||||
feed_panel_remove_item_cb, panel);
|
||||
g_signal_handlers_disconnect_by_func (feed,
|
||||
feed_panel_move_item_cb, panel);
|
||||
|
||||
i = 0;
|
||||
while ((item = katze_array_get_nth_item (feed, i++)))
|
||||
{
|
||||
if (KATZE_IS_ARRAY (item))
|
||||
feed_panel_disconnect_feed (panel, KATZE_ARRAY (item));
|
||||
g_object_unref (item);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
feed_panel_insert_item (FeedPanel* panel,
|
||||
GtkTreeStore* treestore,
|
||||
GtkTreeIter* parent,
|
||||
KatzeItem* item)
|
||||
{
|
||||
g_return_if_fail (KATZE_IS_ITEM (item));
|
||||
|
||||
if (KATZE_IS_ARRAY (item))
|
||||
{
|
||||
g_signal_connect_after (item, "add-item",
|
||||
G_CALLBACK (feed_panel_add_item_cb), panel);
|
||||
g_signal_connect_after (item, "move-item",
|
||||
G_CALLBACK (feed_panel_move_item_cb), panel);
|
||||
|
||||
if (!parent)
|
||||
{
|
||||
g_signal_connect (item, "remove-item",
|
||||
G_CALLBACK (feed_panel_remove_item_cb), panel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
feed_panel_row_activated_cb (GtkTreeView* treeview,
|
||||
GtkTreePath* path,
|
||||
GtkTreeViewColumn* column,
|
||||
FeedPanel* panel)
|
||||
{
|
||||
GtkTreeModel* model;
|
||||
GtkTreeIter iter;
|
||||
KatzeItem* item;
|
||||
const gchar* uri;
|
||||
|
||||
model = gtk_tree_view_get_model (treeview);
|
||||
|
||||
if (gtk_tree_model_get_iter (model, &iter, path))
|
||||
{
|
||||
gtk_tree_model_get (model, &iter, 0, &item, -1);
|
||||
uri = katze_item_get_uri (item);
|
||||
if (uri && *uri)
|
||||
{
|
||||
MidoriWebSettings* settings;
|
||||
MidoriBrowser* browser;
|
||||
gint n;
|
||||
|
||||
browser = midori_browser_get_for_widget (GTK_WIDGET (panel));
|
||||
n = midori_browser_add_item (browser, item);
|
||||
|
||||
settings = katze_object_get_object (browser, "settings");
|
||||
if (!katze_object_get_boolean (settings, "open-tabs-in-the-background"))
|
||||
midori_browser_set_current_page (browser, n);
|
||||
g_object_unref (settings);
|
||||
|
||||
}
|
||||
g_object_unref (item);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
feed_panel_cursor_or_row_changed_cb (GtkTreeView* treeview,
|
||||
FeedPanel* panel)
|
||||
{
|
||||
GtkTreeModel* model;
|
||||
GtkTreeIter iter;
|
||||
KatzeItem* item;
|
||||
gboolean sensitive = FALSE;
|
||||
|
||||
if (katze_tree_view_get_selected_iter (treeview, &model, &iter))
|
||||
{
|
||||
const gchar* uri;
|
||||
const gchar* text;
|
||||
|
||||
gtk_tree_model_get (model, &iter, 0, &item, -1);
|
||||
uri = katze_item_get_uri (item);
|
||||
|
||||
if (KATZE_IS_ARRAY (item))
|
||||
{
|
||||
gint64 date;
|
||||
|
||||
text = NULL;
|
||||
if (!uri)
|
||||
text = g_strdup (katze_item_get_text (KATZE_ITEM (item)));
|
||||
else
|
||||
{
|
||||
KatzeItem* parent;
|
||||
const gchar* puri;
|
||||
|
||||
parent = katze_item_get_parent (item);
|
||||
g_assert (KATZE_IS_ARRAY (parent));
|
||||
date = katze_item_get_added (item);
|
||||
puri = katze_item_get_uri (parent);
|
||||
if (date)
|
||||
{
|
||||
time_t date_t;
|
||||
const struct tm* tm;
|
||||
static gchar date_format[512];
|
||||
gchar* last_updated;
|
||||
|
||||
date_t = (time_t)date;
|
||||
tm = localtime (&date_t);
|
||||
/* Some gcc versions complain about "%c" for no reason */
|
||||
strftime (date_format, sizeof (date_format), "%c", tm);
|
||||
/* i18n: The local date a feed was last updated */
|
||||
last_updated = g_strdup_printf (C_("Feed", "Last updated: %s."),
|
||||
date_format);
|
||||
text = g_strdup_printf (
|
||||
"<html><head><title>feed</title></head>"
|
||||
"<body><h3>%s</h3><p />%s</body></html>",
|
||||
puri, last_updated);
|
||||
g_free (last_updated);
|
||||
}
|
||||
else
|
||||
{
|
||||
text = g_strdup_printf (
|
||||
"<html><head><title>feed</title></head>"
|
||||
"<body><h3>%s</h3></body></html>", puri);
|
||||
}
|
||||
}
|
||||
webkit_web_view_load_html_string (
|
||||
WEBKIT_WEB_VIEW (panel->webview), text ? text : "", uri);
|
||||
g_free ((gchar*) text);
|
||||
|
||||
sensitive = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
text = katze_item_get_text (item);
|
||||
webkit_web_view_load_html_string (
|
||||
WEBKIT_WEB_VIEW (panel->webview), text ? text : "", uri);
|
||||
}
|
||||
g_object_unref (item);
|
||||
}
|
||||
if (GTK_IS_WIDGET (panel->delete))
|
||||
gtk_widget_set_sensitive (panel->delete, sensitive);
|
||||
}
|
||||
|
||||
static void
|
||||
feed_panel_popup_item (GtkWidget* menu,
|
||||
const gchar* stock_id,
|
||||
const gchar* label,
|
||||
KatzeItem* item,
|
||||
gpointer callback,
|
||||
FeedPanel* panel)
|
||||
{
|
||||
const gchar* uri;
|
||||
GtkWidget* menuitem;
|
||||
|
||||
uri = katze_item_get_uri (item);
|
||||
|
||||
menuitem = gtk_image_menu_item_new_from_stock (stock_id, NULL);
|
||||
if (label)
|
||||
gtk_label_set_text_with_mnemonic (GTK_LABEL (gtk_bin_get_child (
|
||||
GTK_BIN (menuitem))), label);
|
||||
g_object_set_data (G_OBJECT (menuitem), "KatzeItem", item);
|
||||
g_signal_connect (menuitem, "activate", G_CALLBACK (callback), panel);
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
|
||||
gtk_widget_show (menuitem);
|
||||
}
|
||||
|
||||
static void
|
||||
feed_panel_open_activate_cb (GtkWidget* menuitem,
|
||||
FeedPanel* panel)
|
||||
{
|
||||
KatzeItem* item;
|
||||
const gchar* uri;
|
||||
|
||||
item = (KatzeItem*)g_object_get_data (G_OBJECT (menuitem), "KatzeItem");
|
||||
uri = katze_item_get_uri (item);
|
||||
|
||||
if (uri && *uri)
|
||||
{
|
||||
MidoriBrowser* browser;
|
||||
|
||||
browser = midori_browser_get_for_widget (GTK_WIDGET (panel));
|
||||
midori_browser_set_current_uri (browser, uri);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
feed_panel_open_in_tab_activate_cb (GtkWidget* menuitem,
|
||||
FeedPanel* panel)
|
||||
{
|
||||
KatzeItem* item;
|
||||
const gchar* uri;
|
||||
guint n;
|
||||
|
||||
item = (KatzeItem*)g_object_get_data (G_OBJECT (menuitem), "KatzeItem");
|
||||
|
||||
if ((uri = katze_item_get_uri (item)) && *uri)
|
||||
{
|
||||
MidoriWebSettings* settings;
|
||||
MidoriBrowser* browser;
|
||||
|
||||
browser = midori_browser_get_for_widget (GTK_WIDGET (panel));
|
||||
n = midori_browser_add_item (browser, item);
|
||||
|
||||
settings = katze_object_get_object (browser, "settings");
|
||||
if (!katze_object_get_boolean (settings, "open-tabs-in-the-background"))
|
||||
midori_browser_set_current_page (browser, n);
|
||||
g_object_unref (settings);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
feed_panel_open_in_window_activate_cb (GtkWidget* menuitem,
|
||||
FeedPanel* panel)
|
||||
{
|
||||
KatzeItem* item;
|
||||
const gchar* uri;
|
||||
|
||||
item = (KatzeItem*)g_object_get_data (G_OBJECT (menuitem), "KatzeItem");
|
||||
uri = katze_item_get_uri (item);
|
||||
|
||||
if (uri && *uri)
|
||||
{
|
||||
MidoriBrowser* browser;
|
||||
browser = midori_browser_get_for_widget (GTK_WIDGET (panel));
|
||||
g_signal_emit_by_name (browser, "new-window", uri);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
feed_panel_delete_activate_cb (GtkWidget* menuitem,
|
||||
FeedPanel* panel)
|
||||
{
|
||||
KatzeItem* item;
|
||||
|
||||
g_return_if_fail (FEED_IS_PANEL (panel));
|
||||
|
||||
item = (KatzeItem*)g_object_get_data (G_OBJECT (menuitem), "KatzeItem");
|
||||
g_signal_emit (panel, signals[REMOVE_FEED], 0, item);
|
||||
}
|
||||
|
||||
static void
|
||||
feed_panel_popup (GtkWidget* widget,
|
||||
GdkEventButton* event,
|
||||
KatzeItem* item,
|
||||
FeedPanel* panel)
|
||||
{
|
||||
GtkWidget* menu;
|
||||
|
||||
menu = gtk_menu_new ();
|
||||
if (!KATZE_IS_ARRAY (item))
|
||||
{
|
||||
feed_panel_popup_item (menu, GTK_STOCK_OPEN, NULL,
|
||||
item, feed_panel_open_activate_cb, panel);
|
||||
feed_panel_popup_item (menu, STOCK_TAB_NEW, _("Open in New _Tab"),
|
||||
item, feed_panel_open_in_tab_activate_cb, panel);
|
||||
feed_panel_popup_item (menu, STOCK_WINDOW_NEW, _("Open in New _Window"),
|
||||
item, feed_panel_open_in_window_activate_cb, panel);
|
||||
}
|
||||
else
|
||||
{
|
||||
feed_panel_popup_item (menu, GTK_STOCK_DELETE, NULL,
|
||||
item, feed_panel_delete_activate_cb, panel);
|
||||
}
|
||||
|
||||
sokoke_widget_popup (widget, GTK_MENU (menu),
|
||||
event, SOKOKE_MENU_POSITION_CURSOR);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
feed_panel_button_release_event_cb (GtkWidget* widget,
|
||||
GdkEventButton* event,
|
||||
FeedPanel* panel)
|
||||
{
|
||||
GtkTreeModel* model;
|
||||
GtkTreeIter iter;
|
||||
|
||||
if (event->button != 2 && event->button != 3)
|
||||
return FALSE;
|
||||
|
||||
if (katze_tree_view_get_selected_iter (GTK_TREE_VIEW (widget), &model, &iter))
|
||||
{
|
||||
KatzeItem* item;
|
||||
|
||||
gtk_tree_model_get (model, &iter, 0, &item, -1);
|
||||
|
||||
if (event->button == 2)
|
||||
{
|
||||
const gchar* uri = katze_item_get_uri (item);
|
||||
|
||||
if (uri && *uri)
|
||||
{
|
||||
MidoriWebSettings* settings;
|
||||
MidoriBrowser* browser;
|
||||
gint n;
|
||||
|
||||
browser = midori_browser_get_for_widget (GTK_WIDGET (panel));
|
||||
n = midori_browser_add_item (browser, item);
|
||||
|
||||
settings = katze_object_get_object (browser, "settings");
|
||||
if (!katze_object_get_boolean (settings, "open-tabs-in-the-background"))
|
||||
midori_browser_set_current_page (browser, n);
|
||||
g_object_unref (settings);
|
||||
}
|
||||
}
|
||||
else
|
||||
feed_panel_popup (widget, event, item, panel);
|
||||
|
||||
g_object_unref (item);
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
feed_panel_popup_menu_cb (GtkWidget* widget,
|
||||
FeedPanel* panel)
|
||||
{
|
||||
GtkTreeModel* model;
|
||||
GtkTreeIter iter;
|
||||
KatzeItem* item;
|
||||
|
||||
if (katze_tree_view_get_selected_iter (GTK_TREE_VIEW (widget), &model, &iter))
|
||||
{
|
||||
gtk_tree_model_get (model, &iter, 0, &item, -1);
|
||||
feed_panel_popup (widget, NULL, item, panel);
|
||||
g_object_unref (item);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
feed_panel_add_feeds (FeedPanel* panel,
|
||||
KatzeItem* feed)
|
||||
{
|
||||
GtkTreeModel* model;
|
||||
|
||||
model = gtk_tree_view_get_model (GTK_TREE_VIEW (panel->treeview));
|
||||
g_assert (GTK_IS_TREE_MODEL (model));
|
||||
|
||||
feed_panel_insert_item (panel, GTK_TREE_STORE (model), NULL, feed);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
webview_button_press_event_cb (GtkWidget* widget,
|
||||
GdkEventButton* event)
|
||||
{
|
||||
/* Disable the popup menu */
|
||||
return (event->button == 3);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
webview_navigation_request_cb (WebKitWebView* web_view,
|
||||
WebKitWebFrame* frame,
|
||||
WebKitNetworkRequest* request,
|
||||
WebKitWebNavigationAction* navigation_action,
|
||||
WebKitWebPolicyDecision* policy_decision,
|
||||
FeedPanel* panel)
|
||||
{
|
||||
if (webkit_web_navigation_action_get_reason (navigation_action) ==
|
||||
WEBKIT_WEB_NAVIGATION_REASON_LINK_CLICKED)
|
||||
{
|
||||
MidoriBrowser* browser;
|
||||
const gchar* uri;
|
||||
gint n;
|
||||
|
||||
browser = midori_browser_get_for_widget (GTK_WIDGET (panel));
|
||||
uri = webkit_network_request_get_uri (request);
|
||||
n = midori_browser_add_uri (browser, uri);
|
||||
midori_browser_set_current_page (browser, n);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static const gchar*
|
||||
feed_panel_get_label (MidoriViewable* viewable)
|
||||
{
|
||||
return _("Feeds");
|
||||
}
|
||||
|
||||
static const gchar*
|
||||
feed_panel_get_stock_id (MidoriViewable* viewable)
|
||||
{
|
||||
return STOCK_FEED_PANEL;
|
||||
}
|
||||
|
||||
static void
|
||||
feed_panel_add_clicked_cb (GtkWidget* toolitem,
|
||||
FeedPanel* panel)
|
||||
{
|
||||
g_return_if_fail (FEED_IS_PANEL (panel));
|
||||
|
||||
g_signal_emit (panel, signals[ADD_FEED], 0);
|
||||
}
|
||||
|
||||
static void
|
||||
feed_panel_delete_clicked_cb (GtkWidget* toolitem,
|
||||
FeedPanel* panel)
|
||||
{
|
||||
GtkTreeModel* model;
|
||||
GtkTreeIter iter;
|
||||
|
||||
g_return_if_fail (FEED_IS_PANEL (panel));
|
||||
|
||||
if (katze_tree_view_get_selected_iter (GTK_TREE_VIEW (panel->treeview),
|
||||
&model, &iter))
|
||||
{
|
||||
KatzeItem* item;
|
||||
|
||||
gtk_tree_model_get (model, &iter, 0, &item, -1);
|
||||
g_signal_emit (panel, signals[REMOVE_FEED], 0, item);
|
||||
g_object_unref (item);
|
||||
}
|
||||
}
|
||||
|
||||
static GtkWidget*
|
||||
feed_panel_get_toolbar (MidoriViewable* viewable)
|
||||
{
|
||||
FeedPanel* panel = FEED_PANEL (viewable);
|
||||
|
||||
if (!panel->toolbar)
|
||||
{
|
||||
GtkWidget* toolbar;
|
||||
GtkToolItem* toolitem;
|
||||
|
||||
toolbar = gtk_toolbar_new ();
|
||||
gtk_toolbar_set_style (GTK_TOOLBAR (toolbar), GTK_TOOLBAR_BOTH_HORIZ);
|
||||
gtk_toolbar_set_icon_size (GTK_TOOLBAR (toolbar), GTK_ICON_SIZE_BUTTON);
|
||||
panel->toolbar = toolbar;
|
||||
toolitem = gtk_tool_button_new_from_stock (GTK_STOCK_ADD);
|
||||
gtk_widget_set_tooltip_text (GTK_WIDGET (toolitem), _("Add new feed"));
|
||||
gtk_tool_item_set_is_important (toolitem, TRUE);
|
||||
g_signal_connect (toolitem, "clicked",
|
||||
G_CALLBACK (feed_panel_add_clicked_cb), panel);
|
||||
gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1);
|
||||
gtk_widget_show (GTK_WIDGET (toolitem));
|
||||
toolitem = gtk_tool_button_new_from_stock (GTK_STOCK_DELETE);
|
||||
gtk_widget_set_tooltip_text (GTK_WIDGET (toolitem), _("Delete feed"));
|
||||
g_signal_connect (toolitem, "clicked",
|
||||
G_CALLBACK (feed_panel_delete_clicked_cb), panel);
|
||||
gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1);
|
||||
gtk_widget_show (GTK_WIDGET (toolitem));
|
||||
panel->delete = GTK_WIDGET (toolitem);;
|
||||
|
||||
feed_panel_cursor_or_row_changed_cb (
|
||||
GTK_TREE_VIEW (panel->treeview), panel);
|
||||
g_signal_connect (panel->delete, "destroy",
|
||||
G_CALLBACK (gtk_widget_destroyed), &panel->delete);
|
||||
}
|
||||
|
||||
return panel->toolbar;
|
||||
}
|
||||
|
||||
static void
|
||||
feed_panel_finalize (GObject* object)
|
||||
{
|
||||
FeedPanel* panel = FEED_PANEL (object);
|
||||
|
||||
g_object_unref (panel->pixbuf);
|
||||
g_object_unref (panel->net);
|
||||
}
|
||||
|
||||
static void
|
||||
feed_panel_viewable_iface_init (MidoriViewableIface* iface)
|
||||
{
|
||||
iface->get_stock_id = feed_panel_get_stock_id;
|
||||
iface->get_label = feed_panel_get_label;
|
||||
iface->get_toolbar = feed_panel_get_toolbar;
|
||||
}
|
||||
|
||||
static void
|
||||
feed_panel_class_init (FeedPanelClass* class)
|
||||
{
|
||||
GObjectClass* gobject_class;
|
||||
|
||||
signals[ADD_FEED] = g_signal_new (
|
||||
"add-feed",
|
||||
G_TYPE_FROM_CLASS (class),
|
||||
(GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
g_cclosure_marshal_VOID__VOID,
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
signals[REMOVE_FEED] = g_signal_new (
|
||||
"remove-feed",
|
||||
G_TYPE_FROM_CLASS (class),
|
||||
(GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
g_cclosure_marshal_VOID__POINTER,
|
||||
G_TYPE_NONE, 1,
|
||||
G_TYPE_POINTER);
|
||||
|
||||
gobject_class = G_OBJECT_CLASS (class);
|
||||
gobject_class->finalize = feed_panel_finalize;
|
||||
}
|
||||
|
||||
static void
|
||||
feed_panel_init (FeedPanel* panel)
|
||||
{
|
||||
GtkTreeStore* model;
|
||||
GtkWidget* treewin;
|
||||
GtkWidget* treeview;
|
||||
GtkWidget* webview;
|
||||
GtkWidget* paned;
|
||||
GtkTreeViewColumn* column;
|
||||
GtkCellRenderer* renderer_pixbuf;
|
||||
GtkCellRenderer* renderer_text;
|
||||
GtkIconFactory *factory;
|
||||
GtkIconSource *icon_source;
|
||||
GtkIconSet *icon_set;
|
||||
WebKitWebSettings* settings;
|
||||
PangoFontDescription* font_desc;
|
||||
const gchar* family;
|
||||
gint size;
|
||||
GtkStockItem items[] =
|
||||
{
|
||||
{ STOCK_FEED_PANEL, N_("_Feeds"), 0, 0, NULL }
|
||||
};
|
||||
|
||||
factory = gtk_icon_factory_new ();
|
||||
gtk_stock_add (items, G_N_ELEMENTS (items));
|
||||
icon_set = gtk_icon_set_new ();
|
||||
icon_source = gtk_icon_source_new ();
|
||||
gtk_icon_source_set_icon_name (icon_source, STOCK_NEWS_FEED);
|
||||
gtk_icon_set_add_source (icon_set, icon_source);
|
||||
gtk_icon_source_free (icon_source);
|
||||
gtk_icon_factory_add (factory, STOCK_FEED_PANEL, icon_set);
|
||||
gtk_icon_set_unref (icon_set);
|
||||
gtk_icon_factory_add_default (factory);
|
||||
g_object_unref (factory);
|
||||
|
||||
panel->net = katze_net_new ();
|
||||
|
||||
model = gtk_tree_store_new (1, KATZE_TYPE_ITEM);
|
||||
treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (model));
|
||||
panel->treeview = treeview;
|
||||
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
|
||||
column = gtk_tree_view_column_new ();
|
||||
renderer_pixbuf = gtk_cell_renderer_pixbuf_new ();
|
||||
gtk_tree_view_column_pack_start (column, renderer_pixbuf, FALSE);
|
||||
gtk_tree_view_column_set_cell_data_func (column, renderer_pixbuf,
|
||||
(GtkTreeCellDataFunc)feed_panel_treeview_render_icon_cb,
|
||||
panel, 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)feed_panel_treeview_render_text_cb,
|
||||
treeview, NULL);
|
||||
gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
|
||||
g_object_unref (model);
|
||||
g_object_connect (treeview,
|
||||
"signal::row-activated",
|
||||
feed_panel_row_activated_cb, panel,
|
||||
"signal::cursor-changed",
|
||||
feed_panel_cursor_or_row_changed_cb, panel,
|
||||
"signal::columns-changed",
|
||||
feed_panel_cursor_or_row_changed_cb, panel,
|
||||
"signal::button-release-event",
|
||||
feed_panel_button_release_event_cb, panel,
|
||||
"signal::popup-menu",
|
||||
feed_panel_popup_menu_cb, panel,
|
||||
NULL);
|
||||
gtk_widget_show (treeview);
|
||||
|
||||
webview = webkit_web_view_new ();
|
||||
font_desc = treeview->style->font_desc;
|
||||
family = pango_font_description_get_family (font_desc);
|
||||
size = pango_font_description_get_size (font_desc) / PANGO_SCALE;
|
||||
settings = webkit_web_settings_new ();
|
||||
g_object_set (settings, "default-font-family", family,
|
||||
"default-font-size", size, NULL);
|
||||
g_object_set (webview, "settings", settings, NULL);
|
||||
gtk_widget_set_size_request (webview, -1, 50);
|
||||
g_object_connect (webview,
|
||||
"signal::navigation-policy-decision-requested",
|
||||
webview_navigation_request_cb, panel,
|
||||
"signal::button-press-event",
|
||||
webview_button_press_event_cb, NULL,
|
||||
"signal::button-release-event",
|
||||
webview_button_press_event_cb, NULL,
|
||||
NULL);
|
||||
panel->webview = webview;
|
||||
|
||||
treewin = gtk_scrolled_window_new (NULL, NULL);
|
||||
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (treewin),
|
||||
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
|
||||
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (treewin),
|
||||
GTK_SHADOW_IN);
|
||||
gtk_container_add (GTK_CONTAINER (treewin), treeview);
|
||||
gtk_widget_show (treewin);
|
||||
|
||||
paned = gtk_vpaned_new ();
|
||||
gtk_paned_pack1 (GTK_PANED (paned), treewin, TRUE, FALSE);
|
||||
gtk_paned_pack2 (GTK_PANED (paned), webview, TRUE, FALSE);
|
||||
gtk_box_pack_start (GTK_BOX (panel), paned, TRUE, TRUE, 0);
|
||||
gtk_widget_show (webview);
|
||||
gtk_widget_show (paned);
|
||||
|
||||
panel->pixbuf = gtk_widget_render_icon (treeview,
|
||||
STOCK_NEWS_FEED, GTK_ICON_SIZE_MENU, NULL);
|
||||
}
|
||||
|
||||
GtkWidget*
|
||||
feed_panel_new (void)
|
||||
{
|
||||
FeedPanel* panel = g_object_new (FEED_TYPE_PANEL, NULL);
|
||||
|
||||
return GTK_WIDGET (panel);
|
||||
}
|
||||
|
51
extensions/feed-panel/feed-panel.h
Normal file
51
extensions/feed-panel/feed-panel.h
Normal file
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
Copyright (C) 2009 Dale Whittaker <dayul@users.sf.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
See the file COPYING for the full license text.
|
||||
*/
|
||||
|
||||
#ifndef __FEED_PANEL_H__
|
||||
#define __FEED_PANEL_H__
|
||||
|
||||
#include <midori/midori.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define FEED_TYPE_PANEL \
|
||||
(feed_panel_get_type ())
|
||||
#define FEED_PANEL(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST ((obj), FEED_TYPE_PANEL, FeedPanel))
|
||||
#define FEED_PANEL_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST ((klass), FEED_TYPE_PANEL, FeedPanelClass))
|
||||
#define FEED_IS_PANEL(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), FEED_TYPE_PANEL))
|
||||
#define FEED_IS_PANEL_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE ((klass), FEED_TYPE_PANEL))
|
||||
#define FEED_PANEL_GET_CLASS(obj) \
|
||||
(G_TYPE_INSTANCE_GET_CLASS ((obj), FEED_TYPE_PANEL, FeedPanelClass))
|
||||
|
||||
typedef struct _FeedPanel FeedPanel;
|
||||
typedef struct _FeedPanelClass FeedPanelClass;
|
||||
|
||||
void
|
||||
feed_panel_add_feeds (FeedPanel* panel,
|
||||
KatzeItem* feed);
|
||||
|
||||
void
|
||||
feed_panel_set_editable (FeedPanel* panel,
|
||||
gboolean editable);
|
||||
|
||||
GType
|
||||
feed_panel_get_type (void);
|
||||
|
||||
GtkWidget*
|
||||
feed_panel_new (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __FEED_PANEL_H__ */
|
264
extensions/feed-panel/feed-parse.c
Normal file
264
extensions/feed-panel/feed-parse.c
Normal file
|
@ -0,0 +1,264 @@
|
|||
/*
|
||||
Copyright (C) 2009 Dale Whittaker <dayul@users.sf.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
See the file COPYING for the full license text.
|
||||
*/
|
||||
|
||||
#include "feed-parse.h"
|
||||
#include <time.h>
|
||||
|
||||
gchar*
|
||||
feed_get_element_string (FeedParser* fparser)
|
||||
{
|
||||
xmlNodePtr node;
|
||||
|
||||
node = fparser->node;
|
||||
|
||||
if (!node->children ||
|
||||
xmlIsBlankNode (node->children) ||
|
||||
node->children->type != XML_TEXT_NODE
|
||||
)
|
||||
{
|
||||
/* Some servers add required elements with no content,
|
||||
* create a dummy string to handle it.
|
||||
*/
|
||||
return g_strdup (" ");
|
||||
}
|
||||
|
||||
return (gchar*)xmlNodeListGetString (fparser->doc, node->children, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
handle_markup_chars (void* user_data,
|
||||
const xmlChar* ch,
|
||||
int len)
|
||||
{
|
||||
if (len > 0)
|
||||
{
|
||||
gchar** markup;
|
||||
gchar* temp;
|
||||
|
||||
markup = (gchar**)user_data;
|
||||
temp = g_strndup ((gchar*)ch, len);
|
||||
*markup = (*markup) ? g_strconcat (*markup, temp, NULL) : g_strdup (temp);
|
||||
g_free (temp);
|
||||
}
|
||||
}
|
||||
|
||||
gchar*
|
||||
feed_remove_markup (gchar* markup)
|
||||
{
|
||||
const xmlChar* stag;
|
||||
if (((stag = xmlStrchr (BAD_CAST markup, '<')) && xmlStrchr (stag, '>')) ||
|
||||
xmlStrchr (BAD_CAST markup, '&'))
|
||||
{
|
||||
gchar* text = NULL;
|
||||
htmlSAXHandlerPtr psax;
|
||||
|
||||
psax = g_new0 (htmlSAXHandler, 1);
|
||||
psax->characters = handle_markup_chars;
|
||||
htmlSAXParseDoc (BAD_CAST markup, "UTF-8", psax, &text);
|
||||
g_free (psax);
|
||||
g_free (markup);
|
||||
return text;
|
||||
}
|
||||
return markup;
|
||||
}
|
||||
|
||||
gchar*
|
||||
feed_get_element_markup (FeedParser* fparser)
|
||||
{
|
||||
gchar* markup;
|
||||
|
||||
markup = feed_get_element_string (fparser);
|
||||
return feed_remove_markup (markup);
|
||||
}
|
||||
|
||||
gint64
|
||||
feed_get_element_date (FeedParser* fparser)
|
||||
{
|
||||
time_t date;
|
||||
gchar* content;
|
||||
|
||||
date = 0;
|
||||
content = feed_get_element_string (fparser);
|
||||
|
||||
if (content)
|
||||
{
|
||||
SoupDate* sdate;
|
||||
|
||||
sdate = soup_date_new_from_string (content);
|
||||
date = soup_date_to_time_t (sdate);
|
||||
soup_date_free (sdate);
|
||||
g_free (content);
|
||||
}
|
||||
return ((gint64)date);
|
||||
}
|
||||
|
||||
KatzeItem*
|
||||
feed_item_exists (KatzeArray* array,
|
||||
KatzeItem* item)
|
||||
{
|
||||
const gchar* guid;
|
||||
gchar* hstr;
|
||||
guint hash;
|
||||
|
||||
guid = katze_item_get_token (item);
|
||||
if (!guid)
|
||||
{
|
||||
hstr = g_strjoin (NULL,
|
||||
katze_item_get_name (item),
|
||||
katze_item_get_uri (item),
|
||||
katze_item_get_text (item),
|
||||
NULL);
|
||||
hash = g_str_hash (hstr);
|
||||
g_free (hstr);
|
||||
|
||||
hstr = g_strdup_printf ("%u", hash);
|
||||
katze_item_set_token (item, hstr);
|
||||
g_free (hstr);
|
||||
|
||||
guid = katze_item_get_token (item);
|
||||
}
|
||||
|
||||
return (katze_array_find_token (array, guid));
|
||||
}
|
||||
|
||||
void
|
||||
feed_parse_node (FeedParser* fparser)
|
||||
{
|
||||
xmlNodePtr node;
|
||||
xmlNodePtr child;
|
||||
|
||||
if (!*fparser->error)
|
||||
{
|
||||
if (fparser->preparse)
|
||||
(*fparser->preparse) (fparser);
|
||||
|
||||
if (fparser->parse)
|
||||
{
|
||||
node = fparser->node;
|
||||
child = node->last;
|
||||
|
||||
while (child)
|
||||
{
|
||||
if (child->type == XML_ELEMENT_NODE)
|
||||
{
|
||||
fparser->node = child;
|
||||
|
||||
(*fparser->parse) (fparser);
|
||||
|
||||
if (*fparser->error)
|
||||
break;
|
||||
}
|
||||
child = child->prev;
|
||||
}
|
||||
fparser->node = node;
|
||||
}
|
||||
|
||||
if (fparser->postparse)
|
||||
(*fparser->postparse) (fparser);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
feed_parse_doc (xmlDocPtr doc,
|
||||
GSList* parsers,
|
||||
KatzeArray* array,
|
||||
GError** error)
|
||||
{
|
||||
FeedParser* fparser;
|
||||
xmlNodePtr root;
|
||||
gboolean isvalid;
|
||||
|
||||
root = xmlDocGetRootElement (doc);
|
||||
|
||||
if (!root)
|
||||
{
|
||||
*error = g_error_new (FEED_PARSE_ERROR,
|
||||
FEED_PARSE_ERROR_MISSING_ELEMENT,
|
||||
_("Failed to find root element in feed XML data."));
|
||||
return;
|
||||
}
|
||||
|
||||
while (parsers)
|
||||
{
|
||||
fparser = (FeedParser*)parsers->data;
|
||||
fparser->error = error;
|
||||
fparser->doc = doc;
|
||||
fparser->node = root;
|
||||
|
||||
if (fparser && fparser->isvalid)
|
||||
{
|
||||
isvalid = (*fparser->isvalid) (fparser);
|
||||
|
||||
if (*fparser->error)
|
||||
return;
|
||||
|
||||
if (isvalid)
|
||||
{
|
||||
fparser->item = KATZE_ITEM (array);
|
||||
|
||||
if (fparser->update &&
|
||||
(*fparser->update) (fparser))
|
||||
feed_parse_node (fparser);
|
||||
}
|
||||
}
|
||||
|
||||
fparser->error = NULL;
|
||||
fparser->doc = NULL;
|
||||
fparser->node = NULL;
|
||||
|
||||
if (isvalid)
|
||||
return;
|
||||
|
||||
parsers = g_slist_next (parsers);
|
||||
}
|
||||
|
||||
*error = g_error_new (FEED_PARSE_ERROR,
|
||||
FEED_PARSE_ERROR_INVALID_FORMAT,
|
||||
_("Unsupported feed format."));
|
||||
}
|
||||
|
||||
gboolean
|
||||
parse_feed (gchar* data,
|
||||
gint64 length,
|
||||
GSList* parsers,
|
||||
KatzeArray* array,
|
||||
GError** error)
|
||||
{
|
||||
xmlDocPtr doc;
|
||||
xmlErrorPtr xerror;
|
||||
|
||||
LIBXML_TEST_VERSION
|
||||
|
||||
doc = xmlReadMemory (
|
||||
data, length, "feedfile.xml", NULL,
|
||||
XML_PARSE_NOWARNING | XML_PARSE_NOERROR /*| XML_PARSE_RECOVER*/
|
||||
);
|
||||
|
||||
if (doc)
|
||||
{
|
||||
feed_parse_doc (doc, parsers, array, error);
|
||||
xmlFreeDoc (doc);
|
||||
}
|
||||
else
|
||||
{
|
||||
xerror = xmlGetLastError ();
|
||||
*error = g_error_new (FEED_PARSE_ERROR,
|
||||
FEED_PARSE_ERROR_PARSE,
|
||||
_("Failed to parse XML feed: %s"),
|
||||
xerror->message);
|
||||
xmlResetLastError ();
|
||||
}
|
||||
xmlCleanupParser ();
|
||||
xmlMemoryDump ();
|
||||
|
||||
return *error ? FALSE : TRUE;
|
||||
}
|
||||
|
85
extensions/feed-panel/feed-parse.h
Normal file
85
extensions/feed-panel/feed-parse.h
Normal file
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
Copyright (C) 2009 Dale Whittaker <dayul@users.sf.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
See the file COPYING for the full license text.
|
||||
*/
|
||||
|
||||
#ifndef __FEED_PARSE_H__
|
||||
#define __FEED_PARSE_H__
|
||||
|
||||
#include <midori/midori.h>
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <libsoup/soup.h>
|
||||
#include <libxml/parser.h>
|
||||
#include <libxml/HTMLparser.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define FEED_PARSE_ERROR g_quark_from_string("FEED_PARSE_ERROR")
|
||||
|
||||
typedef enum
|
||||
{
|
||||
FEED_PARSE_ERROR_PARSE,
|
||||
FEED_PARSE_ERROR_INVALID_FORMAT,
|
||||
FEED_PARSE_ERROR_INVALID_VERSION,
|
||||
FEED_PARSE_ERROR_MISSING_ELEMENT
|
||||
|
||||
} FeedBarError;
|
||||
|
||||
typedef struct _FeedParser
|
||||
{
|
||||
xmlDocPtr doc; /* The XML document */
|
||||
xmlNodePtr node; /* The XML node at a specific point */
|
||||
KatzeItem* item;
|
||||
GError** error;
|
||||
|
||||
gboolean (*isvalid) (struct _FeedParser* fparser);
|
||||
gboolean (*update) (struct _FeedParser* fparser);
|
||||
void (*preparse) (struct _FeedParser* fparser);
|
||||
void (*parse) (struct _FeedParser* fparser);
|
||||
void (*postparse) (struct _FeedParser* fparser);
|
||||
|
||||
} FeedParser;
|
||||
|
||||
#define feed_parser_set_error(fparser, err, msg) \
|
||||
*(fparser)->error = g_error_new ( \
|
||||
FEED_PARSE_ERROR, (err), (msg))
|
||||
|
||||
gchar*
|
||||
feed_get_element_string (FeedParser* fparser);
|
||||
|
||||
gchar*
|
||||
feed_remove_markup (gchar* markup);
|
||||
|
||||
gchar*
|
||||
feed_get_element_markup (FeedParser* fparser);
|
||||
|
||||
gint64
|
||||
feed_get_element_date (FeedParser* fparser);
|
||||
|
||||
KatzeItem*
|
||||
feed_item_exists (KatzeArray* array,
|
||||
KatzeItem* item);
|
||||
void
|
||||
feed_parse_node (FeedParser* fparser);
|
||||
|
||||
gboolean
|
||||
parse_feed (gchar* data,
|
||||
gint64 length,
|
||||
GSList* parsers,
|
||||
KatzeArray* array,
|
||||
GError** error);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __FEED_PARSE_H__ */
|
||||
|
268
extensions/feed-panel/feed-rss.c
Normal file
268
extensions/feed-panel/feed-rss.c
Normal file
|
@ -0,0 +1,268 @@
|
|||
/*
|
||||
Copyright (C) 2009 Dale Whittaker <dayul@users.sf.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
See the file COPYING for the full license text.
|
||||
*/
|
||||
|
||||
#include "feed-rss.h"
|
||||
|
||||
static gboolean
|
||||
rss_is_valid (FeedParser* fparser)
|
||||
{
|
||||
xmlNodePtr node;
|
||||
xmlNodePtr child;
|
||||
xmlChar* str;
|
||||
gboolean valid;
|
||||
|
||||
node = fparser->node;
|
||||
|
||||
if (!(xmlStrcmp (node->name, BAD_CAST "rss")))
|
||||
{
|
||||
if ((str = xmlGetProp (node, BAD_CAST "version")))
|
||||
{
|
||||
valid = !xmlStrcmp (str, BAD_CAST "2.0");
|
||||
xmlFree (str);
|
||||
|
||||
if (valid)
|
||||
{
|
||||
child = node->children;
|
||||
while (child)
|
||||
{
|
||||
if (child->type == XML_ELEMENT_NODE &&
|
||||
!(xmlStrcmp (child->name, BAD_CAST "channel")))
|
||||
{
|
||||
fparser->node = child;
|
||||
return TRUE;
|
||||
}
|
||||
child = child->next;
|
||||
}
|
||||
|
||||
feed_parser_set_error (fparser, FEED_PARSE_ERROR_MISSING_ELEMENT,
|
||||
_("Failed to find \"channel\" element in RSS XML data."));
|
||||
}
|
||||
else
|
||||
{
|
||||
feed_parser_set_error (fparser, FEED_PARSE_ERROR_INVALID_VERSION,
|
||||
_("Unsupported RSS version found."));
|
||||
}
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
rss_update (FeedParser* fparser)
|
||||
{
|
||||
xmlNodePtr node;
|
||||
xmlNodePtr child;
|
||||
gint64 date;
|
||||
gint64 newdate;
|
||||
|
||||
date = katze_item_get_added (fparser->item);
|
||||
|
||||
node = fparser->node;
|
||||
child = node->children;
|
||||
while (child)
|
||||
{
|
||||
if (child->type == XML_ELEMENT_NODE)
|
||||
{
|
||||
if (!(xmlStrcmp (child->name, BAD_CAST "lastBuildDate")))
|
||||
{
|
||||
fparser->node = child;
|
||||
newdate = feed_get_element_date (fparser);
|
||||
fparser->node = node;
|
||||
return (date != newdate);
|
||||
}
|
||||
}
|
||||
child = child->next;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
rss_preparse_item (FeedParser* fparser)
|
||||
{
|
||||
fparser->item = katze_item_new ();
|
||||
}
|
||||
|
||||
static void
|
||||
rss_parse_item (FeedParser* fparser)
|
||||
{
|
||||
xmlNodePtr node;
|
||||
gchar* content;
|
||||
gint64 date;
|
||||
|
||||
node = fparser->node;
|
||||
content = NULL;
|
||||
|
||||
if (!xmlStrcmp (node->name, BAD_CAST "guid"))
|
||||
{
|
||||
content = feed_get_element_string (fparser);
|
||||
katze_item_set_token (fparser->item, content);
|
||||
}
|
||||
else if (!xmlStrcmp (node->name, BAD_CAST "title"))
|
||||
{
|
||||
content = feed_get_element_markup (fparser);
|
||||
katze_item_set_name (fparser->item, content);
|
||||
}
|
||||
else if (!xmlStrcmp (node->name, BAD_CAST "description"))
|
||||
{
|
||||
content = feed_get_element_string (fparser);
|
||||
katze_item_set_text (fparser->item, content);
|
||||
}
|
||||
else if (!xmlStrcmp (node->name, BAD_CAST "pubDate"))
|
||||
{
|
||||
date = feed_get_element_date (fparser);
|
||||
katze_item_set_added (fparser->item, date);
|
||||
}
|
||||
else if (!(xmlStrcmp (node->name, BAD_CAST "link")))
|
||||
{
|
||||
content = feed_get_element_string (fparser);
|
||||
katze_item_set_uri (fparser->item, content);
|
||||
}
|
||||
g_free (content);
|
||||
}
|
||||
|
||||
static void
|
||||
rss_postparse_item (FeedParser* fparser)
|
||||
{
|
||||
if (!*fparser->error)
|
||||
{
|
||||
/*
|
||||
* Verify that the required RSS elements are added
|
||||
* (as per the spec)
|
||||
*/
|
||||
if (!katze_item_get_name (fparser->item))
|
||||
{
|
||||
gchar* desc;
|
||||
|
||||
desc = (gchar*)katze_item_get_text (fparser->item);
|
||||
if (!desc)
|
||||
{
|
||||
feed_parser_set_error (fparser, FEED_PARSE_ERROR_MISSING_ELEMENT,
|
||||
_("Failed to find required RSS \"item\" elements in XML data."));
|
||||
}
|
||||
else
|
||||
{
|
||||
desc = feed_remove_markup (g_strdup (desc));
|
||||
if (desc)
|
||||
{
|
||||
katze_item_set_name (fparser->item, desc);
|
||||
g_free (desc);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((desc = (gchar*)katze_item_get_uri (fparser->item)))
|
||||
katze_item_set_name (fparser->item, desc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (*fparser->error && KATZE_IS_ITEM (fparser->item))
|
||||
{
|
||||
g_object_unref (fparser->item);
|
||||
fparser->item = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
rss_parse_channel (FeedParser* fparser)
|
||||
{
|
||||
FeedParser* eparser;
|
||||
xmlNodePtr node;
|
||||
gchar* content;
|
||||
gint64 date;
|
||||
|
||||
node = fparser->node;
|
||||
content = NULL;
|
||||
|
||||
if (!xmlStrcmp (node->name, BAD_CAST "title"))
|
||||
{
|
||||
content = feed_get_element_markup (fparser);
|
||||
katze_item_set_name (fparser->item, content);
|
||||
}
|
||||
else if (!xmlStrcmp (node->name, BAD_CAST "description"))
|
||||
{
|
||||
content = feed_get_element_string (fparser);
|
||||
katze_item_set_text (fparser->item, content);
|
||||
}
|
||||
else if (!xmlStrcmp (node->name, BAD_CAST "lastBuildDate"))
|
||||
{
|
||||
date = feed_get_element_date (fparser);
|
||||
katze_item_set_added (fparser->item, date);
|
||||
}
|
||||
else if (!(xmlStrcmp (node->name, BAD_CAST "link")))
|
||||
{
|
||||
content = feed_get_element_string (fparser);
|
||||
katze_item_set_uri (fparser->item, content);
|
||||
}
|
||||
else if (!xmlStrcmp (node->name, BAD_CAST "item"))
|
||||
{
|
||||
eparser = g_new0 (FeedParser, 1);
|
||||
eparser->doc = fparser->doc;
|
||||
eparser->node = fparser->node;
|
||||
eparser->error = fparser->error;
|
||||
eparser->preparse = rss_preparse_item;
|
||||
eparser->parse = rss_parse_item;
|
||||
eparser->postparse = rss_postparse_item;
|
||||
|
||||
feed_parse_node (eparser);
|
||||
|
||||
if (KATZE_IS_ITEM (eparser->item))
|
||||
{
|
||||
KatzeItem* item;
|
||||
if (!(item = feed_item_exists (KATZE_ARRAY (fparser->item), eparser->item)))
|
||||
katze_array_add_item (KATZE_ARRAY (fparser->item), eparser->item);
|
||||
else
|
||||
{
|
||||
g_object_unref (eparser->item);
|
||||
katze_array_move_item (KATZE_ARRAY (fparser->item), item, 0);
|
||||
}
|
||||
}
|
||||
g_free (eparser);
|
||||
|
||||
}
|
||||
g_free (content);
|
||||
}
|
||||
|
||||
static void
|
||||
rss_postparse_channel (FeedParser* fparser)
|
||||
{
|
||||
if (!*fparser->error)
|
||||
{
|
||||
/*
|
||||
* Verify that the required RSS elements are added
|
||||
* (as per the spec)
|
||||
*/
|
||||
if (!katze_item_get_name (fparser->item) ||
|
||||
!katze_item_get_text (fparser->item) ||
|
||||
!katze_item_get_uri (fparser->item))
|
||||
{
|
||||
feed_parser_set_error (fparser, FEED_PARSE_ERROR_MISSING_ELEMENT,
|
||||
_("Failed to find required RSS \"channel\" elements in XML data."));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FeedParser*
|
||||
rss_init_parser (void)
|
||||
{
|
||||
FeedParser* fparser;
|
||||
|
||||
fparser = g_new0 (FeedParser, 1);
|
||||
g_return_val_if_fail (fparser, NULL);
|
||||
|
||||
fparser->isvalid = rss_is_valid;
|
||||
fparser->update = rss_update;
|
||||
fparser->parse = rss_parse_channel;
|
||||
fparser->postparse = rss_postparse_channel;
|
||||
|
||||
return fparser;
|
||||
}
|
||||
|
25
extensions/feed-panel/feed-rss.h
Normal file
25
extensions/feed-panel/feed-rss.h
Normal file
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
Copyright (C) 2009 Dale Whittaker <dayul@users.sf.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
See the file COPYING for the full license text.
|
||||
*/
|
||||
|
||||
#ifndef __FEED_RSS_H__
|
||||
#define __FEED_RSS_H__
|
||||
|
||||
#include "feed-parse.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
FeedParser*
|
||||
rss_init_parser (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __FEED_RSS_H__ */
|
||||
|
502
extensions/feed-panel/main.c
Normal file
502
extensions/feed-panel/main.c
Normal file
|
@ -0,0 +1,502 @@
|
|||
/*
|
||||
Copyright (C) 2009 Dale Whittaker <dale@users.sf.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
See the file COPYING for the full license text.
|
||||
*/
|
||||
|
||||
#include "feed-panel.h"
|
||||
#include "feed-atom.h"
|
||||
#include "feed-rss.h"
|
||||
|
||||
#include <midori/midori.h>
|
||||
|
||||
#define EXTENSION_NAME "Feed Panel"
|
||||
#define UPDATE_FREQ 10
|
||||
|
||||
#define feed_get_flags(feed) \
|
||||
GPOINTER_TO_INT (g_object_get_data (G_OBJECT ((feed)), "flags"))
|
||||
|
||||
#define feed_set_flags(feed, flags) \
|
||||
g_object_set_data (G_OBJECT ((feed)), "flags", \
|
||||
GINT_TO_POINTER ((flags)))
|
||||
|
||||
#define feed_has_flags(feed, flags) \
|
||||
((flags) & feed_get_flags ((feed)))
|
||||
|
||||
#define feed_add_flags(feed, flags) \
|
||||
feed_set_flags ((feed), (feed_get_flags ((feed)) | (flags)))
|
||||
|
||||
#define feed_remove_flags(feed, flags) \
|
||||
feed_set_flags ((feed), (feed_get_flags ((feed)) & ~(flags)))
|
||||
|
||||
typedef struct
|
||||
{
|
||||
MidoriBrowser* browser;
|
||||
MidoriExtension* extension;
|
||||
GtkWidget* panel;
|
||||
KatzeArray* feeds;
|
||||
KatzeNet* net;
|
||||
GSList* parsers;
|
||||
|
||||
guint source_id;
|
||||
gboolean is_running;
|
||||
|
||||
} FeedPrivate;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
MidoriExtension* extension;
|
||||
GSList* parsers;
|
||||
KatzeArray* feed;
|
||||
|
||||
} FeedNetPrivate;
|
||||
|
||||
enum
|
||||
{
|
||||
FEED_READ,
|
||||
FEED_REMOVE
|
||||
};
|
||||
|
||||
static void
|
||||
feed_app_add_browser_cb (MidoriApp* app,
|
||||
MidoriBrowser* browser,
|
||||
MidoriExtension* extension);
|
||||
|
||||
static void
|
||||
feed_deactivate_cb (MidoriExtension* extension,
|
||||
FeedPrivate* priv)
|
||||
{
|
||||
if (priv)
|
||||
{
|
||||
MidoriApp* app = midori_extension_get_app (extension);
|
||||
|
||||
g_signal_handlers_disconnect_by_func (app,
|
||||
feed_app_add_browser_cb, extension);
|
||||
g_signal_handlers_disconnect_by_func (extension,
|
||||
feed_deactivate_cb, priv);
|
||||
|
||||
if (priv->source_id)
|
||||
g_source_remove (priv->source_id);
|
||||
g_slist_foreach (priv->parsers, (GFunc)g_free, NULL);
|
||||
g_slist_free (priv->parsers);
|
||||
if (priv->feeds)
|
||||
g_object_unref (priv->net);
|
||||
if (priv->feeds)
|
||||
g_object_unref (priv->feeds);
|
||||
gtk_widget_destroy (priv->panel);
|
||||
g_free (priv);
|
||||
}
|
||||
}
|
||||
|
||||
static KatzeArray*
|
||||
feed_add_item (KatzeArray* feeds,
|
||||
const gchar* uri)
|
||||
{
|
||||
KatzeArray* feed;
|
||||
|
||||
feed = NULL;
|
||||
|
||||
if (uri)
|
||||
{
|
||||
if (katze_array_find_token (feeds, uri))
|
||||
{
|
||||
GtkWidget* dialog;
|
||||
|
||||
dialog = gtk_message_dialog_new (
|
||||
NULL, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
|
||||
_("Error"));
|
||||
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
|
||||
_("Feed '%s' already exists"), uri);
|
||||
gtk_window_set_title (GTK_WINDOW (dialog), EXTENSION_NAME);
|
||||
gtk_widget_show (dialog);
|
||||
g_signal_connect_swapped (dialog, "response",
|
||||
G_CALLBACK (gtk_widget_destroy), dialog);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
KatzeArray* child;
|
||||
|
||||
feed = katze_array_new (KATZE_TYPE_ARRAY);
|
||||
child = katze_array_new (KATZE_TYPE_ITEM);
|
||||
katze_item_set_uri (KATZE_ITEM (feed), uri);
|
||||
katze_item_set_token (KATZE_ITEM (feed), uri);
|
||||
katze_item_set_uri (KATZE_ITEM (child), uri);
|
||||
katze_array_add_item (feeds, feed);
|
||||
katze_array_add_item (feed, child);
|
||||
}
|
||||
}
|
||||
return feed;
|
||||
}
|
||||
|
||||
static void
|
||||
feed_save_items (MidoriExtension* extension,
|
||||
KatzeArray* feed)
|
||||
{
|
||||
KatzeItem* item;
|
||||
gchar** sfeeds;
|
||||
gint i;
|
||||
gint n;
|
||||
|
||||
g_return_if_fail (KATZE_IS_ARRAY (feed));
|
||||
|
||||
n = katze_array_get_length (feed);
|
||||
sfeeds = g_new (gchar*, n + 1);
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
item = katze_array_get_nth_item (feed, i);
|
||||
sfeeds[i] = (gchar*) katze_item_get_uri (KATZE_ITEM (item));
|
||||
}
|
||||
sfeeds[n] = NULL;
|
||||
|
||||
midori_extension_set_string_list (extension, "feeds", sfeeds, n);
|
||||
g_free (sfeeds);
|
||||
}
|
||||
|
||||
static void
|
||||
feed_handle_net_error (FeedNetPrivate* netpriv,
|
||||
const gchar* msg)
|
||||
{
|
||||
KatzeItem* child;
|
||||
const gchar* uri;
|
||||
gint n;
|
||||
|
||||
n = katze_array_get_length (netpriv->feed);
|
||||
g_assert (n == 1);
|
||||
child = katze_array_get_nth_item (netpriv->feed, 0);
|
||||
g_assert (KATZE_IS_ARRAY (child));
|
||||
|
||||
uri = katze_item_get_uri (KATZE_ITEM (netpriv->feed));
|
||||
katze_item_set_name (child, uri);
|
||||
katze_item_set_text (child, msg);
|
||||
katze_item_set_uri (child, NULL);
|
||||
feed_remove_flags (netpriv->feed, FEED_READ);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
feed_status_cb (KatzeNetRequest* request,
|
||||
FeedNetPrivate* netpriv)
|
||||
{
|
||||
if (request->status == KATZE_NET_FAILED ||
|
||||
request->status == KATZE_NET_NOT_FOUND)
|
||||
{
|
||||
gchar* msg;
|
||||
|
||||
msg = g_strdup_printf (_("Error loading feed '%s'"),
|
||||
katze_item_get_uri (KATZE_ITEM (netpriv->feed)));
|
||||
feed_handle_net_error (netpriv, msg);
|
||||
g_free (msg);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
feed_transfer_cb (KatzeNetRequest* request,
|
||||
FeedNetPrivate* netpriv)
|
||||
{
|
||||
GError* error;
|
||||
|
||||
if (request->status == KATZE_NET_MOVED)
|
||||
return;
|
||||
|
||||
g_return_if_fail (KATZE_IS_ARRAY (netpriv->feed));
|
||||
|
||||
error = NULL;
|
||||
|
||||
if (request->data)
|
||||
{
|
||||
KatzeArray* item;
|
||||
const gchar* uri;
|
||||
gint n;
|
||||
|
||||
n = katze_array_get_length (netpriv->feed);
|
||||
g_assert (n == 1);
|
||||
item = katze_array_get_nth_item (netpriv->feed, 0);
|
||||
g_assert (KATZE_IS_ARRAY (item));
|
||||
uri = katze_item_get_uri (KATZE_ITEM (netpriv->feed));
|
||||
katze_item_set_uri (KATZE_ITEM (item), uri);
|
||||
|
||||
if (!parse_feed (request->data, request->length,
|
||||
netpriv->parsers, item, &error))
|
||||
{
|
||||
feed_handle_net_error (netpriv, error->message);
|
||||
g_error_free (error);
|
||||
}
|
||||
|
||||
if (feed_has_flags (netpriv->feed, FEED_REMOVE))
|
||||
{
|
||||
KatzeArray* parent;
|
||||
|
||||
/* deferred remove */
|
||||
parent = katze_item_get_parent (KATZE_ITEM (netpriv->feed));
|
||||
katze_array_remove_item (parent, netpriv->feed);
|
||||
feed_save_items (netpriv->extension, parent);
|
||||
}
|
||||
else
|
||||
feed_set_flags (netpriv->feed, 0);
|
||||
}
|
||||
|
||||
netpriv->parsers = NULL;
|
||||
netpriv->feed = NULL;
|
||||
g_free (netpriv);
|
||||
}
|
||||
|
||||
static void
|
||||
update_feed (FeedPrivate* priv,
|
||||
KatzeItem* feed)
|
||||
{
|
||||
if (!(feed_has_flags (feed, FEED_READ)))
|
||||
{
|
||||
FeedNetPrivate* netpriv;
|
||||
|
||||
feed_add_flags (feed, FEED_READ);
|
||||
netpriv = g_new0 (FeedNetPrivate, 1);
|
||||
netpriv->parsers = priv->parsers;
|
||||
netpriv->extension = priv->extension;
|
||||
netpriv->feed = KATZE_ARRAY (feed);
|
||||
|
||||
katze_net_load_uri (priv->net,
|
||||
katze_item_get_uri (feed),
|
||||
(KatzeNetStatusCb) feed_status_cb,
|
||||
(KatzeNetTransferCb) feed_transfer_cb,
|
||||
netpriv);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
update_feeds (FeedPrivate* priv)
|
||||
{
|
||||
KatzeItem* feed;
|
||||
gint i;
|
||||
gint n;
|
||||
|
||||
if (!priv->is_running)
|
||||
{
|
||||
priv->is_running = TRUE;
|
||||
n = katze_array_get_length (priv->feeds);
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
feed = katze_array_get_nth_item (priv->feeds, i);
|
||||
update_feed (priv, feed);
|
||||
}
|
||||
}
|
||||
priv->is_running = FALSE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
secondary_icon_released_cb (GtkAction* action,
|
||||
GtkWidget* widget,
|
||||
FeedPrivate* priv)
|
||||
{
|
||||
const gchar* uri;
|
||||
|
||||
g_assert (KATZE_IS_ARRAY (priv->feeds));
|
||||
|
||||
uri = midori_location_action_get_uri (MIDORI_LOCATION_ACTION (action));
|
||||
|
||||
if (uri && *uri)
|
||||
{
|
||||
KatzeArray* feed;
|
||||
|
||||
feed = feed_add_item (priv->feeds, uri);
|
||||
if (feed)
|
||||
{
|
||||
feed_save_items (priv->extension, priv->feeds);
|
||||
update_feed (priv, KATZE_ITEM (feed));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
panel_add_feed_cb (FeedPanel* panel,
|
||||
FeedPrivate* priv)
|
||||
{
|
||||
GtkWidget* dialog;
|
||||
GtkSizeGroup* sizegroup;
|
||||
GtkWidget* hbox;
|
||||
GtkWidget* label;
|
||||
GtkWidget* entry;
|
||||
|
||||
dialog = gtk_dialog_new_with_buttons (
|
||||
_("New feed"), GTK_WINDOW (priv->browser),
|
||||
GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR,
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
||||
GTK_STOCK_ADD, GTK_RESPONSE_ACCEPT,
|
||||
NULL);
|
||||
gtk_window_set_icon_name (GTK_WINDOW (dialog), GTK_STOCK_ADD);
|
||||
gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
|
||||
gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), 5);
|
||||
sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
|
||||
|
||||
hbox = gtk_hbox_new (FALSE, 8);
|
||||
gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
|
||||
label = gtk_label_new_with_mnemonic (_("_Address:"));
|
||||
gtk_size_group_add_widget (sizegroup, label);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
|
||||
entry = gtk_entry_new ();
|
||||
gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE);
|
||||
gtk_entry_set_text (GTK_ENTRY (entry), "");
|
||||
gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
|
||||
gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), hbox);
|
||||
gtk_widget_show_all (hbox);
|
||||
|
||||
gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT);
|
||||
if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
|
||||
{
|
||||
const gchar* uri;
|
||||
|
||||
g_assert (KATZE_IS_ARRAY (priv->feeds));
|
||||
|
||||
uri = gtk_entry_get_text (GTK_ENTRY (entry));
|
||||
if (uri && *uri)
|
||||
{
|
||||
KatzeArray* feed;
|
||||
|
||||
feed = feed_add_item (priv->feeds, uri);
|
||||
if (feed)
|
||||
{
|
||||
feed_save_items (priv->extension, priv->feeds);
|
||||
update_feed (priv, KATZE_ITEM (feed));
|
||||
}
|
||||
}
|
||||
}
|
||||
gtk_widget_destroy (dialog);
|
||||
}
|
||||
|
||||
static void
|
||||
panel_remove_feed_cb (FeedPanel* panel,
|
||||
KatzeItem* item,
|
||||
FeedPrivate* priv)
|
||||
{
|
||||
KatzeArray* feed;
|
||||
|
||||
feed = katze_item_get_parent (item);
|
||||
|
||||
g_assert (KATZE_IS_ARRAY (priv->feeds));
|
||||
g_assert (KATZE_IS_ARRAY (feed));
|
||||
|
||||
if (feed_has_flags (feed, FEED_READ))
|
||||
feed_add_flags (feed, FEED_REMOVE);
|
||||
else
|
||||
{
|
||||
feed_add_flags (feed, FEED_READ);
|
||||
katze_array_remove_item (priv->feeds, feed);
|
||||
feed_save_items (priv->extension, priv->feeds);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
feed_app_add_browser_cb (MidoriApp* app,
|
||||
MidoriBrowser* browser,
|
||||
MidoriExtension* extension)
|
||||
{
|
||||
GtkWidget* panel;
|
||||
GtkWidget* addon;
|
||||
GtkActionGroup* action_group;
|
||||
GtkAction* action;
|
||||
KatzeNet* net;
|
||||
KatzeArray* feeds;
|
||||
KatzeArray* feed;
|
||||
FeedPrivate* priv;
|
||||
gchar** sfeeds;
|
||||
gsize i;
|
||||
gsize n;
|
||||
|
||||
priv = g_new0 (FeedPrivate, 1);
|
||||
|
||||
panel = katze_object_get_object (browser, "panel");
|
||||
addon = feed_panel_new ();
|
||||
gtk_widget_show (addon);
|
||||
midori_panel_append_page (MIDORI_PANEL (panel), MIDORI_VIEWABLE (addon));
|
||||
g_object_unref (panel);
|
||||
|
||||
net = katze_net_new ();
|
||||
feeds = katze_array_new (KATZE_TYPE_ARRAY);
|
||||
feed_panel_add_feeds (FEED_PANEL (addon), KATZE_ITEM (feeds));
|
||||
|
||||
priv->extension = extension;
|
||||
priv->browser = browser;
|
||||
priv->panel = addon;
|
||||
priv->net = net;
|
||||
priv->feeds = feeds;
|
||||
priv->parsers = g_slist_prepend (priv->parsers, atom_init_parser ());
|
||||
priv->parsers = g_slist_prepend (priv->parsers, rss_init_parser ());
|
||||
|
||||
sfeeds = midori_extension_get_string_list (extension, "feeds", &n);
|
||||
g_assert (n == 0 || sfeeds);
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
if (sfeeds[i])
|
||||
{
|
||||
feed = feed_add_item (feeds, sfeeds[i]);
|
||||
if (feed)
|
||||
update_feed (priv, KATZE_ITEM (feed));
|
||||
}
|
||||
}
|
||||
g_strdupv (sfeeds);
|
||||
action_group = midori_browser_get_action_group (browser);
|
||||
action = gtk_action_group_get_action (action_group, "Location");
|
||||
|
||||
g_signal_connect (addon, "add-feed",
|
||||
G_CALLBACK (panel_add_feed_cb), priv);
|
||||
g_signal_connect (addon, "remove-feed",
|
||||
G_CALLBACK (panel_remove_feed_cb), priv);
|
||||
g_signal_connect (action, "secondary-icon-released",
|
||||
G_CALLBACK (secondary_icon_released_cb), priv);
|
||||
g_signal_connect (extension, "deactivate",
|
||||
G_CALLBACK (feed_deactivate_cb), priv);
|
||||
|
||||
priv->source_id = g_timeout_add_seconds (UPDATE_FREQ * 60,
|
||||
(GSourceFunc) update_feeds, priv);
|
||||
}
|
||||
|
||||
static void
|
||||
feed_activate_cb (MidoriExtension* extension,
|
||||
MidoriApp* app)
|
||||
{
|
||||
KatzeArray* browsers;
|
||||
MidoriBrowser* browser;
|
||||
guint i;
|
||||
|
||||
browsers = katze_object_get_object (app, "browsers");
|
||||
i = 0;
|
||||
while ((browser = katze_array_get_nth_item (browsers, i++)))
|
||||
feed_app_add_browser_cb (app, browser, extension);
|
||||
g_object_unref (browsers);
|
||||
|
||||
g_signal_connect (app, "add-browser",
|
||||
G_CALLBACK (feed_app_add_browser_cb), extension);
|
||||
}
|
||||
|
||||
MidoriExtension*
|
||||
extension_init (void)
|
||||
{
|
||||
MidoriExtension* extension;
|
||||
gchar* sfeed[2];
|
||||
|
||||
extension = g_object_new (MIDORI_TYPE_EXTENSION,
|
||||
"name", _("Feed Panel"),
|
||||
"description", _("Read Atom/ RSS feeds"),
|
||||
"version", "0.1",
|
||||
"authors", "Dale Whittaker <dayul@users.sf.net>",
|
||||
NULL);
|
||||
|
||||
sfeed[0] = NULL;
|
||||
midori_extension_install_string_list (extension, "feeds", sfeed, 1);
|
||||
|
||||
g_signal_connect (extension, "activate",
|
||||
G_CALLBACK (feed_activate_cb), NULL);
|
||||
|
||||
return extension;
|
||||
}
|
|
@ -13,14 +13,14 @@
|
|||
#include "mouse-gestures.h"
|
||||
|
||||
#define MOUSE_GESTURES_VERSION "0.1"
|
||||
#define DEVIANCE 20 // the deviance to determine if a line is straight or not
|
||||
#define MINLENGTH 50 // the minimal length of a line to be treated as a gesture
|
||||
#define DEVIANCE 20
|
||||
#define MINLENGTH 50
|
||||
|
||||
// #define __MOUSE_GESTURES_DEBUG__ // uncomment for debugging purposes
|
||||
/* #define __MOUSE_GESTURES_DEBUG__ */
|
||||
|
||||
MouseGesture *gesture;
|
||||
|
||||
void mouse_gesture_clear(MouseGesture *g)
|
||||
void mouse_gesture_clear (MouseGesture *g)
|
||||
{
|
||||
g->start.x = 0;
|
||||
g->start.y = 0;
|
||||
|
@ -29,201 +29,225 @@ void mouse_gesture_clear(MouseGesture *g)
|
|||
g->end.x = 0;
|
||||
g->end.y = 0;
|
||||
g->last = MOUSE_BUTTON_UNSET;
|
||||
return;
|
||||
}
|
||||
|
||||
MouseGesture* mouse_gesture_new(void)
|
||||
MouseGesture* mouse_gesture_new (void)
|
||||
{
|
||||
MouseGesture *g = NULL;
|
||||
if((g = g_new(MouseGesture, 1)) == NULL)
|
||||
return(NULL);
|
||||
mouse_gesture_clear(g);
|
||||
return(g);
|
||||
MouseGesture *g = g_new (MouseGesture, 1);
|
||||
mouse_gesture_clear (g);
|
||||
|
||||
return g;
|
||||
}
|
||||
|
||||
static gboolean mouse_gestures_handle_events(GtkWidget *widget, GdkEvent *event, MidoriBrowser *browser)
|
||||
static gboolean mouse_gestures_handle_events (GtkWidget *widget,
|
||||
GdkEvent *event,
|
||||
MidoriBrowser *browser)
|
||||
{
|
||||
if(event->type == GDK_BUTTON_PRESS) // a button was pressed
|
||||
/* A button was pressed */
|
||||
if (event->type == GDK_BUTTON_PRESS)
|
||||
{
|
||||
if(gesture->last == MOUSE_BUTTON_UNSET) // if the gesture was previously cleaned -> new gesture -> new start coordinates
|
||||
/* If the gesture was previously cleaned, start a new gesture and coordinates */
|
||||
if (gesture->last == MOUSE_BUTTON_UNSET)
|
||||
{
|
||||
gesture->start.x = event->button.x;
|
||||
gesture->start.y = event->button.y;
|
||||
gesture->last = event->button.button;
|
||||
}
|
||||
return(TRUE);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else if(event->type == GDK_MOTION_NOTIFY) // the mouse was moved
|
||||
else if (event->type == GDK_MOTION_NOTIFY)
|
||||
{
|
||||
if(gesture->last != MOUSE_BUTTON_UNSET)
|
||||
if (gesture->last != MOUSE_BUTTON_UNSET)
|
||||
{
|
||||
guint x, y;
|
||||
|
||||
x = event->motion.x;
|
||||
y = event->motion.y;
|
||||
if((gesture->start.x - x < DEVIANCE && gesture->start.x - x > -DEVIANCE) ||
|
||||
|
||||
if ((gesture->start.x - x < DEVIANCE && gesture->start.x - x > -DEVIANCE) ||
|
||||
(gesture->start.y - y < DEVIANCE && gesture->start.y - y > -DEVIANCE))
|
||||
{
|
||||
gesture->middle.x = x;
|
||||
gesture->middle.y = y;
|
||||
}
|
||||
else if((gesture->middle.x - x < DEVIANCE && gesture->middle.x - x > -DEVIANCE) ||
|
||||
else if ((gesture->middle.x - x < DEVIANCE && gesture->middle.x - x > -DEVIANCE) ||
|
||||
(gesture->middle.y - y < DEVIANCE && gesture->middle.y - y > -DEVIANCE))
|
||||
{
|
||||
gesture->end.x = x;
|
||||
gesture->end.y = y;
|
||||
}
|
||||
}
|
||||
return(TRUE);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else if(event->type == GDK_BUTTON_RELEASE)
|
||||
else if (event->type == GDK_BUTTON_RELEASE)
|
||||
{
|
||||
if(gesture->last == MOUSE_BUTTON_MIDDLE) // all mouse gestures will use the middle mouse button
|
||||
/* All mouse gestures will use the middle mouse button */
|
||||
if (gesture->last == MOUSE_BUTTON_MIDDLE)
|
||||
{
|
||||
// middle mouse button has been released
|
||||
if(gesture->middle.x - gesture->start.x < DEVIANCE && gesture->middle.x - gesture->start.x > -DEVIANCE)
|
||||
/* The initial horizontal move is between the bounds */
|
||||
if ((gesture->middle.x - gesture->start.x < DEVIANCE) &&
|
||||
(gesture->middle.x - gesture->start.x > -DEVIANCE))
|
||||
{
|
||||
// StartNode to MiddleNode is a straight vertical line
|
||||
if(gesture->middle.y > gesture->start.y + MINLENGTH)
|
||||
/* We initially moved down more than MINLENGTH pixels */
|
||||
if (gesture->middle.y > gesture->start.y + MINLENGTH)
|
||||
{
|
||||
// StartNode to MiddleNode is drawn downwards
|
||||
if(gesture->middle.y - gesture->end.y < DEVIANCE && gesture->middle.y - gesture->end.y > -DEVIANCE && gesture->end.x > gesture->middle.x + MINLENGTH)
|
||||
/* Then we the final vertical move is between the bounds and
|
||||
we moved right more than MINLENGTH pixels */
|
||||
if ((gesture->middle.y - gesture->end.y < DEVIANCE) &&
|
||||
(gesture->middle.y - gesture->end.y > -DEVIANCE) &&
|
||||
(gesture->end.x > gesture->middle.x + MINLENGTH))
|
||||
{
|
||||
// MiddleNode to EndNode is a straight horizontal line (to the right) -> close tab
|
||||
midori_browser_activate_action(browser, "TabClose");
|
||||
#ifdef __MOUSE_GESTURES_DEBUG__
|
||||
g_print("TabClose gesture\n");
|
||||
#endif
|
||||
/* We moved down then right: close the tab */
|
||||
midori_browser_activate_action (browser, "TabClose");
|
||||
}
|
||||
else if(gesture->middle.y - gesture->end.y < DEVIANCE && gesture->middle.y - gesture->end.y > -DEVIANCE && gesture->end.x < gesture->middle.x - MINLENGTH)
|
||||
/* Then we the final vertical move is between the bounds and
|
||||
we moved left more than MINLENGTH pixels */
|
||||
else if ((gesture->middle.y - gesture->end.y < DEVIANCE) &&
|
||||
(gesture->middle.y - gesture->end.y > -DEVIANCE) &&
|
||||
(gesture->end.x + MINLENGTH < gesture->middle.x))
|
||||
{
|
||||
// MiddleNode to EndNode is a straight horizontal line (to the left) -> reload
|
||||
midori_browser_activate_action(browser, "Reload");
|
||||
#ifdef __MOUSE_GESTURES_DEBUG__
|
||||
g_print("Reload gesture\n");
|
||||
#endif
|
||||
/* We moved down then left: reload */
|
||||
midori_browser_activate_action (browser, "Reload");
|
||||
}
|
||||
/* The end node was never updated, we only did a vertical move */
|
||||
else if(gesture->end.y == 0 && gesture->end.x == 0)
|
||||
{
|
||||
// no EndNode, just a vertical line -> new tab
|
||||
midori_browser_activate_action(browser, "TabNew");
|
||||
#ifdef __MOUSE_GESTURES_DEBUG__
|
||||
g_print("TabNew gesture\n");
|
||||
#endif
|
||||
/* We moved down then: create a new tab */
|
||||
midori_browser_activate_action (browser, "TabNew");
|
||||
}
|
||||
}
|
||||
if(gesture->middle.y < gesture->start.y - MINLENGTH)
|
||||
/* We initially moved up more than MINLENGTH pixels */
|
||||
else if (gesture->middle.y + MINLENGTH < gesture->start.y)
|
||||
{
|
||||
// StartNode to MiddleNode is drawn upwards
|
||||
if(gesture->end.y == 0 && gesture->end.x == 0)
|
||||
/* The end node was never updated, we only did a vertical move */
|
||||
if (gesture->end.y == 0 && gesture->end.x == 0)
|
||||
{
|
||||
// no EndNode, just a vertical line -> stop
|
||||
midori_browser_activate_action(browser, "Stop");
|
||||
#ifdef __MOUSE_GESTURES_DEBUG__
|
||||
g_print("Stop gesture\n");
|
||||
#endif
|
||||
/* We moved up: stop */
|
||||
midori_browser_activate_action (browser, "Stop");
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(gesture->middle.y - gesture->start.y < DEVIANCE && gesture->middle.y - gesture->start.y > -DEVIANCE)
|
||||
/* The initial horizontal move is between the bounds */
|
||||
else if ((gesture->middle.y - gesture->start.y < DEVIANCE) &&
|
||||
(gesture->middle.y - gesture->start.y > -DEVIANCE))
|
||||
{
|
||||
// Start Node to MiddleNode is a straight horizontal line
|
||||
if(gesture->middle.x > gesture->start.x + MINLENGTH)
|
||||
/* We initially moved right more than MINLENGTH pixels */
|
||||
if (gesture->middle.x > gesture->start.x + MINLENGTH)
|
||||
{
|
||||
// the line was drawn from left to right
|
||||
if(gesture->end.x == 0 && gesture->end.y == 0)
|
||||
/* The end node was never updated, we only did an horizontal move */
|
||||
if (gesture->end.x == 0 && gesture->end.y == 0)
|
||||
{
|
||||
// we only have one horizontal line from left to right -> forward gesture
|
||||
midori_browser_activate_action(browser, "Forward");
|
||||
#ifdef __MOUSE_GESTURES_DEBUG__
|
||||
g_print("Forward gesture\n");
|
||||
#endif
|
||||
/* We moved right: forward */
|
||||
midori_browser_activate_action (browser, "Forward");
|
||||
}
|
||||
}
|
||||
else if(gesture->middle.x < gesture->start.x - MINLENGTH)
|
||||
/* We initially moved left more than MINLENGTH pixels */
|
||||
else if (gesture->middle.x + MINLENGTH < gesture->start.x)
|
||||
{
|
||||
// the line was drawn from right to left
|
||||
if(gesture->end.x == 0 && gesture->end.y == 0)
|
||||
/* The end node was never updated, we only did an horizontal move */
|
||||
if (gesture->end.x == 0 && gesture->end.y == 0)
|
||||
{
|
||||
// we only have one horizontal line from right to left -> backwards gesture
|
||||
midori_browser_activate_action(browser, "Back");
|
||||
#ifdef __MOUSE_GESTURES_DEBUG__
|
||||
g_print("Back gesture\n");
|
||||
#endif
|
||||
/* We moved left: back */
|
||||
midori_browser_activate_action (browser, "Back");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
mouse_gesture_clear(gesture); // gesture finished, clear it
|
||||
return(TRUE);
|
||||
|
||||
mouse_gesture_clear (gesture);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
return(FALSE); // this event is supposed to be handled again (by someone else's code) since it was irrelevant to us
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void mouse_gestures_tab_cb(MidoriBrowser* browser, GtkWidget *view) // this is performed when a new tab is created
|
||||
static void mouse_gestures_tab_cb (MidoriBrowser* browser, GtkWidget *view)
|
||||
{
|
||||
g_signal_connect(view, "event", G_CALLBACK(mouse_gestures_handle_events), browser); // perform the above callback when an event from the view is received
|
||||
return;
|
||||
g_signal_connect (view, "event", G_CALLBACK (mouse_gestures_handle_events), browser);
|
||||
}
|
||||
|
||||
static void mouse_gestures_browser_cb(MidoriApp *app, MidoriBrowser *browser) // this is performed when ever a new window is created
|
||||
static void mouse_gestures_browser_cb (MidoriApp *app, MidoriBrowser *browser)
|
||||
{
|
||||
g_signal_connect(browser, "add-tab", G_CALLBACK(mouse_gestures_tab_cb), NULL); // connect the above callback to the "add-tab" signal of browser
|
||||
return;
|
||||
g_signal_connect (browser, "add-tab", G_CALLBACK (mouse_gestures_tab_cb), NULL);
|
||||
}
|
||||
|
||||
/* this is performed when the extension is deactivated.
|
||||
disconnect all signal handlers, so that mouse gestures are no longer handled */
|
||||
static void mouse_gestures_deactivate(MidoriExtension *extension, MidoriApp *app)
|
||||
static void mouse_gestures_deactivate (MidoriExtension *extension, MidoriApp *app)
|
||||
{
|
||||
gulong signal_id = g_signal_handler_find(app, G_SIGNAL_MATCH_FUNC, 0, 0, NULL, mouse_gestures_browser_cb, NULL); // get the signal handler id
|
||||
if(signal_id != 0) // if that id is valid
|
||||
g_signal_handler_disconnect(app, signal_id); // disconnect the signal
|
||||
KatzeArray *browsers = katze_object_get_object(app, "browsers"); // get the array that contains all browsers
|
||||
guint i; // our counter variable :)
|
||||
for(i = 0; i < katze_array_get_length(browsers); i++) // from the first to the last browser
|
||||
gulong signal_id;
|
||||
KatzeArray *browsers;
|
||||
guint i;
|
||||
gint j;
|
||||
GtkWidget *notebook;
|
||||
|
||||
signal_id =
|
||||
g_signal_handler_find (app, G_SIGNAL_MATCH_FUNC,
|
||||
0, 0, NULL,
|
||||
mouse_gestures_browser_cb, NULL);
|
||||
|
||||
if(signal_id != 0)
|
||||
g_signal_handler_disconnect (app, signal_id);
|
||||
|
||||
browsers = katze_object_get_object (app, "browsers");
|
||||
|
||||
for (i = 0; i < katze_array_get_length (browsers); i++)
|
||||
{
|
||||
MidoriBrowser *browser = katze_array_get_nth_item(browsers, i); // get a pointer on the current browser
|
||||
signal_id = g_signal_handler_find(browser, G_SIGNAL_MATCH_FUNC, 0, 0, NULL, mouse_gestures_tab_cb, NULL); // search forthe signal handler id
|
||||
if(signal_id != 0) // and if its not invalid..
|
||||
g_signal_handler_disconnect(browser, signal_id); // disconnect it
|
||||
MidoriBrowser *browser;
|
||||
|
||||
GtkWidget *notebook = katze_object_get_object(browser, "notebook"); // get a pointer on the notebook
|
||||
gint j; // another counter
|
||||
for(j = 0; j < gtk_notebook_get_n_pages(GTK_NOTEBOOK(notebook)); j++) // from the first to the last tab
|
||||
browser = katze_array_get_nth_item (browsers, i);
|
||||
|
||||
signal_id =
|
||||
g_signal_handler_find (browser, G_SIGNAL_MATCH_FUNC,
|
||||
0, 0, NULL,
|
||||
mouse_gestures_tab_cb, NULL);
|
||||
|
||||
if (signal_id != 0)
|
||||
g_signal_handler_disconnect (browser, signal_id);
|
||||
|
||||
notebook = katze_object_get_object (browser, "notebook");
|
||||
|
||||
for (j = 0; j < gtk_notebook_get_n_pages (GTK_NOTEBOOK (notebook)); j++)
|
||||
{
|
||||
GtkWidget *page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook), j); // get a pointer on the tab's view
|
||||
signal_id = g_signal_handler_find(page, G_SIGNAL_MATCH_FUNC, 0, 0, NULL, mouse_gestures_handle_events, NULL); // find the signal id of the event handler
|
||||
if(signal_id != 0) // if the id is valid
|
||||
g_signal_handler_disconnect(page, signal_id); // disconnect the handler
|
||||
GtkWidget *page = gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), j);
|
||||
|
||||
signal_id =
|
||||
g_signal_handler_find (page, G_SIGNAL_MATCH_FUNC,
|
||||
0, 0, NULL,
|
||||
mouse_gestures_handle_events, NULL);
|
||||
|
||||
if (signal_id != 0)
|
||||
g_signal_handler_disconnect (page, signal_id);
|
||||
}
|
||||
}
|
||||
g_free(gesture); // free the structure that contains the gesture information
|
||||
return;
|
||||
|
||||
g_signal_handlers_disconnect_by_func (extension, mouse_gestures_deactivate, app);
|
||||
g_free (gesture);
|
||||
}
|
||||
|
||||
static void mouse_gestures_activate(MidoriExtension *extension, MidoriApp *app) // this is performed on extension-activation
|
||||
static void mouse_gestures_activate (MidoriExtension *extension, MidoriApp *app)
|
||||
{
|
||||
g_signal_connect(app, "add-browser", G_CALLBACK(mouse_gestures_browser_cb), NULL); // connect the above callback to the "add-browser" signal of app
|
||||
g_signal_connect(extension, "deactivate", G_CALLBACK(mouse_gestures_deactivate), app); // connect the deactivate callback to the extension
|
||||
return;
|
||||
gesture = mouse_gesture_new ();
|
||||
|
||||
g_signal_connect (app, "add-browser",
|
||||
G_CALLBACK (mouse_gestures_browser_cb), NULL);
|
||||
g_signal_connect (extension, "deactivate",
|
||||
G_CALLBACK (mouse_gestures_deactivate), app);
|
||||
}
|
||||
|
||||
MidoriExtension* extension_init(void)
|
||||
MidoriExtension* extension_init (void)
|
||||
{
|
||||
MidoriExtension* extension = NULL;
|
||||
extension = g_object_new(MIDORI_TYPE_EXTENSION,
|
||||
MidoriExtension* extension;
|
||||
|
||||
extension = g_object_new (MIDORI_TYPE_EXTENSION,
|
||||
"name", _("Mouse Gestures"),
|
||||
"description", _("Control Midori by moving the mouse"),
|
||||
"version", MOUSE_GESTURES_VERSION,
|
||||
"authors", "Matthias Kruk <mkruk@matthiaskruk.de>", NULL);
|
||||
g_signal_connect(extension, "activate", G_CALLBACK(mouse_gestures_activate), NULL); // connect the callback that's executed on activation
|
||||
gesture = NULL; // initialise gesture pointer; initialising pointers is always a good choice
|
||||
if((gesture = mouse_gesture_new()) == NULL) // allocate space for the gesture
|
||||
{
|
||||
// no space could be allocated
|
||||
g_free(extension); // free the space used by this extension
|
||||
return(NULL);
|
||||
}
|
||||
return(extension);
|
||||
|
||||
g_signal_connect (extension, "activate",
|
||||
G_CALLBACK (mouse_gestures_activate), NULL);
|
||||
|
||||
return extension;
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ page_holder_notebook_append_view (GtkWidget* notebook)
|
|||
GtkWidget* label;
|
||||
|
||||
view = midori_view_new (NULL);
|
||||
browser = MIDORI_BROWSER (gtk_widget_get_toplevel (notebook));
|
||||
browser = midori_browser_get_for_widget (notebook);
|
||||
settings = katze_object_get_object (browser, "settings");
|
||||
midori_view_set_settings (MIDORI_VIEW (view), settings);
|
||||
g_object_unref (settings);
|
||||
|
@ -49,7 +49,7 @@ page_holder_button_jump_to_clicked_cb (GtkWidget* button,
|
|||
if (n < 0)
|
||||
n = page_holder_notebook_append_view (notebook);
|
||||
|
||||
browser = MIDORI_BROWSER (gtk_widget_get_toplevel (notebook));
|
||||
browser = midori_browser_get_for_widget (notebook);
|
||||
uri = midori_browser_get_current_uri (browser);
|
||||
view = gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), n);
|
||||
midori_view_set_uri (MIDORI_VIEW (view), uri);
|
||||
|
@ -66,7 +66,7 @@ page_holder_button_add_clicked_cb (GtkWidget* button,
|
|||
|
||||
n = page_holder_notebook_append_view (notebook);
|
||||
view = gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), n);
|
||||
browser = MIDORI_BROWSER (gtk_widget_get_toplevel (notebook));
|
||||
browser = midori_browser_get_for_widget (notebook);
|
||||
uri = midori_browser_get_current_uri (browser);
|
||||
midori_view_set_uri (MIDORI_VIEW (view), uri);
|
||||
}
|
||||
|
|
|
@ -69,7 +69,7 @@ statusbar_features_app_add_browser_cb (MidoriApp* app,
|
|||
gtk_widget_show (image);
|
||||
gtk_container_add (GTK_CONTAINER (button), image);
|
||||
#if GTK_CHECK_VERSION(2, 12, 0)
|
||||
gtk_widget_set_tooltip_text (button, _("Enable plugins"));
|
||||
gtk_widget_set_tooltip_text (button, _("Enable Netscape plugins"));
|
||||
#endif
|
||||
gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, FALSE, 2);
|
||||
gtk_widget_show (button);
|
||||
|
@ -101,8 +101,8 @@ MidoriExtension*
|
|||
extension_init (void)
|
||||
{
|
||||
MidoriExtension* extension = g_object_new (MIDORI_TYPE_EXTENSION,
|
||||
"name", "Statusbar Features",
|
||||
"description", "",
|
||||
"name", _("Statusbar Features"),
|
||||
"description", _("Easily toggle features on web pages on and off"),
|
||||
"version", "0.1",
|
||||
"authors", "Christian Dywan <christian@twotoasts.de>",
|
||||
NULL);
|
||||
|
|
|
@ -7,6 +7,9 @@ for extension in extensions:
|
|||
# Tab Panel isn't useful at this point
|
||||
if extension == 'tab-panel':
|
||||
continue
|
||||
# Adblock is incomplete and not ready for release
|
||||
if extension == 'adblock.c':
|
||||
continue
|
||||
folder = 'extensions' + os.sep + extension
|
||||
if os.path.isdir (folder):
|
||||
files = os.listdir (folder)
|
||||
|
|
|
@ -111,16 +111,10 @@ _katze_array_move_item (KatzeArray* array,
|
|||
static void
|
||||
_katze_array_clear (KatzeArray* array)
|
||||
{
|
||||
guint n;
|
||||
guint i;
|
||||
GObject* item;
|
||||
|
||||
n = g_list_length (array->items);
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
if ((item = g_list_nth_data (array->items, i)))
|
||||
while ((item = g_list_nth_data (array->items, 0)))
|
||||
katze_array_remove_item (array, item);
|
||||
}
|
||||
g_list_free (array->items);
|
||||
array->items = NULL;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
Copyright (C) 2008 Christian Dywan <christian@twotoasts.de>
|
||||
Copyright (C) 2009 Enrico Tröger <enrico.troeger@uvena.de>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -13,6 +14,7 @@
|
|||
|
||||
#include "katze-net.h"
|
||||
#include "katze-utils.h"
|
||||
#include "marshal.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <glib/gi18n.h>
|
||||
|
@ -44,6 +46,7 @@ enum
|
|||
{
|
||||
POPULATE_POPUP,
|
||||
ACTIVATE_ITEM,
|
||||
ACTIVATE_ITEM_ALT,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
|
@ -107,6 +110,30 @@ katze_array_action_class_init (KatzeArrayActionClass* class)
|
|||
G_TYPE_NONE, 1,
|
||||
KATZE_TYPE_ITEM);
|
||||
|
||||
/**
|
||||
* KatzeArrayAction::activate-item-alt:
|
||||
* @array: the object on which the signal is emitted
|
||||
* @item: the item being activated
|
||||
* @button: the mouse button pressed
|
||||
*
|
||||
* An item was clicked with a particular button. Use this if you need
|
||||
* to handle middle or right clicks specially.
|
||||
*
|
||||
* Return value: %TRUE if the event was handled. If %FALSE is returned,
|
||||
* the default "activate-item" signal is emitted.
|
||||
*
|
||||
* Since: 0.1.7
|
||||
**/
|
||||
signals[ACTIVATE_ITEM_ALT] = g_signal_new ("activate-item-alt",
|
||||
G_TYPE_FROM_CLASS (class),
|
||||
(GSignalFlags) (G_SIGNAL_RUN_LAST),
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
katze_cclosure_marshal_BOOLEAN__OBJECT_UINT,
|
||||
G_TYPE_BOOLEAN, 2,
|
||||
KATZE_TYPE_ITEM, G_TYPE_UINT);
|
||||
|
||||
gobject_class = G_OBJECT_CLASS (class);
|
||||
gobject_class->finalize = katze_array_action_finalize;
|
||||
gobject_class->set_property = katze_array_action_set_property;
|
||||
|
@ -206,13 +233,35 @@ katze_array_action_activate (GtkAction* action)
|
|||
}
|
||||
|
||||
static void
|
||||
katze_array_action_menu_item_activate_cb (GtkWidget* proxy,
|
||||
katze_array_action_menu_activate_cb (GtkWidget* proxy,
|
||||
KatzeArrayAction* array_action)
|
||||
{
|
||||
KatzeItem* item = g_object_get_data (G_OBJECT (proxy), "KatzeItem");
|
||||
g_signal_emit (array_action, signals[ACTIVATE_ITEM], 0, item);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
katze_array_action_menu_button_press_cb (GtkWidget* proxy,
|
||||
GdkEventButton* event,
|
||||
KatzeArrayAction* array_action)
|
||||
{
|
||||
KatzeItem* item = g_object_get_data (G_OBJECT (proxy), "KatzeItem");
|
||||
gboolean handled;
|
||||
|
||||
g_signal_emit (array_action, signals[ACTIVATE_ITEM_ALT], 0, item,
|
||||
event->button, &handled);
|
||||
|
||||
if (!handled)
|
||||
g_signal_emit (array_action, signals[ACTIVATE_ITEM], 0, item);
|
||||
|
||||
/* we need to block the 'activate' handler which would be called
|
||||
* otherwise as well */
|
||||
g_signal_handlers_block_by_func (proxy,
|
||||
katze_array_action_menu_activate_cb, array_action);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
katze_array_action_menu_item_select_cb (GtkWidget* proxy,
|
||||
KatzeArrayAction* array_action);
|
||||
|
@ -268,8 +317,13 @@ katze_array_action_generate_menu (KatzeArrayAction* array_action,
|
|||
G_CALLBACK (katze_array_action_menu_item_select_cb), array_action);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_signal_connect (menuitem, "button-press-event",
|
||||
G_CALLBACK (katze_array_action_menu_button_press_cb), array_action);
|
||||
/* we need the 'activate' signal as well for keyboard events */
|
||||
g_signal_connect (menuitem, "activate",
|
||||
G_CALLBACK (katze_array_action_menu_item_activate_cb), array_action);
|
||||
G_CALLBACK (katze_array_action_menu_activate_cb), array_action);
|
||||
}
|
||||
gtk_widget_show (menuitem);
|
||||
}
|
||||
if (!i)
|
||||
|
@ -418,6 +472,44 @@ katze_array_action_item_notify_cb (KatzeItem* item,
|
|||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
katze_array_action_proxy_create_menu_proxy_cb (GtkWidget* proxy,
|
||||
KatzeItem* item)
|
||||
{
|
||||
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));
|
||||
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_IS_ARRAY (item))
|
||||
icon = gtk_widget_render_icon (menuitem,
|
||||
GTK_STOCK_DIRECTORY, GTK_ICON_SIZE_MENU, NULL);
|
||||
else
|
||||
icon = katze_net_load_icon (array_action->net,
|
||||
katze_item_get_uri (item), NULL, proxy, NULL);
|
||||
image = gtk_image_new_from_pixbuf (icon);
|
||||
g_object_unref (icon);
|
||||
}
|
||||
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), image);
|
||||
g_object_set_data (G_OBJECT (menuitem), "KatzeItem", item);
|
||||
g_signal_connect (menuitem, "button-press-event",
|
||||
G_CALLBACK (katze_array_action_menu_button_press_cb), array_action);
|
||||
/* we need the 'activate' signal as well for keyboard events */
|
||||
g_signal_connect (menuitem, "activate",
|
||||
G_CALLBACK (katze_array_action_menu_activate_cb), array_action);
|
||||
gtk_tool_item_set_proxy_menu_item (GTK_TOOL_ITEM (proxy),
|
||||
"katze-tool-item-menu", menuitem);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* katze_array_action_create_tool_item_for:
|
||||
* @array_action: a #KatzeArrayAction
|
||||
|
@ -453,6 +545,8 @@ katze_array_action_create_tool_item_for (KatzeArrayAction* array_action,
|
|||
return gtk_separator_tool_item_new ();
|
||||
|
||||
toolitem = gtk_tool_button_new (NULL, NULL);
|
||||
g_signal_connect (toolitem, "create-menu-proxy",
|
||||
G_CALLBACK (katze_array_action_proxy_create_menu_proxy_cb), item);
|
||||
if (KATZE_IS_ARRAY (item))
|
||||
icon = gtk_widget_render_icon (GTK_WIDGET (toolitem),
|
||||
GTK_STOCK_DIRECTORY, GTK_ICON_SIZE_MENU, NULL);
|
||||
|
|
|
@ -219,14 +219,9 @@ katze_property_proxy (gpointer object,
|
|||
string = g_strdup (G_PARAM_SPEC_STRING (pspec)->default_value);
|
||||
gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (widget),
|
||||
string ? string : "");
|
||||
#if GTK_CHECK_VERSION (2, 12, 0)
|
||||
g_signal_connect (widget, "file-set",
|
||||
G_CALLBACK (proxy_file_file_set_cb), object);
|
||||
#else
|
||||
if (pspec->flags & G_PARAM_WRITABLE)
|
||||
g_signal_connect (widget, "selection-changed",
|
||||
G_CALLBACK (proxy_file_file_set_cb), object);
|
||||
#endif
|
||||
}
|
||||
else if (type == G_TYPE_PARAM_STRING && _hint == g_intern_string ("folder"))
|
||||
{
|
||||
|
@ -238,14 +233,9 @@ katze_property_proxy (gpointer object,
|
|||
string = g_strdup (G_PARAM_SPEC_STRING (pspec)->default_value);
|
||||
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (widget),
|
||||
string ? string : "");
|
||||
#if GTK_CHECK_VERSION (2, 12, 0)
|
||||
g_signal_connect (widget, "file-set",
|
||||
G_CALLBACK (proxy_folder_file_set_cb), object);
|
||||
#else
|
||||
if (pspec->flags & G_PARAM_WRITABLE)
|
||||
g_signal_connect (widget, "selection-changed",
|
||||
G_CALLBACK (proxy_folder_file_set_cb), object);
|
||||
#endif
|
||||
}
|
||||
else if (type == G_TYPE_PARAM_STRING && _hint == g_intern_string ("uri"))
|
||||
{
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
Copyright (C) 2007-2008 Christian Dywan <christian@twotoasts.de>
|
||||
Copyright (C) 2009 Dale Whittaker <dayul@users.sf.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -54,6 +55,22 @@ G_BEGIN_DECLS
|
|||
lvalue = rvalue; \
|
||||
}
|
||||
|
||||
/**
|
||||
* katze_strv_assign:
|
||||
* @lvalue: a string list
|
||||
* @rvalue: the new value
|
||||
*
|
||||
* Frees @lvalue if needed and assigns it the value of @rvalue.
|
||||
*
|
||||
* Since: 0.1.7
|
||||
**/
|
||||
#define katze_strv_assign(lvalue, rvalue) \
|
||||
if (1) \
|
||||
{ \
|
||||
g_strfreev (lvalue); \
|
||||
lvalue = rvalue; \
|
||||
}
|
||||
|
||||
GtkWidget*
|
||||
katze_property_proxy (gpointer object,
|
||||
const gchar* property,
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
VOID:POINTER,INT
|
||||
BOOLEAN:OBJECT,UINT
|
||||
|
|
|
@ -28,12 +28,9 @@ gtk_icon_entry_set_icon_from_pixbuf (GtkEntry* entry,
|
|||
GdkPixbuf* pixbuf)
|
||||
{
|
||||
/* Without this ugly hack pixbuf icons don't work */
|
||||
if (pixbuf)
|
||||
{
|
||||
gtk_widget_hide (GTK_WIDGET (entry));
|
||||
gtk_entry_set_icon_from_pixbuf (entry, position, pixbuf);
|
||||
gtk_widget_show (GTK_WIDGET (entry));
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
@ -1266,6 +1263,10 @@ gtk_icon_entry_set_icon_from_stock (GtkIconEntry *entry,
|
|||
{
|
||||
GdkPixbuf *pixbuf;
|
||||
|
||||
/* FIXME: Due to a bug in GtkIconEntry we need to set a non-NULL icon */
|
||||
if (! stock_id)
|
||||
stock_id = GTK_STOCK_INFO;
|
||||
|
||||
pixbuf = gtk_widget_render_icon (GTK_WIDGET (entry),
|
||||
stock_id,
|
||||
GTK_ICON_SIZE_MENU,
|
||||
|
|
|
@ -39,6 +39,7 @@ G_BEGIN_DECLS
|
|||
#define GTK_TYPE_ICON_ENTRY GTK_TYPE_ENTRY
|
||||
#define gtk_icon_entry_new gtk_entry_new
|
||||
#define gtk_icon_entry_set_icon_from_stock gtk_entry_set_icon_from_stock
|
||||
|
||||
void
|
||||
gtk_icon_entry_set_icon_from_pixbuf (GtkEntry* entry,
|
||||
GtkEntryIconPosition position,
|
||||
|
|
119
midori/main.c
119
midori/main.c
|
@ -35,6 +35,7 @@
|
|||
#else
|
||||
#define is_writable(_cfg_filename) 1
|
||||
#endif
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <glib/gstdio.h>
|
||||
|
@ -71,7 +72,8 @@ build_config_filename (const gchar* filename)
|
|||
}
|
||||
|
||||
static MidoriWebSettings*
|
||||
settings_new_from_file (const gchar* filename)
|
||||
settings_new_from_file (const gchar* filename,
|
||||
gchar*** extensions)
|
||||
{
|
||||
MidoriWebSettings* settings = midori_web_settings_new ();
|
||||
GKeyFile* key_file = g_key_file_new ();
|
||||
|
@ -156,11 +158,17 @@ settings_new_from_file (const gchar* filename)
|
|||
g_warning (_("Invalid configuration value '%s'"), property);
|
||||
}
|
||||
g_free (pspecs);
|
||||
|
||||
*extensions = g_key_file_get_keys (key_file, "extensions", NULL, NULL);
|
||||
|
||||
g_key_file_free (key_file);
|
||||
|
||||
return settings;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
settings_save_to_file (MidoriWebSettings* settings,
|
||||
MidoriApp* app,
|
||||
const gchar* filename,
|
||||
GError** error)
|
||||
{
|
||||
|
@ -172,6 +180,8 @@ settings_save_to_file (MidoriWebSettings* settings,
|
|||
GType type;
|
||||
const gchar* property;
|
||||
gboolean saved;
|
||||
KatzeArray* extensions = katze_object_get_object (app, "extensions");
|
||||
MidoriExtension* extension;
|
||||
|
||||
key_file = g_key_file_new ();
|
||||
class = G_OBJECT_GET_CLASS (settings);
|
||||
|
@ -228,6 +238,14 @@ settings_save_to_file (MidoriWebSettings* settings,
|
|||
g_warning (_("Invalid configuration value '%s'"), property);
|
||||
}
|
||||
g_free (pspecs);
|
||||
|
||||
i = 0;
|
||||
while ((extension = katze_array_get_nth_item (extensions, i++)))
|
||||
if (midori_extension_is_active (extension))
|
||||
g_key_file_set_boolean (key_file, "extensions",
|
||||
g_object_get_data (G_OBJECT (extension), "filename"), TRUE);
|
||||
g_object_unref (extensions);
|
||||
|
||||
saved = sokoke_key_file_save_to_file (key_file, filename, error);
|
||||
g_key_file_free (key_file);
|
||||
return saved;
|
||||
|
@ -710,14 +728,15 @@ midori_app_quit_cb (MidoriApp* app)
|
|||
|
||||
static void
|
||||
settings_notify_cb (MidoriWebSettings* settings,
|
||||
GParamSpec* pspec)
|
||||
GParamSpec* pspec,
|
||||
MidoriApp* app)
|
||||
{
|
||||
gchar* config_file;
|
||||
GError* error;
|
||||
|
||||
config_file = build_config_filename ("config");
|
||||
error = NULL;
|
||||
if (!settings_save_to_file (settings, config_file, &error))
|
||||
if (!settings_save_to_file (settings, app, config_file, &error))
|
||||
{
|
||||
g_warning (_("The configuration couldn't be saved. %s"), error->message);
|
||||
g_error_free (error);
|
||||
|
@ -1147,13 +1166,13 @@ static gboolean
|
|||
midori_load_extensions (gpointer data)
|
||||
{
|
||||
MidoriApp* app = MIDORI_APP (data);
|
||||
gchar** active_extensions = g_object_get_data (G_OBJECT (app), "extensions");
|
||||
KatzeArray* extensions;
|
||||
const gchar* filename;
|
||||
MidoriExtension* extension;
|
||||
guint i;
|
||||
|
||||
/* Load extensions */
|
||||
extensions = katze_array_new (MIDORI_TYPE_EXTENSION);
|
||||
g_object_set (app, "extensions", extensions, NULL);
|
||||
if (g_module_supported ())
|
||||
{
|
||||
/* FIXME: Read extensions from system data dirs */
|
||||
|
@ -1165,6 +1184,8 @@ midori_load_extensions (gpointer data)
|
|||
extension_dir = g_dir_open (extension_path, 0, NULL);
|
||||
if (extension_dir != NULL)
|
||||
{
|
||||
const gchar* filename;
|
||||
|
||||
while ((filename = g_dir_read_name (extension_dir)))
|
||||
{
|
||||
gchar* fullname;
|
||||
|
@ -1186,6 +1207,8 @@ midori_load_extensions (gpointer data)
|
|||
extension = extension_init ();
|
||||
/* FIXME: Validate the extension */
|
||||
/* Signal that we want the extension to load and save */
|
||||
g_object_set_data_full (G_OBJECT (extension), "filename",
|
||||
g_strdup (filename), g_free);
|
||||
midori_extension_get_config_dir (extension);
|
||||
}
|
||||
else
|
||||
|
@ -1197,6 +1220,14 @@ midori_load_extensions (gpointer data)
|
|||
g_warning ("%s", g_module_error ());
|
||||
}
|
||||
katze_array_add_item (extensions, extension);
|
||||
if (active_extensions)
|
||||
{
|
||||
guint i = 0;
|
||||
gchar* name;
|
||||
while ((name = active_extensions[i++]))
|
||||
if (!g_strcmp0 (filename, name))
|
||||
g_signal_emit_by_name (extension, "activate", app);
|
||||
}
|
||||
g_object_unref (extension);
|
||||
}
|
||||
g_dir_close (extension_dir);
|
||||
|
@ -1204,11 +1235,7 @@ midori_load_extensions (gpointer data)
|
|||
g_free (extension_path);
|
||||
}
|
||||
|
||||
g_object_set (app, "extensions", extensions, NULL);
|
||||
|
||||
i = 0;
|
||||
while ((extension = katze_array_get_nth_item (extensions, i++)))
|
||||
g_signal_emit_by_name (extension, "activate", app);
|
||||
g_strfreev (active_extensions);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -1318,6 +1345,33 @@ midori_run_script (const gchar* filename)
|
|||
return 1;
|
||||
}
|
||||
|
||||
#if WEBKIT_CHECK_VERSION (1, 1, 6)
|
||||
static void
|
||||
snapshot_load_finished_cb (GtkWidget* web_view,
|
||||
WebKitWebFrame* web_frame,
|
||||
gchar* filename)
|
||||
{
|
||||
GError* error;
|
||||
GtkPrintOperation* operation = gtk_print_operation_new ();
|
||||
GtkPrintOperationAction action = GTK_PRINT_OPERATION_ACTION_EXPORT;
|
||||
GtkPrintOperationResult result;
|
||||
|
||||
gtk_print_operation_set_export_filename (operation, filename);
|
||||
error = NULL;
|
||||
result = webkit_web_frame_print_full (web_frame, operation, action, &error);
|
||||
|
||||
if (error != NULL)
|
||||
{
|
||||
g_error ("%s", error->message);
|
||||
gtk_main_quit ();
|
||||
}
|
||||
|
||||
g_object_unref (operation);
|
||||
g_print (_("Snapshot saved to: %s\n"), filename);
|
||||
gtk_main_quit ();
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
char** argv)
|
||||
|
@ -1325,6 +1379,7 @@ main (int argc,
|
|||
gchar* webapp;
|
||||
gchar* config;
|
||||
gboolean run;
|
||||
gchar* snapshot;
|
||||
gboolean version;
|
||||
gchar** uris;
|
||||
MidoriApp* app;
|
||||
|
@ -1338,6 +1393,10 @@ main (int argc,
|
|||
N_("Use FOLDER as configuration folder"), N_("FOLDER") },
|
||||
{ "run", 'r', 0, G_OPTION_ARG_NONE, &run,
|
||||
N_("Run the specified filename as javascript"), NULL },
|
||||
#if WEBKIT_CHECK_VERSION (1, 1, 6)
|
||||
{ "snapshot", 's', 0, G_OPTION_ARG_STRING, &snapshot,
|
||||
N_("Take a snapshot of the specified URI"), NULL },
|
||||
#endif
|
||||
{ "version", 'V', 0, G_OPTION_ARG_NONE, &version,
|
||||
N_("Display program version"), NULL },
|
||||
{ G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &uris,
|
||||
|
@ -1345,6 +1404,7 @@ main (int argc,
|
|||
{ NULL }
|
||||
};
|
||||
GString* error_messages;
|
||||
gchar** extensions;
|
||||
MidoriWebSettings* settings;
|
||||
gchar* config_file;
|
||||
MidoriStartup load_on_startup;
|
||||
|
@ -1379,6 +1439,7 @@ main (int argc,
|
|||
webapp = NULL;
|
||||
config = NULL;
|
||||
run = FALSE;
|
||||
snapshot = NULL;
|
||||
version = FALSE;
|
||||
uris = NULL;
|
||||
error = NULL;
|
||||
|
@ -1412,6 +1473,39 @@ main (int argc,
|
|||
return 0;
|
||||
}
|
||||
|
||||
#if WEBKIT_CHECK_VERSION (1, 1, 6)
|
||||
if (snapshot)
|
||||
{
|
||||
gchar* filename;
|
||||
gint fd;
|
||||
GtkWidget* web_view;
|
||||
|
||||
fd = g_file_open_tmp ("snapshot-XXXXXX.pdf", &filename, &error);
|
||||
close (fd);
|
||||
|
||||
error = NULL;
|
||||
if (error)
|
||||
{
|
||||
g_error ("%s", error->message);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (g_unlink (filename) == -1)
|
||||
{
|
||||
g_error ("%s", g_strerror (errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
web_view = webkit_web_view_new ();
|
||||
g_signal_connect (web_view, "load-finished",
|
||||
G_CALLBACK (snapshot_load_finished_cb), filename);
|
||||
webkit_web_view_open (WEBKIT_WEB_VIEW (web_view), snapshot);
|
||||
gtk_main ();
|
||||
g_free (filename);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Web Application support */
|
||||
if (webapp)
|
||||
{
|
||||
|
@ -1497,7 +1591,7 @@ main (int argc,
|
|||
error_messages = g_string_new (NULL);
|
||||
config_file = build_config_filename ("config");
|
||||
error = NULL;
|
||||
settings = settings_new_from_file (config_file);
|
||||
settings = settings_new_from_file (config_file, &extensions);
|
||||
katze_assign (config_file, build_config_filename ("accels"));
|
||||
gtk_accel_map_load (config_file);
|
||||
katze_assign (config_file, build_config_filename ("search"));
|
||||
|
@ -1657,7 +1751,7 @@ main (int argc,
|
|||
katze_assign (config_file, build_config_filename ("config"));
|
||||
if (is_writable (config_file))
|
||||
g_signal_connect_after (settings, "notify",
|
||||
G_CALLBACK (settings_notify_cb), NULL);
|
||||
G_CALLBACK (settings_notify_cb), app);
|
||||
|
||||
katze_assign (config_file, build_config_filename ("search"));
|
||||
if (is_writable (config_file))
|
||||
|
@ -1746,6 +1840,7 @@ main (int argc,
|
|||
G_CALLBACK (midori_app_add_browser_cb), NULL);
|
||||
|
||||
g_idle_add (midori_load_cookie_jar, settings);
|
||||
g_object_set_data (G_OBJECT (app), "extensions", extensions);
|
||||
g_idle_add (midori_load_extensions, app);
|
||||
katze_item_set_parent (KATZE_ITEM (_session), app);
|
||||
g_idle_add (midori_load_session, _session);
|
||||
|
|
|
@ -4,3 +4,4 @@ VOID:BOOLEAN,STRING
|
|||
VOID:OBJECT,ENUM
|
||||
VOID:STRING,BOOLEAN
|
||||
VOID:STRING,INT,STRING
|
||||
VOID:STRING,STRING
|
||||
|
|
|
@ -24,6 +24,20 @@
|
|||
#include <unique/unique.h>
|
||||
#endif
|
||||
|
||||
typedef struct _NotifyNotification NotifyNotification;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
gboolean (*init) (const gchar* app_name);
|
||||
void (*uninit) (void);
|
||||
NotifyNotification* (*notification_new) (const gchar* summary,
|
||||
const gchar* body,
|
||||
const gchar* icon,
|
||||
GtkWidget* attach);
|
||||
gboolean (*notification_show) (NotifyNotification* notification,
|
||||
GError** error);
|
||||
} LibNotifyFuncs;
|
||||
|
||||
struct _MidoriApp
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
@ -41,6 +55,11 @@ struct _MidoriApp
|
|||
KatzeArray* browsers;
|
||||
|
||||
gpointer instance;
|
||||
|
||||
/* libnotify handling */
|
||||
gchar* program_notify_send;
|
||||
GModule* libnotify_module;
|
||||
LibNotifyFuncs libnotify_funcs;
|
||||
};
|
||||
|
||||
struct _MidoriAppClass
|
||||
|
@ -52,6 +71,9 @@ struct _MidoriAppClass
|
|||
(*add_browser) (MidoriApp* app,
|
||||
MidoriBrowser* browser);
|
||||
void
|
||||
(*remove_browser) (MidoriApp* app,
|
||||
MidoriBrowser* browser);
|
||||
void
|
||||
(*quit) (MidoriApp* app);
|
||||
};
|
||||
|
||||
|
@ -75,6 +97,7 @@ enum
|
|||
|
||||
enum {
|
||||
ADD_BROWSER,
|
||||
REMOVE_BROWSER,
|
||||
QUIT,
|
||||
|
||||
LAST_SIGNAL
|
||||
|
@ -85,6 +108,9 @@ static guint signals[LAST_SIGNAL];
|
|||
static void
|
||||
midori_app_finalize (GObject* object);
|
||||
|
||||
static void
|
||||
midori_app_init_libnotify (MidoriApp* app);
|
||||
|
||||
static void
|
||||
midori_app_set_property (GObject* object,
|
||||
guint prop_id,
|
||||
|
@ -109,13 +135,18 @@ midori_browser_focus_in_event_cb (MidoriBrowser* browser,
|
|||
|
||||
static void
|
||||
midori_browser_new_window_cb (MidoriBrowser* browser,
|
||||
const gchar* uri,
|
||||
MidoriBrowser* new_browser,
|
||||
MidoriApp* app)
|
||||
{
|
||||
MidoriBrowser* new_browser = midori_app_create_browser (app);
|
||||
midori_app_add_browser (app, new_browser);
|
||||
g_object_set (new_browser,
|
||||
"settings", app->settings,
|
||||
"bookmarks", app->bookmarks,
|
||||
"trash", app->trash,
|
||||
"search-engines", app->search_engines,
|
||||
"history", app->history,
|
||||
NULL);
|
||||
|
||||
midori_browser_add_uri (new_browser, uri);
|
||||
midori_app_add_browser (app, new_browser);
|
||||
gtk_widget_show (GTK_WIDGET (new_browser));
|
||||
}
|
||||
|
||||
|
@ -131,6 +162,7 @@ static gboolean
|
|||
midori_browser_destroy_cb (MidoriBrowser* browser,
|
||||
MidoriApp* app)
|
||||
{
|
||||
g_signal_emit (app, signals[REMOVE_BROWSER], 0, browser);
|
||||
katze_array_remove_item (app->browsers, browser);
|
||||
if (!katze_array_is_empty (app->browsers))
|
||||
return FALSE;
|
||||
|
@ -160,6 +192,8 @@ _midori_app_add_browser (MidoriApp* app,
|
|||
"signal::destroy", midori_browser_destroy_cb, app,
|
||||
"signal::quit", midori_browser_quit_cb, app,
|
||||
NULL);
|
||||
g_signal_connect_swapped (browser, "send-notification",
|
||||
G_CALLBACK (midori_app_send_notification), app);
|
||||
|
||||
katze_array_add_item (app->browsers, browser);
|
||||
|
||||
|
@ -191,6 +225,26 @@ midori_app_class_init (MidoriAppClass* class)
|
|||
G_TYPE_NONE, 1,
|
||||
MIDORI_TYPE_BROWSER);
|
||||
|
||||
/**
|
||||
* MidoriApp::remove-browser:
|
||||
* @app: the object on which the signal is emitted
|
||||
* @browser: a #MidoriBrowser
|
||||
*
|
||||
* A new browser is being added to the app.
|
||||
*
|
||||
* Since: 0.1.7
|
||||
*/
|
||||
signals[REMOVE_BROWSER] = g_signal_new (
|
||||
"remove-browser",
|
||||
G_TYPE_FROM_CLASS (class),
|
||||
(GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
g_cclosure_marshal_VOID__OBJECT,
|
||||
G_TYPE_NONE, 1,
|
||||
MIDORI_TYPE_BROWSER);
|
||||
|
||||
signals[QUIT] = g_signal_new (
|
||||
"quit",
|
||||
G_TYPE_FROM_CLASS (class),
|
||||
|
@ -461,6 +515,8 @@ midori_app_init (MidoriApp* app)
|
|||
app->browsers = katze_array_new (MIDORI_TYPE_BROWSER);
|
||||
|
||||
app->instance = NULL;
|
||||
|
||||
midori_app_init_libnotify (app);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -481,6 +537,13 @@ midori_app_finalize (GObject* object)
|
|||
|
||||
katze_object_assign (app->instance, NULL);
|
||||
|
||||
if (app->libnotify_module)
|
||||
{
|
||||
app->libnotify_funcs.uninit ();
|
||||
g_module_close (app->libnotify_module);
|
||||
}
|
||||
katze_assign (app->program_notify_send, NULL);
|
||||
|
||||
G_OBJECT_CLASS (midori_app_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
|
@ -752,7 +815,7 @@ midori_app_add_browser (MidoriApp* app,
|
|||
*
|
||||
* Return value: a new #MidoriBrowser
|
||||
*
|
||||
* Since: 1.0.2
|
||||
* Since: 0.1.2
|
||||
**/
|
||||
MidoriBrowser*
|
||||
midori_app_create_browser (MidoriApp* app)
|
||||
|
@ -783,3 +846,86 @@ midori_app_quit (MidoriApp* app)
|
|||
|
||||
g_signal_emit (app, signals[QUIT], 0);
|
||||
}
|
||||
|
||||
static void
|
||||
midori_app_init_libnotify (MidoriApp* app)
|
||||
{
|
||||
gint i;
|
||||
const gchar* sonames[] = { "libnotify.so", "libnotify.so.1", NULL };
|
||||
|
||||
for (i = 0; sonames[i] != NULL && app->libnotify_module == NULL; i++ )
|
||||
{
|
||||
app->libnotify_module = g_module_open (sonames[i], G_MODULE_BIND_LOCAL);
|
||||
}
|
||||
|
||||
if (app->libnotify_module != NULL)
|
||||
{
|
||||
g_module_symbol (app->libnotify_module, "notify_init",
|
||||
(void*) &(app->libnotify_funcs.init));
|
||||
g_module_symbol (app->libnotify_module, "notify_uninit",
|
||||
(void*) &(app->libnotify_funcs.uninit));
|
||||
g_module_symbol (app->libnotify_module, "notify_notification_new",
|
||||
(void*) &(app->libnotify_funcs.notification_new));
|
||||
g_module_symbol (app->libnotify_module, "notify_notification_show",
|
||||
(void*) &(app->libnotify_funcs.notification_show));
|
||||
|
||||
/* init libnotify */
|
||||
if (!app->libnotify_funcs.init || !app->libnotify_funcs.init ("midori"))
|
||||
{
|
||||
g_module_close (app->libnotify_module);
|
||||
app->libnotify_module = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
app->program_notify_send = g_find_program_in_path ("notify-send");
|
||||
}
|
||||
|
||||
/**
|
||||
* midori_app_send_notification:
|
||||
* @app: a #MidoriApp
|
||||
* @title: title of the notification
|
||||
* @message: text of the notification, or NULL
|
||||
*
|
||||
* Send #message to the notification daemon to display it.
|
||||
* This is done by using libnotify if available or by using the program
|
||||
* "notify-send" as a fallback.
|
||||
*
|
||||
* There is no guarantee that the message have been sent and displayed, as
|
||||
* neither libnotify nor "notify-send" might be available or the
|
||||
* notification daemon might not be running.
|
||||
*
|
||||
* Since 0.1.7
|
||||
**/
|
||||
void
|
||||
midori_app_send_notification (MidoriApp* app,
|
||||
const gchar* title,
|
||||
const gchar* message)
|
||||
{
|
||||
gboolean sent = FALSE;
|
||||
|
||||
g_return_if_fail (MIDORI_IS_APP (app));
|
||||
g_return_if_fail (title);
|
||||
|
||||
if (app->libnotify_module)
|
||||
{
|
||||
NotifyNotification* n;
|
||||
|
||||
n = app->libnotify_funcs.notification_new (title, message, "midori", NULL);
|
||||
sent = app->libnotify_funcs.notification_show (n, NULL);
|
||||
g_object_unref (n);
|
||||
}
|
||||
/* Fall back to the command line program "notify-send" */
|
||||
if (!sent && app->program_notify_send)
|
||||
{
|
||||
gchar* msgq = g_shell_quote (message);
|
||||
gchar* titleq = g_shell_quote (title);
|
||||
gchar* command = g_strdup_printf ("%s -i midori %s %s",
|
||||
app->program_notify_send, titleq, msgq);
|
||||
|
||||
g_spawn_command_line_async (command, NULL);
|
||||
|
||||
g_free (titleq);
|
||||
g_free (msgq);
|
||||
g_free (command);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -64,6 +64,11 @@ midori_app_create_browser (MidoriApp* app);
|
|||
void
|
||||
midori_app_quit (MidoriApp* app);
|
||||
|
||||
void
|
||||
midori_app_send_notification (MidoriApp* app,
|
||||
const gchar* title,
|
||||
const gchar* message);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __MIDORI_APP_H__ */
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -88,6 +88,11 @@ void
|
|||
midori_browser_remove_tab (MidoriBrowser* browser,
|
||||
GtkWidget* widget);
|
||||
|
||||
void
|
||||
midori_browser_foreach (MidoriBrowser* browser,
|
||||
GtkCallback callback,
|
||||
gpointer callback_data);
|
||||
|
||||
gint
|
||||
midori_browser_add_item (MidoriBrowser* browser,
|
||||
KatzeItem* item);
|
||||
|
@ -127,6 +132,9 @@ midori_browser_get_current_tab (MidoriBrowser* browser);
|
|||
KatzeArray*
|
||||
midori_browser_get_proxy_array (MidoriBrowser* browser);
|
||||
|
||||
MidoriBrowser*
|
||||
midori_browser_get_for_widget (GtkWidget* widget);
|
||||
|
||||
void
|
||||
midori_browser_quit (MidoriBrowser* browser);
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
Copyright (C) 2008-2009 Christian Dywan <christian@twotoasts.de>
|
||||
Copyright (C) 2009 Dale Whittaker <dayul@users.sf.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -29,7 +30,7 @@ struct _MidoriExtensionPrivate
|
|||
gchar* authors;
|
||||
|
||||
MidoriApp* app;
|
||||
gboolean active;
|
||||
gint active;
|
||||
gchar* config_dir;
|
||||
GList* lsettings;
|
||||
GHashTable* settings;
|
||||
|
@ -60,20 +61,37 @@ typedef struct
|
|||
gchar* value;
|
||||
} MESettingString;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
gchar* name;
|
||||
GType type;
|
||||
gchar** default_value;
|
||||
gchar** value;
|
||||
gsize default_length;
|
||||
gsize length;
|
||||
} MESettingStringList;
|
||||
|
||||
void me_setting_free (gpointer setting)
|
||||
{
|
||||
MESettingString* string_setting = (MESettingString*)setting;
|
||||
MESettingStringList* strlist_setting = (MESettingStringList*)setting;
|
||||
|
||||
g_free (string_setting->name);
|
||||
if (string_setting->type == G_TYPE_STRING)
|
||||
{
|
||||
g_free (string_setting->name);
|
||||
g_free (string_setting->default_value);
|
||||
g_free (string_setting->value);
|
||||
}
|
||||
if (strlist_setting->type == G_TYPE_STRV)
|
||||
{
|
||||
g_free (strlist_setting->name);
|
||||
g_strfreev (strlist_setting->default_value);
|
||||
g_strfreev (strlist_setting->value);
|
||||
}
|
||||
}
|
||||
|
||||
#define midori_extension_can_install_setting(extension, name) \
|
||||
if (extension->priv->active) \
|
||||
if (extension->priv->active > 0) \
|
||||
{ \
|
||||
g_critical ("%s: Settings have to be installed before " \
|
||||
"the extension is activated.", G_STRFUNC); \
|
||||
|
@ -276,6 +294,19 @@ midori_extension_activate_cb (MidoriExtension* extension,
|
|||
else
|
||||
setting->value = g_strdup (setting->default_value);
|
||||
}
|
||||
else if (setting->type == G_TYPE_STRV)
|
||||
{
|
||||
MESettingStringList* setting_ = (MESettingStringList*)setting;
|
||||
if (extension->priv->key_file)
|
||||
{
|
||||
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);
|
||||
}
|
||||
else
|
||||
g_assert_not_reached ();
|
||||
|
||||
|
@ -283,7 +314,7 @@ midori_extension_activate_cb (MidoriExtension* extension,
|
|||
}
|
||||
|
||||
extension->priv->app = g_object_ref (app);
|
||||
extension->priv->active = TRUE;
|
||||
extension->priv->active = 1;
|
||||
/* FIXME: Disconnect all signal handlers */
|
||||
}
|
||||
|
||||
|
@ -294,7 +325,7 @@ midori_extension_init (MidoriExtension* extension)
|
|||
MIDORI_TYPE_EXTENSION, MidoriExtensionPrivate);
|
||||
|
||||
extension->priv->app = NULL;
|
||||
extension->priv->active = FALSE;
|
||||
extension->priv->active = 0;
|
||||
extension->priv->config_dir = NULL;
|
||||
extension->priv->lsettings = NULL;
|
||||
extension->priv->settings = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||
|
@ -416,7 +447,30 @@ midori_extension_is_active (MidoriExtension* extension)
|
|||
{
|
||||
g_return_val_if_fail (MIDORI_IS_EXTENSION (extension), FALSE);
|
||||
|
||||
return extension->priv->active;
|
||||
return extension->priv->active > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* midori_extension_is_deactivating:
|
||||
* @extension: a #MidoriExtension
|
||||
*
|
||||
* Determines if @extension is currently in the process of
|
||||
* being deactivated.
|
||||
*
|
||||
* Extensions remain fully functional even while being
|
||||
* deactivated, so you can for instance still save settings
|
||||
* but you may need to cleanup during deactivation.
|
||||
*
|
||||
* Return value: %TRUE if @extension is deactivating
|
||||
*
|
||||
* Since: 0.1.7
|
||||
**/
|
||||
gboolean
|
||||
midori_extension_is_deactivating (MidoriExtension* extension)
|
||||
{
|
||||
g_return_val_if_fail (MIDORI_IS_EXTENSION (extension), FALSE);
|
||||
|
||||
return extension->priv->active == 2;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -430,8 +484,9 @@ midori_extension_deactivate (MidoriExtension* extension)
|
|||
{
|
||||
g_return_if_fail (midori_extension_is_active (extension));
|
||||
|
||||
extension->priv->active = 2;
|
||||
g_signal_emit (extension, signals[DEACTIVATE], 0);
|
||||
extension->priv->active = FALSE;
|
||||
extension->priv->active = 0;
|
||||
katze_object_assign (extension->priv->app, NULL);
|
||||
}
|
||||
|
||||
|
@ -459,8 +514,7 @@ midori_extension_get_app (MidoriExtension* extension)
|
|||
* @extension: a #MidoriExtension
|
||||
*
|
||||
* Retrieves the path to a directory reserved for configuration
|
||||
* files specific to the extension. For that purpose the 'name'
|
||||
* of the extension is actually part of the path.
|
||||
* files specific to the extension.
|
||||
*
|
||||
* If settings are installed on the extension, they will be
|
||||
* loaded from and saved to a file "config" in this path.
|
||||
|
@ -470,12 +524,16 @@ midori_extension_get_app (MidoriExtension* extension)
|
|||
const gchar*
|
||||
midori_extension_get_config_dir (MidoriExtension* extension)
|
||||
{
|
||||
|
||||
g_return_val_if_fail (midori_extension_is_prepared (extension), NULL);
|
||||
|
||||
if (!extension->priv->config_dir)
|
||||
{
|
||||
gchar* filename = g_object_get_data (G_OBJECT (extension), "filename");
|
||||
g_return_val_if_fail (filename != NULL, NULL);
|
||||
extension->priv->config_dir = g_build_filename (
|
||||
sokoke_set_config_dir (NULL), "extensions",
|
||||
extension->priv->name, NULL);
|
||||
sokoke_set_config_dir (NULL), "extensions", filename, NULL);
|
||||
}
|
||||
|
||||
return extension->priv->config_dir;
|
||||
}
|
||||
|
@ -770,3 +828,115 @@ midori_extension_set_string (MidoriExtension* extension,
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* midori_extension_install_string_list:
|
||||
* @extension: a #MidoriExtension
|
||||
* @name: the name of the setting
|
||||
* @default_value: the default value
|
||||
*
|
||||
* Installs a string list that can be used to conveniently
|
||||
* store user configuration.
|
||||
*
|
||||
* Note that all settings have to be installed before
|
||||
* the extension is activated.
|
||||
*
|
||||
* Since: 0.1.7
|
||||
**/
|
||||
void
|
||||
midori_extension_install_string_list (MidoriExtension* extension,
|
||||
const gchar* name,
|
||||
gchar** default_value,
|
||||
gsize default_length)
|
||||
{
|
||||
MESettingStringList* setting;
|
||||
|
||||
g_return_if_fail (midori_extension_is_prepared (extension));
|
||||
midori_extension_can_install_setting (extension, name);
|
||||
|
||||
me_setting_install (MESettingStringList, g_strdup (name), G_TYPE_STRV,
|
||||
g_strdupv (default_value), NULL);
|
||||
|
||||
setting->default_length = default_length;
|
||||
}
|
||||
|
||||
/**
|
||||
* midori_extension_get_string_list:
|
||||
* @extension: a #MidoriExtension
|
||||
* @name: the name of the setting
|
||||
* @length: return location to store number of strings, or %NULL
|
||||
*
|
||||
* Retrieves the value of the specified setting.
|
||||
*
|
||||
* Return value: a newly allocated NULL-terminated list of strings,
|
||||
* should be freed with g_strfreev()
|
||||
*
|
||||
* Since: 0.1.7
|
||||
**/
|
||||
gchar**
|
||||
midori_extension_get_string_list (MidoriExtension* extension,
|
||||
const gchar* name,
|
||||
gsize* length)
|
||||
{
|
||||
MESettingStringList* setting;
|
||||
|
||||
g_return_val_if_fail (midori_extension_is_prepared (extension), NULL);
|
||||
g_return_val_if_fail (name != NULL, NULL);
|
||||
|
||||
setting = g_hash_table_lookup (extension->priv->settings, name);
|
||||
|
||||
me_setting_type (setting, G_TYPE_STRV, return NULL);
|
||||
|
||||
if (length)
|
||||
*length = setting->length;
|
||||
|
||||
return g_strdupv (setting->value);
|
||||
}
|
||||
|
||||
/**
|
||||
* midori_extension_set_string_list:
|
||||
* @extension: a #MidoriExtension
|
||||
* @name: the name of the setting
|
||||
* @value: the new value
|
||||
* @length: number of strings in @value, or G_MAXSIZE
|
||||
*
|
||||
* Assigns a new value to the specified setting.
|
||||
*
|
||||
* Since: 0.1.7
|
||||
**/
|
||||
void
|
||||
midori_extension_set_string_list (MidoriExtension* extension,
|
||||
const gchar* name,
|
||||
gchar** value,
|
||||
gsize length)
|
||||
{
|
||||
MESettingStringList* setting;
|
||||
|
||||
g_return_if_fail (midori_extension_is_active (extension));
|
||||
g_return_if_fail (name != NULL);
|
||||
|
||||
setting = g_hash_table_lookup (extension->priv->settings, name);
|
||||
|
||||
me_setting_type (setting, G_TYPE_STRV, return);
|
||||
|
||||
katze_strv_assign (setting->value, g_strdupv (value));
|
||||
setting->length = length;
|
||||
|
||||
if (extension->priv->key_file)
|
||||
{
|
||||
GError* error = NULL;
|
||||
/* FIXME: Handle readonly folder/ file */
|
||||
gchar* config_file = g_build_filename (extension->priv->config_dir,
|
||||
"config", NULL);
|
||||
g_mkdir_with_parents (extension->priv->config_dir, 0700);
|
||||
g_key_file_set_string_list (extension->priv->key_file,
|
||||
"settings", name, (const gchar**)value, length);
|
||||
sokoke_key_file_save_to_file (extension->priv->key_file, config_file, &error);
|
||||
if (error)
|
||||
{
|
||||
printf (_("The configuration of the extension '%s' couldn't be saved: %s\n"),
|
||||
extension->priv->name, error->message);
|
||||
g_error_free (error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,6 +54,9 @@ midori_extension_is_prepared (MidoriExtension* extension);
|
|||
gboolean
|
||||
midori_extension_is_active (MidoriExtension* extension);
|
||||
|
||||
gboolean
|
||||
midori_extension_is_deactivating (MidoriExtension* extension);
|
||||
|
||||
void
|
||||
midori_extension_deactivate (MidoriExtension* extension);
|
||||
|
||||
|
@ -105,6 +108,23 @@ midori_extension_set_string (MidoriExtension* extension,
|
|||
const gchar* name,
|
||||
const gchar* value);
|
||||
|
||||
void
|
||||
midori_extension_install_string_list (MidoriExtension* extension,
|
||||
const gchar* name,
|
||||
gchar** default_value,
|
||||
gsize default_length);
|
||||
|
||||
gchar**
|
||||
midori_extension_get_string_list (MidoriExtension* extension,
|
||||
const gchar* name,
|
||||
gsize* length);
|
||||
|
||||
void
|
||||
midori_extension_set_string_list (MidoriExtension* extension,
|
||||
const gchar* name,
|
||||
gchar** value,
|
||||
gsize length);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __MIDORI_EXTENSION_H__ */
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright (C) 2008 Christian Dywan <christian@twotoasts.de>
|
||||
Copyright (C) 2008-2009 Christian Dywan <christian@twotoasts.de>
|
||||
Copyright (C) 2008 Dale Whittaker <dayul@users.sf.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
|
@ -189,12 +189,23 @@ midori_location_action_class_init (MidoriLocationActionClass* class)
|
|||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
}
|
||||
|
||||
/* Allow this to be used in tests, it's otherwise private */
|
||||
/*static*/ GtkWidget*
|
||||
midori_location_action_entry_for_proxy (GtkWidget* proxy)
|
||||
{
|
||||
GtkWidget* alignment = gtk_bin_get_child (GTK_BIN (proxy));
|
||||
GtkWidget* hbox = gtk_bin_get_child (GTK_BIN (alignment));
|
||||
GList* children = gtk_container_get_children (GTK_CONTAINER (hbox));
|
||||
GtkWidget* entry = g_list_nth_data (children, 0);
|
||||
g_list_free (children);
|
||||
return entry;
|
||||
}
|
||||
|
||||
static void
|
||||
midori_location_action_set_model (MidoriLocationAction* location_action,
|
||||
GtkTreeModel* model)
|
||||
{
|
||||
GSList* proxies;
|
||||
GtkWidget* alignment;
|
||||
GtkWidget* location_entry;
|
||||
GtkWidget* entry;
|
||||
|
||||
|
@ -203,8 +214,7 @@ midori_location_action_set_model (MidoriLocationAction* location_action,
|
|||
for (; proxies != NULL; proxies = g_slist_next (proxies))
|
||||
if (GTK_IS_TOOL_ITEM (proxies->data))
|
||||
{
|
||||
alignment = gtk_bin_get_child (GTK_BIN (proxies->data));
|
||||
location_entry = gtk_bin_get_child (GTK_BIN (alignment));
|
||||
location_entry = midori_location_action_entry_for_proxy (proxies->data);
|
||||
entry = gtk_bin_get_child (GTK_BIN (location_entry));
|
||||
|
||||
g_object_set (location_entry, "model", model, NULL);
|
||||
|
@ -379,7 +389,6 @@ static void
|
|||
midori_location_action_activate (GtkAction* action)
|
||||
{
|
||||
GSList* proxies;
|
||||
GtkWidget* alignment;
|
||||
GtkWidget* entry;
|
||||
|
||||
proxies = gtk_action_get_proxies (action);
|
||||
|
@ -387,8 +396,7 @@ midori_location_action_activate (GtkAction* action)
|
|||
for (; proxies != NULL; proxies = g_slist_next (proxies))
|
||||
if (GTK_IS_TOOL_ITEM (proxies->data))
|
||||
{
|
||||
alignment = gtk_bin_get_child (GTK_BIN (proxies->data));
|
||||
entry = gtk_bin_get_child (GTK_BIN (alignment));
|
||||
entry = midori_location_action_entry_for_proxy (proxies->data);
|
||||
|
||||
/* Obviously only one widget can end up with the focus.
|
||||
Yet we can't predict which one that is, can we? */
|
||||
|
@ -399,22 +407,51 @@ midori_location_action_activate (GtkAction* action)
|
|||
GTK_ACTION_CLASS (midori_location_action_parent_class)->activate (action);
|
||||
}
|
||||
|
||||
static void
|
||||
midori_location_action_go_clicked_cb (GtkWidget* button,
|
||||
GtkAction* action)
|
||||
{
|
||||
GtkWidget* hbox = gtk_widget_get_parent (button);
|
||||
GList* children = gtk_container_get_children (GTK_CONTAINER (hbox));
|
||||
GtkWidget* location_entry = g_list_nth_data (children, 0);
|
||||
g_list_free (children);
|
||||
GtkWidget* entry = gtk_bin_get_child (GTK_BIN (location_entry));
|
||||
const gchar* uri = gtk_entry_get_text (GTK_ENTRY (entry));
|
||||
if (uri && *uri)
|
||||
g_signal_emit (action, signals[SUBMIT_URI], 0, uri, FALSE);
|
||||
}
|
||||
|
||||
static GtkWidget*
|
||||
midori_location_action_create_tool_item (GtkAction* action)
|
||||
{
|
||||
GtkWidget* toolitem;
|
||||
GtkWidget* location_entry;
|
||||
GtkWidget* alignment;
|
||||
GtkWidget* hbox;
|
||||
GtkWidget* location_entry;
|
||||
GtkWidget* go_button;
|
||||
GtkWidget* go_icon;
|
||||
|
||||
toolitem = GTK_WIDGET (gtk_tool_item_new ());
|
||||
gtk_tool_item_set_expand (GTK_TOOL_ITEM (toolitem), TRUE);
|
||||
location_entry = midori_location_entry_new ();
|
||||
|
||||
alignment = gtk_alignment_new (0.0f, 0.5f, 1.0f, 0.1f);
|
||||
gtk_container_add (GTK_CONTAINER (alignment), location_entry);
|
||||
gtk_widget_show (location_entry);
|
||||
gtk_container_add (GTK_CONTAINER (toolitem), alignment);
|
||||
gtk_widget_show (alignment);
|
||||
gtk_container_add (GTK_CONTAINER (toolitem), alignment);
|
||||
hbox = gtk_hbox_new (FALSE, 0);
|
||||
gtk_widget_show (hbox);
|
||||
gtk_container_add (GTK_CONTAINER (alignment), hbox);
|
||||
location_entry = midori_location_entry_new ();
|
||||
gtk_widget_show (location_entry);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), location_entry, TRUE, TRUE, 0);
|
||||
go_button = gtk_button_new ();
|
||||
gtk_button_set_focus_on_click (GTK_BUTTON (go_button), FALSE);
|
||||
gtk_button_set_relief (GTK_BUTTON (go_button), GTK_RELIEF_NONE);
|
||||
go_icon = gtk_image_new_from_stock (GTK_STOCK_JUMP_TO, GTK_ICON_SIZE_MENU);
|
||||
gtk_button_set_image (GTK_BUTTON (go_button), go_icon);
|
||||
gtk_widget_show (go_button);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), go_button, FALSE, FALSE, 0);
|
||||
g_signal_connect (go_button, "clicked",
|
||||
G_CALLBACK (midori_location_action_go_clicked_cb), action);
|
||||
|
||||
return toolitem;
|
||||
}
|
||||
|
@ -620,6 +657,10 @@ midori_location_action_set_item (MidoriLocationAction* location_action,
|
|||
GdkPixbuf* icon;
|
||||
GdkPixbuf* new_icon;
|
||||
|
||||
/* Ensure we keep the title if we added the same URI with a title before */
|
||||
if (!item->title)
|
||||
gtk_tree_model_get (location_action->model, iter, TITLE_COL, &item->title, -1);
|
||||
|
||||
gtk_list_store_set (GTK_LIST_STORE (location_action->model), iter,
|
||||
URI_COL, item->uri, TITLE_COL, item->title, -1);
|
||||
|
||||
|
@ -750,10 +791,7 @@ midori_location_entry_action_activated_cb (GtkEntryCompletion* completion,
|
|||
gchar* search;
|
||||
if (!item)
|
||||
return;
|
||||
if (strstr (uri, "%s"))
|
||||
search = g_strdup_printf (uri, keywords);
|
||||
else
|
||||
search = g_strconcat (uri, " ", keywords, NULL);
|
||||
search = sokoke_search_uri (uri, keywords);
|
||||
midori_location_action_set_uri (location_action, search);
|
||||
g_signal_emit (location_action, signals[SUBMIT_URI], 0, search, FALSE);
|
||||
g_free (search);
|
||||
|
@ -858,7 +896,6 @@ static void
|
|||
midori_location_action_connect_proxy (GtkAction* action,
|
||||
GtkWidget* proxy)
|
||||
{
|
||||
GtkWidget* alignment;
|
||||
GtkWidget* entry;
|
||||
MidoriLocationAction* location_action;
|
||||
GtkCellRenderer* renderer;
|
||||
|
@ -873,8 +910,7 @@ midori_location_action_connect_proxy (GtkAction* action,
|
|||
|
||||
if (GTK_IS_TOOL_ITEM (proxy))
|
||||
{
|
||||
alignment = gtk_bin_get_child (GTK_BIN (proxy));
|
||||
entry = gtk_bin_get_child (GTK_BIN (alignment));
|
||||
entry = midori_location_action_entry_for_proxy (proxy);
|
||||
|
||||
midori_location_entry_set_progress (MIDORI_LOCATION_ENTRY (entry),
|
||||
MIDORI_LOCATION_ACTION (action)->progress);
|
||||
|
@ -942,7 +978,6 @@ midori_location_action_set_text (MidoriLocationAction* location_action,
|
|||
const gchar* text)
|
||||
{
|
||||
GSList* proxies;
|
||||
GtkWidget* alignment;
|
||||
GtkWidget* location_entry;
|
||||
GtkWidget* entry;
|
||||
GtkTreeIter iter;
|
||||
|
@ -960,8 +995,7 @@ midori_location_action_set_text (MidoriLocationAction* location_action,
|
|||
for (; proxies != NULL; proxies = g_slist_next (proxies))
|
||||
if (GTK_IS_TOOL_ITEM (proxies->data))
|
||||
{
|
||||
alignment = gtk_bin_get_child (GTK_BIN (proxies->data));
|
||||
location_entry = gtk_bin_get_child (GTK_BIN (alignment));
|
||||
location_entry = midori_location_action_entry_for_proxy (proxies->data);
|
||||
entry = gtk_bin_get_child (GTK_BIN (location_entry));
|
||||
|
||||
gtk_entry_set_text (GTK_ENTRY (entry), text);
|
||||
|
@ -990,7 +1024,6 @@ midori_location_action_set_icon (MidoriLocationAction* location_action,
|
|||
GdkPixbuf* icon)
|
||||
{
|
||||
GSList* proxies;
|
||||
GtkWidget* alignment;
|
||||
GtkWidget* location_entry;
|
||||
GtkWidget* entry;
|
||||
|
||||
|
@ -1002,8 +1035,7 @@ midori_location_action_set_icon (MidoriLocationAction* location_action,
|
|||
for (; proxies != NULL; proxies = g_slist_next (proxies))
|
||||
if (GTK_IS_TOOL_ITEM (proxies->data))
|
||||
{
|
||||
alignment = gtk_bin_get_child (GTK_BIN (proxies->data));
|
||||
location_entry = gtk_bin_get_child (GTK_BIN (alignment));
|
||||
location_entry = midori_location_action_entry_for_proxy (proxies->data);
|
||||
entry = gtk_bin_get_child (GTK_BIN (location_entry));
|
||||
|
||||
gtk_icon_entry_set_icon_from_pixbuf (GTK_ICON_ENTRY (entry),
|
||||
|
@ -1121,7 +1153,6 @@ midori_location_action_add_item (MidoriLocationAction* location_action,
|
|||
const gchar* title)
|
||||
{
|
||||
GSList* proxies;
|
||||
GtkWidget* alignment;
|
||||
GtkWidget* location_entry;
|
||||
GtkWidget* entry;
|
||||
MidoriLocationEntryItem item;
|
||||
|
@ -1147,8 +1178,7 @@ midori_location_action_add_item (MidoriLocationAction* location_action,
|
|||
if (GTK_IS_TOOL_ITEM (proxies->data) &&
|
||||
!strcmp (location_action->uri, uri))
|
||||
{
|
||||
alignment = gtk_bin_get_child (GTK_BIN (proxies->data));
|
||||
location_entry = gtk_bin_get_child (GTK_BIN (alignment));
|
||||
location_entry = midori_location_action_entry_for_proxy (proxies->data);
|
||||
entry = gtk_bin_get_child (GTK_BIN (location_entry));
|
||||
|
||||
gtk_icon_entry_set_icon_from_pixbuf (GTK_ICON_ENTRY (entry),
|
||||
|
@ -1162,7 +1192,6 @@ midori_location_action_set_icon_for_uri (MidoriLocationAction* location_action,
|
|||
const gchar* uri)
|
||||
{
|
||||
GSList* proxies;
|
||||
GtkWidget* alignment;
|
||||
GtkWidget* location_entry;
|
||||
GtkWidget* entry;
|
||||
MidoriLocationEntryItem item;
|
||||
|
@ -1182,8 +1211,7 @@ midori_location_action_set_icon_for_uri (MidoriLocationAction* location_action,
|
|||
if (GTK_IS_TOOL_ITEM (proxies->data) &&
|
||||
!g_strcmp0 (location_action->uri, uri))
|
||||
{
|
||||
alignment = gtk_bin_get_child (GTK_BIN (proxies->data));
|
||||
location_entry = gtk_bin_get_child (GTK_BIN (alignment));
|
||||
location_entry = midori_location_action_entry_for_proxy (proxies->data);
|
||||
entry = gtk_bin_get_child (GTK_BIN (location_entry));
|
||||
|
||||
gtk_icon_entry_set_icon_from_pixbuf (GTK_ICON_ENTRY (entry),
|
||||
|
@ -1223,7 +1251,6 @@ midori_location_action_set_search_engines (MidoriLocationAction* location_action
|
|||
KatzeArray* search_engines)
|
||||
{
|
||||
GSList* proxies;
|
||||
GtkWidget* alignment;
|
||||
GtkWidget* entry;
|
||||
GtkWidget* child;
|
||||
GtkEntryCompletion* completion;
|
||||
|
@ -1241,8 +1268,7 @@ midori_location_action_set_search_engines (MidoriLocationAction* location_action
|
|||
KatzeItem* item;
|
||||
guint i;
|
||||
|
||||
alignment = gtk_bin_get_child (GTK_BIN (proxies->data));
|
||||
entry = gtk_bin_get_child (GTK_BIN (alignment));
|
||||
entry = midori_location_action_entry_for_proxy (proxies->data);
|
||||
child = gtk_bin_get_child (GTK_BIN (entry));
|
||||
|
||||
completion = gtk_entry_get_completion (GTK_ENTRY (child));
|
||||
|
@ -1270,7 +1296,6 @@ midori_location_action_set_progress (MidoriLocationAction* location_action,
|
|||
gdouble progress)
|
||||
{
|
||||
GSList* proxies;
|
||||
GtkWidget* alignment;
|
||||
GtkWidget* entry;
|
||||
|
||||
g_return_if_fail (MIDORI_IS_LOCATION_ACTION (location_action));
|
||||
|
@ -1282,8 +1307,7 @@ midori_location_action_set_progress (MidoriLocationAction* location_action,
|
|||
for (; proxies != NULL; proxies = g_slist_next (proxies))
|
||||
if (GTK_IS_TOOL_ITEM (proxies->data))
|
||||
{
|
||||
alignment = gtk_bin_get_child (GTK_BIN (proxies->data));
|
||||
entry = gtk_bin_get_child (GTK_BIN (alignment));
|
||||
entry = midori_location_action_entry_for_proxy (proxies->data);
|
||||
|
||||
midori_location_entry_set_progress (MIDORI_LOCATION_ENTRY (entry),
|
||||
location_action->progress);
|
||||
|
@ -1295,7 +1319,6 @@ midori_location_action_set_secondary_icon (MidoriLocationAction* location_action
|
|||
const gchar* stock_id)
|
||||
{
|
||||
GSList* proxies;
|
||||
GtkWidget* alignment;
|
||||
GtkWidget* entry;
|
||||
GtkWidget* child;
|
||||
GtkStockItem stock_item;
|
||||
|
@ -1310,16 +1333,11 @@ midori_location_action_set_secondary_icon (MidoriLocationAction* location_action
|
|||
for (; proxies != NULL; proxies = g_slist_next (proxies))
|
||||
if (GTK_IS_TOOL_ITEM (proxies->data))
|
||||
{
|
||||
alignment = gtk_bin_get_child (GTK_BIN (proxies->data));
|
||||
entry = gtk_bin_get_child (GTK_BIN (alignment));
|
||||
entry = midori_location_action_entry_for_proxy (proxies->data);
|
||||
child = gtk_bin_get_child (GTK_BIN (entry));
|
||||
|
||||
if (stock_id)
|
||||
gtk_icon_entry_set_icon_from_stock (GTK_ICON_ENTRY (child),
|
||||
GTK_ICON_ENTRY_SECONDARY, stock_id);
|
||||
else
|
||||
gtk_icon_entry_set_icon_from_pixbuf (GTK_ICON_ENTRY (child),
|
||||
GTK_ICON_ENTRY_SECONDARY, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ struct _MidoriPanel
|
|||
|
||||
GtkWidget* toolbar;
|
||||
GtkToolItem* button_align;
|
||||
GtkToolItem* button_detach;
|
||||
GtkWidget* toolbar_label;
|
||||
GtkWidget* frame;
|
||||
GtkWidget* toolbook;
|
||||
|
@ -195,13 +196,15 @@ midori_panel_detached_window_delete_event_cb (GtkWidget* window,
|
|||
GtkWidget* toolbar = g_object_get_data (G_OBJECT (scrolled), "panel-toolbar");
|
||||
GtkWidget* menuitem = g_object_get_data (G_OBJECT (scrolled), "panel-menuitem");
|
||||
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);
|
||||
gtk_container_add (GTK_CONTAINER (panel->notebook), 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 (_midori_panel_child_for_scrolled (panel, scrolled)));
|
||||
|
@ -210,9 +213,20 @@ midori_panel_detached_window_delete_event_cb (GtkWidget* window,
|
|||
gtk_widget_show (menuitem);
|
||||
g_object_set_data (G_OBJECT (menuitem), "toolitem", toolitem);
|
||||
}
|
||||
midori_panel_set_current_page (panel, n);
|
||||
gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON (toolitem), TRUE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
midori_panel_widget_destroy_cb (GtkWidget* viewable,
|
||||
GtkWidget* widget)
|
||||
{
|
||||
gtk_widget_destroy (widget);
|
||||
g_signal_handlers_disconnect_by_func (
|
||||
viewable, midori_panel_widget_destroy_cb, widget);
|
||||
}
|
||||
|
||||
static void
|
||||
midori_panel_button_detach_clicked_cb (GtkWidget* toolbutton,
|
||||
MidoriPanel* panel)
|
||||
|
@ -221,7 +235,6 @@ midori_panel_button_detach_clicked_cb (GtkWidget* toolbutton,
|
|||
/* FIXME: What happens when the browser is destroyed? */
|
||||
/* FIXME: What about multiple browsers? */
|
||||
/* FIXME: Should we remember if the child was detached? */
|
||||
/* FIXME: Fix label of the sidepanel after removing the widgets */
|
||||
gint n = midori_panel_get_current_page (panel);
|
||||
GtkToolItem* toolitem = gtk_toolbar_get_nth_item (
|
||||
GTK_TOOLBAR (panel->toolbar), n);
|
||||
|
@ -242,6 +255,9 @@ midori_panel_button_detach_clicked_cb (GtkWidget* toolbutton,
|
|||
gtk_container_add (GTK_CONTAINER (window), vbox);
|
||||
if (menuitem)
|
||||
gtk_widget_hide (menuitem);
|
||||
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);
|
||||
|
@ -252,6 +268,12 @@ midori_panel_button_detach_clicked_cb (GtkWidget* toolbutton,
|
|||
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);
|
||||
gtk_toggle_tool_button_set_active (GTK_TOGGLE_TOOL_BUTTON (toolitem), TRUE);
|
||||
if (!gtk_notebook_get_n_pages (GTK_NOTEBOOK (panel->notebook)))
|
||||
gtk_widget_set_sensitive (toolbutton, FALSE);
|
||||
g_signal_connect (window, "delete-event",
|
||||
G_CALLBACK (midori_panel_detached_window_delete_event_cb), panel);
|
||||
gtk_widget_show (window);
|
||||
|
@ -305,6 +327,8 @@ midori_panel_init (MidoriPanel* panel)
|
|||
gtk_container_set_border_width (GTK_CONTAINER (toolitem), 6);
|
||||
gtk_toolbar_insert (GTK_TOOLBAR (labelbar), toolitem, -1);
|
||||
toolitem = gtk_tool_button_new_from_stock (GTK_STOCK_FULLSCREEN);
|
||||
gtk_widget_set_sensitive (GTK_WIDGET (toolitem), FALSE);
|
||||
panel->button_detach = toolitem;
|
||||
gtk_tool_button_set_label (GTK_TOOL_BUTTON (toolitem),
|
||||
_("Detach chosen panel from the window"));
|
||||
gtk_tool_item_set_tooltip_text (GTK_TOOL_ITEM (toolitem),
|
||||
|
@ -518,22 +542,14 @@ static void
|
|||
midori_panel_viewable_destroy_cb (GtkWidget* viewable,
|
||||
MidoriPanel* panel)
|
||||
{
|
||||
gint i = gtk_notebook_page_num (GTK_NOTEBOOK (panel->notebook), viewable);
|
||||
gint i = gtk_notebook_page_num (GTK_NOTEBOOK (panel->notebook),
|
||||
g_object_get_data (G_OBJECT (viewable), "parent"));
|
||||
if (i > -1)
|
||||
gtk_notebook_remove_page (GTK_NOTEBOOK (panel->notebook), i);
|
||||
g_signal_handlers_disconnect_by_func (
|
||||
viewable, midori_panel_viewable_destroy_cb, panel);
|
||||
}
|
||||
|
||||
static void
|
||||
midori_panel_widget_destroy_cb (GtkWidget* viewable,
|
||||
GtkWidget* widget)
|
||||
{
|
||||
gtk_widget_destroy (widget);
|
||||
g_signal_handlers_disconnect_by_func (
|
||||
viewable, midori_panel_widget_destroy_cb, widget);
|
||||
}
|
||||
|
||||
static GtkToolItem*
|
||||
midori_panel_construct_tool_item (MidoriPanel* panel,
|
||||
MidoriViewable* viewable)
|
||||
|
@ -560,6 +576,10 @@ midori_panel_construct_tool_item (MidoriPanel* panel,
|
|||
gtk_toolbar_insert (GTK_TOOLBAR (panel->toolbar), toolitem, -1);
|
||||
g_signal_connect (viewable, "destroy",
|
||||
G_CALLBACK (midori_panel_widget_destroy_cb), toolitem);
|
||||
|
||||
if (gtk_notebook_get_n_pages (GTK_NOTEBOOK (panel->notebook)))
|
||||
gtk_widget_set_sensitive (GTK_WIDGET (panel->button_detach), TRUE);
|
||||
|
||||
return toolitem;
|
||||
}
|
||||
|
||||
|
@ -648,6 +668,7 @@ midori_panel_append_page (MidoriPanel* panel,
|
|||
G_CALLBACK (midori_panel_widget_destroy_cb), menuitem);
|
||||
}
|
||||
|
||||
g_object_set_data (G_OBJECT (viewable), "parent", scrolled);
|
||||
g_signal_connect (viewable, "destroy",
|
||||
G_CALLBACK (midori_panel_viewable_destroy_cb), panel);
|
||||
|
||||
|
|
|
@ -419,89 +419,60 @@ midori_preferences_set_settings (MidoriPreferences* preferences,
|
|||
}
|
||||
FILLED_ADD (hbox, 1, 2, 1, 2);
|
||||
button = katze_property_proxy (settings, "show-crash-dialog", NULL);
|
||||
SPANNED_ADD (button, 0, 2, 2, 3);
|
||||
INDENTED_ADD (button, 0, 1, 2, 3);
|
||||
button = katze_property_proxy (settings, "speed-dial-in-new-tabs", NULL);
|
||||
FILLED_ADD (button, 1, 2, 2, 3);
|
||||
FRAME_NEW (_("Transfers"));
|
||||
TABLE_NEW (4, 2);
|
||||
#if WEBKIT_CHECK_VERSION (1, 1, 3)
|
||||
TABLE_NEW (2, 2);
|
||||
label = katze_property_label (settings, "download-folder");
|
||||
INDENTED_ADD (label, 0, 1, 0, 1);
|
||||
button = katze_property_proxy (settings, "download-folder", "folder");
|
||||
FILLED_ADD (button, 1, 2, 0, 1);
|
||||
#endif
|
||||
label = katze_property_label (settings, "download-manager");
|
||||
label = katze_property_proxy (settings, "ask-for-destination-folder", NULL);
|
||||
gtk_widget_set_sensitive (label, FALSE);
|
||||
INDENTED_ADD (label, 0, 1, 1, 2);
|
||||
hbox = gtk_hbox_new (FALSE, 4);
|
||||
button = gtk_image_new ();
|
||||
gtk_icon_size_lookup_for_settings (gtk_widget_get_settings (button),
|
||||
GTK_ICON_SIZE_MENU, &icon_width, &icon_height);
|
||||
gtk_widget_set_size_request (button, icon_width, icon_height);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 4);
|
||||
entry = katze_property_proxy (settings, "download-manager", NULL);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
|
||||
proxy_download_manager_icon_cb (entry, NULL, GTK_IMAGE (button));
|
||||
g_signal_connect (entry, "focus-out-event",
|
||||
G_CALLBACK (proxy_download_manager_icon_cb), button);
|
||||
FILLED_ADD (hbox, 1, 2, 1, 2);
|
||||
label = katze_property_label (settings, "text-editor");
|
||||
INDENTED_ADD (label, 0, 1, 2, 3);
|
||||
hbox = gtk_hbox_new (FALSE, 4);
|
||||
button = gtk_image_new ();
|
||||
gtk_icon_size_lookup_for_settings (gtk_widget_get_settings (button),
|
||||
GTK_ICON_SIZE_MENU, &icon_width, &icon_height);
|
||||
gtk_widget_set_size_request (button, icon_width, icon_height);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 4);
|
||||
entry = katze_property_proxy (settings, "text-editor", NULL);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
|
||||
proxy_download_manager_icon_cb (entry, NULL, GTK_IMAGE (button));
|
||||
g_signal_connect (entry, "focus-out-event",
|
||||
G_CALLBACK (proxy_download_manager_icon_cb), button);
|
||||
FILLED_ADD (hbox, 1, 2, 2, 3);
|
||||
label = katze_property_label (settings, "news-aggregator");
|
||||
INDENTED_ADD (label, 0, 1, 3, 4);
|
||||
hbox = gtk_hbox_new (FALSE, 4);
|
||||
button = gtk_image_new ();
|
||||
gtk_icon_size_lookup_for_settings (gtk_widget_get_settings (button),
|
||||
GTK_ICON_SIZE_MENU, &icon_width, &icon_height);
|
||||
gtk_widget_set_size_request (button, icon_width, icon_height);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 4);
|
||||
entry = katze_property_proxy (settings, "news-aggregator", NULL);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
|
||||
proxy_download_manager_icon_cb (entry, NULL, GTK_IMAGE (button));
|
||||
g_signal_connect (entry, "focus-out-event",
|
||||
G_CALLBACK (proxy_download_manager_icon_cb), button);
|
||||
FILLED_ADD (hbox, 1, 2, 3, 4);
|
||||
button = katze_property_proxy (settings, "notify-transfer-completed", NULL);
|
||||
/* FIXME: Disable the option if notifications presumably cannot be sent
|
||||
gtk_widget_set_sensitive (button, FALSE); */
|
||||
SPANNED_ADD (button, 1, 2, 1, 2);
|
||||
|
||||
/* Page "Appearance" */
|
||||
PAGE_NEW (GTK_STOCK_SELECT_FONT, _("Appearance"));
|
||||
FRAME_NEW (_("Font settings"));
|
||||
TABLE_NEW (6, 2);
|
||||
TABLE_NEW (7, 2);
|
||||
label = gtk_label_new (_("Default Font Family"));
|
||||
INDENTED_ADD (label, 0, 1, 0, 1);
|
||||
hbox = gtk_hbox_new (FALSE, 4);
|
||||
button = katze_property_proxy (settings, "default-font-family", "font");
|
||||
gtk_widget_set_tooltip_text (button, _("The default font family used to display text"));
|
||||
gtk_box_pack_start (GTK_BOX (hbox), button, TRUE, TRUE, 0);
|
||||
entry = katze_property_proxy (settings, "default-font-size", NULL);
|
||||
gtk_widget_set_tooltip_text (entry, _("The default font size used to display text"));
|
||||
gtk_box_pack_end (GTK_BOX (hbox), entry, FALSE, FALSE, 4);
|
||||
FILLED_ADD (hbox, 1, 2, 0, 1);
|
||||
label = gtk_label_new (_("Minimum Font Size"));
|
||||
label = gtk_label_new (_("Fixed-width Font Family"));
|
||||
INDENTED_ADD (label, 0, 1, 1, 2);
|
||||
button = katze_property_proxy (settings, "monospace-font-family", "font");
|
||||
gtk_widget_set_tooltip_text (button, _("The font family used to display fixed-width text"));
|
||||
INDENTED_ADD (button, 1, 2, 1, 2);
|
||||
label = gtk_label_new (_("Minimum Font Size"));
|
||||
INDENTED_ADD (label, 0, 1, 2, 3);
|
||||
entry = katze_property_proxy (settings, "minimum-font-size", NULL);
|
||||
gtk_widget_set_tooltip_text (entry, _("The minimum font size used to display text"));
|
||||
INDENTED_ADD (entry, 1, 2, 1, 2);
|
||||
INDENTED_ADD (entry, 1, 2, 2, 3);
|
||||
label = katze_property_label (settings, "preferred-encoding");
|
||||
INDENTED_ADD (label, 0, 1, 2, 3);
|
||||
INDENTED_ADD (label, 0, 1, 3, 4);
|
||||
button = katze_property_proxy (settings, "preferred-encoding", NULL);
|
||||
FILLED_ADD (button, 1, 2, 2, 3);
|
||||
FILLED_ADD (button, 1, 2, 3, 4);
|
||||
label = katze_property_label (settings, "default-encoding");
|
||||
gtk_label_set_label (GTK_LABEL (label), _("Encoding"));
|
||||
INDENTED_ADD (label, 0, 1, 3, 4);
|
||||
INDENTED_ADD (label, 0, 1, 4, 5);
|
||||
entry = katze_property_proxy (settings, "default-encoding", NULL);
|
||||
gtk_widget_set_tooltip_text (entry, _("The character encoding to use by default"));
|
||||
g_signal_connect (settings, "notify::preferred-encoding",
|
||||
G_CALLBACK (midori_preferences_notify_preferred_encoding_cb), entry);
|
||||
midori_preferences_notify_preferred_encoding_cb (settings, NULL, entry);
|
||||
FILLED_ADD (entry, 1, 2, 3, 4);
|
||||
FILLED_ADD (entry, 1, 2, 4, 5);
|
||||
|
||||
/* Page "Behavior" */
|
||||
PAGE_NEW (GTK_STOCK_SELECT_COLOR, _("Behavior"));
|
||||
|
@ -528,8 +499,8 @@ midori_preferences_set_settings (MidoriPreferences* preferences,
|
|||
gtk_widget_set_tooltip_text (button, _("Enable embedded scripting languages"));
|
||||
INDENTED_ADD (button, 0, 1, 2, 3);
|
||||
button = katze_property_proxy (settings, "enable-plugins", NULL);
|
||||
gtk_button_set_label (GTK_BUTTON (button), _("Enable plugins"));
|
||||
gtk_widget_set_tooltip_text (button, _("Enable embedded plugin objects"));
|
||||
gtk_button_set_label (GTK_BUTTON (button), _("Enable Netscape plugins"));
|
||||
gtk_widget_set_tooltip_text (button, _("Enable embedded Netscape plugin objects"));
|
||||
SPANNED_ADD (button, 1, 2, 2, 3);
|
||||
button = katze_property_proxy (settings, "enforce-96-dpi", NULL);
|
||||
gtk_button_set_label (GTK_BUTTON (button), _("Enforce 96 dots per inch"));
|
||||
|
@ -543,6 +514,18 @@ midori_preferences_set_settings (MidoriPreferences* preferences,
|
|||
SPANNED_ADD (button, 0, 1, 4, 5);
|
||||
button = katze_property_proxy (settings, "find-while-typing", NULL);
|
||||
SPANNED_ADD (button, 1, 2, 4, 5);
|
||||
#if WEBKIT_CHECK_VERSION (1, 1, 6)
|
||||
FRAME_NEW (_("Spell Checking"));
|
||||
TABLE_NEW (1, 2);
|
||||
button = katze_property_proxy (settings, "enable-spell-checking", NULL);
|
||||
gtk_button_set_label (GTK_BUTTON (button), _("Enable Spell Checking"));
|
||||
gtk_widget_set_tooltip_text (button, _("Enable spell checking while typing"));
|
||||
INDENTED_ADD (button, 0, 1, 0, 1);
|
||||
entry = katze_property_proxy (settings, "spell-checking-languages", NULL);
|
||||
/* i18n: The example should be adjusted to contain a good local default */
|
||||
gtk_widget_set_tooltip_text (entry, _("A comma separated list of languages to be used for spell checking, for example \"en_GB,de_DE\""));
|
||||
FILLED_ADD (entry, 1, 2, 0, 1);
|
||||
#endif
|
||||
|
||||
/* Page "Interface" */
|
||||
PAGE_NEW (GTK_STOCK_CONVERT, _("Interface"));
|
||||
|
@ -586,6 +569,53 @@ midori_preferences_set_settings (MidoriPreferences* preferences,
|
|||
button = katze_property_proxy (settings, "close-buttons-on-tabs", NULL);
|
||||
WIDGET_ADD (button, 1, 2, 5, 6);
|
||||
|
||||
/* Page "Applications" */
|
||||
PAGE_NEW (GTK_STOCK_CONVERT, _("Applications"));
|
||||
FRAME_NEW (_("External applications"));
|
||||
TABLE_NEW (3, 2);
|
||||
label = katze_property_label (settings, "text-editor");
|
||||
INDENTED_ADD (label, 0, 1, 0, 1);
|
||||
hbox = gtk_hbox_new (FALSE, 4);
|
||||
button = gtk_image_new ();
|
||||
gtk_icon_size_lookup_for_settings (gtk_widget_get_settings (button),
|
||||
GTK_ICON_SIZE_MENU, &icon_width, &icon_height);
|
||||
gtk_widget_set_size_request (button, icon_width, icon_height);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 4);
|
||||
entry = katze_property_proxy (settings, "text-editor", NULL);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
|
||||
proxy_download_manager_icon_cb (entry, NULL, GTK_IMAGE (button));
|
||||
g_signal_connect (entry, "focus-out-event",
|
||||
G_CALLBACK (proxy_download_manager_icon_cb), button);
|
||||
FILLED_ADD (hbox, 1, 2, 0, 1);
|
||||
label = katze_property_label (settings, "download-manager");
|
||||
INDENTED_ADD (label, 0, 1, 1, 2);
|
||||
hbox = gtk_hbox_new (FALSE, 4);
|
||||
button = gtk_image_new ();
|
||||
gtk_icon_size_lookup_for_settings (gtk_widget_get_settings (button),
|
||||
GTK_ICON_SIZE_MENU, &icon_width, &icon_height);
|
||||
gtk_widget_set_size_request (button, icon_width, icon_height);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 4);
|
||||
entry = katze_property_proxy (settings, "download-manager", NULL);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
|
||||
proxy_download_manager_icon_cb (entry, NULL, GTK_IMAGE (button));
|
||||
g_signal_connect (entry, "focus-out-event",
|
||||
G_CALLBACK (proxy_download_manager_icon_cb), button);
|
||||
FILLED_ADD (hbox, 1, 2, 1, 2);
|
||||
label = katze_property_label (settings, "news-aggregator");
|
||||
INDENTED_ADD (label, 0, 1, 2, 3);
|
||||
hbox = gtk_hbox_new (FALSE, 4);
|
||||
button = gtk_image_new ();
|
||||
gtk_icon_size_lookup_for_settings (gtk_widget_get_settings (button),
|
||||
GTK_ICON_SIZE_MENU, &icon_width, &icon_height);
|
||||
gtk_widget_set_size_request (button, icon_width, icon_height);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 4);
|
||||
entry = katze_property_proxy (settings, "news-aggregator", NULL);
|
||||
gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
|
||||
proxy_download_manager_icon_cb (entry, NULL, GTK_IMAGE (button));
|
||||
g_signal_connect (entry, "focus-out-event",
|
||||
G_CALLBACK (proxy_download_manager_icon_cb), button);
|
||||
FILLED_ADD (hbox, 1, 2, 2, 3);
|
||||
|
||||
/* Page "Network" */
|
||||
PAGE_NEW (GTK_STOCK_NETWORK, _("Network"));
|
||||
FRAME_NEW (_("Network"));
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
Copyright (C) 2007-2009 Christian Dywan <christian@twotoasts.de>
|
||||
Copyright (C) 2009 Jean-François Guchens <zcx000@gmail.com>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -23,27 +24,27 @@
|
|||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <glib/gi18n.h>
|
||||
#include <glib/gprintf.h>
|
||||
#include <glib/gstdio.h>
|
||||
#include <webkit/webkit.h>
|
||||
|
||||
#if GLIB_CHECK_VERSION (2, 18, 0)
|
||||
#define D_(__domain, __message) g_dgettext (__domain, __message)
|
||||
#elif ENABLE_NLS
|
||||
#define D_(__domain, __message) dgettext (__domain, __message)
|
||||
#else
|
||||
#define D_(__domain, __message) __message
|
||||
#endif
|
||||
|
||||
/* This is unstable API, so we need to declare it */
|
||||
gchar*
|
||||
webkit_web_view_get_selected_text (WebKitWebView* web_view);
|
||||
/* This is public API since WebKitGTK+ 1.1.6 */
|
||||
#if !WEBKIT_CHECK_VERSION (1, 1, 6)
|
||||
void
|
||||
webkit_web_frame_print (WebKitWebFrame* web_frame);
|
||||
#endif
|
||||
|
||||
GdkPixbuf*
|
||||
midori_search_action_get_icon (KatzeNet* net,
|
||||
KatzeItem* item,
|
||||
GtkWidget* widget);
|
||||
|
||||
static void
|
||||
midori_view_construct_web_view (MidoriView* view);
|
||||
|
||||
struct _MidoriView
|
||||
{
|
||||
GtkScrolledWindow parent_instance;
|
||||
|
@ -60,8 +61,9 @@ struct _MidoriView
|
|||
gchar* selected_text;
|
||||
MidoriWebSettings* settings;
|
||||
GtkWidget* web_view;
|
||||
/* KatzeArray* news_feeds; */
|
||||
KatzeArray* news_feeds;
|
||||
|
||||
gboolean speed_dial_in_new_tabs;
|
||||
gchar* download_manager;
|
||||
gchar* news_aggregator;
|
||||
gboolean middle_click_opens_selection;
|
||||
|
@ -135,7 +137,7 @@ enum
|
|||
PROP_LOAD_STATUS,
|
||||
PROP_PROGRESS,
|
||||
PROP_ZOOM_LEVEL,
|
||||
/* PROP_NEWS_FEEDS, */
|
||||
PROP_NEWS_FEEDS,
|
||||
PROP_STATUSBAR_TEXT,
|
||||
PROP_SETTINGS,
|
||||
PROP_NET
|
||||
|
@ -153,6 +155,7 @@ enum {
|
|||
SEARCH_TEXT,
|
||||
ADD_BOOKMARK,
|
||||
SAVE_AS,
|
||||
ADD_SPEED_DIAL,
|
||||
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
@ -179,6 +182,16 @@ midori_view_settings_notify_cb (MidoriWebSettings* settings,
|
|||
GParamSpec* pspec,
|
||||
MidoriView* view);
|
||||
|
||||
static void
|
||||
midori_view_speed_dial_get_thumb (GtkWidget* web_view,
|
||||
const gchar* message,
|
||||
MidoriView* view);
|
||||
|
||||
static void
|
||||
midori_view_speed_dial_save (GtkWidget* web_view,
|
||||
const gchar* message);
|
||||
|
||||
|
||||
static void
|
||||
midori_view_class_init (MidoriViewClass* class)
|
||||
{
|
||||
|
@ -354,6 +367,26 @@ midori_view_class_init (MidoriViewClass* class)
|
|||
G_TYPE_NONE, 1,
|
||||
G_TYPE_STRING);
|
||||
|
||||
/**
|
||||
* MidoriView::add-speed-dial:
|
||||
* @view: the object on which the signal is emitted
|
||||
* @uri: the URI to add to the speed dial
|
||||
*
|
||||
* Emitted when an URI is added to the spee dial page.
|
||||
*
|
||||
* Since: 0.1.7
|
||||
*/
|
||||
signals[ADD_SPEED_DIAL] = g_signal_new (
|
||||
"add-speed-dial",
|
||||
G_TYPE_FROM_CLASS (class),
|
||||
(GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
g_cclosure_marshal_VOID__STRING,
|
||||
G_TYPE_NONE, 1,
|
||||
G_TYPE_STRING);
|
||||
|
||||
gobject_class = G_OBJECT_CLASS (class);
|
||||
gobject_class->finalize = midori_view_finalize;
|
||||
gobject_class->set_property = midori_view_set_property;
|
||||
|
@ -434,14 +467,21 @@ midori_view_class_init (MidoriViewClass* class)
|
|||
1.0f,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
/* g_object_class_install_property (gobject_class,
|
||||
/**
|
||||
* MidoriView:news-feeds:
|
||||
*
|
||||
* The news feeds advertised by the currently loaded page.
|
||||
*
|
||||
* Since: 0.1.7
|
||||
*/
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_NEWS_FEEDS,
|
||||
g_param_spec_object (
|
||||
"news-feeds",
|
||||
"News Feeds",
|
||||
"The list of available news feeds",
|
||||
KATZE_TYPE_ARRAY,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); */
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_STATUSBAR_TEXT,
|
||||
|
@ -471,6 +511,52 @@ midori_view_class_init (MidoriViewClass* class)
|
|||
flags));
|
||||
}
|
||||
|
||||
static void
|
||||
midori_view_update_title (MidoriView* view)
|
||||
{
|
||||
/* If left-to-right text is combined with right-to-left text the default
|
||||
behaviour of Pango can result in awkwardly aligned text. For example
|
||||
"بستيان نوصر (hadess) | An era comes to an end - Midori" becomes
|
||||
"hadess) | An era comes to an end - Midori) بستيان نوصر". So to prevent
|
||||
this we insert an LRE character before the title which indicates that
|
||||
we want left-to-right but retains the direction of right-to-left text. */
|
||||
if (view->title && !g_str_has_prefix (view->title, ""))
|
||||
{
|
||||
gchar* new_title = g_strconcat ("", view->title, NULL);
|
||||
katze_assign (view->title, new_title);
|
||||
}
|
||||
#define title midori_view_get_display_title (view)
|
||||
if (view->tab_label)
|
||||
{
|
||||
/* If the title starts with the presumed name of the website, we
|
||||
ellipsize differently, to emphasize the subtitle */
|
||||
if (gtk_label_get_angle (GTK_LABEL (view->tab_title)) == 0.0)
|
||||
{
|
||||
SoupURI* uri = soup_uri_new (view->uri);
|
||||
const gchar* host = uri ? (uri->host ? uri->host : "") : "";
|
||||
const gchar* name = g_str_has_prefix (host, "www.") ? &host[4] : host;
|
||||
guint i = 0;
|
||||
while (name[i++])
|
||||
if (name[i] == '.')
|
||||
break;
|
||||
if (!g_ascii_strncasecmp (title, name, i))
|
||||
gtk_label_set_ellipsize (GTK_LABEL (view->tab_title), PANGO_ELLIPSIZE_START);
|
||||
else
|
||||
gtk_label_set_ellipsize (GTK_LABEL (view->tab_title), PANGO_ELLIPSIZE_END);
|
||||
if (uri)
|
||||
soup_uri_free (uri);
|
||||
}
|
||||
gtk_label_set_text (GTK_LABEL (view->tab_title), title);
|
||||
gtk_widget_set_tooltip_text (view->tab_title, title);
|
||||
}
|
||||
if (view->menu_item)
|
||||
gtk_label_set_text (GTK_LABEL (gtk_bin_get_child (GTK_BIN (
|
||||
view->menu_item))), title);
|
||||
if (view->item)
|
||||
katze_item_set_name (view->item, title);
|
||||
#undef title
|
||||
}
|
||||
|
||||
static GdkPixbuf*
|
||||
midori_view_mime_icon (GtkIconTheme* icon_theme,
|
||||
const gchar* format,
|
||||
|
@ -502,7 +588,10 @@ midori_view_update_icon (MidoriView* view,
|
|||
{
|
||||
icon_theme = gtk_icon_theme_get_for_screen (screen);
|
||||
if ((parts = g_strsplit (view->mime_type, "/", 2)))
|
||||
parts = (parts[0] && parts[1]) ? parts : NULL;
|
||||
{
|
||||
if (!(parts[0] && parts[1]))
|
||||
katze_assign (parts, NULL);
|
||||
}
|
||||
}
|
||||
else
|
||||
parts = NULL;
|
||||
|
@ -623,6 +712,55 @@ webkit_web_view_progress_changed_cb (WebKitWebView* web_view,
|
|||
g_object_notify (G_OBJECT (view), "progress");
|
||||
}
|
||||
|
||||
#if WEBKIT_CHECK_VERSION (1, 1, 6)
|
||||
static gboolean
|
||||
webkit_web_view_load_error_cb (WebKitWebView* web_view,
|
||||
WebKitWebFrame* web_frame,
|
||||
const gchar* uri,
|
||||
GError* error,
|
||||
MidoriView* view)
|
||||
{
|
||||
const gchar* template_file = DATADIR "/midori/res/error.html";
|
||||
gchar* template;
|
||||
|
||||
if (g_file_get_contents (template_file, &template, NULL, NULL))
|
||||
{
|
||||
SoupServer* res_server;
|
||||
guint port;
|
||||
gchar* res_root;
|
||||
gchar* stock_root;
|
||||
gchar* message;
|
||||
gchar* result;
|
||||
|
||||
res_server = sokoke_get_res_server ();
|
||||
port = soup_server_get_port (res_server);
|
||||
res_root = g_strdup_printf ("http://localhost:%d/res", port);
|
||||
stock_root = g_strdup_printf ("http://localhost:%d/stock", port);
|
||||
|
||||
message = g_strdup_printf (_("The page '%s' couldn't be loaded."), uri);
|
||||
result = sokoke_replace_variables (template,
|
||||
"{title}", _("Error"),
|
||||
"{message}", message,
|
||||
"{description}", error->message,
|
||||
"{tryagain}", _("Try again"),
|
||||
"{res}", res_root,
|
||||
"{stock}", stock_root,
|
||||
NULL);
|
||||
g_free (template);
|
||||
g_free (message);
|
||||
|
||||
webkit_web_frame_load_alternate_string (web_frame,
|
||||
result, res_root, uri);
|
||||
g_free (res_root);
|
||||
g_free (stock_root);
|
||||
g_free (result);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
#else
|
||||
static void
|
||||
webkit_web_frame_load_done_cb (WebKitWebFrame* web_frame,
|
||||
gboolean success,
|
||||
|
@ -653,6 +791,7 @@ webkit_web_frame_load_done_cb (WebKitWebFrame* web_frame,
|
|||
|
||||
midori_view_update_load_status (view, MIDORI_LOAD_FINISHED);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
webkit_web_view_load_finished_cb (WebKitWebView* web_view,
|
||||
|
@ -668,14 +807,34 @@ webkit_web_view_load_finished_cb (WebKitWebView* web_view,
|
|||
if (view->news_aggregator && *view->news_aggregator)
|
||||
{
|
||||
JSContextRef js_context = webkit_web_frame_get_global_context (web_frame);
|
||||
/* This snippet joins the available news feeds into a string like this:
|
||||
URI1|title1,URI2|title2
|
||||
FIXME: Ensure separators contained in the string can't break it */
|
||||
gchar* value = sokoke_js_script_eval (js_context,
|
||||
"function feeds (l) { var f = new Array (); for (i in l) "
|
||||
"{ var t = l[i].type; "
|
||||
"if (t && (t.indexOf ('rss') != -1 || t.indexOf ('atom') != -1)) "
|
||||
"f.push (l[i].href); } return f; }"
|
||||
"f.push (l[i].href + '|' + l[i].title); } return f; }"
|
||||
"feeds (document.getElementsByTagName ('link'))", NULL);
|
||||
gchar** items = g_strsplit (value, ",", 0);
|
||||
gchar** iter;
|
||||
|
||||
katze_array_clear (view->news_feeds);
|
||||
for (iter = items; iter && *iter; iter++)
|
||||
{
|
||||
gchar** parts = g_strsplit (*iter, "|", 2);
|
||||
KatzeItem* item = g_object_new (KATZE_TYPE_ITEM,
|
||||
"uri", parts ? *parts : "",
|
||||
"name", parts && *parts ? parts[1] : NULL,
|
||||
NULL);
|
||||
katze_array_add_item (view->news_feeds, item);
|
||||
g_object_unref (item);
|
||||
g_strfreev (parts);
|
||||
}
|
||||
g_strfreev (items);
|
||||
g_object_set_data (G_OBJECT (view), "news-feeds",
|
||||
value && *value ? (void*)1 : (void*)0);
|
||||
g_free (value);
|
||||
/* Ensure load-status is notified again, whether it changed or not */
|
||||
g_object_notify (G_OBJECT (view), "load-status");
|
||||
}
|
||||
|
@ -683,6 +842,26 @@ webkit_web_view_load_finished_cb (WebKitWebView* web_view,
|
|||
g_object_thaw_notify (G_OBJECT (view));
|
||||
}
|
||||
|
||||
#if WEBKIT_CHECK_VERSION (1, 1, 4)
|
||||
static void
|
||||
webkit_web_view_notify_uri_cb (WebKitWebView* web_view,
|
||||
GParamSpec* pspec,
|
||||
MidoriView* view)
|
||||
{
|
||||
g_object_get (web_view, "uri", &view->uri, NULL);
|
||||
g_object_notify (G_OBJECT (view), "uri");
|
||||
}
|
||||
|
||||
static void
|
||||
webkit_web_view_notify_title_cb (WebKitWebView* web_view,
|
||||
GParamSpec* pspec,
|
||||
MidoriView* view)
|
||||
{
|
||||
g_object_get (web_view, "title", &view->title, NULL);
|
||||
midori_view_update_title (view);
|
||||
g_object_notify (G_OBJECT (view), "title");
|
||||
}
|
||||
#else
|
||||
static void
|
||||
webkit_web_view_title_changed_cb (WebKitWebView* web_view,
|
||||
WebKitWebFrame* web_frame,
|
||||
|
@ -691,6 +870,7 @@ webkit_web_view_title_changed_cb (WebKitWebView* web_view,
|
|||
{
|
||||
g_object_set (view, "title", title, NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
webkit_web_view_statusbar_text_changed_cb (WebKitWebView* web_view,
|
||||
|
@ -814,6 +994,17 @@ gtk_widget_button_press_event_cb (WebKitWebView* web_view,
|
|||
case 9:
|
||||
midori_view_go_forward (view);
|
||||
return TRUE;
|
||||
/*
|
||||
* On some fancier mice the scroll wheel can be used to scroll horizontally.
|
||||
* A middle click usually registers both a middle click (2) and a
|
||||
* horizontal scroll (11 or 12).
|
||||
* We catch horizontal scrolls and ignore them to prevent middle clicks from
|
||||
* accidentally being interpreted as first button clicks.
|
||||
*/
|
||||
case 11:
|
||||
return TRUE;
|
||||
case 12:
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
|
@ -829,10 +1020,15 @@ gtk_widget_key_press_event_cb (WebKitWebView* web_view,
|
|||
if (character == (event->keyval | 0x01000000))
|
||||
return FALSE;
|
||||
|
||||
if (view->find_while_typing && !webkit_web_view_can_cut_clipboard (web_view)
|
||||
if (character == '.' || character == '/')
|
||||
character = '\0';
|
||||
else if (!view->find_while_typing)
|
||||
return FALSE;
|
||||
|
||||
if (!webkit_web_view_can_cut_clipboard (web_view)
|
||||
&& !webkit_web_view_can_paste_clipboard (web_view))
|
||||
{
|
||||
gchar* text = g_strdup_printf ("%c", character);
|
||||
gchar* text = character ? g_strdup_printf ("%c", character) : g_strdup ("");
|
||||
|
||||
g_signal_emit (view, signals[SEARCH_TEXT], 0, TRUE, text);
|
||||
g_free (text);
|
||||
|
@ -875,10 +1071,10 @@ midori_web_view_menu_new_tab_activate_cb (GtkWidget* widget,
|
|||
}
|
||||
|
||||
static void
|
||||
midori_web_view_menu_new_window_activate_cb (GtkWidget* widget,
|
||||
midori_web_view_menu_action_add_speed_dial_cb (GtkWidget* widget,
|
||||
MidoriView* view)
|
||||
{
|
||||
g_signal_emit (view, signals[NEW_WINDOW], 0, view->link_uri);
|
||||
g_signal_emit (view, signals[ADD_SPEED_DIAL], 0, view->link_uri);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -893,10 +1089,7 @@ midori_web_view_menu_search_web_activate_cb (GtkWidget* widget,
|
|||
else
|
||||
g_object_get (view->settings, "location-entry-search",
|
||||
&search, NULL);
|
||||
if (strstr (search, "%s"))
|
||||
uri = g_strdup_printf (search, view->selected_text);
|
||||
else
|
||||
uri = g_strconcat (search, view->selected_text, NULL);
|
||||
uri = sokoke_search_uri (search, view->selected_text);
|
||||
g_free (search);
|
||||
|
||||
g_signal_emit (view, signals[NEW_TAB], 0, uri,
|
||||
|
@ -918,7 +1111,7 @@ static void
|
|||
midori_web_view_menu_download_activate_cb (GtkWidget* widget,
|
||||
MidoriView* view)
|
||||
{
|
||||
sokoke_spawn_program (view->download_manager, view->link_uri);
|
||||
sokoke_spawn_program (view->download_manager, view->link_uri, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -993,9 +1186,6 @@ webkit_web_view_populate_popup_cb (WebKitWebView* web_view,
|
|||
/* hack to localize menu item */
|
||||
label = gtk_bin_get_child (GTK_BIN (menuitem));
|
||||
gtk_label_set_label (GTK_LABEL (label), _("Open Link in New _Window"));
|
||||
/* hack to implement New Window */
|
||||
g_signal_connect (menuitem, "activate",
|
||||
G_CALLBACK (midori_web_view_menu_new_window_activate_cb), view);
|
||||
menuitem = (GtkWidget*)g_list_nth_data (items, 3);
|
||||
g_list_free (items);
|
||||
#if WEBKIT_CHECK_VERSION (1, 1, 3)
|
||||
|
@ -1102,9 +1292,13 @@ webkit_web_view_populate_popup_cb (WebKitWebView* web_view,
|
|||
menuitem = (GtkWidget*)g_list_nth_data (items, 3);
|
||||
/* hack to localize menu item */
|
||||
if (GTK_IS_BIN (menuitem))
|
||||
{
|
||||
GtkStockItem stock_item;
|
||||
if (gtk_stock_lookup (GTK_STOCK_REFRESH, &stock_item))
|
||||
{
|
||||
label = gtk_bin_get_child (GTK_BIN (menuitem));
|
||||
gtk_label_set_label (GTK_LABEL (label), D_("gtk20", "_Refresh"));
|
||||
gtk_label_set_label (GTK_LABEL (label), stock_item.label);
|
||||
}
|
||||
}
|
||||
g_list_free (items);
|
||||
menuitem = gtk_image_menu_item_new_with_mnemonic (_("Undo Close Tab"));
|
||||
|
@ -1116,15 +1310,28 @@ webkit_web_view_populate_popup_cb (WebKitWebView* web_view,
|
|||
G_CALLBACK (midori_web_view_menu_action_activate_cb), view);
|
||||
/* FIXME: Make this sensitive only when there is a tab to undo */
|
||||
gtk_widget_show (menuitem);
|
||||
|
||||
menuitem = gtk_separator_menu_item_new ();
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
|
||||
gtk_widget_show (menuitem);
|
||||
|
||||
menuitem = gtk_image_menu_item_new_from_stock (STOCK_BOOKMARK_ADD, NULL);
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
|
||||
g_object_set_data (G_OBJECT (menuitem), "action", "BookmarkAdd");
|
||||
g_signal_connect (menuitem, "activate",
|
||||
G_CALLBACK (midori_web_view_menu_action_activate_cb), view);
|
||||
gtk_widget_show (menuitem);
|
||||
|
||||
if (view->speed_dial_in_new_tabs && !midori_view_is_blank (view))
|
||||
{
|
||||
menuitem = gtk_image_menu_item_new_with_mnemonic (_("Add to Speed _dial"));
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
|
||||
g_object_set_data (G_OBJECT (menuitem), "action", "AddSpeedDial");
|
||||
g_signal_connect (menuitem, "activate",
|
||||
G_CALLBACK (midori_web_view_menu_action_add_speed_dial_cb), view);
|
||||
gtk_widget_show (menuitem);
|
||||
}
|
||||
|
||||
menuitem = gtk_image_menu_item_new_from_stock (GTK_STOCK_SAVE_AS, NULL);
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
|
||||
g_object_set_data (G_OBJECT (menuitem), "action", "SaveAs");
|
||||
|
@ -1135,6 +1342,7 @@ webkit_web_view_populate_popup_cb (WebKitWebView* web_view,
|
|||
saving either. If that changes, we need to think of something. */
|
||||
if (!midori_view_can_view_source (view))
|
||||
gtk_widget_set_sensitive (menuitem, FALSE);
|
||||
|
||||
menuitem = gtk_image_menu_item_new_with_mnemonic (_("View _Source"));
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
|
||||
g_object_set_data (G_OBJECT (menuitem), "action", "SourceView");
|
||||
|
@ -1143,6 +1351,7 @@ webkit_web_view_populate_popup_cb (WebKitWebView* web_view,
|
|||
gtk_widget_show (menuitem);
|
||||
if (!midori_view_can_view_source (view))
|
||||
gtk_widget_set_sensitive (menuitem, FALSE);
|
||||
|
||||
menuitem = gtk_image_menu_item_new_from_stock (GTK_STOCK_PRINT, NULL);
|
||||
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
|
||||
g_object_set_data (G_OBJECT (menuitem), "action", "Print");
|
||||
|
@ -1187,7 +1396,7 @@ webkit_web_view_create_web_view_cb (GtkWidget* web_view,
|
|||
"net", view->net,
|
||||
"settings", view->settings,
|
||||
NULL);
|
||||
midori_view_set_uri (MIDORI_VIEW (new_view), "");
|
||||
midori_view_construct_web_view (MIDORI_VIEW (new_view));
|
||||
g_signal_connect (MIDORI_VIEW (new_view)->web_view, "web-view-ready",
|
||||
G_CALLBACK (webkit_web_view_web_view_ready_cb), view);
|
||||
return MIDORI_VIEW (new_view)->web_view;
|
||||
|
@ -1322,14 +1531,20 @@ webkit_web_view_download_requested_cb (GtkWidget* web_view,
|
|||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
static gboolean
|
||||
webkit_web_view_console_message_cb (GtkWidget* web_view,
|
||||
const gchar* message,
|
||||
guint line,
|
||||
const gchar* source_id,
|
||||
MidoriView* view)
|
||||
{
|
||||
if (!strncmp (message, "speed_dial-get-thumbnail", 22))
|
||||
midori_view_speed_dial_get_thumb (web_view, message, view);
|
||||
else if (!strncmp (message, "speed_dial-save", 13))
|
||||
midori_view_speed_dial_save (web_view, message);
|
||||
else
|
||||
g_signal_emit (view, signals[CONSOLE_MESSAGE], 0, message, line, source_id);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1355,6 +1570,8 @@ midori_view_init (MidoriView* view)
|
|||
view->statusbar_text = NULL;
|
||||
view->link_uri = NULL;
|
||||
view->selected_text = NULL;
|
||||
view->news_feeds = katze_array_new (KATZE_TYPE_ITEM);
|
||||
|
||||
view->item = NULL;
|
||||
|
||||
view->download_manager = NULL;
|
||||
|
@ -1382,6 +1599,7 @@ midori_view_finalize (GObject* object)
|
|||
katze_assign (view->statusbar_text, NULL);
|
||||
katze_assign (view->link_uri, NULL);
|
||||
katze_assign (view->selected_text, NULL);
|
||||
katze_object_assign (view->news_feeds, NULL);
|
||||
|
||||
katze_object_assign (view->settings, NULL);
|
||||
katze_object_assign (view->item, NULL);
|
||||
|
@ -1408,18 +1626,7 @@ midori_view_set_property (GObject* object,
|
|||
{
|
||||
case PROP_TITLE:
|
||||
katze_assign (view->title, g_value_dup_string (value));
|
||||
#define title midori_view_get_display_title (view)
|
||||
if (view->tab_label)
|
||||
{
|
||||
gtk_label_set_text (GTK_LABEL (view->tab_title), title);
|
||||
gtk_widget_set_tooltip_text (view->tab_title, title);
|
||||
}
|
||||
if (view->menu_item)
|
||||
gtk_label_set_text (GTK_LABEL (gtk_bin_get_child (GTK_BIN (
|
||||
view->menu_item))), title);
|
||||
if (view->item)
|
||||
katze_item_set_name (view->item, title);
|
||||
#undef title
|
||||
midori_view_update_title (view);
|
||||
break;
|
||||
case PROP_ZOOM_LEVEL:
|
||||
midori_view_set_zoom_level (view, g_value_get_float (value));
|
||||
|
@ -1472,6 +1679,9 @@ midori_view_get_property (GObject* object,
|
|||
case PROP_ZOOM_LEVEL:
|
||||
g_value_set_float (value, midori_view_get_zoom_level (view));
|
||||
break;
|
||||
case PROP_NEWS_FEEDS:
|
||||
g_value_set_object (value, view->news_feeds);
|
||||
break;
|
||||
case PROP_STATUSBAR_TEXT:
|
||||
g_value_set_string (value, view->statusbar_text);
|
||||
break;
|
||||
|
@ -1509,6 +1719,7 @@ _midori_view_update_settings (MidoriView* view)
|
|||
gboolean zoom_text_and_images;
|
||||
|
||||
g_object_get (view->settings,
|
||||
"speed-dial-in-new-tabs", &view->speed_dial_in_new_tabs,
|
||||
"download-manager", &view->download_manager,
|
||||
"news-aggregator", &view->news_aggregator,
|
||||
"zoom-text-and-images", &zoom_text_and_images,
|
||||
|
@ -1536,7 +1747,11 @@ midori_view_settings_notify_cb (MidoriWebSettings* settings,
|
|||
g_value_init (&value, pspec->value_type);
|
||||
g_object_get_property (G_OBJECT (view->settings), name, &value);
|
||||
|
||||
if (name == g_intern_string ("download-manager"))
|
||||
if (name == g_intern_string ("speed-dial-in-new-tabs"))
|
||||
{
|
||||
view->speed_dial_in_new_tabs = g_value_get_boolean (&value);
|
||||
}
|
||||
else if (name == g_intern_string ("download-manager"))
|
||||
{
|
||||
katze_assign (view->download_manager, g_value_dup_string (&value));
|
||||
}
|
||||
|
@ -1710,6 +1925,8 @@ midori_view_construct_web_view (MidoriView* view)
|
|||
WebKitWebFrame* web_frame;
|
||||
gpointer inspector;
|
||||
|
||||
g_return_if_fail (!view->web_view);
|
||||
|
||||
view->web_view = webkit_web_view_new ();
|
||||
|
||||
/* Load something to avoid a bug where WebKit might not set a main frame */
|
||||
|
@ -1725,15 +1942,22 @@ midori_view_construct_web_view (MidoriView* view)
|
|||
webkit_web_view_progress_changed_cb, view,
|
||||
"signal::load-finished",
|
||||
webkit_web_view_load_finished_cb, view,
|
||||
#if WEBKIT_CHECK_VERSION (1, 1, 4)
|
||||
"signal::notify::uri",
|
||||
webkit_web_view_notify_uri_cb, view,
|
||||
"signal::notify::title",
|
||||
webkit_web_view_notify_title_cb, view,
|
||||
#else
|
||||
"signal::title-changed",
|
||||
webkit_web_view_title_changed_cb, view,
|
||||
#endif
|
||||
"signal::status-bar-text-changed",
|
||||
webkit_web_view_statusbar_text_changed_cb, view,
|
||||
"signal::hovering-over-link",
|
||||
webkit_web_view_hovering_over_link_cb, view,
|
||||
"signal::button-press-event",
|
||||
gtk_widget_button_press_event_cb, view,
|
||||
"signal::key-press-event",
|
||||
"signal-after::key-press-event",
|
||||
gtk_widget_key_press_event_cb, view,
|
||||
"signal::scroll-event",
|
||||
gtk_widget_scroll_event_cb, view,
|
||||
|
@ -1751,12 +1975,18 @@ midori_view_construct_web_view (MidoriView* view)
|
|||
"signal::download-requested",
|
||||
webkit_web_view_download_requested_cb, view,
|
||||
#endif
|
||||
#if WEBKIT_CHECK_VERSION (1, 1, 6)
|
||||
"signal::load-error",
|
||||
webkit_web_view_load_error_cb, view,
|
||||
#endif
|
||||
NULL);
|
||||
|
||||
#if !WEBKIT_CHECK_VERSION (1, 1, 6)
|
||||
g_object_connect (web_frame,
|
||||
"signal::load-done",
|
||||
webkit_web_frame_load_done_cb, view,
|
||||
NULL);
|
||||
#endif
|
||||
|
||||
if (view->settings)
|
||||
{
|
||||
|
@ -1787,17 +2017,81 @@ midori_view_set_uri (MidoriView* view,
|
|||
|
||||
g_return_if_fail (MIDORI_IS_VIEW (view));
|
||||
|
||||
/* Treat "about:blank" and "" equally, see midori_view_is_blank(). */
|
||||
if (!g_strcmp0 (uri, "about:blank")) uri = "";
|
||||
if (!uri) uri = "";
|
||||
|
||||
if (1)
|
||||
{
|
||||
if (!view->web_view)
|
||||
midori_view_construct_web_view (view);
|
||||
|
||||
if (view->speed_dial_in_new_tabs && !g_strcmp0 (uri, ""))
|
||||
{
|
||||
SoupServer* res_server;
|
||||
guint port;
|
||||
gchar* res_root;
|
||||
gchar* speed_dial_head;
|
||||
gchar* speed_dial_body;
|
||||
gchar* body_fname;
|
||||
gchar* stock_root;
|
||||
|
||||
katze_assign (view->uri, g_strdup (""));
|
||||
|
||||
g_file_get_contents (DATADIR "/midori/res/speeddial-head.html",
|
||||
&speed_dial_head, NULL, NULL);
|
||||
|
||||
res_server = sokoke_get_res_server ();
|
||||
port = soup_server_get_port (res_server);
|
||||
res_root = g_strdup_printf ("http://localhost:%d/res", port);
|
||||
stock_root = g_strdup_printf ("http://localhost:%d/stock", port);
|
||||
body_fname = g_build_filename (sokoke_set_config_dir (NULL),
|
||||
"speeddial.json", NULL);
|
||||
|
||||
if (!g_file_test (body_fname, G_FILE_TEST_EXISTS))
|
||||
{
|
||||
if (g_file_get_contents (DATADIR "/midori/res/speeddial.json",
|
||||
&speed_dial_body, NULL, NULL))
|
||||
g_file_set_contents (body_fname, speed_dial_body, -1, NULL);
|
||||
else
|
||||
speed_dial_body = g_strdup ("");
|
||||
}
|
||||
else
|
||||
g_file_get_contents (body_fname, &speed_dial_body, NULL, NULL);
|
||||
|
||||
data = sokoke_replace_variables (speed_dial_head,
|
||||
"{res}", res_root,
|
||||
"{stock}", stock_root,
|
||||
"{json_data}", speed_dial_body,
|
||||
"{title}", _("Speed dial"),
|
||||
"{click_to_add}", _("Click to add a shortcut"),
|
||||
"{enter_shortcut_address}", _("Enter shortcut address"),
|
||||
"{enter_shortcut_name}", _("Enter shortcut title"),
|
||||
"{are_you_sure}", _("Are you sure you want to delete this shortcut?"), NULL);
|
||||
|
||||
|
||||
#if WEBKIT_CHECK_VERSION (1, 1, 6)
|
||||
webkit_web_frame_load_alternate_string (
|
||||
webkit_web_view_get_main_frame (WEBKIT_WEB_VIEW (view->web_view)),
|
||||
data, res_root, "about:blank");
|
||||
#else
|
||||
webkit_web_view_load_html_string (
|
||||
WEBKIT_WEB_VIEW (view->web_view), data, res_root);
|
||||
#endif
|
||||
|
||||
g_free (res_root);
|
||||
g_free (stock_root);
|
||||
g_free (data);
|
||||
g_free (speed_dial_head);
|
||||
g_free (speed_dial_body);
|
||||
g_free (body_fname);
|
||||
}
|
||||
/* This is not prefectly elegant, but creating an
|
||||
error page inline is the simplest solution. */
|
||||
if (g_str_has_prefix (uri, "error:"))
|
||||
else if (g_str_has_prefix (uri, "error:"))
|
||||
{
|
||||
data = NULL;
|
||||
#if !WEBKIT_CHECK_VERSION (1, 1, 3)
|
||||
if (!strncmp (uri, "error:nodisplay ", 16))
|
||||
{
|
||||
gchar* title;
|
||||
|
@ -1814,7 +2108,8 @@ midori_view_set_uri (MidoriView* view,
|
|||
title, title, view->uri, view->mime_type);
|
||||
g_free (title);
|
||||
}
|
||||
else if (!strncmp (uri, "error:nodocs ", 13))
|
||||
#endif
|
||||
if (!strncmp (uri, "error:nodocs ", 13))
|
||||
{
|
||||
gchar* title;
|
||||
|
||||
|
@ -1850,13 +2145,7 @@ midori_view_set_uri (MidoriView* view,
|
|||
}
|
||||
else if (g_str_has_prefix (uri, "mailto:"))
|
||||
{
|
||||
if (!gtk_show_uri (NULL, uri, GDK_CURRENT_TIME, NULL))
|
||||
{
|
||||
/* Fallback to Exo for example if GConf isn't setup */
|
||||
gchar* command = g_strconcat ("exo-open ", uri, NULL);
|
||||
g_spawn_command_line_async (command, NULL);
|
||||
g_free (command);
|
||||
}
|
||||
sokoke_show_uri (NULL, uri, GDK_CURRENT_TIME, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1945,11 +2234,10 @@ midori_view_get_display_title (MidoriView* view)
|
|||
{
|
||||
g_return_val_if_fail (MIDORI_IS_VIEW (view), "about:blank");
|
||||
|
||||
if (midori_view_is_blank (view))
|
||||
return _("Blank page");
|
||||
|
||||
if (view->title && *view->title)
|
||||
return view->title;
|
||||
if (midori_view_is_blank (view))
|
||||
return _("Blank page");
|
||||
return midori_view_get_display_uri (view);
|
||||
}
|
||||
|
||||
|
@ -2154,6 +2442,7 @@ midori_view_update_tab_title (GtkWidget* label,
|
|||
if (angle == 0.0 || angle == 360.0)
|
||||
{
|
||||
gtk_widget_set_size_request (label, width * size, -1);
|
||||
if (gtk_label_get_ellipsize (GTK_LABEL (label)) != PANGO_ELLIPSIZE_START)
|
||||
gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_END);
|
||||
}
|
||||
else
|
||||
|
@ -2468,9 +2757,15 @@ midori_view_reload (MidoriView* view,
|
|||
|
||||
g_return_if_fail (MIDORI_IS_VIEW (view));
|
||||
|
||||
#if WEBKIT_CHECK_VERSION (1, 1, 6)
|
||||
/* WebKit 1.1.6 doesn't handle "alternate content" flawlessly,
|
||||
so reloading via Javascript works but not via API calls. */
|
||||
title = g_strdup (_("Error"));
|
||||
#else
|
||||
/* Error pages are special, we want to try loading the destination
|
||||
again, not the error page which isn't even a proper page */
|
||||
title = g_strdup_printf (_("Not found - %s"), view->uri);
|
||||
#endif
|
||||
if (view->title && strstr (title, view->title))
|
||||
webkit_web_view_open (WEBKIT_WEB_VIEW (view->web_view), view->uri);
|
||||
else if (from_cache)
|
||||
|
@ -2679,3 +2974,193 @@ midori_view_execute_script (MidoriView* view,
|
|||
webkit_web_view_execute_script (WEBKIT_WEB_VIEW (view->web_view), script);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* For now this is private API */
|
||||
GdkPixbuf*
|
||||
midori_view_get_snapshot (MidoriView* view,
|
||||
guint width,
|
||||
guint height)
|
||||
{
|
||||
GtkWidget* web_view;
|
||||
GdkRectangle rect;
|
||||
GdkPixmap* pixmap;
|
||||
GdkEvent event;
|
||||
gboolean result;
|
||||
GdkColormap* colormap;
|
||||
GdkPixbuf* pixbuf;
|
||||
|
||||
g_return_val_if_fail (MIDORI_IS_VIEW (view), NULL);
|
||||
web_view = gtk_bin_get_child (GTK_BIN (view));
|
||||
g_return_val_if_fail (web_view->window, NULL);
|
||||
|
||||
rect.x = web_view->allocation.x;
|
||||
rect.y = web_view->allocation.y;
|
||||
rect.width = web_view->allocation.width;
|
||||
rect.height = web_view->allocation.height;
|
||||
|
||||
pixmap = gdk_pixmap_new (web_view->window,
|
||||
web_view->allocation.width, web_view->allocation.height,
|
||||
gdk_drawable_get_depth (web_view->window));
|
||||
event.expose.type = GDK_EXPOSE;
|
||||
event.expose.window = pixmap;
|
||||
event.expose.send_event = FALSE;
|
||||
event.expose.count = 0;
|
||||
event.expose.area.x = 0;
|
||||
event.expose.area.y = 0;
|
||||
gdk_drawable_get_size (GDK_DRAWABLE (web_view->window),
|
||||
&event.expose.area.width, &event.expose.area.height);
|
||||
event.expose.region = gdk_region_rectangle (&event.expose.area);
|
||||
|
||||
g_signal_emit_by_name (web_view, "expose-event", &event, &result);
|
||||
|
||||
colormap = gdk_drawable_get_colormap (pixmap);
|
||||
pixbuf = gdk_pixbuf_get_from_drawable (NULL, pixmap, colormap, 0, 0,
|
||||
0, 0, rect.width, rect.height);
|
||||
g_object_unref (pixmap);
|
||||
|
||||
if (width || height)
|
||||
{
|
||||
GdkPixbuf* scaled;
|
||||
if (!width)
|
||||
width = rect.width;
|
||||
if (!height)
|
||||
height = rect.height;
|
||||
scaled = gdk_pixbuf_scale_simple (pixbuf, width, height,
|
||||
GDK_INTERP_TILES);
|
||||
g_object_unref (pixbuf);
|
||||
return scaled;
|
||||
}
|
||||
|
||||
return pixbuf;
|
||||
}
|
||||
|
||||
static void
|
||||
thumb_view_load_status_cb (MidoriView* thumb_view,
|
||||
GParamSpec* pspec,
|
||||
MidoriView* view)
|
||||
{
|
||||
GdkPixbuf* img;
|
||||
gchar* file_content;
|
||||
gchar* encoded;
|
||||
gchar* dom_id;
|
||||
gchar* js;
|
||||
gsize sz;
|
||||
|
||||
if (katze_object_get_enum (thumb_view, "load-status") != MIDORI_LOAD_FINISHED)
|
||||
return;
|
||||
|
||||
img = midori_view_get_snapshot (MIDORI_VIEW (thumb_view), 160, 107);
|
||||
gdk_pixbuf_save_to_buffer (img, &file_content, &sz, "png", NULL, "compression", "7", NULL);
|
||||
encoded = g_base64_encode ((guchar *)file_content, sz );
|
||||
|
||||
/* Call Javascript function to replace shortcut's content */
|
||||
dom_id = g_object_get_data (G_OBJECT (thumb_view), "dom-id");
|
||||
js = g_strdup_printf ("setThumbnail('%s','%s','%s');",
|
||||
dom_id, encoded, thumb_view->uri);
|
||||
webkit_web_view_execute_script (WEBKIT_WEB_VIEW (view->web_view), js);
|
||||
free (js);
|
||||
g_object_unref (img);
|
||||
|
||||
g_free (dom_id);
|
||||
g_free (encoded);
|
||||
g_free (file_content);
|
||||
|
||||
gtk_widget_destroy (GTK_WIDGET (thumb_view));
|
||||
}
|
||||
|
||||
/**
|
||||
* midori_view_speed_dial_inject_thumb
|
||||
* @view: a #MidoriView
|
||||
* @filename: filename of the thumbnail
|
||||
* @dom_id: Id of the shortcut on speed_dial page in wich to inject content
|
||||
* @url: url of the shortcut
|
||||
*/
|
||||
static void
|
||||
midori_view_speed_dial_inject_thumb (MidoriView* view,
|
||||
gchar* filename,
|
||||
gchar* dom_id,
|
||||
gchar* url)
|
||||
{
|
||||
GtkWidget* thumb_view;
|
||||
MidoriWebSettings* settings;
|
||||
GtkWidget* browser;
|
||||
GtkWidget* notebook;
|
||||
GtkWidget* label;
|
||||
|
||||
thumb_view = midori_view_new (view->net);
|
||||
settings = g_object_new (MIDORI_TYPE_WEB_SETTINGS, "enable-scripts", FALSE,
|
||||
"enable-plugins", FALSE, "auto-load-images", TRUE, NULL);
|
||||
midori_view_set_settings (MIDORI_VIEW (thumb_view), settings);
|
||||
browser = gtk_widget_get_toplevel (GTK_WIDGET (view));
|
||||
if (!GTK_IS_WINDOW (browser))
|
||||
return;
|
||||
/* 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 = katze_object_get_object (browser, "notebook");
|
||||
if (!notebook)
|
||||
return;
|
||||
gtk_container_add (GTK_CONTAINER (notebook), thumb_view);
|
||||
/* We use an empty label. It's not invisible but at least hard to spot. */
|
||||
label = gtk_event_box_new ();
|
||||
gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook), thumb_view, label);
|
||||
g_object_unref (notebook);
|
||||
gtk_widget_show (thumb_view);
|
||||
g_object_set_data (G_OBJECT (thumb_view), "dom-id", dom_id);
|
||||
g_signal_connect (thumb_view, "notify::load-status",
|
||||
G_CALLBACK (thumb_view_load_status_cb), view);
|
||||
midori_view_set_uri (MIDORI_VIEW (thumb_view), url);
|
||||
}
|
||||
|
||||
/**
|
||||
* midori_view_speed_dial_save
|
||||
* @web_view: a #WebkitView
|
||||
* @message: Console log data
|
||||
*
|
||||
* Load a thumbnail, and set the DOM
|
||||
*
|
||||
* message[0] == console message call
|
||||
* message[1] == shortcut id in the DOM
|
||||
* message[2] == shortcut uri
|
||||
*
|
||||
**/
|
||||
static void
|
||||
midori_view_speed_dial_get_thumb (GtkWidget* web_view,
|
||||
const gchar* message,
|
||||
MidoriView* view)
|
||||
{
|
||||
gchar** t_data = g_strsplit (message," ", 4);
|
||||
|
||||
if (t_data[1] == NULL || t_data[2] == NULL )
|
||||
return;
|
||||
|
||||
midori_view_speed_dial_inject_thumb (view, NULL,
|
||||
g_strdup (t_data[1]), g_strdup (t_data[2]));
|
||||
g_strfreev (t_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* midori_view_speed_dial_save
|
||||
* @web_view: a #WebkitView
|
||||
*
|
||||
* Save speed_dial DOM structure to body template
|
||||
*
|
||||
**/
|
||||
static void
|
||||
midori_view_speed_dial_save (GtkWidget* web_view,
|
||||
const gchar* message)
|
||||
{
|
||||
gchar* json = g_strdup (message + 15);
|
||||
gchar* fname = g_build_filename (sokoke_set_config_dir (NULL),
|
||||
"speeddial.json", NULL);
|
||||
|
||||
GRegex* reg_double = g_regex_new ("\\\\\"", 0, 0, NULL);
|
||||
gchar* safe = g_regex_replace_literal (reg_double, json, -1, 0, "\\\\\"", 0, NULL);
|
||||
g_file_set_contents (fname, safe, -1, NULL);
|
||||
|
||||
g_free (fname);
|
||||
g_free (json);
|
||||
g_free (safe);
|
||||
g_regex_unref (reg_double);
|
||||
}
|
||||
|
|
|
@ -49,7 +49,10 @@ struct _MidoriWebSettings
|
|||
MidoriStartup load_on_startup;
|
||||
gchar* homepage;
|
||||
gboolean show_crash_dialog;
|
||||
gboolean speed_dial_in_new_tabs;
|
||||
gchar* download_folder;
|
||||
gboolean ask_for_destination_folder;
|
||||
gboolean notify_transfer_completed;
|
||||
gchar* download_manager;
|
||||
gchar* text_editor;
|
||||
gchar* news_aggregator;
|
||||
|
@ -81,6 +84,8 @@ struct _MidoriWebSettings
|
|||
MidoriIdentity identify_as;
|
||||
gchar* ident_string;
|
||||
gint cache_size;
|
||||
|
||||
gint clear_private_data;
|
||||
};
|
||||
|
||||
struct _MidoriWebSettingsClass
|
||||
|
@ -119,7 +124,10 @@ enum
|
|||
PROP_LOAD_ON_STARTUP,
|
||||
PROP_HOMEPAGE,
|
||||
PROP_SHOW_CRASH_DIALOG,
|
||||
PROP_SPEED_DIAL_IN_NEW_TABS,
|
||||
PROP_DOWNLOAD_FOLDER,
|
||||
PROP_ASK_FOR_DESTINATION_FOLDER,
|
||||
PROP_NOTIFY_TRANSFER_COMPLETED,
|
||||
PROP_DOWNLOAD_MANAGER,
|
||||
PROP_TEXT_EDITOR,
|
||||
PROP_NEWS_AGGREGATOR,
|
||||
|
@ -135,8 +143,6 @@ enum
|
|||
PROP_OPEN_TABS_NEXT_TO_CURRENT,
|
||||
PROP_OPEN_POPUPS_IN_TABS,
|
||||
|
||||
PROP_ENFORCE_96_DPI,
|
||||
PROP_ENABLE_DEVELOPER_EXTRAS,
|
||||
PROP_ZOOM_TEXT_AND_IMAGES,
|
||||
PROP_FIND_WHILE_TYPING,
|
||||
PROP_ACCEPT_COOKIES,
|
||||
|
@ -152,7 +158,9 @@ enum
|
|||
PROP_AUTO_DETECT_PROXY,
|
||||
PROP_IDENTIFY_AS,
|
||||
PROP_IDENT_STRING,
|
||||
PROP_CACHE_SIZE
|
||||
PROP_CACHE_SIZE,
|
||||
|
||||
PROP_CLEAR_PRIVATE_DATA
|
||||
};
|
||||
|
||||
GType
|
||||
|
@ -541,7 +549,7 @@ midori_web_settings_class_init (MidoriWebSettingsClass* class)
|
|||
_("Load on Startup"),
|
||||
_("What to load on startup"),
|
||||
MIDORI_TYPE_STARTUP,
|
||||
MIDORI_STARTUP_HOMEPAGE,
|
||||
MIDORI_STARTUP_LAST_OPEN_PAGES,
|
||||
flags));
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
|
@ -569,6 +577,27 @@ midori_web_settings_class_init (MidoriWebSettingsClass* class)
|
|||
TRUE,
|
||||
flags));
|
||||
|
||||
/**
|
||||
* MidoriWebSettings:speed-dial-in-new-tabs:
|
||||
*
|
||||
* Show spee dial in newly opened tabs.
|
||||
*
|
||||
* Since: 0.1.7
|
||||
*/
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_SPEED_DIAL_IN_NEW_TABS,
|
||||
g_param_spec_boolean (
|
||||
"speed-dial-in-new-tabs",
|
||||
/* i18n: Speed dial, webpage shortcuts, named for the phone function */
|
||||
_("Show speed dial in new tabs"),
|
||||
_("Show speed dial in newly opened tabs"),
|
||||
TRUE,
|
||||
#if GTK_CHECK_VERSION (2, 14, 0)
|
||||
flags));
|
||||
#else
|
||||
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
|
||||
#endif
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_DOWNLOAD_FOLDER,
|
||||
g_param_spec_string (
|
||||
|
@ -582,6 +611,46 @@ midori_web_settings_class_init (MidoriWebSettingsClass* class)
|
|||
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
|
||||
#endif
|
||||
|
||||
/**
|
||||
* MidoriWebSettings:ask-for-destination-folder:
|
||||
*
|
||||
* Whether to ask for the destination folder when downloading a file.
|
||||
*
|
||||
* Since: 0.1.7
|
||||
*/
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_ASK_FOR_DESTINATION_FOLDER,
|
||||
g_param_spec_boolean (
|
||||
"ask-for-destination-folder",
|
||||
_("Ask for the destination folder"),
|
||||
_("Whether to ask for the destination folder when downloading a file"),
|
||||
FALSE,
|
||||
#if WEBKIT_CHECK_VERSION (1, 1, 3)
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
#else
|
||||
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
|
||||
#endif
|
||||
|
||||
/**
|
||||
* MidoriWebSettings:notify-transfer-completed:
|
||||
*
|
||||
* Whether to show a notification when a transfer has been completed.
|
||||
*
|
||||
* Since: 0.1.7
|
||||
*/
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_NOTIFY_TRANSFER_COMPLETED,
|
||||
g_param_spec_boolean (
|
||||
"notify-transfer-completed",
|
||||
_("Notify when a transfer has been completed"),
|
||||
_("Whether to show a notification when a transfer has been completed"),
|
||||
TRUE,
|
||||
#if WEBKIT_CHECK_VERSION (1, 1, 3)
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
#else
|
||||
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
|
||||
#endif
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_DOWNLOAD_MANAGER,
|
||||
g_param_spec_string (
|
||||
|
@ -882,6 +951,23 @@ midori_web_settings_class_init (MidoriWebSettingsClass* class)
|
|||
_("The allowed size of the cache"),
|
||||
0, G_MAXINT, 100,
|
||||
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
/**
|
||||
* MidoriWebSettings:clear-private-data:
|
||||
*
|
||||
* The private data selected for deletion.
|
||||
*
|
||||
* Since: 0.1.7
|
||||
*/
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_CLEAR_PRIVATE_DATA,
|
||||
g_param_spec_int (
|
||||
"clear-private-data",
|
||||
_("Clear private data"),
|
||||
_("The private data selected for deletion"),
|
||||
0, G_MAXINT, 0,
|
||||
flags));
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -889,7 +975,7 @@ notify_default_encoding_cb (GObject* object,
|
|||
GParamSpec* pspec)
|
||||
{
|
||||
MidoriWebSettings* web_settings;
|
||||
const gchar* string;
|
||||
gchar* string;
|
||||
const gchar* encoding;
|
||||
|
||||
web_settings = MIDORI_WEB_SETTINGS (object);
|
||||
|
@ -908,12 +994,14 @@ notify_default_encoding_cb (GObject* object,
|
|||
web_settings->preferred_encoding = MIDORI_ENCODING_WESTERN;
|
||||
else
|
||||
web_settings->preferred_encoding = MIDORI_ENCODING_CUSTOM;
|
||||
g_free (string);
|
||||
g_object_notify (object, "preferred-encoding");
|
||||
}
|
||||
|
||||
static void
|
||||
midori_web_settings_init (MidoriWebSettings* web_settings)
|
||||
{
|
||||
web_settings->notify_transfer_completed = TRUE;
|
||||
web_settings->download_folder = g_strdup (midori_get_download_dir ());
|
||||
web_settings->http_proxy = NULL;
|
||||
web_settings->open_popups_in_tabs = TRUE;
|
||||
|
@ -928,6 +1016,20 @@ midori_web_settings_init (MidoriWebSettings* web_settings)
|
|||
static void
|
||||
midori_web_settings_finalize (GObject* object)
|
||||
{
|
||||
MidoriWebSettings* web_settings;
|
||||
|
||||
web_settings = MIDORI_WEB_SETTINGS (object);
|
||||
|
||||
katze_assign (web_settings->toolbar_items, NULL);
|
||||
katze_assign (web_settings->homepage, NULL);
|
||||
katze_assign (web_settings->download_folder, NULL);
|
||||
katze_assign (web_settings->download_manager, NULL);
|
||||
katze_assign (web_settings->text_editor, NULL);
|
||||
katze_assign (web_settings->news_aggregator, NULL);
|
||||
katze_assign (web_settings->location_entry_search, NULL);
|
||||
katze_assign (web_settings->http_proxy, NULL);
|
||||
katze_assign (web_settings->ident_string, NULL);
|
||||
|
||||
G_OBJECT_CLASS (midori_web_settings_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
|
@ -1076,9 +1178,18 @@ midori_web_settings_set_property (GObject* object,
|
|||
case PROP_SHOW_CRASH_DIALOG:
|
||||
web_settings->show_crash_dialog = g_value_get_boolean (value);
|
||||
break;
|
||||
case PROP_SPEED_DIAL_IN_NEW_TABS:
|
||||
web_settings->speed_dial_in_new_tabs = g_value_get_boolean (value);
|
||||
break;
|
||||
case PROP_DOWNLOAD_FOLDER:
|
||||
katze_assign (web_settings->download_folder, g_value_dup_string (value));
|
||||
break;
|
||||
case PROP_ASK_FOR_DESTINATION_FOLDER:
|
||||
web_settings->ask_for_destination_folder = g_value_get_boolean (value);
|
||||
break;
|
||||
case PROP_NOTIFY_TRANSFER_COMPLETED:
|
||||
web_settings->notify_transfer_completed = g_value_get_boolean (value);
|
||||
break;
|
||||
case PROP_DOWNLOAD_MANAGER:
|
||||
katze_assign (web_settings->download_manager, g_value_dup_string (value));
|
||||
break;
|
||||
|
@ -1190,6 +1301,9 @@ midori_web_settings_set_property (GObject* object,
|
|||
case PROP_CACHE_SIZE:
|
||||
web_settings->cache_size = g_value_get_int (value);
|
||||
break;
|
||||
case PROP_CLEAR_PRIVATE_DATA:
|
||||
web_settings->clear_private_data = g_value_get_int (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
@ -1275,9 +1389,18 @@ midori_web_settings_get_property (GObject* object,
|
|||
case PROP_SHOW_CRASH_DIALOG:
|
||||
g_value_set_boolean (value, web_settings->show_crash_dialog);
|
||||
break;
|
||||
case PROP_SPEED_DIAL_IN_NEW_TABS:
|
||||
g_value_set_boolean (value, web_settings->speed_dial_in_new_tabs);
|
||||
break;
|
||||
case PROP_DOWNLOAD_FOLDER:
|
||||
g_value_set_string (value, web_settings->download_folder);
|
||||
break;
|
||||
case PROP_ASK_FOR_DESTINATION_FOLDER:
|
||||
g_value_set_boolean (value, web_settings->ask_for_destination_folder);
|
||||
break;
|
||||
case PROP_NOTIFY_TRANSFER_COMPLETED:
|
||||
g_value_set_boolean (value, web_settings->notify_transfer_completed);
|
||||
break;
|
||||
case PROP_DOWNLOAD_MANAGER:
|
||||
g_value_set_string (value, web_settings->download_manager);
|
||||
break;
|
||||
|
@ -1319,12 +1442,6 @@ midori_web_settings_get_property (GObject* object,
|
|||
g_value_set_boolean (value, web_settings->open_popups_in_tabs);
|
||||
break;
|
||||
|
||||
case PROP_ENFORCE_96_DPI:
|
||||
g_value_set_boolean (value, FALSE);
|
||||
break;
|
||||
case PROP_ENABLE_DEVELOPER_EXTRAS:
|
||||
g_value_set_boolean (value, FALSE);
|
||||
break;
|
||||
case PROP_ZOOM_TEXT_AND_IMAGES:
|
||||
g_value_set_boolean (value, web_settings->zoom_text_and_images);
|
||||
break;
|
||||
|
@ -1374,6 +1491,9 @@ midori_web_settings_get_property (GObject* object,
|
|||
case PROP_CACHE_SIZE:
|
||||
g_value_set_int (value, web_settings->cache_size);
|
||||
break;
|
||||
case PROP_CLEAR_PRIVATE_DATA:
|
||||
g_value_set_int (value, web_settings->clear_private_data);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
|
|
259
midori/sokoke.c
259
midori/sokoke.c
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
Copyright (C) 2007-2009 Christian Dywan <christian@twotoasts.de>
|
||||
Copyright (C) 2009 Dale Whittaker <dayul@users.sf.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -12,6 +13,8 @@
|
|||
#include "sokoke.h"
|
||||
#include "midori-stock.h"
|
||||
|
||||
#include "compat.h"
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
@ -93,9 +96,53 @@ error_dialog (const gchar* short_message,
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* sokoke_show_uri:
|
||||
* @screen: a #GdkScreen, or %NULL
|
||||
* @uri: the URI to show
|
||||
* @timestamp: the timestamp of the event
|
||||
* @error: the location of a #GError, or %NULL
|
||||
*
|
||||
* Shows the specified URI with an appropriate application. This
|
||||
* supports xdg-open, exo-open and gnome-open as fallbacks if
|
||||
* GIO doesn't do the trick.
|
||||
*
|
||||
* Return value: %TRUE on success, %FALSE if an error occurred
|
||||
**/
|
||||
gboolean
|
||||
sokoke_show_uri (GdkScreen* screen,
|
||||
const gchar* uri,
|
||||
guint32 timestamp,
|
||||
GError** error)
|
||||
{
|
||||
const gchar* fallbacks [] = { "xdg-open", "exo-open", "gnome-open" };
|
||||
gsize i;
|
||||
|
||||
g_return_val_if_fail (GDK_IS_SCREEN (screen) || !screen, FALSE);
|
||||
g_return_val_if_fail (uri != NULL, FALSE);
|
||||
g_return_val_if_fail (!error || !*error, FALSE);
|
||||
|
||||
if (gtk_show_uri (screen, uri, timestamp, error))
|
||||
return TRUE;
|
||||
|
||||
for (i = 0; i < G_N_ELEMENTS (fallbacks); i++)
|
||||
{
|
||||
gchar* command = g_strconcat (fallbacks[i], " ", uri, NULL);
|
||||
gboolean result = g_spawn_command_line_async (command, error);
|
||||
g_free (command);
|
||||
if (result)
|
||||
return TRUE;
|
||||
if (error)
|
||||
*error = NULL;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
sokoke_spawn_program (const gchar* command,
|
||||
const gchar* argument)
|
||||
const gchar* argument,
|
||||
gboolean quote)
|
||||
{
|
||||
gchar* argument_escaped;
|
||||
gchar* command_ready;
|
||||
|
@ -105,7 +152,7 @@ sokoke_spawn_program (const gchar* command,
|
|||
g_return_val_if_fail (command != NULL, FALSE);
|
||||
g_return_val_if_fail (argument != NULL, FALSE);
|
||||
|
||||
argument_escaped = g_shell_quote (argument);
|
||||
argument_escaped = quote ? g_shell_quote (argument) : g_strdup (argument);
|
||||
if (strstr (command, "%s"))
|
||||
command_ready = g_strdup_printf (command, argument_escaped);
|
||||
else
|
||||
|
@ -175,6 +222,8 @@ sokoke_idn_to_punycode (gchar* uri)
|
|||
g_utf8_strncpy (buffer, hostname, offset);
|
||||
hostname = buffer;
|
||||
}
|
||||
else
|
||||
hostname = g_strdup (hostname);
|
||||
}
|
||||
else
|
||||
hostname = g_strdup (uri);
|
||||
|
@ -213,6 +262,36 @@ sokoke_idn_to_punycode (gchar* uri)
|
|||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* sokoke_search_uri:
|
||||
* @uri: a search URI with or without %s
|
||||
* @keywords: keywords
|
||||
*
|
||||
* Takes a search engine URI and inserts the specified
|
||||
* keywords. The @keywords are percent encoded. If the
|
||||
* search URI contains a %s they keywords are inserted
|
||||
* in that place, otherwise appended to the URI.
|
||||
*
|
||||
* Return value: a newly allocated search URI
|
||||
**/
|
||||
gchar* sokoke_search_uri (const gchar* uri,
|
||||
const gchar* keywords)
|
||||
{
|
||||
gchar* escaped;
|
||||
gchar* search;
|
||||
|
||||
g_return_val_if_fail (uri != NULL, NULL);
|
||||
g_return_val_if_fail (keywords != NULL, NULL);
|
||||
|
||||
escaped = g_uri_escape_string (keywords, " :/", TRUE);
|
||||
if (strstr (uri, "%s"))
|
||||
search = g_strdup_printf (uri, escaped);
|
||||
else
|
||||
search = g_strconcat (uri, escaped, NULL);
|
||||
g_free (escaped);
|
||||
return search;
|
||||
}
|
||||
|
||||
gchar*
|
||||
sokoke_magic_uri (const gchar* uri,
|
||||
KatzeArray* search_engines)
|
||||
|
@ -279,13 +358,8 @@ sokoke_magic_uri (const gchar* uri,
|
|||
if (parts[0] && parts[1])
|
||||
if ((item = katze_array_find_token (search_engines, parts[0])))
|
||||
{
|
||||
gchar* uri_ = g_uri_escape_string (parts[1], " :/", TRUE);
|
||||
search_uri = katze_item_get_uri (item);
|
||||
if (strstr (search_uri, "%s"))
|
||||
search = g_strdup_printf (search_uri, uri_);
|
||||
else
|
||||
search = g_strconcat (search_uri, uri_, NULL);
|
||||
g_free (uri_);
|
||||
search = sokoke_search_uri (search_uri, parts[1]);
|
||||
}
|
||||
g_strfreev (parts);
|
||||
return search;
|
||||
|
@ -353,8 +427,10 @@ sokoke_get_desktop (void)
|
|||
/* Are we running in Xfce? */
|
||||
gint result;
|
||||
gchar *out = NULL;
|
||||
gchar *err = NULL;
|
||||
gboolean success = g_spawn_command_line_sync ("xprop -root _DT_SAVE_MODE",
|
||||
&out, NULL, &result, NULL);
|
||||
&out, &err, &result, NULL);
|
||||
g_free (err);
|
||||
if (success && ! result && out != NULL && strstr (out, "xfce4") != NULL)
|
||||
desktop = SOKOKE_DESKTOP_XFCE;
|
||||
else
|
||||
|
@ -430,34 +506,6 @@ sokoke_xfce_header_new (const gchar* icon,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
GtkWidget*
|
||||
sokoke_superuser_warning_new (void)
|
||||
{
|
||||
/* Create a horizontal bar with a security warning
|
||||
This returns NULL if the user is no superuser */
|
||||
#if HAVE_UNISTD_H
|
||||
if (G_UNLIKELY (!geteuid ())) /* effective superuser? */
|
||||
{
|
||||
GtkWidget* hbox;
|
||||
GtkWidget* label;
|
||||
|
||||
hbox = gtk_event_box_new ();
|
||||
gtk_widget_modify_bg (hbox, GTK_STATE_NORMAL,
|
||||
&hbox->style->bg[GTK_STATE_SELECTED]);
|
||||
/* i18n: A superuser, or system administrator, may not be 'root' */
|
||||
label = gtk_label_new (_("Warning: You are using a superuser account!"));
|
||||
gtk_misc_set_padding (GTK_MISC (label), 0, 2);
|
||||
gtk_widget_modify_fg (GTK_WIDGET (label), GTK_STATE_NORMAL,
|
||||
>K_WIDGET (label)->style->fg[GTK_STATE_SELECTED]);
|
||||
gtk_widget_show (label);
|
||||
gtk_container_add (GTK_CONTAINER (hbox), GTK_WIDGET (label));
|
||||
gtk_widget_show (hbox);
|
||||
return hbox;
|
||||
}
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GtkWidget*
|
||||
sokoke_hig_frame_new (const gchar* title)
|
||||
{
|
||||
|
@ -607,6 +655,25 @@ sokoke_key_file_get_boolean_default (GKeyFile* key_file,
|
|||
return g_key_file_get_boolean (key_file, group, key, 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)
|
||||
{
|
||||
gchar** value = g_key_file_get_string_list (key_file, group, key, length, NULL);
|
||||
if (!value)
|
||||
{
|
||||
value = g_strdupv (default_value);
|
||||
if (length)
|
||||
*length = *default_length;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
gboolean
|
||||
sokoke_key_file_save_to_file (GKeyFile* key_file,
|
||||
const gchar* filename,
|
||||
|
@ -788,7 +855,7 @@ sokoke_register_stock_items (void)
|
|||
{ STOCK_STYLES, N_("User_styles"), 0, 0, GTK_STOCK_SELECT_COLOR },
|
||||
{ STOCK_TAB_NEW, N_("New _Tab"), 0, 0, GTK_STOCK_ADD },
|
||||
{ STOCK_TRANSFERS, N_("_Transfers"), 0, 0, GTK_STOCK_SAVE },
|
||||
{ STOCK_PLUGINS, N_("P_lugins"), 0, 0, GTK_STOCK_CONVERT },
|
||||
{ STOCK_PLUGINS, N_("Netscape p_lugins"), 0, 0, GTK_STOCK_CONVERT },
|
||||
{ STOCK_USER_TRASH, N_("_Closed Tabs and Windows"), 0, 0, "gtk-undo-ltr" },
|
||||
{ STOCK_WINDOW_NEW, N_("New _Window"), 0, 0, GTK_STOCK_ADD },
|
||||
};
|
||||
|
@ -880,3 +947,119 @@ sokoke_remove_path (const gchar* path,
|
|||
g_rmdir (path);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
res_server_handler_cb (SoupServer* res_server,
|
||||
SoupMessage* msg,
|
||||
const gchar* path,
|
||||
GHashTable* query,
|
||||
SoupClientContext* client,
|
||||
gpointer data)
|
||||
{
|
||||
if (g_str_has_prefix (path, "/res"))
|
||||
{
|
||||
gchar* filename = g_strconcat (DATADIR "/midori", path, NULL);
|
||||
gchar* contents;
|
||||
gsize length;
|
||||
|
||||
if (g_file_get_contents (filename, &contents, &length, NULL))
|
||||
{
|
||||
gchar* content_type = g_content_type_guess (filename, (guchar*)contents,
|
||||
length, NULL);
|
||||
gchar* mime_type = g_content_type_get_mime_type (content_type);
|
||||
g_free (content_type);
|
||||
soup_message_set_response (msg, mime_type, SOUP_MEMORY_TAKE,
|
||||
contents, length);
|
||||
g_free (mime_type);
|
||||
soup_message_set_status (msg, 200);
|
||||
}
|
||||
else
|
||||
soup_message_set_status (msg, 404);
|
||||
g_free (filename);
|
||||
}
|
||||
else if (g_str_has_prefix (path, "/stock/"))
|
||||
{
|
||||
GtkIconTheme* icon_theme = gtk_icon_theme_get_default ();
|
||||
const gchar* icon_name = &path[7] ? &path[7] : "";
|
||||
gint icon_size = 22;
|
||||
GdkPixbuf* icon;
|
||||
gchar* contents;
|
||||
gsize length;
|
||||
|
||||
if (g_ascii_isalpha (icon_name[0]))
|
||||
icon_size = strstr (icon_name, "dialog") ? 48 : 22;
|
||||
else if (g_ascii_isdigit (icon_name[0]))
|
||||
{
|
||||
guint i = 0;
|
||||
while (icon_name[i])
|
||||
if (icon_name[i++] == '/')
|
||||
{
|
||||
gchar* size = g_strndup (icon_name, i - 1);
|
||||
icon_size = atoi (size);
|
||||
g_free (size);
|
||||
icon_name = &icon_name[i];
|
||||
}
|
||||
}
|
||||
|
||||
icon = gtk_icon_theme_load_icon (icon_theme, icon_name,
|
||||
icon_size, 0, NULL);
|
||||
if (!icon)
|
||||
icon = gtk_icon_theme_load_icon (icon_theme, "gtk-missing-image",
|
||||
icon_size, 0, NULL);
|
||||
|
||||
gdk_pixbuf_save_to_buffer (icon, &contents, &length, "png", NULL, NULL);
|
||||
g_object_unref (icon);
|
||||
soup_message_set_response (msg, "image/png", SOUP_MEMORY_TAKE,
|
||||
contents, length);
|
||||
soup_message_set_status (msg, 200);
|
||||
}
|
||||
else
|
||||
{
|
||||
soup_message_set_status (msg, 404);
|
||||
}
|
||||
}
|
||||
|
||||
SoupServer*
|
||||
sokoke_get_res_server (void)
|
||||
{
|
||||
static SoupServer* res_server = NULL;
|
||||
SoupAddress* addr = NULL;
|
||||
|
||||
if (G_UNLIKELY (!res_server))
|
||||
{
|
||||
addr = soup_address_new ("localhost", SOUP_ADDRESS_ANY_PORT);
|
||||
soup_address_resolve_sync (addr, NULL);
|
||||
res_server = soup_server_new ("interface", addr, NULL);
|
||||
g_object_unref (addr);
|
||||
soup_server_add_handler (res_server, "/",
|
||||
res_server_handler_cb, NULL, NULL);
|
||||
soup_server_run_async (res_server);
|
||||
}
|
||||
|
||||
return res_server;
|
||||
}
|
||||
|
||||
gchar*
|
||||
sokoke_replace_variables (const gchar* template,
|
||||
const gchar* variable_first, ...)
|
||||
{
|
||||
gchar* result = g_strdup (template);
|
||||
const gchar* variable;
|
||||
|
||||
va_list args;
|
||||
va_start (args, variable_first);
|
||||
|
||||
for (variable = variable_first; variable; variable = va_arg (args, const gchar*))
|
||||
{
|
||||
const gchar* value = va_arg (args, const gchar*);
|
||||
GRegex* regex = g_regex_new (variable, 0, 0, NULL);
|
||||
gchar* replaced = result;
|
||||
result = g_regex_replace_literal (regex, replaced, -1, 0, value, 0, NULL);
|
||||
g_free (replaced);
|
||||
g_regex_unref (regex);
|
||||
}
|
||||
|
||||
va_end (args);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
Copyright (C) 2007-2008 Christian Dywan <christian@twotoasts.de>
|
||||
Copyright (C) 2009 Dale Whittaker <dayul@users.sf.net>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -15,7 +16,7 @@
|
|||
#include <katze/katze.h>
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include <libsoup/soup.h>
|
||||
#include <JavaScriptCore/JavaScript.h>
|
||||
|
||||
gchar*
|
||||
|
@ -26,9 +27,19 @@ sokoke_js_script_eval (JSContextRef js_context,
|
|||
/* Many themes need this hack for small toolbars to work */
|
||||
#define GTK_ICON_SIZE_SMALL_TOOLBAR GTK_ICON_SIZE_BUTTON
|
||||
|
||||
gboolean
|
||||
sokoke_show_uri (GdkScreen* screen,
|
||||
const gchar* uri,
|
||||
guint32 timestamp,
|
||||
GError** error);
|
||||
|
||||
gboolean
|
||||
sokoke_spawn_program (const gchar* command,
|
||||
const gchar* argument);
|
||||
const gchar* argument,
|
||||
gboolean quote);
|
||||
|
||||
gchar* sokoke_search_uri (const gchar* uri,
|
||||
const gchar* keywords);
|
||||
|
||||
gchar*
|
||||
sokoke_magic_uri (const gchar* uri,
|
||||
|
@ -62,9 +73,6 @@ GtkWidget*
|
|||
sokoke_xfce_header_new (const gchar* icon,
|
||||
const gchar* title);
|
||||
|
||||
GtkWidget*
|
||||
sokoke_superuser_warning_new (void);
|
||||
|
||||
GtkWidget*
|
||||
sokoke_hig_frame_new (const gchar* title);
|
||||
|
||||
|
@ -104,6 +112,15 @@ sokoke_key_file_get_boolean_default (GKeyFile* key_file,
|
|||
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,
|
||||
|
@ -134,4 +151,11 @@ gboolean
|
|||
sokoke_remove_path (const gchar* path,
|
||||
gboolean ignore_errors);
|
||||
|
||||
SoupServer*
|
||||
sokoke_get_res_server (void);
|
||||
|
||||
gchar*
|
||||
sokoke_replace_variables (const gchar* template,
|
||||
const gchar* variable_first, ...);
|
||||
|
||||
#endif /* !__SOKOKE_H__ */
|
||||
|
|
|
@ -527,7 +527,7 @@ midori_addons_finalize (GObject* object)
|
|||
}
|
||||
|
||||
static gboolean
|
||||
_metadata_from_file (const gchar* filename,
|
||||
js_metadata_from_file (const gchar* filename,
|
||||
GSList** includes,
|
||||
GSList** excludes,
|
||||
gchar** name,
|
||||
|
@ -601,6 +601,82 @@ _metadata_from_file (const gchar* filename,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
css_metadata_from_file (const gchar* filename,
|
||||
GSList** includes,
|
||||
GSList** excludes)
|
||||
{
|
||||
GIOChannel* channel;
|
||||
gchar* line;
|
||||
gchar* rest_of_line;
|
||||
|
||||
if (!g_file_test (filename, G_FILE_TEST_IS_REGULAR | G_FILE_TEST_IS_SYMLINK))
|
||||
return FALSE;
|
||||
|
||||
channel = g_io_channel_new_file (filename, "r", 0);
|
||||
if (!channel)
|
||||
return FALSE;
|
||||
|
||||
while (g_io_channel_read_line (channel, &line, NULL, NULL, NULL)
|
||||
== G_IO_STATUS_NORMAL)
|
||||
{
|
||||
if (g_str_has_prefix (line, "@namespace"))
|
||||
; /* FIXME: Check "http://www.w3.org/1999/xhtml", skip otherwise */
|
||||
else if (g_str_has_prefix (line, "@-moz-document"))
|
||||
{ /* FIXME: We merely look for includes. We should honor blocks. */
|
||||
if (includes)
|
||||
{
|
||||
gchar** parts;
|
||||
guint i;
|
||||
|
||||
rest_of_line = g_strdup (line + strlen ("@-moz-document"));
|
||||
rest_of_line = g_strstrip (rest_of_line);
|
||||
parts = g_strsplit (rest_of_line, " ", 0);
|
||||
i = 0;
|
||||
while (parts[i])
|
||||
{
|
||||
if (g_str_has_prefix (parts[i], "url-prefix("))
|
||||
{
|
||||
gchar* value = g_strdup (parts[i] + strlen ("url-prefix("));
|
||||
guint j;
|
||||
|
||||
if (value[0] != '\'' && value[0] != '"')
|
||||
{
|
||||
/* Wrong syntax, abort */
|
||||
g_free (value);
|
||||
g_strfreev (parts);
|
||||
g_free (line);
|
||||
g_io_channel_shutdown (channel, false, 0);
|
||||
g_slist_free (*includes);
|
||||
g_slist_free (*excludes);
|
||||
*includes = NULL;
|
||||
*excludes = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
j = 1;
|
||||
while (value[j] != '\0')
|
||||
{
|
||||
if (value[j] == value[0])
|
||||
break;
|
||||
j++;
|
||||
}
|
||||
*includes = g_slist_prepend (*includes, g_strndup (value + 1, j - 1));
|
||||
g_free (value);
|
||||
}
|
||||
/* FIXME: Recognize "domain" */
|
||||
i++;
|
||||
}
|
||||
g_strfreev (parts);
|
||||
}
|
||||
}
|
||||
g_free (line);
|
||||
}
|
||||
g_io_channel_shutdown (channel, false, 0);
|
||||
g_io_channel_unref (channel);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gchar*
|
||||
_convert_to_simple_regexp (const gchar* pattern)
|
||||
{
|
||||
|
@ -742,6 +818,7 @@ _js_style_from_file (JSContextRef js_context,
|
|||
error = NULL;
|
||||
if (g_file_get_contents (filename, &style, NULL, &error))
|
||||
{
|
||||
guint meta = 0;
|
||||
n = strlen (style);
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
|
@ -751,7 +828,34 @@ _js_style_from_file (JSContextRef js_context,
|
|||
/* Change all single quotes to double quotes */
|
||||
if (style[i] == '\'')
|
||||
style[i] = '\"';
|
||||
/* Turn metadata we inspected earlier into comments */
|
||||
if (!meta && style[i] == '@')
|
||||
{
|
||||
style[i] = '/';
|
||||
meta++;
|
||||
}
|
||||
else if (meta == 1 && (style[i] == '-' || style[i] == 'n'))
|
||||
{
|
||||
style[i] = '*';
|
||||
meta++;
|
||||
}
|
||||
else if (meta == 2 && style[i] == '{')
|
||||
{
|
||||
style[i - 1] = '*';
|
||||
style[i] = '/';
|
||||
meta++;
|
||||
}
|
||||
else if (meta == 3 && style[i] == '{')
|
||||
meta++;
|
||||
else if (meta == 4 && style[i] == '}')
|
||||
meta--;
|
||||
else if (meta == 3 && style[i] == '}')
|
||||
{
|
||||
style[i] = ' ';
|
||||
meta = 0;
|
||||
}
|
||||
}
|
||||
|
||||
style_script = g_strdup_printf (
|
||||
"window.addEventListener ('DOMContentLoaded',"
|
||||
"function () {"
|
||||
|
@ -1031,7 +1135,7 @@ midori_addons_update_elements (MidoriAddons* addons)
|
|||
if (addons->kind == MIDORI_ADDON_USER_SCRIPTS)
|
||||
{
|
||||
name = NULL;
|
||||
if (!_metadata_from_file (fullname, &includes, &excludes,
|
||||
if (!js_metadata_from_file (fullname, &includes, &excludes,
|
||||
&name, &description))
|
||||
broken = TRUE;
|
||||
|
||||
|
@ -1041,6 +1145,11 @@ midori_addons_update_elements (MidoriAddons* addons)
|
|||
displayname = name;
|
||||
}
|
||||
}
|
||||
else if (addons->kind == MIDORI_ADDON_USER_STYLES)
|
||||
{
|
||||
if (!css_metadata_from_file (fullname, &includes, &excludes))
|
||||
broken = TRUE;
|
||||
}
|
||||
|
||||
element = g_new (struct AddonElement, 1);
|
||||
element->name = displayname;
|
||||
|
|
|
@ -116,10 +116,9 @@ midori_bookmarks_get_stock_id (MidoriViewable* viewable)
|
|||
static void
|
||||
midori_bookmarks_add_clicked_cb (GtkWidget* toolitem)
|
||||
{
|
||||
GtkWidget* browser = gtk_widget_get_toplevel (toolitem);
|
||||
MidoriBrowser* browser = midori_browser_get_for_widget (toolitem);
|
||||
/* FIXME: Take selected folder into account */
|
||||
midori_browser_edit_bookmark_dialog_new (MIDORI_BROWSER (browser),
|
||||
NULL, TRUE, FALSE);
|
||||
midori_browser_edit_bookmark_dialog_new (browser, NULL, TRUE, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -140,9 +139,8 @@ midori_bookmarks_edit_clicked_cb (GtkWidget* toolitem,
|
|||
is_separator = !KATZE_IS_ARRAY (item) && !katze_item_get_uri (item);
|
||||
if (!is_separator)
|
||||
{
|
||||
GtkWidget* browser = gtk_widget_get_toplevel (toolitem);
|
||||
midori_browser_edit_bookmark_dialog_new (MIDORI_BROWSER (browser),
|
||||
item, FALSE, FALSE);
|
||||
MidoriBrowser* browser = midori_browser_get_for_widget (toolitem);
|
||||
midori_browser_edit_bookmark_dialog_new (browser, item, FALSE, FALSE);
|
||||
}
|
||||
|
||||
g_object_unref (item);
|
||||
|
@ -177,9 +175,9 @@ midori_bookmarks_delete_clicked_cb (GtkWidget* toolitem,
|
|||
static void
|
||||
midori_bookmarks_folder_clicked_cb (GtkWidget* toolitem)
|
||||
{
|
||||
GtkWidget* browser = gtk_widget_get_toplevel (toolitem);
|
||||
MidoriBrowser* browser = midori_browser_get_for_widget (GTK_WIDGET (toolitem));
|
||||
/* FIXME: Take selected folder into account */
|
||||
midori_browser_edit_bookmark_dialog_new (MIDORI_BROWSER (browser),
|
||||
midori_browser_edit_bookmark_dialog_new (browser,
|
||||
NULL, TRUE, TRUE);
|
||||
}
|
||||
|
||||
|
@ -614,10 +612,8 @@ midori_bookmarks_row_activated_cb (GtkTreeView* treeview,
|
|||
uri = katze_item_get_uri (item);
|
||||
if (uri && *uri)
|
||||
{
|
||||
GtkWidget* browser;
|
||||
|
||||
browser = gtk_widget_get_toplevel (GTK_WIDGET (bookmarks));
|
||||
midori_browser_set_current_uri (MIDORI_BROWSER (browser), uri);
|
||||
MidoriBrowser* browser = midori_browser_get_for_widget (GTK_WIDGET (bookmarks));
|
||||
midori_browser_set_current_uri (browser, uri);
|
||||
}
|
||||
|
||||
g_object_unref (item);
|
||||
|
@ -664,8 +660,8 @@ midori_bookmarks_open_activate_cb (GtkWidget* menuitem,
|
|||
|
||||
if (uri && *uri)
|
||||
{
|
||||
GtkWidget* browser = gtk_widget_get_toplevel (GTK_WIDGET (bookmarks));
|
||||
midori_browser_set_current_uri (MIDORI_BROWSER (browser), uri);
|
||||
MidoriBrowser* browser = midori_browser_get_for_widget (GTK_WIDGET (bookmarks));
|
||||
midori_browser_set_current_uri (browser, uri);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -687,14 +683,14 @@ midori_bookmarks_open_in_tab_activate_cb (GtkWidget* menuitem,
|
|||
{
|
||||
if ((uri = katze_item_get_uri (child)) && *uri)
|
||||
{
|
||||
GtkWidget* browser;
|
||||
MidoriBrowser* browser;
|
||||
MidoriWebSettings* settings;
|
||||
|
||||
browser = gtk_widget_get_toplevel (GTK_WIDGET (bookmarks));
|
||||
n = midori_browser_add_item (MIDORI_BROWSER (browser), child);
|
||||
browser = midori_browser_get_for_widget (GTK_WIDGET (bookmarks));
|
||||
n = midori_browser_add_item (browser, child);
|
||||
settings = katze_object_get_object (browser, "settings");
|
||||
if (!katze_object_get_boolean (settings, "open-tabs-in-the-background"))
|
||||
midori_browser_set_current_page (MIDORI_BROWSER (browser), n);
|
||||
midori_browser_set_current_page (browser, n);
|
||||
g_object_unref (settings);
|
||||
}
|
||||
i++;
|
||||
|
@ -704,14 +700,14 @@ midori_bookmarks_open_in_tab_activate_cb (GtkWidget* menuitem,
|
|||
{
|
||||
if ((uri = katze_item_get_uri (item)) && *uri)
|
||||
{
|
||||
GtkWidget* browser;
|
||||
MidoriBrowser* browser;
|
||||
MidoriWebSettings* settings;
|
||||
|
||||
browser = gtk_widget_get_toplevel (GTK_WIDGET (bookmarks));
|
||||
n = midori_browser_add_item (MIDORI_BROWSER (browser), item);
|
||||
browser = midori_browser_get_for_widget (GTK_WIDGET (bookmarks));
|
||||
n = midori_browser_add_item (browser, item);
|
||||
settings = katze_object_get_object (browser, "settings");
|
||||
if (!katze_object_get_boolean (settings, "open-tabs-in-the-background"))
|
||||
midori_browser_set_current_page (MIDORI_BROWSER (browser), n);
|
||||
midori_browser_set_current_page (browser, n);
|
||||
g_object_unref (settings);
|
||||
}
|
||||
}
|
||||
|
@ -729,7 +725,7 @@ midori_bookmarks_open_in_window_activate_cb (GtkWidget* menuitem,
|
|||
|
||||
if (uri && *uri)
|
||||
{
|
||||
GtkWidget* browser = gtk_widget_get_toplevel (GTK_WIDGET (bookmarks));
|
||||
MidoriBrowser* browser = midori_browser_get_for_widget (GTK_WIDGET (bookmarks));
|
||||
g_signal_emit_by_name (browser, "new-window", uri);
|
||||
}
|
||||
}
|
||||
|
@ -746,8 +742,8 @@ midori_bookmarks_edit_activate_cb (GtkWidget* menuitem,
|
|||
|
||||
if (!is_separator)
|
||||
{
|
||||
GtkWidget* browser = gtk_widget_get_toplevel (GTK_WIDGET (bookmarks));
|
||||
midori_browser_edit_bookmark_dialog_new (MIDORI_BROWSER (browser), item, FALSE, FALSE);
|
||||
MidoriBrowser* browser = midori_browser_get_for_widget (GTK_WIDGET (bookmarks));
|
||||
midori_browser_edit_bookmark_dialog_new (browser, item, FALSE, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -825,12 +821,12 @@ midori_bookmarks_button_release_event_cb (GtkWidget* widget,
|
|||
|
||||
if (uri && *uri)
|
||||
{
|
||||
GtkWidget* browser;
|
||||
MidoriBrowser* browser;
|
||||
gint n;
|
||||
|
||||
browser = gtk_widget_get_toplevel (widget);
|
||||
n = midori_browser_add_uri (MIDORI_BROWSER (browser), uri);
|
||||
midori_browser_set_current_page (MIDORI_BROWSER (browser), n);
|
||||
browser = midori_browser_get_for_widget (widget);
|
||||
n = midori_browser_add_uri (browser, uri);
|
||||
midori_browser_set_current_page (browser, n);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
@ -231,8 +231,8 @@ static void
|
|||
midori_console_hierarchy_changed_cb (MidoriConsole* console,
|
||||
GtkWidget* old_parent)
|
||||
{
|
||||
GtkWidget* browser = gtk_widget_get_toplevel (GTK_WIDGET (console));
|
||||
if (GTK_WIDGET_TOPLEVEL (browser))
|
||||
MidoriBrowser* browser = midori_browser_get_for_widget (GTK_WIDGET (console));
|
||||
if (MIDORI_IS_BROWSER (browser))
|
||||
g_signal_connect (browser, "add-tab",
|
||||
G_CALLBACK (midori_console_browser_add_tab_cb), console);
|
||||
}
|
||||
|
|
|
@ -199,7 +199,8 @@ midori_extensions_set_property (GObject* object,
|
|||
case PROP_APP:
|
||||
{
|
||||
KatzeArray* array;
|
||||
guint i, n;
|
||||
MidoriExtension* extension;
|
||||
guint i;
|
||||
|
||||
/* FIXME: Handle NULL and subsequent assignments */
|
||||
extensions->app = g_value_get_object (value);
|
||||
|
@ -207,10 +208,9 @@ midori_extensions_set_property (GObject* object,
|
|||
g_signal_connect (array, "add-item",
|
||||
G_CALLBACK (midori_extensions_add_item_cb), extensions);
|
||||
|
||||
if ((n = katze_array_get_length (array)))
|
||||
for (i = 0; i < n; i++)
|
||||
midori_extensions_add_item_cb (array,
|
||||
katze_array_get_nth_item (array, i), extensions);
|
||||
i = 0;
|
||||
while ((extension = katze_array_get_nth_item (array, i++)))
|
||||
midori_extensions_add_item_cb (array, extension, extensions);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -270,8 +270,11 @@ midori_extensions_treeview_render_text_cb (GtkTreeViewColumn* column,
|
|||
g_free (name);
|
||||
g_free (version);
|
||||
g_free (desc);
|
||||
g_object_set (renderer, "text", text, NULL);
|
||||
g_object_set (renderer, "text", text,
|
||||
"sensitive", midori_extension_is_active (extension),
|
||||
NULL);
|
||||
g_free (text);
|
||||
g_object_unref (extension);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -303,6 +306,8 @@ midori_extensions_treeview_row_activated_cb (GtkTreeView* treeview,
|
|||
!midori_extension_is_active (extension));
|
||||
gtk_widget_set_sensitive (GTK_WIDGET (button_disable),
|
||||
midori_extension_is_active (extension));
|
||||
/* FIXME: Update only the appropriate row */
|
||||
gtk_widget_queue_draw (GTK_WIDGET (treeview));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -117,10 +117,9 @@ midori_history_get_stock_id (MidoriViewable* viewable)
|
|||
static void
|
||||
midori_history_add_clicked_cb (GtkWidget* toolitem)
|
||||
{
|
||||
GtkWidget* browser = gtk_widget_get_toplevel (toolitem);
|
||||
MidoriBrowser* browser = midori_browser_get_for_widget (toolitem);
|
||||
/* FIXME: Take selected folder into account */
|
||||
midori_browser_edit_bookmark_dialog_new (MIDORI_BROWSER (browser),
|
||||
NULL, TRUE, FALSE);
|
||||
midori_browser_edit_bookmark_dialog_new (browser, NULL, TRUE, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -152,11 +151,11 @@ static void
|
|||
midori_history_clear_clicked_cb (GtkWidget* toolitem,
|
||||
MidoriHistory* history)
|
||||
{
|
||||
GtkWidget* browser;
|
||||
MidoriBrowser* browser;
|
||||
GtkWidget* dialog;
|
||||
gint result;
|
||||
|
||||
browser = gtk_widget_get_toplevel (GTK_WIDGET (history));
|
||||
browser = midori_browser_get_for_widget (GTK_WIDGET (history));
|
||||
dialog = gtk_message_dialog_new (GTK_WINDOW (browser),
|
||||
GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO,
|
||||
|
@ -275,7 +274,8 @@ midori_history_clear_cb (KatzeArray* array,
|
|||
|
||||
static void
|
||||
midori_history_disconnect_folder (MidoriHistory* history,
|
||||
KatzeArray* array)
|
||||
KatzeArray* array,
|
||||
gboolean unref)
|
||||
{
|
||||
KatzeItem* item;
|
||||
guint i;
|
||||
|
@ -293,7 +293,8 @@ midori_history_disconnect_folder (MidoriHistory* history,
|
|||
while ((item = katze_array_get_nth_item (array, i++)))
|
||||
{
|
||||
if (KATZE_IS_ARRAY (item))
|
||||
midori_history_disconnect_folder (history, KATZE_ARRAY (item));
|
||||
midori_history_disconnect_folder (history, KATZE_ARRAY (item), unref);
|
||||
if (unref)
|
||||
g_object_unref (item);
|
||||
}
|
||||
}
|
||||
|
@ -309,6 +310,7 @@ midori_history_add_item_cb (KatzeArray* array,
|
|||
|
||||
g_return_if_fail (KATZE_IS_ARRAY (array));
|
||||
g_return_if_fail (KATZE_IS_ITEM (added_item));
|
||||
g_return_if_fail (MIDORI_IS_HISTORY (history));
|
||||
|
||||
if (KATZE_IS_ARRAY (added_item))
|
||||
{
|
||||
|
@ -392,7 +394,7 @@ midori_history_remove_item_cb (KatzeArray* array,
|
|||
g_assert (KATZE_IS_ITEM (removed_item));
|
||||
|
||||
if (KATZE_IS_ARRAY (removed_item))
|
||||
midori_history_disconnect_folder (history, KATZE_ARRAY (removed_item));
|
||||
midori_history_disconnect_folder (history, KATZE_ARRAY (removed_item), TRUE);
|
||||
|
||||
model = gtk_tree_view_get_model (GTK_TREE_VIEW (history->treeview));
|
||||
midori_history_remove_iter (model, NULL, removed_item);
|
||||
|
@ -424,7 +426,7 @@ midori_history_clear_cb (KatzeArray* array,
|
|||
midori_history_remove_item_cb (array, item, history);
|
||||
}
|
||||
|
||||
midori_history_disconnect_folder (history, array);
|
||||
midori_history_disconnect_folder (history, array, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -459,7 +461,6 @@ midori_history_insert_item (MidoriHistory* history,
|
|||
age = day - pday;
|
||||
gtk_tree_store_insert_with_values (treestore, &iter, parent,
|
||||
0, 0, item, 1, age, -1);
|
||||
g_object_unref (item);
|
||||
piter = &iter;
|
||||
}
|
||||
i = 0;
|
||||
|
@ -481,7 +482,7 @@ midori_history_set_app (MidoriHistory* history,
|
|||
|
||||
if (history->array)
|
||||
{
|
||||
midori_history_disconnect_folder (history, history->array);
|
||||
midori_history_disconnect_folder (history, history->array, TRUE);
|
||||
g_object_unref (history->array);
|
||||
model = gtk_tree_view_get_model (GTK_TREE_VIEW (history->treeview));
|
||||
gtk_tree_store_clear (GTK_TREE_STORE (model));
|
||||
|
@ -499,7 +500,7 @@ midori_history_set_app (MidoriHistory* history,
|
|||
|
||||
model = gtk_tree_view_get_model (GTK_TREE_VIEW (history->treeview));
|
||||
midori_history_insert_item (history, GTK_TREE_STORE (model),
|
||||
NULL, KATZE_ITEM (g_object_ref (history->array)), day);
|
||||
NULL, KATZE_ITEM (history->array), day);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -597,13 +598,13 @@ midori_history_treeview_render_text_cb (GtkTreeViewColumn* column,
|
|||
}
|
||||
else if (age > 6)
|
||||
{
|
||||
sdate = g_strdup_printf (_("A week ago"));
|
||||
sdate = _("A week ago");
|
||||
g_object_set (renderer, "text", sdate, NULL);
|
||||
g_free (sdate);
|
||||
}
|
||||
else if (age > 1)
|
||||
{
|
||||
sdate = g_strdup_printf (_("%d days ago"), (gint)age);
|
||||
sdate = g_strdup_printf (ngettext ("%d day ago",
|
||||
"%d days ago", (gint)age), (gint)age);
|
||||
g_object_set (renderer, "text", sdate, NULL);
|
||||
g_free (sdate);
|
||||
}
|
||||
|
@ -641,10 +642,10 @@ midori_history_row_activated_cb (GtkTreeView* treeview,
|
|||
uri = katze_item_get_uri (item);
|
||||
if (uri && *uri)
|
||||
{
|
||||
GtkWidget* browser;
|
||||
MidoriBrowser* browser;
|
||||
|
||||
browser = gtk_widget_get_toplevel (GTK_WIDGET (history));
|
||||
midori_browser_set_current_uri (MIDORI_BROWSER (browser), uri);
|
||||
browser = midori_browser_get_for_widget (GTK_WIDGET (history));
|
||||
midori_browser_set_current_uri (browser, uri);
|
||||
}
|
||||
|
||||
g_object_unref (item);
|
||||
|
@ -691,8 +692,8 @@ midori_history_open_activate_cb (GtkWidget* menuitem,
|
|||
|
||||
if (uri && *uri)
|
||||
{
|
||||
GtkWidget* browser = gtk_widget_get_toplevel (GTK_WIDGET (history));
|
||||
midori_browser_set_current_uri (MIDORI_BROWSER (browser), uri);
|
||||
MidoriBrowser* browser = midori_browser_get_for_widget (GTK_WIDGET (history));
|
||||
midori_browser_set_current_uri (browser, uri);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -714,14 +715,14 @@ midori_history_open_in_tab_activate_cb (GtkWidget* menuitem,
|
|||
{
|
||||
if ((uri = katze_item_get_uri (child)) && *uri)
|
||||
{
|
||||
GtkWidget* browser;
|
||||
MidoriBrowser* browser;
|
||||
MidoriWebSettings* settings;
|
||||
|
||||
browser = gtk_widget_get_toplevel (GTK_WIDGET (history));
|
||||
n = midori_browser_add_item (MIDORI_BROWSER (browser), child);
|
||||
browser = midori_browser_get_for_widget (GTK_WIDGET (history));
|
||||
n = midori_browser_add_item (browser, child);
|
||||
settings = katze_object_get_object (browser, "settings");
|
||||
if (!katze_object_get_boolean (settings, "open-tabs-in-the-background"))
|
||||
midori_browser_set_current_page (MIDORI_BROWSER (browser), n);
|
||||
midori_browser_set_current_page (browser, n);
|
||||
g_object_unref (settings);
|
||||
}
|
||||
i++;
|
||||
|
@ -731,14 +732,14 @@ midori_history_open_in_tab_activate_cb (GtkWidget* menuitem,
|
|||
{
|
||||
if ((uri = katze_item_get_uri (item)) && *uri)
|
||||
{
|
||||
GtkWidget* browser;
|
||||
MidoriBrowser* browser;
|
||||
MidoriWebSettings* settings;
|
||||
|
||||
browser = gtk_widget_get_toplevel (GTK_WIDGET (history));
|
||||
n = midori_browser_add_item (MIDORI_BROWSER (browser), item);
|
||||
browser = midori_browser_get_for_widget (GTK_WIDGET (history));
|
||||
n = midori_browser_add_item (browser, item);
|
||||
settings = katze_object_get_object (browser, "settings");
|
||||
if (!katze_object_get_boolean (settings, "open-tabs-in-the-background"))
|
||||
midori_browser_set_current_page (MIDORI_BROWSER (browser), n);
|
||||
midori_browser_set_current_page (browser, n);
|
||||
g_object_unref (settings);
|
||||
}
|
||||
}
|
||||
|
@ -756,7 +757,7 @@ midori_history_open_in_window_activate_cb (GtkWidget* menuitem,
|
|||
|
||||
if (uri && *uri)
|
||||
{
|
||||
GtkWidget* browser = gtk_widget_get_toplevel (GTK_WIDGET (history));
|
||||
MidoriBrowser* browser = midori_browser_get_for_widget (GTK_WIDGET (history));
|
||||
g_signal_emit_by_name (browser, "new-window", uri);
|
||||
}
|
||||
}
|
||||
|
@ -773,8 +774,8 @@ midori_history_bookmark_activate_cb (GtkWidget* menuitem,
|
|||
|
||||
if (uri && *uri)
|
||||
{
|
||||
GtkWidget* browser = gtk_widget_get_toplevel (GTK_WIDGET (history));
|
||||
midori_browser_edit_bookmark_dialog_new (MIDORI_BROWSER (browser), item, TRUE, FALSE);
|
||||
MidoriBrowser* browser = midori_browser_get_for_widget (GTK_WIDGET (history));
|
||||
midori_browser_edit_bookmark_dialog_new (browser, item, TRUE, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -852,12 +853,12 @@ midori_history_button_release_event_cb (GtkWidget* widget,
|
|||
|
||||
if (uri && *uri)
|
||||
{
|
||||
GtkWidget* browser;
|
||||
MidoriBrowser* browser;
|
||||
gint n;
|
||||
|
||||
browser = gtk_widget_get_toplevel (widget);
|
||||
n = midori_browser_add_uri (MIDORI_BROWSER (browser), uri);
|
||||
midori_browser_set_current_page (MIDORI_BROWSER (browser), n);
|
||||
browser = midori_browser_get_for_widget (widget);
|
||||
n = midori_browser_add_uri (browser, uri);
|
||||
midori_browser_set_current_page (browser, n);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -967,6 +968,10 @@ midori_history_finalize (GObject* object)
|
|||
|
||||
if (history->app)
|
||||
g_object_unref (history->app);
|
||||
|
||||
/* FIXME: We don't unref items (last argument is FALSE) because
|
||||
our reference counting is incorrect. */
|
||||
midori_history_disconnect_folder (history, history->array, FALSE);
|
||||
g_object_unref (history->array);
|
||||
}
|
||||
|
||||
|
|
|
@ -84,7 +84,7 @@ midori_plugins_class_init (MidoriPluginsClass* class)
|
|||
static const gchar*
|
||||
midori_plugins_get_label (MidoriViewable* viewable)
|
||||
{
|
||||
return _("Plugins");
|
||||
return _("Netscape plugins");
|
||||
}
|
||||
|
||||
static const gchar*
|
||||
|
@ -277,6 +277,10 @@ midori_plugins_init (MidoriPlugins* plugins)
|
|||
const gchar* plugin_name;
|
||||
const gchar* plugin_description;
|
||||
|
||||
/* Ignore files which don't have the correct suffix */
|
||||
if (!g_str_has_suffix (filename, G_MODULE_SUFFIX))
|
||||
continue;
|
||||
|
||||
fullname = g_build_filename (plugin_path, filename, NULL);
|
||||
module = g_module_open (fullname, G_MODULE_BIND_LOCAL);
|
||||
g_free (fullname);
|
||||
|
|
|
@ -100,8 +100,23 @@ midori_transfers_button_clear_clicked_cb (GtkToolItem* toolitem,
|
|||
{
|
||||
GtkTreeModel* model = gtk_tree_view_get_model (
|
||||
GTK_TREE_VIEW (transfers->treeview));
|
||||
/* FIXME: Clear only finished and cancelled downloads */
|
||||
gtk_tree_store_clear (GTK_TREE_STORE (model));
|
||||
GtkTreeIter iter;
|
||||
gint n = 0;
|
||||
while ((gtk_tree_model_iter_nth_child (model, &iter, NULL, n++)))
|
||||
{
|
||||
#if WEBKIT_CHECK_VERSION (1, 1, 3)
|
||||
WebKitDownload* download;
|
||||
WebKitDownloadStatus status;
|
||||
|
||||
gtk_tree_model_get (model, &iter, 1, &download, -1);
|
||||
|
||||
status = webkit_download_get_status (download);
|
||||
if (status == WEBKIT_DOWNLOAD_STATUS_FINISHED
|
||||
|| status == WEBKIT_DOWNLOAD_STATUS_CANCELLED)
|
||||
gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
|
||||
g_object_unref (download);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static GtkWidget*
|
||||
|
@ -173,8 +188,8 @@ midori_transfers_browser_add_download_cb (MidoriBrowser* browser,
|
|||
|
||||
treeview = GTK_TREE_VIEW (transfers->treeview);
|
||||
model = gtk_tree_view_get_model (treeview);
|
||||
gtk_tree_store_insert_with_values (GTK_TREE_STORE (model),
|
||||
NULL, NULL, G_MAXINT,
|
||||
gtk_list_store_insert_with_values (GTK_LIST_STORE (model),
|
||||
NULL, G_MAXINT,
|
||||
0, NULL, 1, download, -1);
|
||||
g_signal_connect (download, "notify::progress",
|
||||
G_CALLBACK (midori_transfers_download_notify_progress_cb), transfers);
|
||||
|
@ -326,17 +341,10 @@ midori_transfers_treeview_row_activated_cb (GtkTreeView* treeview,
|
|||
case WEBKIT_DOWNLOAD_STATUS_FINISHED:
|
||||
{
|
||||
const gchar* uri;
|
||||
gboolean success;
|
||||
|
||||
uri = webkit_download_get_destination_uri (download);
|
||||
success = gtk_show_uri (gtk_widget_get_screen (GTK_WIDGET (
|
||||
sokoke_show_uri (gtk_widget_get_screen (GTK_WIDGET (
|
||||
treeview)), uri, gtk_get_current_event_time (), NULL);
|
||||
if (!success)
|
||||
{
|
||||
gchar* command = g_strconcat ("exo-open ", uri, NULL);
|
||||
success = g_spawn_command_line_async (command, NULL);
|
||||
g_free (command);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WEBKIT_DOWNLOAD_STATUS_CANCELLED:
|
||||
|
@ -354,10 +362,13 @@ midori_transfers_hierarchy_changed_cb (MidoriTransfers* transfers,
|
|||
GtkWidget* old_parent)
|
||||
{
|
||||
#if WEBKIT_CHECK_VERSION (1, 1, 3)
|
||||
GtkWidget* browser = gtk_widget_get_toplevel (GTK_WIDGET (transfers));
|
||||
if (GTK_WIDGET_TOPLEVEL (browser))
|
||||
MidoriBrowser* browser = midori_browser_get_for_widget (GTK_WIDGET (transfers));
|
||||
if (MIDORI_IS_BROWSER (browser))
|
||||
g_signal_connect (browser, "add-download",
|
||||
G_CALLBACK (midori_transfers_browser_add_download_cb), transfers);
|
||||
if (old_parent)
|
||||
g_signal_handlers_disconnect_by_func (old_parent,
|
||||
midori_transfers_browser_add_download_cb, transfers);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -368,7 +379,7 @@ midori_transfers_init (MidoriTransfers* transfers)
|
|||
GtkTreeViewColumn* column;
|
||||
GtkCellRenderer* renderer_pixbuf;
|
||||
GtkCellRenderer* renderer_text;
|
||||
GtkTreeStore* treestore = gtk_tree_store_new (2, GDK_TYPE_PIXBUF, G_TYPE_OBJECT);
|
||||
GtkListStore* treestore = gtk_list_store_new (2, GDK_TYPE_PIXBUF, G_TYPE_OBJECT);
|
||||
transfers->treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (treestore));
|
||||
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (transfers->treeview), FALSE);
|
||||
column = gtk_tree_view_column_new ();
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
# set of available languages (in alphabetic order)
|
||||
da de el en_GB es et fi fr gl he hu id it ja nl pl pt_PT ru sv tr uk zh_CN zh_TW
|
||||
cs da de el en_GB es et fi fr gl he hu id it ja nl pl pt ro ru sk sv tr uk zh_CN zh_TW
|
||||
|
|
|
@ -24,8 +24,15 @@ katze/katze-utils.c
|
|||
katze/katze-item.c
|
||||
katze/katze-array.c
|
||||
katze/katze-arrayaction.c
|
||||
extensions/adblock.c
|
||||
extensions/colorful-tabs.c
|
||||
extensions/cookie-manager.c
|
||||
extensions/cookie-manager/cookie-manager.c
|
||||
extensions/cookie-manager/cookie-manager-page.c
|
||||
extensions/feed-panel/feed-atom.c
|
||||
extensions/feed-panel/feed-panel.c
|
||||
extensions/feed-panel/feed-parse.c
|
||||
extensions/feed-panel/feed-rss.c
|
||||
extensions/feed-panel/main.c
|
||||
extensions/mouse-gestures/main.c
|
||||
extensions/page-holder.c
|
||||
extensions/statusbar-features.c
|
||||
|
|
1045
po/midori.pot
1045
po/midori.pot
File diff suppressed because it is too large
Load diff
1724
po/pt_PT.po
1724
po/pt_PT.po
File diff suppressed because it is too large
Load diff
1362
po/zh_CN.po
1362
po/zh_CN.po
File diff suppressed because it is too large
Load diff
|
@ -38,6 +38,7 @@ browser_create (void)
|
|||
GtkAction* action = actions->data;
|
||||
if (g_strcmp0 (gtk_action_get_name (action), "WindowClose"))
|
||||
if (g_strcmp0 (gtk_action_get_name (action), "EncodingCustom"))
|
||||
if (g_strcmp0 (gtk_action_get_name (action), "AddSpeedDial"))
|
||||
gtk_action_activate (action);
|
||||
actions = g_list_next (actions);
|
||||
}
|
||||
|
|
|
@ -15,6 +15,10 @@
|
|||
|
||||
#include "midori.h"
|
||||
|
||||
/* This is a private function */
|
||||
GtkWidget*
|
||||
midori_location_action_entry_for_proxy (GtkWidget* proxy);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const gchar* uri;
|
||||
|
@ -41,7 +45,6 @@ completion_count (void)
|
|||
{
|
||||
MidoriLocationAction* action;
|
||||
GtkWidget* toolitem;
|
||||
GtkWidget* alignment;
|
||||
GtkWidget* location_entry;
|
||||
GtkWidget* entry;
|
||||
GtkTreeModel* model;
|
||||
|
@ -49,8 +52,7 @@ completion_count (void)
|
|||
|
||||
action = g_object_new (MIDORI_TYPE_LOCATION_ACTION, NULL);
|
||||
toolitem = gtk_action_create_tool_item (GTK_ACTION (action));
|
||||
alignment = gtk_bin_get_child (GTK_BIN (toolitem));
|
||||
location_entry = gtk_bin_get_child (GTK_BIN (alignment));
|
||||
location_entry = midori_location_action_entry_for_proxy (toolitem);
|
||||
entry = gtk_bin_get_child (GTK_BIN (location_entry));
|
||||
model = gtk_combo_box_get_model (GTK_COMBO_BOX (location_entry));
|
||||
|
||||
|
@ -129,7 +131,6 @@ completion_fill (void)
|
|||
{
|
||||
MidoriLocationAction* action;
|
||||
GtkWidget* toolitem;
|
||||
GtkWidget* alignment;
|
||||
GtkWidget* location_entry;
|
||||
GtkWidget* entry;
|
||||
GtkTreeModel* model;
|
||||
|
@ -138,8 +139,7 @@ completion_fill (void)
|
|||
|
||||
action = g_object_new (MIDORI_TYPE_LOCATION_ACTION, NULL);
|
||||
toolitem = gtk_action_create_tool_item (GTK_ACTION (action));
|
||||
alignment = gtk_bin_get_child (GTK_BIN (toolitem));
|
||||
location_entry = gtk_bin_get_child (GTK_BIN (alignment));
|
||||
location_entry = midori_location_action_entry_for_proxy (toolitem);
|
||||
entry = gtk_bin_get_child (GTK_BIN (location_entry));
|
||||
|
||||
g_print ("...\n");
|
||||
|
@ -217,7 +217,6 @@ completion_match (void)
|
|||
{
|
||||
MidoriLocationAction* action;
|
||||
GtkWidget* toolitem;
|
||||
GtkWidget* alignment;
|
||||
GtkWidget* location_entry;
|
||||
GtkWidget* entry;
|
||||
GtkEntryCompletion* completion;
|
||||
|
@ -230,8 +229,7 @@ completion_match (void)
|
|||
midori_location_action_thaw (action);
|
||||
|
||||
toolitem = gtk_action_create_tool_item (GTK_ACTION (action));
|
||||
alignment = gtk_bin_get_child (GTK_BIN (toolitem));
|
||||
location_entry = gtk_bin_get_child (GTK_BIN (alignment));
|
||||
location_entry = midori_location_action_entry_for_proxy (toolitem);
|
||||
entry = gtk_bin_get_child (GTK_BIN (location_entry));
|
||||
completion = gtk_entry_get_completion (GTK_ENTRY (entry));
|
||||
g_signal_connect (completion, "insert-prefix",
|
||||
|
|
|
@ -75,6 +75,21 @@ extension_mock_object (void)
|
|||
return extension;
|
||||
}
|
||||
|
||||
static void
|
||||
katze_assert_cmpstrv (gchar** values1,
|
||||
gsize length1,
|
||||
gchar** values2,
|
||||
gsize length2)
|
||||
{
|
||||
gsize i;
|
||||
|
||||
g_assert ((values1 && values2) || (!values1 && !values2));
|
||||
/* g_assert_cmpint (length1, ==, length2); */
|
||||
|
||||
for (i = 0; i < length1; i++)
|
||||
g_assert_cmpstr (values1[i], ==, values2[i]);
|
||||
}
|
||||
|
||||
static void
|
||||
extension_settings (void)
|
||||
{
|
||||
|
@ -83,6 +98,9 @@ extension_settings (void)
|
|||
gboolean nihilist;
|
||||
gint age;
|
||||
const gchar* lastname;
|
||||
gchar* pet_names[] = {"Tiger", "Bonzo", "Streuner", NULL};
|
||||
gchar** names;
|
||||
gsize names_n;
|
||||
|
||||
app = midori_app_new ();
|
||||
extension = extension_mock_object ();
|
||||
|
@ -126,6 +144,27 @@ extension_settings (void)
|
|||
lastname = midori_extension_get_string (extension, "lastname");
|
||||
g_assert_cmpstr (lastname, ==, "Theodor Fontane");
|
||||
midori_extension_deactivate (extension);
|
||||
|
||||
extension = extension_mock_object ();
|
||||
midori_extension_install_string_list (extension, "pets", pet_names, 3);
|
||||
names = midori_extension_get_string_list (extension, "pets", &names_n);
|
||||
katze_assert_cmpstrv (NULL, 0, names, names_n);
|
||||
g_strfreev (names);
|
||||
g_signal_emit_by_name (extension, "activate", app);
|
||||
names = midori_extension_get_string_list (extension, "pets", &names_n);
|
||||
katze_assert_cmpstrv (pet_names, 3, names, names_n);
|
||||
g_strfreev (names);
|
||||
/* names = g_strsplit ("Carla,Fluffy,Goro,Kitty", ",", 0);
|
||||
midori_extension_set_string_list (extension, "pets", names, G_MAXSIZE);
|
||||
g_strfreev (names);
|
||||
names = midori_extension_get_string_list (extension, "pets", &names_n);
|
||||
g_assert_cmpint (names_n, ==, 4); */
|
||||
names = g_strsplit ("Carla,Fluffy,Goro,Kitty", ",", 0);
|
||||
midori_extension_set_string_list (extension, "pets", names, 2);
|
||||
g_strfreev (names);
|
||||
names = midori_extension_get_string_list (extension, "pets", &names_n);
|
||||
g_assert_cmpint (names_n, ==, 2);
|
||||
midori_extension_deactivate (extension);
|
||||
}
|
||||
|
||||
int
|
||||
|
|
221
tests/history.c
Normal file
221
tests/history.c
Normal file
|
@ -0,0 +1,221 @@
|
|||
/*
|
||||
Copyright (C) 2009 Christian Dywan <christian@twotoasts.de>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
See the file COPYING for the full license text.
|
||||
*/
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include "midori.h"
|
||||
#include "midori-history.h"
|
||||
#include "sokoke.h"
|
||||
|
||||
static void
|
||||
history_panel_create (void)
|
||||
{
|
||||
MidoriApp* app;
|
||||
MidoriHistory* history;
|
||||
gpointer value;
|
||||
|
||||
app = g_object_new (MIDORI_TYPE_APP, NULL);
|
||||
|
||||
history = g_object_new (MIDORI_TYPE_HISTORY, NULL);
|
||||
value = katze_object_get_object (history, "app");
|
||||
g_assert (value == NULL);
|
||||
gtk_widget_destroy (GTK_WIDGET (history));
|
||||
|
||||
history = g_object_new (MIDORI_TYPE_HISTORY, "app", app, NULL);
|
||||
value = katze_object_get_object (history, "app");
|
||||
g_assert (value == app);
|
||||
gtk_widget_destroy (GTK_WIDGET (history));
|
||||
|
||||
history = g_object_new (MIDORI_TYPE_HISTORY, NULL);
|
||||
g_object_set (history, "app", app, NULL);
|
||||
value = katze_object_get_object (history, "app");
|
||||
g_assert (value == app);
|
||||
gtk_widget_destroy (GTK_WIDGET (history));
|
||||
}
|
||||
|
||||
static KatzeItem*
|
||||
bookmark_new (const gchar* uri,
|
||||
const gchar* title)
|
||||
{
|
||||
return g_object_new (KATZE_TYPE_ITEM, "uri", uri, "name", title, NULL);
|
||||
}
|
||||
|
||||
static KatzeArray*
|
||||
folder_new (const gchar* title)
|
||||
{
|
||||
KatzeArray* folder;
|
||||
|
||||
folder = katze_array_new (KATZE_TYPE_ARRAY);
|
||||
g_object_set (folder, "name", title, NULL);
|
||||
return folder;
|
||||
}
|
||||
|
||||
static void
|
||||
history_panel_fill (void)
|
||||
{
|
||||
MidoriApp* app;
|
||||
KatzeArray* array;
|
||||
MidoriHistory* history;
|
||||
GList* children;
|
||||
GtkWidget* treeview;
|
||||
GtkTreeModel* model;
|
||||
GtkTreeIter iter;
|
||||
KatzeItem* bookmark;
|
||||
KatzeArray* folder;
|
||||
guint n;
|
||||
gpointer value;
|
||||
|
||||
app = g_object_new (MIDORI_TYPE_APP, NULL);
|
||||
array = katze_array_new (KATZE_TYPE_ARRAY);
|
||||
g_object_set (app, "history", array, NULL);
|
||||
value = katze_object_get_object (app, "history");
|
||||
g_assert (value == array);
|
||||
history = g_object_new (MIDORI_TYPE_HISTORY, "app", app, NULL);
|
||||
children = gtk_container_get_children (GTK_CONTAINER (history));
|
||||
treeview = g_list_nth_data (children, 0);
|
||||
g_list_free (children);
|
||||
g_assert (GTK_IS_TREE_VIEW (treeview));
|
||||
model = gtk_tree_view_get_model (GTK_TREE_VIEW (treeview));
|
||||
g_assert (GTK_IS_TREE_MODEL (model));
|
||||
n = gtk_tree_model_iter_n_children (model, NULL);
|
||||
g_assert_cmpint (n, ==, 0);
|
||||
bookmark = bookmark_new ("http://www.example.com", "Example");
|
||||
katze_array_add_item (array, bookmark);
|
||||
n = gtk_tree_model_iter_n_children (model, NULL);
|
||||
g_assert_cmpint (n, ==, 1);
|
||||
katze_array_remove_item (array, bookmark);
|
||||
n = gtk_tree_model_iter_n_children (model, NULL);
|
||||
g_assert_cmpint (n, ==, 0);
|
||||
bookmark = bookmark_new ("http://www.example.com", "Example");
|
||||
katze_array_add_item (array, bookmark);
|
||||
folder = folder_new ("Empty");
|
||||
katze_array_add_item (array, folder);
|
||||
n = gtk_tree_model_iter_n_children (model, NULL);
|
||||
g_assert_cmpint (n, ==, 2);
|
||||
katze_array_remove_item (array, folder);
|
||||
n = gtk_tree_model_iter_n_children (model, NULL);
|
||||
g_assert_cmpint (n, ==, 1);
|
||||
folder = folder_new ("Empty");
|
||||
katze_array_add_item (array, folder);
|
||||
folder = folder_new ("Kurioses");
|
||||
katze_array_add_item (array, folder);
|
||||
bookmark = bookmark_new ("http://www.ende.de", "Das Ende");
|
||||
katze_array_add_item (folder, bookmark);
|
||||
n = gtk_tree_model_iter_n_children (model, NULL);
|
||||
g_assert_cmpint (n, ==, 3);
|
||||
folder = folder_new ("Miscellaneous");
|
||||
katze_array_add_item (array, folder);
|
||||
gtk_tree_model_iter_nth_child (model, &iter, NULL, 3);
|
||||
n = gtk_tree_model_iter_n_children (model, &iter);
|
||||
g_assert_cmpint (n, ==, 0);
|
||||
bookmark = bookmark_new ("http://thesaurus.reference.com/", "Thesaurus");
|
||||
katze_array_add_item (folder, bookmark);
|
||||
n = gtk_tree_model_iter_n_children (model, &iter);
|
||||
g_assert_cmpint (n, ==, 1);
|
||||
bookmark = bookmark_new ("http://en.wikipedia.org/", "Wikipedia");
|
||||
katze_array_add_item (folder, bookmark);
|
||||
n = gtk_tree_model_iter_n_children (model, &iter);
|
||||
g_assert_cmpint (n, ==, 2);
|
||||
katze_array_remove_item (folder, bookmark);
|
||||
n = gtk_tree_model_iter_n_children (model, &iter);
|
||||
g_assert_cmpint (n, ==, 1);
|
||||
katze_array_remove_item (array, folder);
|
||||
n = gtk_tree_model_iter_n_children (model, NULL);
|
||||
g_assert_cmpint (n, ==, 3);
|
||||
katze_array_add_item (array, folder);
|
||||
/* katze_array_clear (folder);
|
||||
n = gtk_tree_model_iter_n_children (model, &iter);
|
||||
g_assert_cmpint (n, ==, 0); */
|
||||
katze_array_clear (array);
|
||||
n = gtk_tree_model_iter_n_children (model, NULL);
|
||||
g_assert_cmpint (n, ==, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
notify_load_status_cb (GtkWidget* view,
|
||||
GParamSpec* pspec,
|
||||
guint* done)
|
||||
{
|
||||
MidoriLoadStatus status;
|
||||
|
||||
status = midori_view_get_load_status (MIDORI_VIEW (view));
|
||||
if (*done == 2 && status == MIDORI_LOAD_COMMITTED)
|
||||
*done = 1;
|
||||
else if (*done == 1 && status == MIDORI_LOAD_FINISHED)
|
||||
*done = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
history_browser_add (void)
|
||||
{
|
||||
MidoriBrowser* browser;
|
||||
MidoriWebSettings* settings;
|
||||
KatzeArray* array;
|
||||
GtkWidget* view;
|
||||
guint done;
|
||||
KatzeItem* date;
|
||||
gsize i;
|
||||
GtkActionGroup* action_group;
|
||||
GtkAction* action;
|
||||
|
||||
browser = midori_browser_new ();
|
||||
settings = midori_web_settings_new ();
|
||||
array = katze_array_new (KATZE_TYPE_ARRAY);
|
||||
g_object_set (browser, "settings", settings, "history", array, NULL);
|
||||
view = midori_view_new (NULL);
|
||||
midori_browser_add_tab (browser, view);
|
||||
midori_view_set_uri (MIDORI_VIEW (view),
|
||||
"data:text/html;charset=utf-8,<title>Test</title>Test");
|
||||
g_signal_connect (view, "notify::load-status",
|
||||
G_CALLBACK (notify_load_status_cb), &done);
|
||||
done = 2;
|
||||
while (done)
|
||||
gtk_main_iteration ();
|
||||
g_assert_cmpint (katze_array_get_length (array), ==, 1);
|
||||
date = katze_array_get_nth_item (array, 0);
|
||||
g_assert_cmpint (katze_array_get_length (KATZE_ARRAY (date)), ==, 1);
|
||||
i = 0;
|
||||
gtk_widget_show (view);
|
||||
midori_browser_set_current_tab (browser, view);
|
||||
g_assert (midori_browser_get_current_tab (browser) == view);
|
||||
done = 2;
|
||||
action_group = midori_browser_get_action_group (browser);
|
||||
action = gtk_action_group_get_action (action_group, "Location");
|
||||
midori_location_action_set_uri (MIDORI_LOCATION_ACTION (action),
|
||||
"data:text/html;charset=utf-8,<title>Test</title>Test");
|
||||
g_signal_emit_by_name (action, "submit-uri",
|
||||
"data:text/html;charset=utf-8,<title>Test</title>Test", FALSE);
|
||||
while (done)
|
||||
gtk_main_iteration ();
|
||||
g_assert_cmpint (katze_array_get_length (array), ==, 1);
|
||||
date = katze_array_get_nth_item (array, 0);
|
||||
g_assert_cmpint (katze_array_get_length (KATZE_ARRAY (date)), ==, 1);
|
||||
i = 0;
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
char** argv)
|
||||
{
|
||||
/* libSoup uses threads, so we need to initialize threads. */
|
||||
if (!g_thread_supported ()) g_thread_init (NULL);
|
||||
g_test_init (&argc, &argv, NULL);
|
||||
gtk_init_check (&argc, &argv);
|
||||
sokoke_register_stock_items ();
|
||||
|
||||
g_test_add_func ("/history/panel/create", history_panel_create);
|
||||
g_test_add_func ("/history/panel/fill", history_panel_fill);
|
||||
g_test_add_func ("/history/browser/add", history_browser_add);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
|
@ -62,6 +62,7 @@ magic_uri_uri (void)
|
|||
test_input ("http://example.com", "http://example.com");
|
||||
test_input ("example.com", "http://example.com");
|
||||
test_input ("example.com", "http://example.com");
|
||||
test_input ("www.google..com", "http://www.google..com");
|
||||
test_input ("/home/user/midori.html", "file:///home/user/midori.html");
|
||||
a = g_get_current_dir ();
|
||||
b = g_strconcat ("file://", a, G_DIR_SEPARATOR_S, "magic-uri.c", NULL);
|
||||
|
@ -139,6 +140,7 @@ magic_uri_search (void)
|
|||
test_input ("g conference \"April 2, 7:00 am\"", NULL);
|
||||
test_input ("max@mustermann.de", NULL);
|
||||
test_input ("g max@mustermann.de", NULL);
|
||||
test_input ("g inurl:http://twotoasts.de bug", NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
19
wscript
19
wscript
|
@ -22,7 +22,7 @@ import UnitTest
|
|||
|
||||
major = 0
|
||||
minor = 1
|
||||
micro = 6
|
||||
micro = 7
|
||||
|
||||
APPNAME = 'midori'
|
||||
VERSION = str (major) + '.' + str (minor) + '.' + str (micro)
|
||||
|
@ -212,7 +212,6 @@ def configure (conf):
|
|||
print "User documentation: " + user_docs + " (docutils)"
|
||||
print "API documentation: " + api_docs + " (gtk-doc)"
|
||||
print
|
||||
print "Optional run time dependencies:"
|
||||
print "Single instance: " + unique + " (unique)"
|
||||
if unique == 'yes' and conf.check_cfg (modversion='unique-1.0') == '1.0.4':
|
||||
Utils.pprint ('RED', 'unique 1.0.4 found, this version is erroneous.')
|
||||
|
@ -336,9 +335,13 @@ def build (bld):
|
|||
' -o ' + blddir + '/data/logo-shade.png ' + \
|
||||
srcdir + '/data/logo-shade.svg'
|
||||
if not Utils.exec_command (command):
|
||||
bld.install_files ('${DATADIR}/' + APPNAME, blddir + '/data/logo-shade.png')
|
||||
bld.install_files ('${DATADIR}/' + APPNAME + '/res', blddir + '/data/logo-shade.png')
|
||||
else:
|
||||
Utils.pprint ('BLUE', "logo-shade could not be rasterized.")
|
||||
bld.install_files ('${DATADIR}/' + APPNAME + '/res', 'data/error.html')
|
||||
bld.install_files ('${DATADIR}/' + APPNAME + '/res', 'data/speeddial-head.html')
|
||||
bld.install_files ('${DATADIR}/' + APPNAME + '/res', 'data/speeddial.json')
|
||||
bld.install_files ('${DATADIR}/' + APPNAME + '/res', 'data/mootools.js')
|
||||
|
||||
if Options.commands['check']:
|
||||
bld.add_subdirs ('tests')
|
||||
|
@ -393,8 +396,12 @@ def shutdown ():
|
|||
elif Options.options.run:
|
||||
folder = os.path.dirname (Build.bld.env['waf_config_files'][0])
|
||||
try:
|
||||
ext = 'MIDORI_EXTENSION_PATH=' + folder + os.sep + 'extensions'
|
||||
nls = 'NLSPATH=' + folder + os.sep + 'po'
|
||||
relfolder = os.path.relpath (folder)
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
ext = 'MIDORI_EXTENSION_PATH=' + relfolder + os.sep + 'extensions'
|
||||
nls = 'NLSPATH=' + relfolder + os.sep + 'po'
|
||||
lang = os.environ['LANG']
|
||||
try:
|
||||
for lang in os.listdir (folder + os.sep + 'po'):
|
||||
|
@ -410,7 +417,7 @@ def shutdown ():
|
|||
'LC_MESSAGES' + os.sep + APPNAME + '.mo')
|
||||
except:
|
||||
pass
|
||||
command = folder + os.sep + APPNAME + os.sep + APPNAME
|
||||
command = relfolder + os.sep + APPNAME + os.sep + APPNAME
|
||||
print ext + ' ' + nls + ' ' + command
|
||||
Utils.exec_command (ext + ' ' + nls + ' ' + command)
|
||||
except:
|
||||
|
|
Loading…
Reference in a new issue