Imported Upstream version 0.1.6
64
AUTHORS
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
This file is licensed under the terms of the expat license, see the file EXPAT.
|
||||||
|
|
||||||
|
Developers:
|
||||||
|
Christian Dywan <christian@twotoasts.de>
|
||||||
|
|
||||||
|
Contributors:
|
||||||
|
Ori Bernstein <ori@eigenstate.org>
|
||||||
|
Przemek Sitek <el.pescado@gazeta.pl>
|
||||||
|
Enrico Tröger <enrico.troeger@uvena.de>
|
||||||
|
Arnaud Renevier <arenevier@fdn.fr>
|
||||||
|
Dale Whittaker <dayul@users.sf.net>
|
||||||
|
Anders F Björklund <afb@macports.org>
|
||||||
|
Alexander Hesse <alex@phicode.de>
|
||||||
|
Brian Vuyk <brian@brianvuyk.com>
|
||||||
|
Nick Schermer <nick@xfce.org>
|
||||||
|
Matthias Kruk <mkruk@matthiaskruk.de>
|
||||||
|
Johannes Reinhardt <jreinhardt@ist-dein-freund.de>
|
||||||
|
|
||||||
|
Graphics:
|
||||||
|
extension: Nancy Runge <nancy@twotoasts.de>
|
||||||
|
midori: Nancy Runge <nancy@twotoasts.de>
|
||||||
|
news-feed: Nancy Runge <nancy@twotoasts.de>
|
||||||
|
logo-shade: Nancy Runge <nancy@twotoasts.de>
|
||||||
|
|
||||||
|
Translations:
|
||||||
|
da: Per Kongstad <p_kongstad@op.pl>
|
||||||
|
de: Enrico Tröger <enrico.troeger@uvena.de>
|
||||||
|
de: Christian Dywan <christian@twotoasts.de>
|
||||||
|
el: Evaggelos Balaskas <ebalaskas@ebalaskas.gr>
|
||||||
|
en_GB: Bastien Nocera <hadess@hadess.net>
|
||||||
|
en_GB: Abigail Brady <morwen@evilmagic.org>
|
||||||
|
es: Miguel Anxo Bouzada <mbouzada@gmail.com>
|
||||||
|
es: Antonio Sanchez <introlinux@gmail.com>
|
||||||
|
es: Christian Dywan <christian@twotoasts.de>
|
||||||
|
es: Elega <elega@elega.com.ar>
|
||||||
|
et: Kristjan Siimson <epost@ksiimson.se>
|
||||||
|
fi: Elias Julkunen <elias.julkunen@gmail.com>
|
||||||
|
fr: Christian Dywan <christian@twotoasts.de>
|
||||||
|
fr: Adrien Nader <camaradetux@gmail.com>
|
||||||
|
fr: Robert-André Mauchin <zebob.m@pengzone.org>
|
||||||
|
fr: Pascal Gervais <pggervais@yahoo.ca>
|
||||||
|
gl: Miguel Anxo Bouzada <mbouzada@gmail.com>
|
||||||
|
he: Shlomi Israel <sijproject@gmail.com>
|
||||||
|
hu: SZERVÁC Attila <sas@321.hu>
|
||||||
|
id: Andhika Padmawan <andhika.padmawan@gmail.com>
|
||||||
|
it: Sergio Durzu <sergio.durzu@ildeposito.org>
|
||||||
|
ja: Masato Hashimoto <cabezon.hashimoto@gmail.com>
|
||||||
|
nl: Vincent Tunru <projects@vinnl.nl>
|
||||||
|
pl: Przemysław Sitek <el.pescado@gazeta.pl>
|
||||||
|
pl: Lukasz Romanowicz <romanowicz88@gmail.com>
|
||||||
|
pt_PT: Sérgio Marques <smarquespt@gmail.com>
|
||||||
|
ru: Troitskiy Nikita <niktr@mail.ru>
|
||||||
|
ru: Anton Shestakov <engored@ya.ru>
|
||||||
|
sv: Mikael Magnusson <mikachu@comhem.se>
|
||||||
|
tr: Mirat Can Bayrak <MiratCanBayrak@gmail.com>
|
||||||
|
uk: Dmitry Nikitin <luckas_fb@mail.ru>
|
||||||
|
zh_CN: Stanley Zhang <yatzhang@gmail.com>
|
||||||
|
zh_TW: Wei-Lun Chao <william.chao@ossii.com.tw>
|
||||||
|
|
||||||
|
Code from other projects:
|
||||||
|
GTK+/ GdkPixbuf, Matthias Clasen <mclasen@redhat.com>
|
||||||
|
GTK+/ GtkEntry, Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||||
|
Modified by the GTK+ Team and others 1997-2000
|
||||||
|
libSoup/ CookieJarText, Copyright (C) 2008 Xan Lopez <xan@gnome.org>, Dan Winship <danw@gnome.org>
|
504
COPYING
Normal file
|
@ -0,0 +1,504 @@
|
||||||
|
GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
Version 2.1, February 1999
|
||||||
|
|
||||||
|
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
[This is the first released version of the Lesser GPL. It also counts
|
||||||
|
as the successor of the GNU Library Public License, version 2, hence
|
||||||
|
the version number 2.1.]
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The licenses for most software are designed to take away your
|
||||||
|
freedom to share and change it. By contrast, the GNU General Public
|
||||||
|
Licenses are intended to guarantee your freedom to share and change
|
||||||
|
free software--to make sure the software is free for all its users.
|
||||||
|
|
||||||
|
This license, the Lesser General Public License, applies to some
|
||||||
|
specially designated software packages--typically libraries--of the
|
||||||
|
Free Software Foundation and other authors who decide to use it. You
|
||||||
|
can use it too, but we suggest you first think carefully about whether
|
||||||
|
this license or the ordinary General Public License is the better
|
||||||
|
strategy to use in any particular case, based on the explanations below.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom of use,
|
||||||
|
not price. Our General Public Licenses are designed to make sure that
|
||||||
|
you have the freedom to distribute copies of free software (and charge
|
||||||
|
for this service if you wish); that you receive source code or can get
|
||||||
|
it if you want it; that you can change the software and use pieces of
|
||||||
|
it in new free programs; and that you are informed that you can do
|
||||||
|
these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to make restrictions that forbid
|
||||||
|
distributors to deny you these rights or to ask you to surrender these
|
||||||
|
rights. These restrictions translate to certain responsibilities for
|
||||||
|
you if you distribute copies of the library or if you modify it.
|
||||||
|
|
||||||
|
For example, if you distribute copies of the library, whether gratis
|
||||||
|
or for a fee, you must give the recipients all the rights that we gave
|
||||||
|
you. You must make sure that they, too, receive or can get the source
|
||||||
|
code. If you link other code with the library, you must provide
|
||||||
|
complete object files to the recipients, so that they can relink them
|
||||||
|
with the library after making changes to the library and recompiling
|
||||||
|
it. And you must show them these terms so they know their rights.
|
||||||
|
|
||||||
|
We protect your rights with a two-step method: (1) we copyright the
|
||||||
|
library, and (2) we offer you this license, which gives you legal
|
||||||
|
permission to copy, distribute and/or modify the library.
|
||||||
|
|
||||||
|
To protect each distributor, we want to make it very clear that
|
||||||
|
there is no warranty for the free library. Also, if the library is
|
||||||
|
modified by someone else and passed on, the recipients should know
|
||||||
|
that what they have is not the original version, so that the original
|
||||||
|
author's reputation will not be affected by problems that might be
|
||||||
|
introduced by others.
|
||||||
|
|
||||||
|
Finally, software patents pose a constant threat to the existence of
|
||||||
|
any free program. We wish to make sure that a company cannot
|
||||||
|
effectively restrict the users of a free program by obtaining a
|
||||||
|
restrictive license from a patent holder. Therefore, we insist that
|
||||||
|
any patent license obtained for a version of the library must be
|
||||||
|
consistent with the full freedom of use specified in this license.
|
||||||
|
|
||||||
|
Most GNU software, including some libraries, is covered by the
|
||||||
|
ordinary GNU General Public License. This license, the GNU Lesser
|
||||||
|
General Public License, applies to certain designated libraries, and
|
||||||
|
is quite different from the ordinary General Public License. We use
|
||||||
|
this license for certain libraries in order to permit linking those
|
||||||
|
libraries into non-free programs.
|
||||||
|
|
||||||
|
When a program is linked with a library, whether statically or using
|
||||||
|
a shared library, the combination of the two is legally speaking a
|
||||||
|
combined work, a derivative of the original library. The ordinary
|
||||||
|
General Public License therefore permits such linking only if the
|
||||||
|
entire combination fits its criteria of freedom. The Lesser General
|
||||||
|
Public License permits more lax criteria for linking other code with
|
||||||
|
the library.
|
||||||
|
|
||||||
|
We call this license the "Lesser" General Public License because it
|
||||||
|
does Less to protect the user's freedom than the ordinary General
|
||||||
|
Public License. It also provides other free software developers Less
|
||||||
|
of an advantage over competing non-free programs. These disadvantages
|
||||||
|
are the reason we use the ordinary General Public License for many
|
||||||
|
libraries. However, the Lesser license provides advantages in certain
|
||||||
|
special circumstances.
|
||||||
|
|
||||||
|
For example, on rare occasions, there may be a special need to
|
||||||
|
encourage the widest possible use of a certain library, so that it becomes
|
||||||
|
a de-facto standard. To achieve this, non-free programs must be
|
||||||
|
allowed to use the library. A more frequent case is that a free
|
||||||
|
library does the same job as widely used non-free libraries. In this
|
||||||
|
case, there is little to gain by limiting the free library to free
|
||||||
|
software only, so we use the Lesser General Public License.
|
||||||
|
|
||||||
|
In other cases, permission to use a particular library in non-free
|
||||||
|
programs enables a greater number of people to use a large body of
|
||||||
|
free software. For example, permission to use the GNU C Library in
|
||||||
|
non-free programs enables many more people to use the whole GNU
|
||||||
|
operating system, as well as its variant, the GNU/Linux operating
|
||||||
|
system.
|
||||||
|
|
||||||
|
Although the Lesser General Public License is Less protective of the
|
||||||
|
users' freedom, it does ensure that the user of a program that is
|
||||||
|
linked with the Library has the freedom and the wherewithal to run
|
||||||
|
that program using a modified version of the Library.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow. Pay close attention to the difference between a
|
||||||
|
"work based on the library" and a "work that uses the library". The
|
||||||
|
former contains code derived from the library, whereas the latter must
|
||||||
|
be combined with the library in order to run.
|
||||||
|
|
||||||
|
GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
0. This License Agreement applies to any software library or other
|
||||||
|
program which contains a notice placed by the copyright holder or
|
||||||
|
other authorized party saying it may be distributed under the terms of
|
||||||
|
this Lesser General Public License (also called "this License").
|
||||||
|
Each licensee is addressed as "you".
|
||||||
|
|
||||||
|
A "library" means a collection of software functions and/or data
|
||||||
|
prepared so as to be conveniently linked with application programs
|
||||||
|
(which use some of those functions and data) to form executables.
|
||||||
|
|
||||||
|
The "Library", below, refers to any such software library or work
|
||||||
|
which has been distributed under these terms. A "work based on the
|
||||||
|
Library" means either the Library or any derivative work under
|
||||||
|
copyright law: that is to say, a work containing the Library or a
|
||||||
|
portion of it, either verbatim or with modifications and/or translated
|
||||||
|
straightforwardly into another language. (Hereinafter, translation is
|
||||||
|
included without limitation in the term "modification".)
|
||||||
|
|
||||||
|
"Source code" for a work means the preferred form of the work for
|
||||||
|
making modifications to it. For a library, complete source code means
|
||||||
|
all the source code for all modules it contains, plus any associated
|
||||||
|
interface definition files, plus the scripts used to control compilation
|
||||||
|
and installation of the library.
|
||||||
|
|
||||||
|
Activities other than copying, distribution and modification are not
|
||||||
|
covered by this License; they are outside its scope. The act of
|
||||||
|
running a program using the Library is not restricted, and output from
|
||||||
|
such a program is covered only if its contents constitute a work based
|
||||||
|
on the Library (independent of the use of the Library in a tool for
|
||||||
|
writing it). Whether that is true depends on what the Library does
|
||||||
|
and what the program that uses the Library does.
|
||||||
|
|
||||||
|
1. You may copy and distribute verbatim copies of the Library's
|
||||||
|
complete source code as you receive it, in any medium, provided that
|
||||||
|
you conspicuously and appropriately publish on each copy an
|
||||||
|
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||||
|
all the notices that refer to this License and to the absence of any
|
||||||
|
warranty; and distribute a copy of this License along with the
|
||||||
|
Library.
|
||||||
|
|
||||||
|
You may charge a fee for the physical act of transferring a copy,
|
||||||
|
and you may at your option offer warranty protection in exchange for a
|
||||||
|
fee.
|
||||||
|
|
||||||
|
2. You may modify your copy or copies of the Library or any portion
|
||||||
|
of it, thus forming a work based on the Library, and copy and
|
||||||
|
distribute such modifications or work under the terms of Section 1
|
||||||
|
above, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) The modified work must itself be a software library.
|
||||||
|
|
||||||
|
b) You must cause the files modified to carry prominent notices
|
||||||
|
stating that you changed the files and the date of any change.
|
||||||
|
|
||||||
|
c) You must cause the whole of the work to be licensed at no
|
||||||
|
charge to all third parties under the terms of this License.
|
||||||
|
|
||||||
|
d) If a facility in the modified Library refers to a function or a
|
||||||
|
table of data to be supplied by an application program that uses
|
||||||
|
the facility, other than as an argument passed when the facility
|
||||||
|
is invoked, then you must make a good faith effort to ensure that,
|
||||||
|
in the event an application does not supply such function or
|
||||||
|
table, the facility still operates, and performs whatever part of
|
||||||
|
its purpose remains meaningful.
|
||||||
|
|
||||||
|
(For example, a function in a library to compute square roots has
|
||||||
|
a purpose that is entirely well-defined independent of the
|
||||||
|
application. Therefore, Subsection 2d requires that any
|
||||||
|
application-supplied function or table used by this function must
|
||||||
|
be optional: if the application does not supply it, the square
|
||||||
|
root function must still compute square roots.)
|
||||||
|
|
||||||
|
These requirements apply to the modified work as a whole. If
|
||||||
|
identifiable sections of that work are not derived from the Library,
|
||||||
|
and can be reasonably considered independent and separate works in
|
||||||
|
themselves, then this License, and its terms, do not apply to those
|
||||||
|
sections when you distribute them as separate works. But when you
|
||||||
|
distribute the same sections as part of a whole which is a work based
|
||||||
|
on the Library, the distribution of the whole must be on the terms of
|
||||||
|
this License, whose permissions for other licensees extend to the
|
||||||
|
entire whole, and thus to each and every part regardless of who wrote
|
||||||
|
it.
|
||||||
|
|
||||||
|
Thus, it is not the intent of this section to claim rights or contest
|
||||||
|
your rights to work written entirely by you; rather, the intent is to
|
||||||
|
exercise the right to control the distribution of derivative or
|
||||||
|
collective works based on the Library.
|
||||||
|
|
||||||
|
In addition, mere aggregation of another work not based on the Library
|
||||||
|
with the Library (or with a work based on the Library) on a volume of
|
||||||
|
a storage or distribution medium does not bring the other work under
|
||||||
|
the scope of this License.
|
||||||
|
|
||||||
|
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||||
|
License instead of this License to a given copy of the Library. To do
|
||||||
|
this, you must alter all the notices that refer to this License, so
|
||||||
|
that they refer to the ordinary GNU General Public License, version 2,
|
||||||
|
instead of to this License. (If a newer version than version 2 of the
|
||||||
|
ordinary GNU General Public License has appeared, then you can specify
|
||||||
|
that version instead if you wish.) Do not make any other change in
|
||||||
|
these notices.
|
||||||
|
|
||||||
|
Once this change is made in a given copy, it is irreversible for
|
||||||
|
that copy, so the ordinary GNU General Public License applies to all
|
||||||
|
subsequent copies and derivative works made from that copy.
|
||||||
|
|
||||||
|
This option is useful when you wish to copy part of the code of
|
||||||
|
the Library into a program that is not a library.
|
||||||
|
|
||||||
|
4. You may copy and distribute the Library (or a portion or
|
||||||
|
derivative of it, under Section 2) in object code or executable form
|
||||||
|
under the terms of Sections 1 and 2 above provided that you accompany
|
||||||
|
it with the complete corresponding machine-readable source code, which
|
||||||
|
must be distributed under the terms of Sections 1 and 2 above on a
|
||||||
|
medium customarily used for software interchange.
|
||||||
|
|
||||||
|
If distribution of object code is made by offering access to copy
|
||||||
|
from a designated place, then offering equivalent access to copy the
|
||||||
|
source code from the same place satisfies the requirement to
|
||||||
|
distribute the source code, even though third parties are not
|
||||||
|
compelled to copy the source along with the object code.
|
||||||
|
|
||||||
|
5. A program that contains no derivative of any portion of the
|
||||||
|
Library, but is designed to work with the Library by being compiled or
|
||||||
|
linked with it, is called a "work that uses the Library". Such a
|
||||||
|
work, in isolation, is not a derivative work of the Library, and
|
||||||
|
therefore falls outside the scope of this License.
|
||||||
|
|
||||||
|
However, linking a "work that uses the Library" with the Library
|
||||||
|
creates an executable that is a derivative of the Library (because it
|
||||||
|
contains portions of the Library), rather than a "work that uses the
|
||||||
|
library". The executable is therefore covered by this License.
|
||||||
|
Section 6 states terms for distribution of such executables.
|
||||||
|
|
||||||
|
When a "work that uses the Library" uses material from a header file
|
||||||
|
that is part of the Library, the object code for the work may be a
|
||||||
|
derivative work of the Library even though the source code is not.
|
||||||
|
Whether this is true is especially significant if the work can be
|
||||||
|
linked without the Library, or if the work is itself a library. The
|
||||||
|
threshold for this to be true is not precisely defined by law.
|
||||||
|
|
||||||
|
If such an object file uses only numerical parameters, data
|
||||||
|
structure layouts and accessors, and small macros and small inline
|
||||||
|
functions (ten lines or less in length), then the use of the object
|
||||||
|
file is unrestricted, regardless of whether it is legally a derivative
|
||||||
|
work. (Executables containing this object code plus portions of the
|
||||||
|
Library will still fall under Section 6.)
|
||||||
|
|
||||||
|
Otherwise, if the work is a derivative of the Library, you may
|
||||||
|
distribute the object code for the work under the terms of Section 6.
|
||||||
|
Any executables containing that work also fall under Section 6,
|
||||||
|
whether or not they are linked directly with the Library itself.
|
||||||
|
|
||||||
|
6. As an exception to the Sections above, you may also combine or
|
||||||
|
link a "work that uses the Library" with the Library to produce a
|
||||||
|
work containing portions of the Library, and distribute that work
|
||||||
|
under terms of your choice, provided that the terms permit
|
||||||
|
modification of the work for the customer's own use and reverse
|
||||||
|
engineering for debugging such modifications.
|
||||||
|
|
||||||
|
You must give prominent notice with each copy of the work that the
|
||||||
|
Library is used in it and that the Library and its use are covered by
|
||||||
|
this License. You must supply a copy of this License. If the work
|
||||||
|
during execution displays copyright notices, you must include the
|
||||||
|
copyright notice for the Library among them, as well as a reference
|
||||||
|
directing the user to the copy of this License. Also, you must do one
|
||||||
|
of these things:
|
||||||
|
|
||||||
|
a) Accompany the work with the complete corresponding
|
||||||
|
machine-readable source code for the Library including whatever
|
||||||
|
changes were used in the work (which must be distributed under
|
||||||
|
Sections 1 and 2 above); and, if the work is an executable linked
|
||||||
|
with the Library, with the complete machine-readable "work that
|
||||||
|
uses the Library", as object code and/or source code, so that the
|
||||||
|
user can modify the Library and then relink to produce a modified
|
||||||
|
executable containing the modified Library. (It is understood
|
||||||
|
that the user who changes the contents of definitions files in the
|
||||||
|
Library will not necessarily be able to recompile the application
|
||||||
|
to use the modified definitions.)
|
||||||
|
|
||||||
|
b) Use a suitable shared library mechanism for linking with the
|
||||||
|
Library. A suitable mechanism is one that (1) uses at run time a
|
||||||
|
copy of the library already present on the user's computer system,
|
||||||
|
rather than copying library functions into the executable, and (2)
|
||||||
|
will operate properly with a modified version of the library, if
|
||||||
|
the user installs one, as long as the modified version is
|
||||||
|
interface-compatible with the version that the work was made with.
|
||||||
|
|
||||||
|
c) Accompany the work with a written offer, valid for at
|
||||||
|
least three years, to give the same user the materials
|
||||||
|
specified in Subsection 6a, above, for a charge no more
|
||||||
|
than the cost of performing this distribution.
|
||||||
|
|
||||||
|
d) If distribution of the work is made by offering access to copy
|
||||||
|
from a designated place, offer equivalent access to copy the above
|
||||||
|
specified materials from the same place.
|
||||||
|
|
||||||
|
e) Verify that the user has already received a copy of these
|
||||||
|
materials or that you have already sent this user a copy.
|
||||||
|
|
||||||
|
For an executable, the required form of the "work that uses the
|
||||||
|
Library" must include any data and utility programs needed for
|
||||||
|
reproducing the executable from it. However, as a special exception,
|
||||||
|
the materials to be distributed need not include anything that is
|
||||||
|
normally distributed (in either source or binary form) with the major
|
||||||
|
components (compiler, kernel, and so on) of the operating system on
|
||||||
|
which the executable runs, unless that component itself accompanies
|
||||||
|
the executable.
|
||||||
|
|
||||||
|
It may happen that this requirement contradicts the license
|
||||||
|
restrictions of other proprietary libraries that do not normally
|
||||||
|
accompany the operating system. Such a contradiction means you cannot
|
||||||
|
use both them and the Library together in an executable that you
|
||||||
|
distribute.
|
||||||
|
|
||||||
|
7. You may place library facilities that are a work based on the
|
||||||
|
Library side-by-side in a single library together with other library
|
||||||
|
facilities not covered by this License, and distribute such a combined
|
||||||
|
library, provided that the separate distribution of the work based on
|
||||||
|
the Library and of the other library facilities is otherwise
|
||||||
|
permitted, and provided that you do these two things:
|
||||||
|
|
||||||
|
a) Accompany the combined library with a copy of the same work
|
||||||
|
based on the Library, uncombined with any other library
|
||||||
|
facilities. This must be distributed under the terms of the
|
||||||
|
Sections above.
|
||||||
|
|
||||||
|
b) Give prominent notice with the combined library of the fact
|
||||||
|
that part of it is a work based on the Library, and explaining
|
||||||
|
where to find the accompanying uncombined form of the same work.
|
||||||
|
|
||||||
|
8. You may not copy, modify, sublicense, link with, or distribute
|
||||||
|
the Library except as expressly provided under this License. Any
|
||||||
|
attempt otherwise to copy, modify, sublicense, link with, or
|
||||||
|
distribute the Library is void, and will automatically terminate your
|
||||||
|
rights under this License. However, parties who have received copies,
|
||||||
|
or rights, from you under this License will not have their licenses
|
||||||
|
terminated so long as such parties remain in full compliance.
|
||||||
|
|
||||||
|
9. You are not required to accept this License, since you have not
|
||||||
|
signed it. However, nothing else grants you permission to modify or
|
||||||
|
distribute the Library or its derivative works. These actions are
|
||||||
|
prohibited by law if you do not accept this License. Therefore, by
|
||||||
|
modifying or distributing the Library (or any work based on the
|
||||||
|
Library), you indicate your acceptance of this License to do so, and
|
||||||
|
all its terms and conditions for copying, distributing or modifying
|
||||||
|
the Library or works based on it.
|
||||||
|
|
||||||
|
10. Each time you redistribute the Library (or any work based on the
|
||||||
|
Library), the recipient automatically receives a license from the
|
||||||
|
original licensor to copy, distribute, link with or modify the Library
|
||||||
|
subject to these terms and conditions. You may not impose any further
|
||||||
|
restrictions on the recipients' exercise of the rights granted herein.
|
||||||
|
You are not responsible for enforcing compliance by third parties with
|
||||||
|
this License.
|
||||||
|
|
||||||
|
11. If, as a consequence of a court judgment or allegation of patent
|
||||||
|
infringement or for any other reason (not limited to patent issues),
|
||||||
|
conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot
|
||||||
|
distribute so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you
|
||||||
|
may not distribute the Library at all. For example, if a patent
|
||||||
|
license would not permit royalty-free redistribution of the Library by
|
||||||
|
all those who receive copies directly or indirectly through you, then
|
||||||
|
the only way you could satisfy both it and this License would be to
|
||||||
|
refrain entirely from distribution of the Library.
|
||||||
|
|
||||||
|
If any portion of this section is held invalid or unenforceable under any
|
||||||
|
particular circumstance, the balance of the section is intended to apply,
|
||||||
|
and the section as a whole is intended to apply in other circumstances.
|
||||||
|
|
||||||
|
It is not the purpose of this section to induce you to infringe any
|
||||||
|
patents or other property right claims or to contest validity of any
|
||||||
|
such claims; this section has the sole purpose of protecting the
|
||||||
|
integrity of the free software distribution system which is
|
||||||
|
implemented by public license practices. Many people have made
|
||||||
|
generous contributions to the wide range of software distributed
|
||||||
|
through that system in reliance on consistent application of that
|
||||||
|
system; it is up to the author/donor to decide if he or she is willing
|
||||||
|
to distribute software through any other system and a licensee cannot
|
||||||
|
impose that choice.
|
||||||
|
|
||||||
|
This section is intended to make thoroughly clear what is believed to
|
||||||
|
be a consequence of the rest of this License.
|
||||||
|
|
||||||
|
12. If the distribution and/or use of the Library is restricted in
|
||||||
|
certain countries either by patents or by copyrighted interfaces, the
|
||||||
|
original copyright holder who places the Library under this License may add
|
||||||
|
an explicit geographical distribution limitation excluding those countries,
|
||||||
|
so that distribution is permitted only in or among countries not thus
|
||||||
|
excluded. In such case, this License incorporates the limitation as if
|
||||||
|
written in the body of this License.
|
||||||
|
|
||||||
|
13. The Free Software Foundation may publish revised and/or new
|
||||||
|
versions of the Lesser General Public License from time to time.
|
||||||
|
Such new versions will be similar in spirit to the present version,
|
||||||
|
but may differ in detail to address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the Library
|
||||||
|
specifies a version number of this License which applies to it and
|
||||||
|
"any later version", you have the option of following the terms and
|
||||||
|
conditions either of that version or of any later version published by
|
||||||
|
the Free Software Foundation. If the Library does not specify a
|
||||||
|
license version number, you may choose any version ever published by
|
||||||
|
the Free Software Foundation.
|
||||||
|
|
||||||
|
14. If you wish to incorporate parts of the Library into other free
|
||||||
|
programs whose distribution conditions are incompatible with these,
|
||||||
|
write to the author to ask for permission. For software which is
|
||||||
|
copyrighted by the Free Software Foundation, write to the Free
|
||||||
|
Software Foundation; we sometimes make exceptions for this. Our
|
||||||
|
decision will be guided by the two goals of preserving the free status
|
||||||
|
of all derivatives of our free software and of promoting the sharing
|
||||||
|
and reuse of software generally.
|
||||||
|
|
||||||
|
NO WARRANTY
|
||||||
|
|
||||||
|
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||||
|
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||||
|
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||||
|
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||||
|
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||||
|
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||||
|
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||||
|
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||||
|
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||||
|
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||||
|
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||||
|
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||||
|
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||||
|
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||||
|
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||||
|
DAMAGES.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Libraries
|
||||||
|
|
||||||
|
If you develop a new library, and you want it to be of the greatest
|
||||||
|
possible use to the public, we recommend making it free software that
|
||||||
|
everyone can redistribute and change. You can do so by permitting
|
||||||
|
redistribution under these terms (or, alternatively, under the terms of the
|
||||||
|
ordinary General Public License).
|
||||||
|
|
||||||
|
To apply these terms, attach the following notices to the library. It is
|
||||||
|
safest to attach them to the start of each source file to most effectively
|
||||||
|
convey the exclusion of warranty; and each file should have at least the
|
||||||
|
"copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the library's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or your
|
||||||
|
school, if any, to sign a "copyright disclaimer" for the library, if
|
||||||
|
necessary. Here is a sample; alter the names:
|
||||||
|
|
||||||
|
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||||
|
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
|
||||||
|
|
||||||
|
<signature of Ty Coon>, 1 April 1990
|
||||||
|
Ty Coon, President of Vice
|
||||||
|
|
||||||
|
That's all there is to it!
|
||||||
|
|
||||||
|
|
314
ChangeLog
Normal file
|
@ -0,0 +1,314 @@
|
||||||
|
This file is licensed under the terms of the expat license, see the file EXPAT.
|
||||||
|
|
||||||
|
v0.1.6:
|
||||||
|
+ Add Delete All to transferbar
|
||||||
|
+ Show search in context menu
|
||||||
|
+ Implement 'Default' search engine
|
||||||
|
+ Show only icons in Statusbar Features
|
||||||
|
+ Implement Clear private data
|
||||||
|
+ Support News Feed icon and external aggregator
|
||||||
|
+ Fix reloading of Not found pages
|
||||||
|
+ Fixup spaces when middle click opening
|
||||||
|
+ Fix possibly wrong identificaton string
|
||||||
|
+ Optionally search engines in completion
|
||||||
|
+ Optionally Gtk 2.16 entry progress and icon
|
||||||
|
+ Experimental panel detaching
|
||||||
|
+ Support external download manager again
|
||||||
|
+ Implement '-a', '--app' argument
|
||||||
|
+ Implement '-c', '--config' argument
|
||||||
|
+ Fix a bookmark saving issue
|
||||||
|
+ Support data: URIs in the address entry
|
||||||
|
+ Several performance and memory leak fixes
|
||||||
|
+ Load cookies idle to accelerate startup
|
||||||
|
+ Support mailto: links
|
||||||
|
+ Save tab reordering in the session
|
||||||
|
+ Add a Cookie Manager extension
|
||||||
|
+ Fix crashers in Colourful Tabs
|
||||||
|
|
||||||
|
v0.1.5:
|
||||||
|
+ Add a Colorful Tabs extension
|
||||||
|
+ Support downloading with WebKitGTK+ 1.1.3
|
||||||
|
+ Load and save settings of extensions
|
||||||
|
+ Drop internal source view
|
||||||
|
+ Require WebKitGTK+ 1.1.1, Glib 2.16 and libsoup 2.25.2
|
||||||
|
|
||||||
|
v0.1.4:
|
||||||
|
+ Automatic inline find can be disabled
|
||||||
|
+ Implement an Encoding menu
|
||||||
|
+ Add Open all in Tabs for bookmarks and history
|
||||||
|
+ Bookmarks can be moved to other folders
|
||||||
|
+ Fix blank page 'loading' and HTTP authentication
|
||||||
|
+ Display history dates in the local format
|
||||||
|
+ Allow editing of completion items
|
||||||
|
|
||||||
|
v0.1.3:
|
||||||
|
+ Sidepanel can be aligned on the right
|
||||||
|
+ Bookmarks can be organized in folders
|
||||||
|
+ Support find as you type
|
||||||
|
+ Support international domain names
|
||||||
|
+ Tweak location completion
|
||||||
|
+ Provide default search engines
|
||||||
|
+ Integrate with Maemo if available
|
||||||
|
+ Implement Mouse Gestures extension
|
||||||
|
+ Implement a Plugins panel
|
||||||
|
+ Editing the toolbar via a context menu
|
||||||
|
+ Introduce Zoom Text and Images preference
|
||||||
|
|
||||||
|
v0.1.2:
|
||||||
|
+ Open new tabs by clicking on the tabbar
|
||||||
|
+ Refactor and speed up location completion
|
||||||
|
+ Show a Crash dialog after crashes
|
||||||
|
+ Dynamically save files when needed
|
||||||
|
+ Support Back/ Forward mouse buttons
|
||||||
|
+ Support javascript: bookmarklets
|
||||||
|
+ Implement Proxy and Identification string
|
||||||
|
+ Implement cookie storage on disk
|
||||||
|
+ Remove autotooled build system
|
||||||
|
+ Add a new Extensions panel
|
||||||
|
+ Implement opening of new windows
|
||||||
|
+ Display tooltips in Preferences
|
||||||
|
|
||||||
|
v0.1.1:
|
||||||
|
+ Reimplement page holder as an extension
|
||||||
|
+ Introduce a C extension interface
|
||||||
|
+ Introduce unit tests for automated testing
|
||||||
|
+ Implement history based location completion
|
||||||
|
+ Support the Web Inspector in new WebKit versions
|
||||||
|
+ Bookmarkbar properly reflects changes
|
||||||
|
+ Improve overall OS X integration
|
||||||
|
+ Add a Text Editor Preference
|
||||||
|
+ Add a Compat sidebar Preference
|
||||||
|
+ Add an Open external pages in Preference
|
||||||
|
+ Implement source view and cached favicons with libsoup
|
||||||
|
|
||||||
|
v0.1.0:
|
||||||
|
+ Allow for hiding the menubar
|
||||||
|
+ Make the navigationbar customizable
|
||||||
|
+ Implement a History panel
|
||||||
|
+ Remove the HTTP Proxy hack
|
||||||
|
+ Add an Always Show Tabbar Preference
|
||||||
|
+ Implement 404 error pages
|
||||||
|
+ Remove the Primary Clipboard hack
|
||||||
|
+ Provide user documentation
|
||||||
|
+ Display Not found errors when possible
|
||||||
|
+ Remove Stylesheet and Zoom Stepping preferences
|
||||||
|
+ Make dialogs more compact
|
||||||
|
+ Ellipsize extremely long menu items
|
||||||
|
+ Save the trash again when quitting
|
||||||
|
+ Implement enabling/ disabling addons
|
||||||
|
|
||||||
|
v0.0.21:
|
||||||
|
+ Update some translations
|
||||||
|
+ Show progress in location when statusbar is hidden
|
||||||
|
+ Alt + Enter in location should issue a new tab
|
||||||
|
+ Warn at configure time if GVfs is not installed
|
||||||
|
+ Remove GVfs code that could caused huge problems
|
||||||
|
+ Update wad to 1.4.4 to fix building on some systems
|
||||||
|
|
||||||
|
v0.0.20:
|
||||||
|
+ Single instance support using Unique
|
||||||
|
+ Make it clear that WAF is preferred
|
||||||
|
+ Provide an 'extension' icon
|
||||||
|
+ Load user styles from ~/.local/share/midori/styles
|
||||||
|
+ Use Ctrl+Shift+T for Undo Close Tab
|
||||||
|
+ Add "open-tabs-next-to-current" preference
|
||||||
|
+ Use rsvg-convert instead of imagemagick's convert
|
||||||
|
+ @name in the meta data of userscripts is recognized
|
||||||
|
+ Remove "small-toolbar" preference
|
||||||
|
|
||||||
|
v0.0.19:
|
||||||
|
+ Improved Greasemonkey compatibility
|
||||||
|
+ Improve multiple window support
|
||||||
|
+ Use WAF buildscripts, still keeping autotools
|
||||||
|
+ Install and use Midori logo
|
||||||
|
+ Support zooming and printing
|
||||||
|
+ Enhance Gjs functionality
|
||||||
|
+ Refactor in some places, particularly Web Search
|
||||||
|
+ Implement favicons and source view with GIO
|
||||||
|
+ Introduce new fancy location entry
|
||||||
|
+ Detect and show news feeds on web sites
|
||||||
|
+ Save the session as needed, not only on quit
|
||||||
|
+ Reintroduce Download Manager preference
|
||||||
|
|
||||||
|
v0.0.18:
|
||||||
|
+ First attempt at userscripts and extensions.
|
||||||
|
+ Show hidden location/ web search temporarily when needed.
|
||||||
|
+ Turn prefs into MidoriPreferences
|
||||||
|
+ Fix background tabs, strings and new tab focus.
|
||||||
|
+ Switch configuration to MidoriWebSettings.
|
||||||
|
+ Remove 'External programs' logic
|
||||||
|
+ Append the closed tabs items as a proper submenu.
|
||||||
|
+ The location is empty and focused by default
|
||||||
|
+ Implement proper menu positioning.
|
||||||
|
+ Implement the Console panel for script messages.
|
||||||
|
+ Implement localization via Gettext.
|
||||||
|
+ Initial refactoring work, regressions expected
|
||||||
|
+ Build fix: Webkit's header and pkgconfig name have changed.
|
||||||
|
+ Implement Fullscreen mode
|
||||||
|
|
||||||
|
v0.0.17:
|
||||||
|
+ Add a preference to choose a user stylesheet.
|
||||||
|
+ Implement a few preferences with new settings API in WebKit
|
||||||
|
+ Implement Add Bookmark and a small panel toolbar
|
||||||
|
+ Escape search engine name and description.
|
||||||
|
+ Cleanup and WebKit API update
|
||||||
|
+ Make sure selection actions have a widget.
|
||||||
|
+ Allow Find Next and Find Previous when the findbox is hidden.
|
||||||
|
+ Fixed the header of the KatzeThrobber
|
||||||
|
+ Move XBEL implementation to katze.
|
||||||
|
+ Implement a throbber widget.
|
||||||
|
+ Always enable Select All if an editable widget is focussed.
|
||||||
|
+ Previous/ next tab menu items should be disabled when not needed.
|
||||||
|
+ Handle the context menu on button press, not release.
|
||||||
|
+ Open the default page only if there is no session and no uri on the cli.
|
||||||
|
|
||||||
|
v0.0.16:
|
||||||
|
+ Implement editing menu items for the web view.
|
||||||
|
+ Implement the bookmarks panel with editing capabilities.
|
||||||
|
+ Prevent repeated checks for the desktop environment.
|
||||||
|
+ Fix coding style in sokoke.c/ sokoke.h, particularly variable names.
|
||||||
|
+ Don't update the remembered window size when maximized.
|
||||||
|
+ Don't remember the window position but the size only.
|
||||||
|
+ Command line uris should replace the default page.
|
||||||
|
+ More effective status updates and less entry flickering
|
||||||
|
+ Enable inline find for websites
|
||||||
|
+ Make the progressbar work properly again
|
||||||
|
+ Build fix: Adapt WebKit api changes
|
||||||
|
+ Add Tab Size to preferences dialog
|
||||||
|
|
||||||
|
v0.0.15:
|
||||||
|
+ Build fix: Remove search api
|
||||||
|
|
||||||
|
v0.0.14:
|
||||||
|
+ FIX Reopening a tab from the trash causes a crash
|
||||||
|
+ FIX An untitled website keeps the previous title
|
||||||
|
+ FIX When switching tabs the location/ title isn't updated correctly
|
||||||
|
+ FIX Issues with the preferences dialog
|
||||||
|
+ Disable location completion for now
|
||||||
|
+ Save tabtrash to file
|
||||||
|
+ Restructure some code
|
||||||
|
+ Remove color picker and throbber
|
||||||
|
+ Change the license to LGPL
|
||||||
|
|
||||||
|
v0.0.13:
|
||||||
|
+ Adapt WebKit api change, remove engine wrappers, remove dialog hack
|
||||||
|
+ Improve XBEL loading and saving
|
||||||
|
+ Show dialog and backup files on startup errors
|
||||||
|
+ Rearranged and removed some menus
|
||||||
|
|
||||||
|
v0.0.12:
|
||||||
|
+ FIX Improve flawed window creation
|
||||||
|
+ Build with and eliminate all compiler warnings
|
||||||
|
+ Implement clipboard handling menus
|
||||||
|
+ Allow editing of search engines
|
||||||
|
+ Update search engines properly
|
||||||
|
+ Implement bookmarks saving
|
||||||
|
+ Implement session saving and loading
|
||||||
|
+ Cleaned up and revised most code
|
||||||
|
+ Remove legacy webi code
|
||||||
|
|
||||||
|
v0.0.11:
|
||||||
|
+ FIX Back/ forward and initial check menu item states
|
||||||
|
+ Remove rather useless debugging helpers
|
||||||
|
+ Improvements on the preferences
|
||||||
|
+ First attempt at websearch
|
||||||
|
+ Preserve typed uri on tab switch
|
||||||
|
+ First attempt at bookmarks, readonly for now
|
||||||
|
+ Add an animated throbber
|
||||||
|
|
||||||
|
v0.0.10:
|
||||||
|
+ FIX Can crash on context menu or new protocol
|
||||||
|
+ FIX Location isn't updated on tab switch
|
||||||
|
+ Remember last window position and size
|
||||||
|
+ Implement Open menu item
|
||||||
|
+ Allow using location and web search if hidden
|
||||||
|
|
||||||
|
v0.0.9:
|
||||||
|
+ FIX Close tab not insensitive for only one tab
|
||||||
|
+ FIX Debug output is broken
|
||||||
|
+ Display uri when hovering a link
|
||||||
|
+ Implement link uri related part of context menu
|
||||||
|
+ Implement alt/ middle/ shift click link
|
||||||
|
+ First attempt at external protocol handlers
|
||||||
|
+ Initial download manager integration
|
||||||
|
+ Adapt WebKit api prefix change
|
||||||
|
+ More code reorganization and cleanup
|
||||||
|
|
||||||
|
v0.0.8:
|
||||||
|
+ FIX Crash when invoking document context menu via keyboard
|
||||||
|
+ FIX Can't build with debug = yes on GTK+2.12
|
||||||
|
+ Changes related to icons in the gui
|
||||||
|
+ Reorganize code by splitting into several files
|
||||||
|
+ Switch from WebkitGdk to WebkitGtk
|
||||||
|
|
||||||
|
v0.0.7:
|
||||||
|
+ FIX Make settings finally work flawlessly
|
||||||
|
+ FIX Can crash when settings are opened
|
||||||
|
+ Handle all panels in a general way
|
||||||
|
+ Install xdg compliant desktop file
|
||||||
|
+ Implement location and web search menu items
|
||||||
|
+ Display a loading icon on tabs again
|
||||||
|
+ Changed the settings dialog again
|
||||||
|
|
||||||
|
v0.0.6:
|
||||||
|
+ FIX Closing an individual tab doesn't work correctly.
|
||||||
|
+ FIX Doesn't build with gtkwebcore.
|
||||||
|
+ Reimplement menus and and navibar with GtkUIManager.
|
||||||
|
+ Improve document handling in general.
|
||||||
|
+ Finished tab trash menu.
|
||||||
|
+ Implement searchbox default text.
|
||||||
|
+ Remove some gtkwebcore code.
|
||||||
|
+ Use Xfce style dialog in Xfce.
|
||||||
|
+ Implement a few settings.
|
||||||
|
+ Change the panel's look.
|
||||||
|
+ Implement a 'pageholder' panel.
|
||||||
|
|
||||||
|
v0.0.5:
|
||||||
|
+ Implement a few more signals for WebkitGdk.
|
||||||
|
+ Add tooltips to navigation toolbar buttons.
|
||||||
|
+ First attempt on a settings dialog.
|
||||||
|
+ Reimplemented color picker.
|
||||||
|
+ Autocompletion for location and searchbox.
|
||||||
|
+ Changed menu items and incremental findbar.
|
||||||
|
+ Implement tab switching via keyboard.
|
||||||
|
|
||||||
|
v0.0.4:
|
||||||
|
+ FIX Midori segfaults when quitting.
|
||||||
|
+ FIX Config loading and saving is broken.
|
||||||
|
+ Switch WebkitGdk to gtk api and make it the build default.
|
||||||
|
+ Register custom stock icons instead of icon theme magic.
|
||||||
|
+ Implement dynamic window menu.
|
||||||
|
+ First attempt on resizable panels.
|
||||||
|
+ Add about dialog.
|
||||||
|
|
||||||
|
v0.0.3:
|
||||||
|
+ FIX Refresh via menu or shortcut crashes the browser.
|
||||||
|
+ FIX Assertions with and visibility of the progressbar.
|
||||||
|
+ FIX Tabs are not reorderable.
|
||||||
|
+ Package versions in ./configure result and --version output.
|
||||||
|
+ Improve view menu and add tools menu.
|
||||||
|
+ Replace deprecated functions and macros.
|
||||||
|
+ Implement settings saving and loading.
|
||||||
|
+ Fill the common context menu with items
|
||||||
|
+ Allow multiple homepages, seperated by '|'.
|
||||||
|
+ Make code typesafe and C++ friendly.
|
||||||
|
+ Initially support WebkitGdk directly.
|
||||||
|
+ Urlify location inputs automatically.
|
||||||
|
|
||||||
|
v0.0.2:
|
||||||
|
+ Dynamic tab trash menu.
|
||||||
|
+ Update UI when page is changed.
|
||||||
|
+ Enhanced WebkitGtk support.
|
||||||
|
+ New function sokoke_dialog_run_modeless.
|
||||||
|
+ Finished on_document_request_script_prompt.
|
||||||
|
+ One name and version, visible in the user agent.
|
||||||
|
+ Changed some accelerators and menu items.
|
||||||
|
+ Create and destroy color picker properly.
|
||||||
|
+ Ctrl + Wheel resets the zoom level.
|
||||||
|
+ Escape in the location entry resets the uri.
|
||||||
|
+ Use gtk-webcore prefix instead of osb now.
|
||||||
|
+ Save keybindings on quit.
|
||||||
|
+ Fancy autotools build setup.
|
||||||
|
|
||||||
|
v0.0.1:
|
||||||
|
+ Initial release
|
18
EXPAT
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of this software and associated documentation files (the
|
||||||
|
"Software"), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included
|
||||||
|
in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||||
|
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||||
|
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||||
|
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
94
HACKING
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
This file is licensed under the terms of the expat license, see the file EXPAT.
|
||||||
|
|
||||||
|
It is 4 spaces, no tabs, preferrably at 80 columns per line.
|
||||||
|
|
||||||
|
The preferred coding style is explained by example.
|
||||||
|
|
||||||
|
Source file example:
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright
|
||||||
|
LICENSE TEXT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "foo.h"
|
||||||
|
|
||||||
|
#include "bar.h"
|
||||||
|
|
||||||
|
#include <glib.h>
|
||||||
|
|
||||||
|
void
|
||||||
|
foobar (FooEnum bar, const gchar* foo)
|
||||||
|
{
|
||||||
|
gint n, i;
|
||||||
|
|
||||||
|
if (!foo)
|
||||||
|
return;
|
||||||
|
|
||||||
|
#ifdef BAR_STRICT
|
||||||
|
if (bar == FOO_N)
|
||||||
|
{
|
||||||
|
g_print ("illegal value for 'bar'.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* this is an example */
|
||||||
|
switch (bar)
|
||||||
|
{
|
||||||
|
case FOO_FOO:
|
||||||
|
n = bar + 1;
|
||||||
|
break;
|
||||||
|
case FOO_BAR:
|
||||||
|
n = bar + 10;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
n = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
g_print ("%s\n", foo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Header file example:
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright
|
||||||
|
LICENSE TEXT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __FOO_H__
|
||||||
|
#define __FOO_H__ 1
|
||||||
|
|
||||||
|
#ifdef HAVE_BAR_H
|
||||||
|
#define BAR_STRICT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Types */
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
FOO_FOO,
|
||||||
|
FOO_BAR,
|
||||||
|
FOO_N
|
||||||
|
} FooEnum;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
FooEnum foo_bar;
|
||||||
|
} FooStruct;
|
||||||
|
|
||||||
|
/* Declarations */
|
||||||
|
|
||||||
|
void
|
||||||
|
foo_bar (FooEnum bar,
|
||||||
|
const gchar* foo);
|
||||||
|
|
||||||
|
const gchar*
|
||||||
|
foo_foo (FooStruct foo_struct,
|
||||||
|
guint number,
|
||||||
|
gboolean flag);
|
||||||
|
|
||||||
|
#endif /* !__FOO_H__ */
|
56
INSTALL
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
This file is licensed under the terms of the expat license, see the file EXPAT.
|
||||||
|
|
||||||
|
+++ Installing Midori +++
|
||||||
|
|
||||||
|
Building and installing Midori is straightforward.
|
||||||
|
|
||||||
|
Make sure you have Python 2.4 or higher installed.
|
||||||
|
|
||||||
|
Change to the Midori folder on your hard disk in a terminal.
|
||||||
|
|
||||||
|
Run './waf configure'
|
||||||
|
|
||||||
|
Run './waf build'
|
||||||
|
|
||||||
|
You can now run Midori from the build folder like so
|
||||||
|
|
||||||
|
'./waf build --run'
|
||||||
|
|
||||||
|
This is a convenience that will load extensions as well as
|
||||||
|
localizations from the build folder.
|
||||||
|
|
||||||
|
You can install it with './waf install'
|
||||||
|
|
||||||
|
For further options run './waf --help'
|
||||||
|
|
||||||
|
+++ Debugging Midori +++
|
||||||
|
|
||||||
|
Run './waf configure -d full' from the Midori folder.
|
||||||
|
|
||||||
|
Run './waf build'
|
||||||
|
|
||||||
|
Midori is now built with debugging symbols.
|
||||||
|
|
||||||
|
Make sure you have installed 'gdb', the GNU Debugger.
|
||||||
|
|
||||||
|
Run Midori as 'gdb _build_/default/midori/midori'.
|
||||||
|
|
||||||
|
Try to reproduce a crash that you experienced earlier,
|
||||||
|
this time Midori will freeze at the point of the crash.
|
||||||
|
Switch to your terminal, type bt ('backtrace') and hit Return.
|
||||||
|
What you obtained now is a backtrace that should include
|
||||||
|
function names and line numbers.
|
||||||
|
|
||||||
|
If the problem is a warning and not a crash, try this:
|
||||||
|
|
||||||
|
'G_DEBUG=all gdb _build_/default/midori/midori'
|
||||||
|
|
||||||
|
If you are interested in HTTP communication, try this:
|
||||||
|
|
||||||
|
'MIDORI_SOUP_DEBUG=2 _build_/default/midori/midori'
|
||||||
|
|
||||||
|
Where '2' can be a level between 0 and 3.
|
||||||
|
|
||||||
|
For further information a tutorial for gdb and
|
||||||
|
reading up on how you can install debugging
|
||||||
|
symbols for libraries used by Midori are recommended.
|
26
README
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
This file is licensed under the terms of the expat license, see the file EXPAT.
|
||||||
|
|
||||||
|
Midori is a lightweight web browser.
|
||||||
|
|
||||||
|
* Full integration with GTK+2.
|
||||||
|
* Fast rendering with WebKit.
|
||||||
|
* Tabs, windows and session management.
|
||||||
|
* Flexibly configurable Web Search.
|
||||||
|
* User scripts and user styles support.
|
||||||
|
* Straightforward bookmark management.
|
||||||
|
* Customizable and extensible interface.
|
||||||
|
* Extensions written in C.
|
||||||
|
|
||||||
|
Requirements: GTK+ 2.10, WebkitGTK+ 1.1.1, libXML2, libsoup 2.25.2
|
||||||
|
|
||||||
|
Optional: Unique 0.9, libidn, sqlite 3.0, docutils
|
||||||
|
|
||||||
|
For installation instructions read INSTALL.
|
||||||
|
|
||||||
|
Please report comments, suggestions and bugs to:
|
||||||
|
http://www.twotoasts.de/bugs
|
||||||
|
|
||||||
|
And join the IRC channel #midori on irc.freenode.net
|
||||||
|
|
||||||
|
Check for new versions at:
|
||||||
|
http://www.twotoasts.de
|
43
TODO
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
This file is licensed under the terms of the expat license, see the file EXPAT.
|
||||||
|
|
||||||
|
TODO:
|
||||||
|
. Use an update timeout in KatzePropertyProxy instead of only focus-out
|
||||||
|
. Show a loading mouse pointer
|
||||||
|
. Scroll tabs w/o switching tabs
|
||||||
|
. Import and export of the bookmarks file, or using one from a specific path
|
||||||
|
. Custom context menu actions, like in Thunar or Epiphany
|
||||||
|
. Custom tab names
|
||||||
|
. Analogus to blocked popups, blocked scripts moving layers on load (extension)
|
||||||
|
. Per-site blocking of individual elements on a page
|
||||||
|
. Statusbar icon 'cookies blocked', icon 'popups blocked'
|
||||||
|
. Per-site settings accessible via statusbar icons, ie. cookies, popups, plugins
|
||||||
|
. CookieSafe like, a list of cookies, with type, block, allow
|
||||||
|
. Automatic update checks (browser, extensions)?
|
||||||
|
. Auto-group tabs by opener, with colors?
|
||||||
|
. Mark (dogear) a selection so that it isn't cleared implicitly, multiply on one page
|
||||||
|
. Have an internal uri scheme, eg. 'res:', to reference eg. themed icons
|
||||||
|
. 'about:' uris: about, blank, cache, config, plugins
|
||||||
|
. Panel of open tabs (with tree-structure), optional thumbnail-view
|
||||||
|
. Spell check support
|
||||||
|
. Check specific bookmarks for updates automatically (extension)
|
||||||
|
. Mark "new" as well as "actually modified" tabs specially (even over sessions)
|
||||||
|
. SearchEngine: "Show in context menu"
|
||||||
|
. Use libnotify for events, e.g. download finished
|
||||||
|
. Save screenshot of a document?
|
||||||
|
. Right-click a textbox in a search form and choose 'add to websearch'
|
||||||
|
. Honor design principle "no warnings but undo of backups"?
|
||||||
|
. Support widgets 1.0 spec in tool windows and standalone?
|
||||||
|
. Blank page: several custom links, displayed as thumbnails, like Opera?
|
||||||
|
. Handle downloads, optionally in a downloadbar
|
||||||
|
. Protected tabs prompt when attempting to close them
|
||||||
|
. Provide a 'sleep mode' after a crash where open documents are loaded manually
|
||||||
|
. Option to run plugins or scripts only on demand, like NoScript, per-site
|
||||||
|
. Optional http redirection manually or on timeout
|
||||||
|
. Style: none, compatible (b/w), default, [styles], "media", ["media" styles], ...
|
||||||
|
. Mouse pointer coordinates in the status bar (extension)
|
||||||
|
. Draw rectangle with the mouse, x/y/x2/y2 in the statusbar (extension)
|
||||||
|
. Formfill (like Opera's magic wand)
|
||||||
|
. Private browsing mode (no browsing, download or search history)
|
||||||
|
. Shared bookmarks and config
|
||||||
|
. Custom-mode, e.g. hide menubar and use help icon to have a help viewer
|
||||||
|
. Prevent dead tabs: download, aborted page
|
41
TRANSLATE
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
This file is licensed under the terms of the expat license, see the file EXPAT.
|
||||||
|
|
||||||
|
+++ Translating Midori +++
|
||||||
|
|
||||||
|
If you want to translate Midori, here are a few helpful tips.
|
||||||
|
|
||||||
|
To update the localization template:
|
||||||
|
|
||||||
|
./waf build --update-po
|
||||||
|
|
||||||
|
If you want to add a new language 'aa', create it like this:
|
||||||
|
|
||||||
|
cd po
|
||||||
|
msginit -l aa_CC -o aa.po -i midori.pot
|
||||||
|
sed -i 's/PACKAGE/midori/g' aa.po
|
||||||
|
|
||||||
|
Make sure you add your language to the file po/LINGUAS.
|
||||||
|
Just open the file with a text editor and add your code.
|
||||||
|
|
||||||
|
To check your language 'aa' for errors, do this:
|
||||||
|
|
||||||
|
msgfmt -c --check-accelerators=_ aa.po
|
||||||
|
|
||||||
|
To test your changes, run Midori like so:
|
||||||
|
|
||||||
|
./waf build --run
|
||||||
|
|
||||||
|
This is a convenience command that will setup localization in
|
||||||
|
the build folder so you don't need to install translations.
|
||||||
|
|
||||||
|
To run Midori in a particular language, run it like this:
|
||||||
|
|
||||||
|
LANG=fr_FR.utf8 ./waf build --run
|
||||||
|
|
||||||
|
As a general rule, your localization should be based off of the
|
||||||
|
current git repository or the latest midori.pot in git.
|
||||||
|
|
||||||
|
Some strings have comments, starting with 'i18n', which are meant
|
||||||
|
to describe the role of a string to translators.
|
||||||
|
Please don't hesitate to ask for additional descriptive comments
|
||||||
|
for any unclear strings that you are uncertain about.
|
153
configure
vendored
Executable file
|
@ -0,0 +1,153 @@
|
||||||
|
#! /bin/sh
|
||||||
|
|
||||||
|
# waf configure wrapper
|
||||||
|
|
||||||
|
# Fancy colors used to beautify the output a bit.
|
||||||
|
#
|
||||||
|
if [ "$NOCOLOR" ] ; then
|
||||||
|
NORMAL=""
|
||||||
|
BOLD=""
|
||||||
|
RED=""
|
||||||
|
YELLOW=""
|
||||||
|
GREEN=""
|
||||||
|
else
|
||||||
|
NORMAL="\033[0m"
|
||||||
|
BOLD="\033[1m"
|
||||||
|
RED="\033[91m"
|
||||||
|
YELLOW="\033[01;93m"
|
||||||
|
GREEN="\033[92m"
|
||||||
|
fi
|
||||||
|
|
||||||
|
EXIT_SUCCESS=0
|
||||||
|
EXIT_FAILURE=1
|
||||||
|
EXIT_ERROR=2
|
||||||
|
EXIT_BUG=10
|
||||||
|
|
||||||
|
CUR_DIR=$PWD
|
||||||
|
|
||||||
|
#possible relative path
|
||||||
|
WORKINGDIR=`dirname $0`
|
||||||
|
cd $WORKINGDIR
|
||||||
|
#abs path
|
||||||
|
WORKINGDIR=`pwd`
|
||||||
|
cd $CUR_DIR
|
||||||
|
|
||||||
|
# Checks for Python interpreter. Honours $PYTHON if set. Stores path to
|
||||||
|
# interpreter in $PYTHON.
|
||||||
|
#
|
||||||
|
checkPython()
|
||||||
|
{
|
||||||
|
if [ -z "$PYTHON" ] ; then
|
||||||
|
PYTHON=`which python 2>/dev/null`
|
||||||
|
fi
|
||||||
|
printf "Checking for Python\t\t\t: "
|
||||||
|
if [ ! -x "$PYTHON" ] ; then
|
||||||
|
printf $RED"not found!"$NORMAL"\n"
|
||||||
|
echo "Please make sure that the Python interpreter is available in your PATH"
|
||||||
|
echo "or invoke configure using the PYTHON flag, e.g."
|
||||||
|
echo "$ PYTHON=/usr/local/bin/python configure"
|
||||||
|
exit $EXIT_FAILURE
|
||||||
|
fi
|
||||||
|
printf $GREEN"$PYTHON"$NORMAL"\n"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Checks for WAF. Honours $WAF if set. Stores path to 'waf' in $WAF.
|
||||||
|
# Requires that $PYTHON is set.
|
||||||
|
#
|
||||||
|
checkWAF()
|
||||||
|
{
|
||||||
|
printf "Checking for WAF\t\t\t: "
|
||||||
|
#installed miniwaf in sourcedir
|
||||||
|
if [ -z "$WAF" ] ; then
|
||||||
|
if [ -f "${WORKINGDIR}/waf" ] ; then
|
||||||
|
WAF="${WORKINGDIR}/waf"
|
||||||
|
if [ ! -x "$WAF" ] ; then
|
||||||
|
chmod +x $WAF
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if [ -z "$WAF" ] ; then
|
||||||
|
if [ -f "${WORKINGDIR}/waf-light" ] ; then
|
||||||
|
${WORKINGDIR}/waf-light --make-waf
|
||||||
|
WAF="${WORKINGDIR}/waf"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
#global installed waf with waf->waf.py link
|
||||||
|
if [ -z "$WAF" ] ; then
|
||||||
|
WAF=`which waf 2>/dev/null`
|
||||||
|
fi
|
||||||
|
# neither waf nor miniwaf could be found
|
||||||
|
if [ ! -x "$WAF" ] ; then
|
||||||
|
printf $RED"not found"$NORMAL"\n"
|
||||||
|
echo "Go to http://code.google.com/p/waf/"
|
||||||
|
echo "and download a waf version"
|
||||||
|
exit $EXIT_FAILURE
|
||||||
|
else
|
||||||
|
printf $GREEN"$WAF"$NORMAL"\n"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Generates a Makefile. Requires that $WAF is set.
|
||||||
|
#
|
||||||
|
generateMakefile()
|
||||||
|
{
|
||||||
|
cat > Makefile << EOF
|
||||||
|
#!/usr/bin/make -f
|
||||||
|
# Waf Makefile wrapper
|
||||||
|
WAF_HOME=$CUR_DIR
|
||||||
|
|
||||||
|
all:
|
||||||
|
@$WAF build
|
||||||
|
|
||||||
|
all-debug:
|
||||||
|
@$WAF -v build
|
||||||
|
|
||||||
|
all-progress:
|
||||||
|
@$WAF -p build
|
||||||
|
|
||||||
|
install:
|
||||||
|
@if test -n "\$(DESTDIR)"; then \\
|
||||||
|
$WAF install --destdir="\$(DESTDIR)"; \\
|
||||||
|
else \\
|
||||||
|
$WAF install; \\
|
||||||
|
fi;
|
||||||
|
|
||||||
|
.PHONY: install
|
||||||
|
|
||||||
|
uninstall:
|
||||||
|
@if test -n "\$(DESTDIR)"; then \\
|
||||||
|
$WAF uninstall --destdir="\$(DESTDIR)"; \\
|
||||||
|
else \\
|
||||||
|
$WAF uninstall; \\
|
||||||
|
fi;
|
||||||
|
|
||||||
|
clean:
|
||||||
|
@$WAF clean
|
||||||
|
|
||||||
|
distclean:
|
||||||
|
@$WAF distclean
|
||||||
|
@-rm -rf _build_
|
||||||
|
@-rm -f Makefile
|
||||||
|
|
||||||
|
check:
|
||||||
|
@$WAF check
|
||||||
|
|
||||||
|
dist:
|
||||||
|
@$WAF dist
|
||||||
|
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
checkPython
|
||||||
|
checkWAF
|
||||||
|
|
||||||
|
echo "calling waf configure with parameters"
|
||||||
|
$WAF configure $* || exit $EXIT_ERROR
|
||||||
|
|
||||||
|
if [ -f "Makefile" ] ; then
|
||||||
|
echo ""
|
||||||
|
else
|
||||||
|
generateMakefile
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit $EXIT_SUCCESS
|
3
data/com.nokia.midori.service
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
[D-BUS Service]
|
||||||
|
Name=com.nokia.midori
|
||||||
|
Exec=/usr/bin/midori
|
150
data/logo-shade.svg
Normal file
|
@ -0,0 +1,150 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="307.65372"
|
||||||
|
height="350"
|
||||||
|
id="svg2418"
|
||||||
|
sodipodi:version="0.32"
|
||||||
|
inkscape:version="0.46"
|
||||||
|
version="1.0"
|
||||||
|
inkscape:export-filename="/home/user/logo-shade.png"
|
||||||
|
inkscape:export-xdpi="90"
|
||||||
|
inkscape:export-ydpi="90"
|
||||||
|
sodipodi:docname="logo-shade.svg"
|
||||||
|
inkscape:output_extension="org.inkscape.output.svg.inkscape">
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
gridtolerance="10000"
|
||||||
|
guidetolerance="10"
|
||||||
|
objecttolerance="10"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="1.03"
|
||||||
|
inkscape:cx="74.949357"
|
||||||
|
inkscape:cy="143.09941"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:window-width="1253"
|
||||||
|
inkscape:window-height="682"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="22" />
|
||||||
|
<defs
|
||||||
|
id="defs2420">
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient3412">
|
||||||
|
<stop
|
||||||
|
id="stop3414"
|
||||||
|
offset="0"
|
||||||
|
style="stop-color:#ffffff;stop-opacity:0.59836066;" />
|
||||||
|
<stop
|
||||||
|
id="stop3416"
|
||||||
|
offset="1"
|
||||||
|
style="stop-color:#97f839;stop-opacity:0;" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient3458">
|
||||||
|
<stop
|
||||||
|
id="stop3460"
|
||||||
|
offset="0"
|
||||||
|
style="stop-color:#88fe38;stop-opacity:1;" />
|
||||||
|
<stop
|
||||||
|
id="stop3462"
|
||||||
|
offset="1"
|
||||||
|
style="stop-color:#ffffff;stop-opacity:0;" />
|
||||||
|
</linearGradient>
|
||||||
|
<inkscape:perspective
|
||||||
|
id="perspective2426"
|
||||||
|
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
|
||||||
|
inkscape:vp_z="744.09448 : 526.18109 : 1"
|
||||||
|
inkscape:vp_y="0 : 1000 : 0"
|
||||||
|
inkscape:vp_x="0 : 526.18109 : 1"
|
||||||
|
sodipodi:type="inkscape:persp3d" />
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient3458-648">
|
||||||
|
<stop
|
||||||
|
id="stop2423"
|
||||||
|
offset="0"
|
||||||
|
style="stop-color:#bababa;stop-opacity:1;" />
|
||||||
|
<stop
|
||||||
|
id="stop2425"
|
||||||
|
offset="1"
|
||||||
|
style="stop-color:#ffffff;stop-opacity:0;" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient3412-967">
|
||||||
|
<stop
|
||||||
|
id="stop2429"
|
||||||
|
offset="0"
|
||||||
|
style="stop-color:#ffffff;stop-opacity:0.59836066;" />
|
||||||
|
<stop
|
||||||
|
id="stop2431"
|
||||||
|
offset="1"
|
||||||
|
style="stop-color:#bababa;stop-opacity:0;" />
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
<metadata
|
||||||
|
id="metadata2423">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:creator>
|
||||||
|
<cc:Agent>
|
||||||
|
<dc:title>Nancy Runge <nancy@twotoasts.de></dc:title>
|
||||||
|
</cc:Agent>
|
||||||
|
</dc:creator>
|
||||||
|
<cc:license
|
||||||
|
rdf:resource="http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html" />
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
transform="translate(-280.66056,-644.09745)"
|
||||||
|
id="layer1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
inkscape:label="Layer 1">
|
||||||
|
<g
|
||||||
|
id="g2546"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:#bcbcbc;stroke-opacity:1"
|
||||||
|
transform="matrix(2.7318355,0,0,2.7318355,-731.07518,-1421.3016)">
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="ccsscccsc"
|
||||||
|
id="path3598"
|
||||||
|
d="M 479.0149,757.44485 C 463.33929,760.3524 390.05715,768.6009 373.75783,823.05659 C 368.99751,841.48441 371.67629,866.55457 392.88608,865.62945 C 394.38911,865.56465 394.54399,866.0597 395.07871,867.32475 C 403.8111,887.98406 426.11314,884.657 430.13518,876.12801 C 430.41248,875.53998 429.75994,876.1331 430.13518,876.12801 C 452.01909,891.1113 463.94687,870.37434 470.8404,851.89287 C 479.26032,835.85799 484.40756,769.09622 479.90163,773.41411 C 403.13312,846.97906 403.28006,782.18757 479.0149,757.44485"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#bcbcbc;stroke-width:2.79349113000000004;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||||
|
<path
|
||||||
|
id="path3606"
|
||||||
|
d="M 394.6271,866.42646 C 389.11843,841.31269 395.51037,833.40754 398.10369,830.14819"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#bcbcbc;stroke-width:2.79349113000000004;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
sodipodi:nodetypes="cc" />
|
||||||
|
<path
|
||||||
|
id="path3608"
|
||||||
|
d="M 430.04511,875.57142 C 422.884,860.41673 424.07276,847.90995 429.16085,838.58891"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:#bcbcbc;stroke-width:2.79349113000000004;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
sodipodi:nodetypes="cc" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g2551"
|
||||||
|
style="fill:#e8e8e8;fill-opacity:1;stroke:none"
|
||||||
|
transform="matrix(2.7318355,0,0,2.7318355,-731.59243,-1420.9344)">
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="cccccccccccc"
|
||||||
|
id="path2553"
|
||||||
|
d="M 447.08573,768.31725 C 436.04919,774.1595 397.92257,781.58705 381.33359,820.27881 C 377.02863,833.88105 375.31278,851.44676 387.44516,857.54862 C 385.16801,848.06163 387.57514,834.11288 393.43272,827.57808 C 397.5473,821.96506 405.70797,826.00823 403.09775,831.29165 C 401.29067,836.46522 394.76631,843.8643 399.87669,863.28435 C 404.09154,874.85534 415.25599,879.58634 422.43347,873.92723 C 414.92666,858.12585 420.32228,825.17457 433.92305,832.69366 C 440.70334,836.82119 424.80942,848.38632 435.43821,869.81488 C 448.73626,880.75776 460.15899,863.55615 464.02222,850.63024 C 472.18961,832.82769 477.16809,790.8233 475.1786,786.29359 C 410.97397,845.50147 395.61545,794.24336 447.07098,768.23969"
|
||||||
|
style="fill:#e8e8e8;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:2.79349113;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 6.3 KiB |
14
data/midori.desktop.in
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
[Desktop Entry]
|
||||||
|
Version=1.0
|
||||||
|
Type=Application
|
||||||
|
_Name=Midori
|
||||||
|
_GenericName=Web Browser
|
||||||
|
_Comment=Lightweight web browser
|
||||||
|
Categories=GTK;Network;WebBrowser;
|
||||||
|
MimeType=text/html;text/xml;application/xhtml+xml;application/xml;
|
||||||
|
Exec=midori %u
|
||||||
|
Icon=midori
|
||||||
|
Terminal=false
|
||||||
|
StartupNotify=true
|
||||||
|
X-Osso-Type=application/x-executable
|
||||||
|
X-Osso-Service=midori
|
21
data/search
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
|
||||||
|
[Google]
|
||||||
|
name=Google
|
||||||
|
text=Web Search
|
||||||
|
uri=http://www.google.com/search?q=%s
|
||||||
|
icon=
|
||||||
|
token=g
|
||||||
|
|
||||||
|
[Wikipedia]
|
||||||
|
name=Wikipedia
|
||||||
|
text=The free encyclopedia
|
||||||
|
uri=http://en.wikipedia.org/wiki/%s
|
||||||
|
icon=
|
||||||
|
token=wp
|
||||||
|
|
||||||
|
[TheFreeDictionary]
|
||||||
|
name=The Free Dictionary
|
||||||
|
text=Dictionary, Encyclopedia and Thesaurus
|
||||||
|
uri=http://www.thefreedictionary.com/%s
|
||||||
|
icon=
|
||||||
|
token=fd
|
34
docs/api/wscript_build
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
#! /usr/bin/env python
|
||||||
|
# WAF build script for midori
|
||||||
|
# This file is licensed under the terms of the expat license, see the file EXPAT.
|
||||||
|
|
||||||
|
import pproc as subprocess
|
||||||
|
|
||||||
|
for module in ('midori', 'katze'):
|
||||||
|
try:
|
||||||
|
if not os.access ('_build_', os.F_OK):
|
||||||
|
Utils.check_dir ('_build_')
|
||||||
|
if not os.access ('_build_/docs', os.F_OK):
|
||||||
|
Utils.check_dir ('_build_/docs')
|
||||||
|
if not os.access ('_build_/docs/api', os.F_OK):
|
||||||
|
Utils.check_dir ('_build_/docs/api')
|
||||||
|
subprocess.call (['gtkdoc-scan', '--module=' + module,
|
||||||
|
'--source-dir=' + module, '--output-dir=_build_/docs/api/' + module,
|
||||||
|
'--rebuild-sections', '--rebuild-types'])
|
||||||
|
os.chdir ('_build_/docs/api/' + module)
|
||||||
|
subprocess.call (['gtkdoc-mktmpl', '--module=' + module,
|
||||||
|
'--output-dir=.' + module])
|
||||||
|
subprocess.call (['gtkdoc-mkdb', '--module=' + module,
|
||||||
|
'--source-dir=.', '--output-dir=xml',
|
||||||
|
'--source-suffixes=c,h', '--output-format=xml',
|
||||||
|
'--default-includes=%s/%s.h' % (module, module),
|
||||||
|
'--sgml-mode', '--main-sgml-file=%s.sgml' % module])
|
||||||
|
if not os.access ('html', os.F_OK):
|
||||||
|
Utils.check_dir ('html')
|
||||||
|
os.chdir ('html')
|
||||||
|
subprocess.call (['gtkdoc-mkhtml', module, '../%s.sgml' % module])
|
||||||
|
Utils.pprint ('YELLOW', "Created documentation for %s." % module)
|
||||||
|
os.chdir ('../../../../..')
|
||||||
|
except Exception, msg:
|
||||||
|
print msg
|
||||||
|
Utils.pprint ('RED', "Failed to create documentation for %s." % module)
|
114
docs/user/midori.css
Normal file
|
@ -0,0 +1,114 @@
|
||||||
|
/*
|
||||||
|
:Author: Christian Dywan
|
||||||
|
:Contact: christian@twotoasts.de
|
||||||
|
:Copyright: This file is licensed under the terms of the expat license, see the file EXPAT.
|
||||||
|
|
||||||
|
Stylesheet for Midori's documentation based on a version of Enrico Troeger.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@media screen {
|
||||||
|
|
||||||
|
body {
|
||||||
|
background-color: #f6fff3;
|
||||||
|
color: #404040;
|
||||||
|
margin-left: 0.4em;
|
||||||
|
width: 60em;
|
||||||
|
font-size: 90%;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #013100;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:visited {
|
||||||
|
color: #7E558E;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1, h2, h3 {
|
||||||
|
font-family: sans-serif;
|
||||||
|
color: #002a00;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
border-top: 1px dotted;
|
||||||
|
margin-top: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1.title {
|
||||||
|
text-align: left }
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
margin-top: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2.subtitle {
|
||||||
|
text-align: left }
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
padding-left: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote, pre {
|
||||||
|
border: 1px solid;
|
||||||
|
padding: 0.4em;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote {
|
||||||
|
font-family: sans-serif;
|
||||||
|
background-color: #DBEDD5;
|
||||||
|
border: 1px dotted;
|
||||||
|
border-left: 4px solid;
|
||||||
|
border-color: #9FD98C;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
background-color: #deefd4;
|
||||||
|
border: 1px dotted;
|
||||||
|
border-left: 4px solid;
|
||||||
|
border-color: #9acb7d;
|
||||||
|
}
|
||||||
|
|
||||||
|
tt, pre, code {
|
||||||
|
color: #002a00;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
border: 1px solid #9acb7f;
|
||||||
|
}
|
||||||
|
|
||||||
|
th {
|
||||||
|
border: none;
|
||||||
|
background-color: #9acb7d;
|
||||||
|
}
|
||||||
|
|
||||||
|
tr:nth-child(even) {
|
||||||
|
background-color: #d3eac6;
|
||||||
|
}
|
||||||
|
|
||||||
|
td {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.docinfo-name {
|
||||||
|
color: #002a00;
|
||||||
|
}
|
||||||
|
|
||||||
|
p.admonition-title {
|
||||||
|
color: #990000;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.note {
|
||||||
|
margin: 1em 3em;
|
||||||
|
padding: 0em;
|
||||||
|
}
|
||||||
|
|
||||||
|
dt {
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
254
docs/user/midori.txt
Normal file
|
@ -0,0 +1,254 @@
|
||||||
|
.. |(version)| replace:: 0.1.6
|
||||||
|
|
||||||
|
'''''''
|
||||||
|
Midori
|
||||||
|
'''''''
|
||||||
|
|
||||||
|
-----------------------------------------
|
||||||
|
A lightweight, portable GTK+ web browser
|
||||||
|
-----------------------------------------
|
||||||
|
|
||||||
|
:Authors: Christian Dywan
|
||||||
|
:Date: $Date: 2009-04-14 18:00:35 +0100 (Tue, 14 Apr 2009) $
|
||||||
|
:Version: |(version)|
|
||||||
|
|
||||||
|
Copyright © 2008-2009
|
||||||
|
|
||||||
|
This documentation is distributed under the terms of the
|
||||||
|
`GNU Lesser General Public License`_; 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.
|
||||||
|
|
||||||
|
|
||||||
|
.. contents::
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Introduction
|
||||||
|
''''''''''''
|
||||||
|
|
||||||
|
|
||||||
|
What is Midori
|
||||||
|
--------------
|
||||||
|
|
||||||
|
Midori is a lightweight and portable web browser based on Gtk+. The
|
||||||
|
interface is designed to be intuitive yet powerful.
|
||||||
|
|
||||||
|
* Full integration with GTK+2.
|
||||||
|
* Fast rendering with WebKit.
|
||||||
|
* Tabs, windows and session management.
|
||||||
|
* Flexibly configurable Web Search.
|
||||||
|
* User scripts and user styles support.
|
||||||
|
* Straightforward bookmark management.
|
||||||
|
* Customizable and extensible interface.
|
||||||
|
* Extensions written in C.
|
||||||
|
|
||||||
|
|
||||||
|
Running Midori
|
||||||
|
--------------
|
||||||
|
|
||||||
|
|
||||||
|
* If you are using a graphical desktop environment you will usually find
|
||||||
|
Midori in the menu under Network.
|
||||||
|
|
||||||
|
* You can also run Midori from a console or a Run dialog.
|
||||||
|
See also `Command line usage`.
|
||||||
|
|
||||||
|
$ midori
|
||||||
|
|
||||||
|
A browser window appears where you can start navigating the web right away.
|
||||||
|
|
||||||
|
|
||||||
|
The main interface
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
|
||||||
|
The main browser window consists of a few basic elements:
|
||||||
|
|
||||||
|
|
||||||
|
* The menubar. It's pretty much standardized and gives you access to
|
||||||
|
allmost all features, many of the items have a keyboard shortcut by default.
|
||||||
|
See also `Keyboard shortcuts`_.
|
||||||
|
|
||||||
|
* The navigationbar. It lets you open tabs, go back and forward, enter
|
||||||
|
addresses, search the web and reopen closed tabs.
|
||||||
|
See also `The navigationbar`.
|
||||||
|
|
||||||
|
* The sidepanel. It takes a pretty central role in the functionality it provides,
|
||||||
|
yet it can be hidden and resized to not distract you.
|
||||||
|
See also `The sidepanel`.
|
||||||
|
|
||||||
|
* The statusbar. It displays informational text when hovering something
|
||||||
|
with a pointer. That's it.
|
||||||
|
|
||||||
|
|
||||||
|
Taking a closer look
|
||||||
|
''''''''''''''''''''
|
||||||
|
|
||||||
|
|
||||||
|
Command line usage
|
||||||
|
------------------
|
||||||
|
|
||||||
|
|
||||||
|
Running Midori normally works as follows:
|
||||||
|
|
||||||
|
|
||||||
|
* $ midori
|
||||||
|
|
||||||
|
Just run a new instance of Midori. If an instance of Midori is already
|
||||||
|
running a new window in that instance will be opened.
|
||||||
|
|
||||||
|
* $ midori [URIs]
|
||||||
|
|
||||||
|
You can supply any number of URIs to open as arguments. If you have a
|
||||||
|
saved session or a running instance they will be added to the last
|
||||||
|
active window.
|
||||||
|
|
||||||
|
* $ midori [URI1]|[URI2]|...
|
||||||
|
|
||||||
|
You can separate URIS by a pipe (|) as well. They are handled as if you
|
||||||
|
provided all URIs as separate arguments.
|
||||||
|
|
||||||
|
* $ midori --run [JAVASCRIPT]
|
||||||
|
|
||||||
|
If you pass the filename of a javascript Midori will attempt to run
|
||||||
|
the contents of the file as javascript code.
|
||||||
|
|
||||||
|
|
||||||
|
Note that support for opening tabs in an existing instance depends on
|
||||||
|
your build and may not be available on some platforms.
|
||||||
|
|
||||||
|
|
||||||
|
The following arguments are supported if you call Midori from a command line.
|
||||||
|
|
||||||
|
|
||||||
|
+-------+--------------------+------------------------------------------------+
|
||||||
|
| Short | Long option | Function |
|
||||||
|
+=======+====================+================================================+
|
||||||
|
| -a | --app | Run ADDRESS as a web application |
|
||||||
|
+-------+--------------------+------------------------------------------------+
|
||||||
|
| -c | --config | Use FOLDER as configuration folder |
|
||||||
|
+-------+--------------------+------------------------------------------------+
|
||||||
|
| -r | --run | Run the specified filename as javascript |
|
||||||
|
+-------+--------------------+------------------------------------------------+
|
||||||
|
| -V | --version | Show version information and exit. |
|
||||||
|
+-------+--------------------+------------------------------------------------+
|
||||||
|
|
||||||
|
|
||||||
|
Configuration files
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
|
||||||
|
The configuration files in Midori that save related states are by default
|
||||||
|
stored in the folder ~/.config/midori in the home directory. It is possible
|
||||||
|
to use a different folder by specifying '--config' on the command line.
|
||||||
|
|
||||||
|
The files stored in the primary configuration folder are the following:
|
||||||
|
|
||||||
|
+----------------+------------------------------------------------------------+
|
||||||
|
| Filename | Contents |
|
||||||
|
+================+============================================================+
|
||||||
|
| accels | Keyboard shortcuts, GtkAccelMap resource |
|
||||||
|
+----------------+------------------------------------------------------------+
|
||||||
|
| bookmarks.xbel | Bookmarks, XBEL |
|
||||||
|
+----------------+------------------------------------------------------------+
|
||||||
|
| config | Preferences, text key file |
|
||||||
|
+----------------+------------------------------------------------------------+
|
||||||
|
| cookies.txt | Cookies, Mozilla text cookies |
|
||||||
|
+----------------+------------------------------------------------------------+
|
||||||
|
| history.db | History, sqlite3 |
|
||||||
|
+----------------+------------------------------------------------------------+
|
||||||
|
| running | A file created to track whether Midori quit cleanly |
|
||||||
|
+----------------+------------------------------------------------------------+
|
||||||
|
| session.xbel | The current or last session, ie. open tabs, |
|
||||||
|
+----------------+------------------------------------------------------------+
|
||||||
|
| tabtrash.xbel | The 10 last closed tabs |
|
||||||
|
+----------------+------------------------------------------------------------+
|
||||||
|
|
||||||
|
Note that generally manual modifications to these files aren't recommended. As
|
||||||
|
an exception, while Midori is *not* running, it is possible to edit or
|
||||||
|
replace the 'bookmarks.xbel' as long as it is valid XBEL/ XML.
|
||||||
|
|
||||||
|
Currently while Midori is running it will happily overwrite files as needed and
|
||||||
|
never read back any changes.
|
||||||
|
|
||||||
|
Incidentally Midori will recognize readonly files and not write modifications
|
||||||
|
to readonly files back to disk. This can be useful for kiosk systems where
|
||||||
|
particular changes shouldn't be saved.
|
||||||
|
|
||||||
|
|
||||||
|
Keyboard shortcuts
|
||||||
|
------------------
|
||||||
|
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
The navigationbar
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
|
||||||
|
The navigationbar is the primary toolbar containing notably back and forward
|
||||||
|
buttons, the location entry and a search entry. Except for the location entry
|
||||||
|
any item can be removed and others can be added by right-clicking the toolbar
|
||||||
|
and using the Add and Remove menu items.
|
||||||
|
|
||||||
|
|
||||||
|
The sidepanel
|
||||||
|
-------------
|
||||||
|
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
Extensions
|
||||||
|
----------
|
||||||
|
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
Frequently asked questions
|
||||||
|
''''''''''''''''''''''''''
|
||||||
|
|
||||||
|
|
||||||
|
How do you pronounce Midori and what does it mean anyway?
|
||||||
|
---------------------------------------------------------
|
||||||
|
|
||||||
|
Pronounce it "midoɺi", with a Bavarian/ Japanese "r" or "Mee-Doh-Ree"
|
||||||
|
in English or read it Italian. The name comes from the Japanese word
|
||||||
|
緑 (みどり) for the colour "green".
|
||||||
|
|
||||||
|
|
||||||
|
What does the logo mean?
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
The paw of a green cat. Obviously. Also it resembles the letter "M"
|
||||||
|
in "Midori". The curving is supposed to emphasize speed.
|
||||||
|
|
||||||
|
|
||||||
|
On which platforms does Midori run currently?
|
||||||
|
---------------------------------------------
|
||||||
|
|
||||||
|
Midori is basically very portable and should run on all platforms that
|
||||||
|
its dependencies support.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Under which license is Midori distributed?
|
||||||
|
------------------------------------------
|
||||||
|
|
||||||
|
Midori, documentation and all delivered artwork are licensed under the LGPL2.
|
||||||
|
|
||||||
|
|
||||||
|
GNU Lesser General Public License
|
||||||
|
'''''''''''''''''''''''''''''''''
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
Version 2.1, February 1999
|
||||||
|
|
||||||
|
FIXME: Provide full license text
|
||||||
|
|
151
extensions/colorful-tabs.c
Normal file
|
@ -0,0 +1,151 @@
|
||||||
|
/*
|
||||||
|
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>
|
||||||
|
|
||||||
|
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,
|
||||||
|
MidoriExtension* extension)
|
||||||
|
{
|
||||||
|
GtkWidget* label;
|
||||||
|
SoupURI* uri;
|
||||||
|
gchar* hash;
|
||||||
|
gchar* colorstr;
|
||||||
|
GdkColor color;
|
||||||
|
|
||||||
|
label = midori_view_get_proxy_tab_label (view);
|
||||||
|
if (!midori_extension_get_boolean (extension, "tint"))
|
||||||
|
{
|
||||||
|
gtk_widget_modify_bg (label, GTK_STATE_NORMAL, NULL);
|
||||||
|
gtk_widget_modify_bg (label, GTK_STATE_ACTIVE, NULL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Find a color that is unique to an address. We merely compute
|
||||||
|
a hash value, pick the first 6 + 1 characters and turn the
|
||||||
|
first into a hash sign, ie. #8b424b. In case a color is too
|
||||||
|
dark, we lighten it up a litte. Finally we make the event box
|
||||||
|
visible and modify its background. */
|
||||||
|
|
||||||
|
if ((uri = soup_uri_new (midori_view_get_display_uri (view))) && uri->host)
|
||||||
|
{
|
||||||
|
hash = g_compute_checksum_for_string (G_CHECKSUM_MD5, uri->host, -1);
|
||||||
|
soup_uri_free (uri);
|
||||||
|
colorstr = g_strndup (hash, 6 + 1);
|
||||||
|
g_free (hash);
|
||||||
|
colorstr[0] = '#';
|
||||||
|
gdk_color_parse (colorstr, &color);
|
||||||
|
if (color.red < 35000)
|
||||||
|
color.red += 25000 + (color.blue + 1) / 2;
|
||||||
|
if (color.green < 35000)
|
||||||
|
color.green += 25000 + (color.red + 1) / 2;
|
||||||
|
if (color.blue < 35000)
|
||||||
|
color.blue += 25000 + (color.green + 1) / 2;
|
||||||
|
gtk_event_box_set_visible_window (GTK_EVENT_BOX (label), TRUE);
|
||||||
|
gtk_widget_modify_bg (label, GTK_STATE_NORMAL, &color);
|
||||||
|
gtk_widget_modify_bg (label, GTK_STATE_ACTIVE, &color);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gtk_widget_modify_bg (label, GTK_STATE_NORMAL, NULL);
|
||||||
|
gtk_widget_modify_bg (label, GTK_STATE_ACTIVE, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
colorful_tabs_browser_add_tab_cb (MidoriBrowser* browser,
|
||||||
|
MidoriView* view,
|
||||||
|
MidoriExtension* extension)
|
||||||
|
{
|
||||||
|
g_signal_connect (view, "notify::uri",
|
||||||
|
G_CALLBACK (colorful_tabs_view_notify_uri_cb), extension);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
colorful_tabs_app_add_browser_cb (MidoriApp* app,
|
||||||
|
MidoriBrowser* browser,
|
||||||
|
MidoriExtension* extension)
|
||||||
|
{
|
||||||
|
GtkWidget* statusbar;
|
||||||
|
GtkWidget* bbox;
|
||||||
|
GtkWidget* button;
|
||||||
|
|
||||||
|
statusbar = katze_object_get_object (browser, "statusbar");
|
||||||
|
bbox = gtk_hbox_new (FALSE, 0);
|
||||||
|
button = gtk_check_button_new_with_label (_("Tint tabs distinctly"));
|
||||||
|
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button),
|
||||||
|
midori_extension_get_boolean (extension, "tint"));
|
||||||
|
gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, FALSE, 2);
|
||||||
|
gtk_widget_show (button);
|
||||||
|
gtk_widget_show (bbox);
|
||||||
|
gtk_box_pack_start (GTK_BOX (statusbar), bbox, FALSE, FALSE, 3);
|
||||||
|
|
||||||
|
g_signal_connect (button, "toggled",
|
||||||
|
G_CALLBACK (colorful_tabs_button_toggled_cb), extension);
|
||||||
|
g_signal_connect (browser, "add-tab",
|
||||||
|
G_CALLBACK (colorful_tabs_browser_add_tab_cb), extension);
|
||||||
|
g_signal_connect (extension, "deactivate",
|
||||||
|
G_CALLBACK (colorful_tabs_deactivate_cb), bbox);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
colorful_tabs_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++)))
|
||||||
|
colorful_tabs_app_add_browser_cb (app, browser, extension);
|
||||||
|
g_signal_connect (app, "add-browser",
|
||||||
|
G_CALLBACK (colorful_tabs_app_add_browser_cb), extension);
|
||||||
|
}
|
||||||
|
|
||||||
|
MidoriExtension*
|
||||||
|
extension_init (void)
|
||||||
|
{
|
||||||
|
MidoriExtension* extension = g_object_new (MIDORI_TYPE_EXTENSION,
|
||||||
|
"name", _("Colorful Tabs"),
|
||||||
|
"description", _("Tint each tab distinctly"),
|
||||||
|
"version", "0.1",
|
||||||
|
"authors", "Christian Dywan <christian@twotoasts.de>",
|
||||||
|
NULL);
|
||||||
|
midori_extension_install_boolean (extension, "tint", FALSE);
|
||||||
|
|
||||||
|
g_signal_connect (extension, "activate",
|
||||||
|
G_CALLBACK (colorful_tabs_activate_cb), NULL);
|
||||||
|
|
||||||
|
return extension;
|
||||||
|
}
|
970
extensions/cookie-manager.c
Normal file
|
@ -0,0 +1,970 @@
|
||||||
|
/*
|
||||||
|
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 <time.h>
|
||||||
|
#include <midori/midori.h>
|
||||||
|
#include <webkit/webkit.h>
|
||||||
|
#include <midori/gtkiconentry.h>
|
||||||
|
|
||||||
|
#define CM_DEBUG 0
|
||||||
|
|
||||||
|
#define STOCK_COOKIE_MANAGER "cookie-manager"
|
||||||
|
#define CM_EMPTY_LABEL_TEXT "\n\n\n\n\n\n"
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
COL_NAME,
|
||||||
|
COL_COOKIE,
|
||||||
|
COL_VISIBLE,
|
||||||
|
N_COLUMNS
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct _CMData
|
||||||
|
{
|
||||||
|
MidoriApp *app;
|
||||||
|
MidoriBrowser *browser;
|
||||||
|
MidoriExtension *extension;
|
||||||
|
|
||||||
|
GtkWidget *panel_page;
|
||||||
|
GtkWidget *desc_label;
|
||||||
|
GtkWidget *delete_button;
|
||||||
|
GtkWidget *delete_popup_button;
|
||||||
|
GtkWidget *delete_all_button;
|
||||||
|
GtkWidget *expand_buttons[4];
|
||||||
|
|
||||||
|
GtkWidget *treeview;
|
||||||
|
GtkTreeStore *store;
|
||||||
|
GtkTreeModel *filter;
|
||||||
|
|
||||||
|
GtkWidget *filter_entry;
|
||||||
|
|
||||||
|
GtkWidget *popup_menu;
|
||||||
|
|
||||||
|
SoupCookieJar *jar;
|
||||||
|
GSList *cookies;
|
||||||
|
|
||||||
|
guint timer_id;
|
||||||
|
gint ignore_changed_count;
|
||||||
|
} CMData;
|
||||||
|
|
||||||
|
static void cm_app_add_browser_cb(MidoriApp *app, MidoriBrowser *browser, MidoriExtension *ext);
|
||||||
|
static void cm_filter_tree(CMData *cmdata, const gchar *filter_text);
|
||||||
|
static void cm_deactivate_cb(MidoriExtension *extension, CMData *cmdata);
|
||||||
|
static void cm_jar_changed_cb(SoupCookieJar *jar, SoupCookie *old, SoupCookie *new, CMData *cmdata);
|
||||||
|
|
||||||
|
|
||||||
|
#if CM_DEBUG
|
||||||
|
static gchar *cookie_to_string(SoupCookie *c)
|
||||||
|
{
|
||||||
|
if (c != NULL)
|
||||||
|
{
|
||||||
|
static gchar s[256]; /* this might be too small but for debugging it should be ok */
|
||||||
|
g_snprintf(s, sizeof(s), "%s\t%s = %s", c->domain, c->name, c->value);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
static void cm_free_cookie_list(CMData *cmdata)
|
||||||
|
{
|
||||||
|
if (cmdata->cookies != NULL)
|
||||||
|
{
|
||||||
|
GSList *l;
|
||||||
|
|
||||||
|
for (l = cmdata->cookies; l != NULL; l = g_slist_next(l))
|
||||||
|
soup_cookie_free(l->data);
|
||||||
|
g_slist_free(cmdata->cookies);
|
||||||
|
cmdata->cookies = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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);
|
||||||
|
g_signal_handlers_disconnect_by_func(cmdata->jar, cm_jar_changed_cb, cmdata);
|
||||||
|
|
||||||
|
cm_free_cookie_list(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 && GTK_IS_WIDGET(cmdata->panel_page))
|
||||||
|
gtk_widget_destroy(cmdata->panel_page);
|
||||||
|
|
||||||
|
gtk_widget_destroy(cmdata->popup_menu);
|
||||||
|
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_refresh_store(CMData *cmdata)
|
||||||
|
{
|
||||||
|
GSList *l;
|
||||||
|
GHashTable *parents;
|
||||||
|
GtkTreeIter iter;
|
||||||
|
GtkTreeIter *parent_iter;
|
||||||
|
SoupCookie *cookie;
|
||||||
|
const gchar *filter_text;
|
||||||
|
|
||||||
|
g_object_ref(cmdata->filter);
|
||||||
|
gtk_tree_view_set_model(GTK_TREE_VIEW(cmdata->treeview), NULL);
|
||||||
|
|
||||||
|
gtk_tree_store_clear(cmdata->store);
|
||||||
|
|
||||||
|
/* free the old list */
|
||||||
|
cm_free_cookie_list(cmdata);
|
||||||
|
|
||||||
|
cmdata->cookies = soup_cookie_jar_all_cookies(cmdata->jar);
|
||||||
|
|
||||||
|
/* Hashtable holds domain names as keys, the corresponding tree iters as values */
|
||||||
|
parents = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
|
||||||
|
|
||||||
|
for (l = cmdata->cookies; l != NULL; l = g_slist_next(l))
|
||||||
|
{
|
||||||
|
cookie = l->data;
|
||||||
|
|
||||||
|
/* look for the parent item for the current domain name and create it if it doesn't exist */
|
||||||
|
if ((parent_iter = (GtkTreeIter*) g_hash_table_lookup(parents, cookie->domain)) == NULL)
|
||||||
|
{
|
||||||
|
parent_iter = g_new0(GtkTreeIter, 1);
|
||||||
|
|
||||||
|
gtk_tree_store_append(cmdata->store, parent_iter, NULL);
|
||||||
|
gtk_tree_store_set(cmdata->store, parent_iter,
|
||||||
|
COL_NAME, cookie->domain,
|
||||||
|
COL_COOKIE, NULL,
|
||||||
|
COL_VISIBLE, TRUE,
|
||||||
|
-1);
|
||||||
|
|
||||||
|
g_hash_table_insert(parents, g_strdup(cookie->domain), parent_iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
gtk_tree_store_append(cmdata->store, &iter, parent_iter);
|
||||||
|
gtk_tree_store_set(cmdata->store, &iter,
|
||||||
|
COL_NAME, cookie->name,
|
||||||
|
COL_COOKIE, cookie,
|
||||||
|
COL_VISIBLE, TRUE,
|
||||||
|
-1);
|
||||||
|
}
|
||||||
|
g_hash_table_destroy(parents);
|
||||||
|
|
||||||
|
gtk_tree_view_set_model(GTK_TREE_VIEW(cmdata->treeview), GTK_TREE_MODEL(cmdata->filter));
|
||||||
|
g_object_unref(cmdata->filter);
|
||||||
|
|
||||||
|
/* if a filter is set, apply it again */
|
||||||
|
filter_text = gtk_entry_get_text(GTK_ENTRY(cmdata->filter_entry));
|
||||||
|
if (*filter_text != '\0')
|
||||||
|
{
|
||||||
|
cm_filter_tree(cmdata, filter_text);
|
||||||
|
gtk_tree_view_expand_all(GTK_TREE_VIEW(cmdata->treeview));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static gchar *cm_get_cookie_description_text(SoupCookie *cookie)
|
||||||
|
{
|
||||||
|
static gchar date_fmt[512];
|
||||||
|
gchar *expires;
|
||||||
|
gchar *text;
|
||||||
|
time_t expiration_time;
|
||||||
|
const struct tm *tm;
|
||||||
|
|
||||||
|
g_return_val_if_fail(cookie != NULL, NULL);
|
||||||
|
|
||||||
|
if (cookie->expires != NULL)
|
||||||
|
{
|
||||||
|
expiration_time = soup_date_to_time_t(cookie->expires);
|
||||||
|
tm = localtime(&expiration_time);
|
||||||
|
/* even if some gcc versions complain about "%c", there is nothing wrong with and here we
|
||||||
|
* want to use it */
|
||||||
|
strftime(date_fmt, sizeof(date_fmt), "%c", tm);
|
||||||
|
expires = date_fmt;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
expires = _("At the end of the session");
|
||||||
|
|
||||||
|
text = g_markup_printf_escaped(
|
||||||
|
_("<b>Host</b>: %s\n<b>Name</b>: %s\n<b>Value</b>: %s\n<b>Path</b>: %s\n"
|
||||||
|
"<b>Secure</b>: %s\n<b>Expires</b>: %s"),
|
||||||
|
cookie->domain,
|
||||||
|
cookie->name,
|
||||||
|
cookie->value,
|
||||||
|
cookie->path,
|
||||||
|
cookie->secure ? _("Yes") : _("No"),
|
||||||
|
expires);
|
||||||
|
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void cm_set_button_sensitiveness(CMData *cmdata, gboolean set)
|
||||||
|
{
|
||||||
|
guint i, len;
|
||||||
|
gboolean expand_set = (gtk_tree_model_iter_n_children(cmdata->filter, NULL) > 0);
|
||||||
|
|
||||||
|
gtk_widget_set_sensitive(cmdata->delete_popup_button, set);
|
||||||
|
gtk_widget_set_sensitive(cmdata->delete_button, set);
|
||||||
|
|
||||||
|
gtk_widget_set_sensitive(cmdata->delete_all_button, expand_set);
|
||||||
|
len = G_N_ELEMENTS(cmdata->expand_buttons);
|
||||||
|
for (i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
gtk_widget_set_sensitive(cmdata->expand_buttons[i], expand_set);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void cm_tree_selection_changed_cb(GtkTreeSelection *selection, CMData *cmdata)
|
||||||
|
{
|
||||||
|
GtkTreeIter iter, iter_store;
|
||||||
|
GtkTreeModel *model;
|
||||||
|
gchar *text;
|
||||||
|
gboolean valid = TRUE;
|
||||||
|
gboolean delete_possible = FALSE;
|
||||||
|
SoupCookie *cookie;
|
||||||
|
|
||||||
|
if (! gtk_tree_selection_get_selected(selection, &model, &iter))
|
||||||
|
valid = FALSE;
|
||||||
|
else
|
||||||
|
gtk_tree_model_filter_convert_iter_to_child_iter(GTK_TREE_MODEL_FILTER(model),
|
||||||
|
&iter_store, &iter);
|
||||||
|
|
||||||
|
if (valid && gtk_tree_store_iter_is_valid(cmdata->store, &iter_store))
|
||||||
|
{
|
||||||
|
delete_possible = TRUE;
|
||||||
|
|
||||||
|
gtk_tree_model_get(model, &iter, COL_COOKIE, &cookie, -1);
|
||||||
|
if (cookie != NULL)
|
||||||
|
{
|
||||||
|
text = cm_get_cookie_description_text(cookie);
|
||||||
|
|
||||||
|
gtk_label_set_markup(GTK_LABEL(cmdata->desc_label), text);
|
||||||
|
|
||||||
|
g_free(text);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
valid = FALSE;
|
||||||
|
}
|
||||||
|
/* This is a bit hack'ish but we add some empty lines to get a minimum height of the
|
||||||
|
* label at the bottom without any font size calculation. */
|
||||||
|
if (! valid)
|
||||||
|
gtk_label_set_text(GTK_LABEL(cmdata->desc_label), CM_EMPTY_LABEL_TEXT);
|
||||||
|
cm_set_button_sensitiveness(cmdata, delete_possible);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static gboolean cm_tree_button_press_event_cb(GtkWidget *widget, GdkEventButton *ev, CMData *cmdata)
|
||||||
|
{
|
||||||
|
if (ev->type == GDK_2BUTTON_PRESS)
|
||||||
|
{
|
||||||
|
GtkTreeSelection *selection;
|
||||||
|
GtkTreeModel *model;
|
||||||
|
GtkTreeIter iter;
|
||||||
|
|
||||||
|
selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(widget));
|
||||||
|
|
||||||
|
if (gtk_tree_selection_get_selected(selection, &model, &iter))
|
||||||
|
{
|
||||||
|
/* double click on parent node expands/collapses it */
|
||||||
|
if (gtk_tree_model_iter_has_child(model, &iter))
|
||||||
|
{
|
||||||
|
GtkTreePath *path = gtk_tree_model_get_path(model, &iter);
|
||||||
|
|
||||||
|
if (gtk_tree_view_row_expanded(GTK_TREE_VIEW(widget), path))
|
||||||
|
gtk_tree_view_collapse_row(GTK_TREE_VIEW(widget), path);
|
||||||
|
else
|
||||||
|
gtk_tree_view_expand_row(GTK_TREE_VIEW(widget), path, FALSE);
|
||||||
|
|
||||||
|
gtk_tree_path_free(path);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void cm_tree_show_popup_menu(GtkWidget *widget, GdkEventButton *event, CMData *cmdata)
|
||||||
|
{
|
||||||
|
gint button, event_time;
|
||||||
|
|
||||||
|
if (event != NULL)
|
||||||
|
{
|
||||||
|
button = event->button;
|
||||||
|
event_time = event->time;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
button = 0;
|
||||||
|
event_time = gtk_get_current_event_time ();
|
||||||
|
}
|
||||||
|
|
||||||
|
gtk_menu_popup(GTK_MENU(cmdata->popup_menu), NULL, NULL, NULL, NULL, button, event_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static gboolean cm_tree_popup_menu_cb(GtkWidget *widget, CMData *cmdata)
|
||||||
|
{
|
||||||
|
cm_tree_show_popup_menu(widget, NULL, cmdata);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static gboolean cm_tree_button_release_event_cb(GtkWidget *widget, GdkEventButton *ev, CMData *cmdata)
|
||||||
|
{
|
||||||
|
if (ev->button == 3)
|
||||||
|
{
|
||||||
|
cm_tree_show_popup_menu(widget, ev, cmdata);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void cm_tree_popup_collapse_activate_cb(GtkCheckMenuItem *item, CMData *cmdata)
|
||||||
|
{
|
||||||
|
gtk_tree_view_collapse_all(GTK_TREE_VIEW(cmdata->treeview));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void cm_tree_popup_expand_activate_cb(GtkCheckMenuItem *item, CMData *cmdata)
|
||||||
|
{
|
||||||
|
gtk_tree_view_expand_all(GTK_TREE_VIEW(cmdata->treeview));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void cm_store_remove(CMData *cmdata, GtkTreeIter *iter_model)
|
||||||
|
{
|
||||||
|
GtkTreeIter iter_store;
|
||||||
|
|
||||||
|
gtk_tree_model_filter_convert_iter_to_child_iter(
|
||||||
|
GTK_TREE_MODEL_FILTER(cmdata->filter), &iter_store, iter_model);
|
||||||
|
gtk_tree_store_remove(cmdata->store, &iter_store);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void cm_delete_cookie(GtkTreeModel *model, GtkTreeIter *child, CMData *cmdata)
|
||||||
|
{
|
||||||
|
SoupCookie *cookie;
|
||||||
|
|
||||||
|
gtk_tree_model_get(model, child, COL_COOKIE, &cookie, -1);
|
||||||
|
|
||||||
|
if (cookie != NULL)
|
||||||
|
{
|
||||||
|
cmdata->ignore_changed_count++;
|
||||||
|
|
||||||
|
soup_cookie_jar_delete_cookie(cmdata->jar, cookie);
|
||||||
|
/* the SoupCookie object is freed when the whole list gets updated */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void cm_button_delete_clicked_cb(GtkToolButton *button, CMData *cmdata)
|
||||||
|
{
|
||||||
|
GtkTreeIter iter, iter_store, child;
|
||||||
|
GtkTreeModel *model;
|
||||||
|
GtkTreeSelection *selection;
|
||||||
|
|
||||||
|
selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(cmdata->treeview));
|
||||||
|
if (! gtk_tree_selection_get_selected(selection, &model, &iter))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (gtk_tree_model_iter_has_child(model, &iter))
|
||||||
|
{
|
||||||
|
GtkTreePath *path = gtk_tree_model_get_path(model, &iter);
|
||||||
|
|
||||||
|
while (gtk_tree_model_iter_children(model, &child, &iter))
|
||||||
|
{
|
||||||
|
cm_delete_cookie(model, &child, cmdata);
|
||||||
|
cm_store_remove(cmdata, &child);
|
||||||
|
/* we retrieve again the iter at path because it got invalid by the delete operation */
|
||||||
|
gtk_tree_model_get_iter(model, &iter, path);
|
||||||
|
}
|
||||||
|
gtk_tree_path_free(path);
|
||||||
|
/* remove/hide the parent */
|
||||||
|
gtk_tree_model_filter_convert_iter_to_child_iter(GTK_TREE_MODEL_FILTER(cmdata->filter),
|
||||||
|
&iter_store, &iter);
|
||||||
|
if (gtk_tree_model_iter_has_child(GTK_TREE_MODEL(cmdata->store), &iter_store))
|
||||||
|
gtk_tree_store_set(cmdata->store, &iter_store, COL_VISIBLE, FALSE, -1);
|
||||||
|
else
|
||||||
|
cm_store_remove(cmdata, &iter);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GtkTreePath *path_store, *path_model;
|
||||||
|
|
||||||
|
gtk_tree_model_filter_convert_iter_to_child_iter(GTK_TREE_MODEL_FILTER(cmdata->filter),
|
||||||
|
&iter_store, &iter);
|
||||||
|
path_store = gtk_tree_model_get_path(GTK_TREE_MODEL(cmdata->store), &iter_store);
|
||||||
|
path_model = gtk_tree_model_get_path(model, &iter);
|
||||||
|
|
||||||
|
cm_delete_cookie(model, &iter, cmdata);
|
||||||
|
gtk_tree_store_remove(cmdata->store, &iter_store);
|
||||||
|
|
||||||
|
/* check whether the parent still has children, otherwise delete it */
|
||||||
|
if (gtk_tree_path_up(path_store))
|
||||||
|
{
|
||||||
|
gtk_tree_model_get_iter(GTK_TREE_MODEL(cmdata->store), &iter_store, path_store);
|
||||||
|
if (! gtk_tree_model_iter_has_child(GTK_TREE_MODEL(cmdata->store), &iter_store))
|
||||||
|
/* remove the empty parent */
|
||||||
|
gtk_tree_store_remove(cmdata->store, &iter_store);
|
||||||
|
}
|
||||||
|
/* now for the filter model */
|
||||||
|
if (gtk_tree_path_up(path_model))
|
||||||
|
{
|
||||||
|
gtk_tree_model_get_iter(model, &iter, path_model);
|
||||||
|
if (! gtk_tree_model_iter_has_child(model, &iter))
|
||||||
|
{
|
||||||
|
gtk_tree_model_filter_convert_iter_to_child_iter(
|
||||||
|
GTK_TREE_MODEL_FILTER(cmdata->filter), &iter_store, &iter);
|
||||||
|
/* hide the empty parent */
|
||||||
|
gtk_tree_store_set(cmdata->store, &iter_store, COL_VISIBLE, FALSE, -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gtk_tree_path_free(path_store);
|
||||||
|
gtk_tree_path_free(path_model);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void cm_delete_all_cookies_real(CMData *cmdata)
|
||||||
|
{
|
||||||
|
GtkTreeIter iter, iter_store, child;
|
||||||
|
GtkTreePath *path_first, *path;
|
||||||
|
GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(cmdata->treeview));
|
||||||
|
|
||||||
|
path_first = gtk_tree_path_new_first();
|
||||||
|
while (gtk_tree_model_get_iter(model, &iter, path_first))
|
||||||
|
{
|
||||||
|
path = gtk_tree_model_get_path(model, &iter);
|
||||||
|
while (gtk_tree_model_iter_children(model, &child, &iter))
|
||||||
|
{
|
||||||
|
cm_delete_cookie(model, &child, cmdata);
|
||||||
|
cm_store_remove(cmdata, &child);
|
||||||
|
/* we retrieve again the iter at path because it got invalid by the delete operation */
|
||||||
|
gtk_tree_model_get_iter(model, &iter, path);
|
||||||
|
}
|
||||||
|
gtk_tree_path_free(path);
|
||||||
|
/* remove/hide the parent */
|
||||||
|
gtk_tree_model_filter_convert_iter_to_child_iter(GTK_TREE_MODEL_FILTER(cmdata->filter),
|
||||||
|
&iter_store, &iter);
|
||||||
|
if (gtk_tree_model_iter_has_child(GTK_TREE_MODEL(cmdata->store), &iter_store))
|
||||||
|
gtk_tree_store_set(cmdata->store, &iter_store, COL_VISIBLE, FALSE, -1);
|
||||||
|
else
|
||||||
|
cm_store_remove(cmdata, &iter);
|
||||||
|
}
|
||||||
|
gtk_tree_path_free(path_first);
|
||||||
|
|
||||||
|
cm_set_button_sensitiveness(cmdata, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void cm_button_delete_all_clicked_cb(GtkToolButton *button, CMData *cmdata)
|
||||||
|
{
|
||||||
|
GtkWidget *dialog;
|
||||||
|
GtkWidget *toplevel = gtk_widget_get_toplevel(GTK_WIDGET(button));
|
||||||
|
const gchar *filter_text;
|
||||||
|
|
||||||
|
dialog = gtk_message_dialog_new(GTK_WINDOW(toplevel),
|
||||||
|
GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||||
|
GTK_MESSAGE_QUESTION,
|
||||||
|
GTK_BUTTONS_YES_NO,
|
||||||
|
_("Do you really want to delete all cookies?"));
|
||||||
|
|
||||||
|
gtk_window_set_title(GTK_WINDOW(dialog), _("Question"));
|
||||||
|
/* steal Midori's icon :) */
|
||||||
|
gtk_window_set_icon_name(GTK_WINDOW(dialog), gtk_window_get_icon_name(GTK_WINDOW(toplevel)));
|
||||||
|
|
||||||
|
filter_text = gtk_entry_get_text(GTK_ENTRY(cmdata->filter_entry));
|
||||||
|
if (*filter_text != '\0')
|
||||||
|
{
|
||||||
|
gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),
|
||||||
|
_("Only the visible cookies are deleted which match the entered filter string."));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_YES)
|
||||||
|
cm_delete_all_cookies_real(cmdata);
|
||||||
|
|
||||||
|
gtk_widget_destroy(dialog);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void cm_tree_drag_data_get_cb(GtkWidget *widget, GdkDragContext *drag_context,
|
||||||
|
GtkSelectionData *data, guint info, guint ltime, CMData *cmdata)
|
||||||
|
{
|
||||||
|
GtkTreeIter iter, iter_store;
|
||||||
|
GtkTreeSelection *selection;
|
||||||
|
GtkTreeModel *model;
|
||||||
|
|
||||||
|
selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(cmdata->treeview));
|
||||||
|
if (! gtk_tree_selection_get_selected(selection, &model, &iter))
|
||||||
|
return;
|
||||||
|
|
||||||
|
gtk_tree_model_filter_convert_iter_to_child_iter(
|
||||||
|
GTK_TREE_MODEL_FILTER(model), &iter_store, &iter);
|
||||||
|
|
||||||
|
if (gtk_tree_store_iter_is_valid(cmdata->store, &iter_store))
|
||||||
|
{
|
||||||
|
SoupCookie *cookie;
|
||||||
|
gchar *name, *text;
|
||||||
|
|
||||||
|
gtk_tree_model_get(model, &iter, COL_NAME, &name, COL_COOKIE, &cookie, -1);
|
||||||
|
|
||||||
|
if (cookie == NULL && name != NULL)
|
||||||
|
{
|
||||||
|
/* skip a leading dot */
|
||||||
|
text = (*name == '.') ? name + 1 : name;
|
||||||
|
|
||||||
|
gtk_selection_data_set_text(data, text, -1);
|
||||||
|
}
|
||||||
|
g_free(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if GTK_CHECK_VERSION(2, 12, 0)
|
||||||
|
static gboolean cm_tree_query_tooltip(GtkWidget *widget, gint x, gint y, gboolean keyboard_mode,
|
||||||
|
GtkTooltip *tooltip, CMData *cmdata)
|
||||||
|
{
|
||||||
|
GtkTreeIter iter;
|
||||||
|
GtkTreeModel *model;
|
||||||
|
|
||||||
|
if (gtk_tree_view_get_tooltip_context(GTK_TREE_VIEW(widget), &x, &y,
|
||||||
|
keyboard_mode, &model, NULL, &iter))
|
||||||
|
{
|
||||||
|
gchar *tooltip_text;
|
||||||
|
SoupCookie *cookie;
|
||||||
|
|
||||||
|
gtk_tree_model_get(model, &iter, COL_COOKIE, &cookie, -1);
|
||||||
|
|
||||||
|
if (cookie == NULL) /* not an item */
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
tooltip_text = cm_get_cookie_description_text(cookie);
|
||||||
|
|
||||||
|
gtk_tooltip_set_markup(tooltip, tooltip_text);
|
||||||
|
|
||||||
|
g_free(tooltip_text);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
static gboolean cm_filter_match(const gchar *haystack, const gchar *needle)
|
||||||
|
{
|
||||||
|
gchar *haystack_lowered, *needle_lowered;
|
||||||
|
gboolean result;
|
||||||
|
|
||||||
|
/* empty strings always match */
|
||||||
|
if (haystack == NULL || needle == NULL || *needle == '\0')
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
haystack_lowered = g_utf8_strdown(haystack, -1);
|
||||||
|
needle_lowered = g_utf8_strdown(needle, -1);
|
||||||
|
|
||||||
|
/* if one of both could not be converted into lower case, skip those */
|
||||||
|
if (haystack_lowered == NULL || needle_lowered == NULL)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
result = (strstr(haystack_lowered, needle_lowered) != NULL);
|
||||||
|
|
||||||
|
g_free(haystack_lowered);
|
||||||
|
g_free(needle_lowered);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void cm_filter_tree(CMData *cmdata, const gchar *filter_text)
|
||||||
|
{
|
||||||
|
GtkTreeIter iter, child;
|
||||||
|
GtkTreeModel *model;
|
||||||
|
gboolean show_child, show_parent;
|
||||||
|
gboolean child_visible;
|
||||||
|
gint i, n;
|
||||||
|
gchar *name;
|
||||||
|
gchar *domain;
|
||||||
|
|
||||||
|
model = GTK_TREE_MODEL(cmdata->store);
|
||||||
|
if (! gtk_tree_model_get_iter_first(model, &iter))
|
||||||
|
return;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (gtk_tree_model_iter_has_child(model, &iter))
|
||||||
|
{
|
||||||
|
child_visible = FALSE;
|
||||||
|
|
||||||
|
gtk_tree_model_get(model, &iter, COL_NAME, &domain, -1);
|
||||||
|
show_parent = cm_filter_match(domain, filter_text);
|
||||||
|
g_free(domain);
|
||||||
|
n = gtk_tree_model_iter_n_children(model, &iter);
|
||||||
|
for (i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
gtk_tree_model_iter_nth_child(model, &child, &iter, i);
|
||||||
|
|
||||||
|
gtk_tree_model_get(model, &child, COL_NAME, &name, -1);
|
||||||
|
show_child = show_parent || cm_filter_match(name, filter_text);
|
||||||
|
g_free(name);
|
||||||
|
|
||||||
|
if (show_child)
|
||||||
|
child_visible = TRUE;
|
||||||
|
|
||||||
|
gtk_tree_store_set(cmdata->store, &child, COL_VISIBLE, show_child, -1);
|
||||||
|
}
|
||||||
|
gtk_tree_store_set(cmdata->store, &iter, COL_VISIBLE, child_visible, -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (gtk_tree_model_iter_next(model, &iter));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void cm_filter_entry_changed_cb(GtkEditable *editable, CMData *cmdata)
|
||||||
|
{
|
||||||
|
const gchar *text = gtk_entry_get_text(GTK_ENTRY(editable));
|
||||||
|
|
||||||
|
cm_filter_tree(cmdata, text);
|
||||||
|
|
||||||
|
if (*text != '\0')
|
||||||
|
gtk_tree_view_expand_all(GTK_TREE_VIEW(cmdata->treeview));
|
||||||
|
else
|
||||||
|
gtk_tree_view_collapse_all(GTK_TREE_VIEW(cmdata->treeview));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void cm_filter_entry_clear_icon_released_cb(GtkIconEntry *e, gint pos, gint btn, CMData *cmdata)
|
||||||
|
{
|
||||||
|
if (pos == GTK_ICON_ENTRY_SECONDARY)
|
||||||
|
gtk_entry_set_text(GTK_ENTRY(e), "");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void cm_tree_prepare(CMData *cmdata)
|
||||||
|
{
|
||||||
|
GtkCellRenderer *renderer;
|
||||||
|
GtkTreeViewColumn *column;
|
||||||
|
GtkTreeSelection *sel;
|
||||||
|
GtkWidget *tree;
|
||||||
|
GtkWidget *item;
|
||||||
|
GtkWidget *menu;
|
||||||
|
|
||||||
|
cmdata->treeview = tree = gtk_tree_view_new();
|
||||||
|
cmdata->store = gtk_tree_store_new(N_COLUMNS, G_TYPE_STRING, SOUP_TYPE_COOKIE, G_TYPE_BOOLEAN);
|
||||||
|
|
||||||
|
renderer = gtk_cell_renderer_text_new();
|
||||||
|
column = gtk_tree_view_column_new_with_attributes(
|
||||||
|
_("Name"), renderer, "text", COL_NAME, NULL);
|
||||||
|
gtk_tree_view_column_set_sort_indicator(column, TRUE);
|
||||||
|
gtk_tree_view_column_set_sort_column_id(column, COL_NAME);
|
||||||
|
gtk_tree_view_column_set_resizable(GTK_TREE_VIEW_COLUMN(column), TRUE);
|
||||||
|
gtk_tree_view_append_column(GTK_TREE_VIEW(tree), column);
|
||||||
|
|
||||||
|
gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(tree), TRUE);
|
||||||
|
gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(tree), FALSE);
|
||||||
|
gtk_tree_view_set_search_column(GTK_TREE_VIEW(tree), COL_NAME);
|
||||||
|
gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(cmdata->store), COL_NAME, GTK_SORT_ASCENDING);
|
||||||
|
|
||||||
|
/* selection handling */
|
||||||
|
sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree));
|
||||||
|
gtk_tree_selection_set_mode(sel, GTK_SELECTION_SINGLE);
|
||||||
|
|
||||||
|
/* setting filter and model */
|
||||||
|
cmdata->filter = gtk_tree_model_filter_new(GTK_TREE_MODEL(cmdata->store), NULL);
|
||||||
|
gtk_tree_model_filter_set_visible_column(GTK_TREE_MODEL_FILTER(cmdata->filter), COL_VISIBLE);
|
||||||
|
|
||||||
|
gtk_tree_view_set_model(GTK_TREE_VIEW(tree), GTK_TREE_MODEL(cmdata->filter));
|
||||||
|
g_object_unref(cmdata->store);
|
||||||
|
g_object_unref(cmdata->filter);
|
||||||
|
|
||||||
|
/* signals */
|
||||||
|
g_signal_connect(sel, "changed", G_CALLBACK(cm_tree_selection_changed_cb), cmdata);
|
||||||
|
g_signal_connect(tree, "button-press-event", G_CALLBACK(cm_tree_button_press_event_cb), cmdata);
|
||||||
|
g_signal_connect(tree, "button-release-event", G_CALLBACK(cm_tree_button_release_event_cb), cmdata);
|
||||||
|
g_signal_connect(tree, "popup-menu", G_CALLBACK(cm_tree_popup_menu_cb), cmdata);
|
||||||
|
|
||||||
|
/* tooltips */
|
||||||
|
#if GTK_CHECK_VERSION(2, 12, 0)
|
||||||
|
gtk_widget_set_has_tooltip(tree, TRUE);
|
||||||
|
g_signal_connect(tree, "query-tooltip", G_CALLBACK(cm_tree_query_tooltip), cmdata);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* drag'n'drop */
|
||||||
|
gtk_tree_view_enable_model_drag_source(
|
||||||
|
GTK_TREE_VIEW(tree),
|
||||||
|
GDK_BUTTON1_MASK,
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
GDK_ACTION_COPY
|
||||||
|
);
|
||||||
|
gtk_drag_source_add_text_targets(tree);
|
||||||
|
/*gtk_drag_source_add_uri_targets(tree);*/
|
||||||
|
g_signal_connect(tree, "drag-data-get", G_CALLBACK(cm_tree_drag_data_get_cb), cmdata);
|
||||||
|
|
||||||
|
/* popup menu */
|
||||||
|
menu = gtk_menu_new();
|
||||||
|
|
||||||
|
item = gtk_image_menu_item_new_from_stock(GTK_STOCK_DELETE, NULL);
|
||||||
|
gtk_widget_show(item);
|
||||||
|
gtk_container_add(GTK_CONTAINER(menu), item);
|
||||||
|
g_signal_connect(item, "activate", G_CALLBACK(cm_button_delete_clicked_cb), cmdata);
|
||||||
|
cmdata->delete_popup_button = item;
|
||||||
|
|
||||||
|
item = gtk_separator_menu_item_new();
|
||||||
|
gtk_widget_show(item);
|
||||||
|
gtk_container_add(GTK_CONTAINER(menu), item);
|
||||||
|
|
||||||
|
item = gtk_image_menu_item_new_with_mnemonic(_("_Expand All"));
|
||||||
|
gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item),
|
||||||
|
gtk_image_new_from_stock(GTK_STOCK_ADD, GTK_ICON_SIZE_MENU));
|
||||||
|
gtk_widget_show(item);
|
||||||
|
gtk_container_add(GTK_CONTAINER(menu), item);
|
||||||
|
g_signal_connect(item, "activate", G_CALLBACK(cm_tree_popup_expand_activate_cb), cmdata);
|
||||||
|
cmdata->expand_buttons[2] = item;
|
||||||
|
|
||||||
|
item = gtk_image_menu_item_new_with_mnemonic(_("_Collapse All"));
|
||||||
|
gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item),
|
||||||
|
gtk_image_new_from_icon_name(GTK_STOCK_REMOVE, GTK_ICON_SIZE_MENU));
|
||||||
|
gtk_widget_show(item);
|
||||||
|
gtk_container_add(GTK_CONTAINER(menu), item);
|
||||||
|
g_signal_connect(item, "activate", G_CALLBACK(cm_tree_popup_collapse_activate_cb), cmdata);
|
||||||
|
cmdata->expand_buttons[3] = item;
|
||||||
|
|
||||||
|
cmdata->popup_menu = menu;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static gboolean cm_delayed_refresh(CMData *cmdata)
|
||||||
|
{
|
||||||
|
cm_refresh_store(cmdata);
|
||||||
|
cmdata->timer_id = 0;
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void cm_jar_changed_cb(SoupCookieJar *jar, SoupCookie *old, SoupCookie *new, CMData *cmdata)
|
||||||
|
{
|
||||||
|
if (cmdata->ignore_changed_count > 0)
|
||||||
|
{
|
||||||
|
cmdata->ignore_changed_count--;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We delay these events a little bit to avoid too many rebuilds of the tree.
|
||||||
|
* Some websites (like Flyspray bugtrackers sent a whole bunch of cookies at once. */
|
||||||
|
if (cmdata->timer_id == 0)
|
||||||
|
{
|
||||||
|
cmdata->timer_id = g_timeout_add_seconds(1, (GSourceFunc) cm_delayed_refresh, cmdata);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void cm_app_add_browser_cb(MidoriApp *app, MidoriBrowser *browser, MidoriExtension *ext)
|
||||||
|
{
|
||||||
|
GtkWidget *panel;
|
||||||
|
GtkWidget *tree_swin;
|
||||||
|
GtkWidget *desc_swin;
|
||||||
|
GtkWidget *toolbar;
|
||||||
|
GtkWidget *paned;
|
||||||
|
GtkWidget *filter_hbox;
|
||||||
|
GtkWidget *filter_label;
|
||||||
|
GtkToolItem *toolitem;
|
||||||
|
SoupSession *session;
|
||||||
|
CMData *cmdata;
|
||||||
|
|
||||||
|
cmdata = g_new0(CMData, 1);
|
||||||
|
cmdata->app = app;
|
||||||
|
cmdata->extension = ext;
|
||||||
|
cmdata->browser = browser;
|
||||||
|
|
||||||
|
panel = katze_object_get_object(browser, "panel");
|
||||||
|
toolbar = gtk_toolbar_new();
|
||||||
|
gtk_toolbar_set_style(GTK_TOOLBAR(toolbar), GTK_TOOLBAR_BOTH_HORIZ);
|
||||||
|
gtk_toolbar_set_icon_size(GTK_TOOLBAR(toolbar), GTK_ICON_SIZE_BUTTON);
|
||||||
|
gtk_widget_show(toolbar);
|
||||||
|
|
||||||
|
toolitem = gtk_tool_button_new_from_stock(GTK_STOCK_DELETE);
|
||||||
|
gtk_tool_item_set_is_important(toolitem, TRUE);
|
||||||
|
g_signal_connect(toolitem, "clicked", G_CALLBACK(cm_button_delete_clicked_cb), cmdata);
|
||||||
|
gtk_widget_show(GTK_WIDGET(toolitem));
|
||||||
|
gtk_widget_set_sensitive(GTK_WIDGET(toolitem), FALSE);
|
||||||
|
gtk_toolbar_insert(GTK_TOOLBAR(toolbar), toolitem, -1);
|
||||||
|
cmdata->delete_button = GTK_WIDGET(toolitem);
|
||||||
|
|
||||||
|
toolitem = gtk_tool_button_new_from_stock(GTK_STOCK_DELETE);
|
||||||
|
gtk_tool_button_set_label(GTK_TOOL_BUTTON(toolitem), _("Delete All"));
|
||||||
|
gtk_tool_item_set_tooltip_text(toolitem,
|
||||||
|
_("Deletes all shown cookies. "
|
||||||
|
"If a filter is set, only those cookies are deleted which match the filter."));
|
||||||
|
gtk_tool_item_set_is_important(toolitem, TRUE);
|
||||||
|
g_signal_connect(toolitem, "clicked", G_CALLBACK(cm_button_delete_all_clicked_cb), cmdata);
|
||||||
|
gtk_widget_show(GTK_WIDGET(toolitem));
|
||||||
|
gtk_toolbar_insert(GTK_TOOLBAR(toolbar), toolitem, -1);
|
||||||
|
cmdata->delete_all_button = GTK_WIDGET(toolitem);
|
||||||
|
|
||||||
|
toolitem = gtk_separator_tool_item_new();
|
||||||
|
gtk_separator_tool_item_set_draw(GTK_SEPARATOR_TOOL_ITEM(toolitem), FALSE);
|
||||||
|
gtk_tool_item_set_expand(toolitem, TRUE);
|
||||||
|
gtk_toolbar_insert(GTK_TOOLBAR(toolbar), toolitem, -1);
|
||||||
|
gtk_widget_show(GTK_WIDGET(toolitem));
|
||||||
|
|
||||||
|
toolitem = gtk_tool_button_new_from_stock(GTK_STOCK_ADD);
|
||||||
|
gtk_tool_item_set_tooltip_text(toolitem, _("Expand All"));
|
||||||
|
g_signal_connect(toolitem, "clicked", G_CALLBACK(cm_tree_popup_expand_activate_cb), cmdata);
|
||||||
|
gtk_widget_show(GTK_WIDGET(toolitem));
|
||||||
|
gtk_toolbar_insert(GTK_TOOLBAR(toolbar), toolitem, -1);
|
||||||
|
cmdata->expand_buttons[0] = GTK_WIDGET(toolitem);
|
||||||
|
|
||||||
|
toolitem = gtk_tool_button_new_from_stock(GTK_STOCK_REMOVE);
|
||||||
|
gtk_tool_item_set_tooltip_text(toolitem, _("Collapse All"));
|
||||||
|
g_signal_connect(toolitem, "clicked", G_CALLBACK(cm_tree_popup_collapse_activate_cb), cmdata);
|
||||||
|
gtk_widget_show(GTK_WIDGET(toolitem));
|
||||||
|
gtk_toolbar_insert(GTK_TOOLBAR(toolbar), toolitem, -1);
|
||||||
|
cmdata->expand_buttons[1] = GTK_WIDGET(toolitem);
|
||||||
|
|
||||||
|
cmdata->desc_label = gtk_label_new(CM_EMPTY_LABEL_TEXT);
|
||||||
|
gtk_label_set_selectable(GTK_LABEL(cmdata->desc_label), TRUE);
|
||||||
|
gtk_label_set_line_wrap(GTK_LABEL(cmdata->desc_label), TRUE);
|
||||||
|
gtk_label_set_line_wrap_mode(GTK_LABEL(cmdata->desc_label), PANGO_WRAP_CHAR);
|
||||||
|
gtk_misc_set_alignment(GTK_MISC(cmdata->desc_label), 0, 0);
|
||||||
|
gtk_misc_set_padding(GTK_MISC(cmdata->desc_label), 3, 3);
|
||||||
|
gtk_widget_show(cmdata->desc_label);
|
||||||
|
|
||||||
|
desc_swin = gtk_scrolled_window_new(NULL, NULL);
|
||||||
|
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(desc_swin),
|
||||||
|
GTK_POLICY_AUTOMATIC, GTK_POLICY_NEVER);
|
||||||
|
gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(desc_swin), GTK_SHADOW_NONE);
|
||||||
|
gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(desc_swin), cmdata->desc_label);
|
||||||
|
gtk_widget_show(desc_swin);
|
||||||
|
|
||||||
|
cm_tree_prepare(cmdata);
|
||||||
|
gtk_widget_show(cmdata->treeview);
|
||||||
|
|
||||||
|
tree_swin = gtk_scrolled_window_new(NULL, NULL);
|
||||||
|
gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(tree_swin),
|
||||||
|
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
|
||||||
|
gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(tree_swin), GTK_SHADOW_IN);
|
||||||
|
gtk_container_add(GTK_CONTAINER(tree_swin), cmdata->treeview);
|
||||||
|
gtk_widget_show(tree_swin);
|
||||||
|
|
||||||
|
filter_label = gtk_label_new(_("Filter:"));
|
||||||
|
gtk_widget_show(filter_label);
|
||||||
|
|
||||||
|
cmdata->filter_entry = gtk_icon_entry_new();
|
||||||
|
gtk_widget_set_tooltip_text(cmdata->filter_entry,
|
||||||
|
_("Enter a filter string to show only cookies whose name or domain "
|
||||||
|
"field match the entered filter"));
|
||||||
|
gtk_widget_show(cmdata->filter_entry);
|
||||||
|
gtk_icon_entry_set_icon_from_stock(GTK_ICON_ENTRY(cmdata->filter_entry),
|
||||||
|
GTK_ICON_ENTRY_SECONDARY, GTK_STOCK_CLEAR);
|
||||||
|
gtk_icon_entry_set_icon_highlight(GTK_ICON_ENTRY (cmdata->filter_entry),
|
||||||
|
GTK_ICON_ENTRY_SECONDARY, TRUE);
|
||||||
|
g_signal_connect(cmdata->filter_entry, "icon-release",
|
||||||
|
G_CALLBACK(cm_filter_entry_clear_icon_released_cb), NULL);
|
||||||
|
g_signal_connect(cmdata->filter_entry, "changed", G_CALLBACK(cm_filter_entry_changed_cb), cmdata);
|
||||||
|
g_signal_connect(cmdata->filter_entry, "activate", G_CALLBACK(cm_filter_entry_changed_cb), cmdata);
|
||||||
|
|
||||||
|
filter_hbox = gtk_hbox_new(FALSE, 0);
|
||||||
|
gtk_box_pack_start(GTK_BOX(filter_hbox), filter_label, FALSE, FALSE, 3);
|
||||||
|
gtk_box_pack_start(GTK_BOX(filter_hbox), cmdata->filter_entry, TRUE, TRUE, 3);
|
||||||
|
gtk_widget_show(filter_hbox);
|
||||||
|
|
||||||
|
paned = gtk_vpaned_new();
|
||||||
|
gtk_paned_pack1(GTK_PANED(paned), tree_swin, TRUE, FALSE);
|
||||||
|
gtk_paned_pack2(GTK_PANED(paned), desc_swin, FALSE, FALSE);
|
||||||
|
gtk_widget_show(paned);
|
||||||
|
|
||||||
|
cmdata->panel_page = gtk_vbox_new(FALSE, 0);
|
||||||
|
gtk_box_pack_start(GTK_BOX(cmdata->panel_page), filter_hbox, FALSE, FALSE, 5);
|
||||||
|
gtk_box_pack_start(GTK_BOX(cmdata->panel_page), paned, TRUE, TRUE, 0);
|
||||||
|
gtk_widget_show(cmdata->panel_page);
|
||||||
|
|
||||||
|
/* setup soup */
|
||||||
|
session = webkit_get_default_session();
|
||||||
|
cmdata->jar = SOUP_COOKIE_JAR(soup_session_get_feature(session, soup_cookie_jar_get_type()));
|
||||||
|
g_signal_connect(cmdata->jar, "changed", G_CALLBACK(cm_jar_changed_cb), cmdata);
|
||||||
|
|
||||||
|
cm_refresh_store(cmdata);
|
||||||
|
|
||||||
|
midori_panel_append_widget(MIDORI_PANEL(panel), cmdata->panel_page,
|
||||||
|
STOCK_COOKIE_MANAGER, _("Cookie Manager"), toolbar);
|
||||||
|
|
||||||
|
g_signal_connect(ext, "deactivate", G_CALLBACK(cm_deactivate_cb), cmdata);
|
||||||
|
g_signal_connect(browser, "destroy", G_CALLBACK(cm_browser_close_cb), cmdata);
|
||||||
|
|
||||||
|
g_object_unref(panel);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void cm_activate_cb(MidoriExtension *extension, MidoriApp *app, gpointer data)
|
||||||
|
{
|
||||||
|
KatzeArray* browsers;
|
||||||
|
MidoriBrowser* browser;
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
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.1",
|
||||||
|
"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;
|
||||||
|
}
|
229
extensions/mouse-gestures/main.c
Normal file
|
@ -0,0 +1,229 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2009 Matthias Kruk <mkruk@matthiaskruk.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 "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 __MOUSE_GESTURES_DEBUG__ // uncomment for debugging purposes
|
||||||
|
|
||||||
|
MouseGesture *gesture;
|
||||||
|
|
||||||
|
void mouse_gesture_clear(MouseGesture *g)
|
||||||
|
{
|
||||||
|
g->start.x = 0;
|
||||||
|
g->start.y = 0;
|
||||||
|
g->middle.x = 0;
|
||||||
|
g->middle.y = 0;
|
||||||
|
g->end.x = 0;
|
||||||
|
g->end.y = 0;
|
||||||
|
g->last = MOUSE_BUTTON_UNSET;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseGesture* mouse_gesture_new(void)
|
||||||
|
{
|
||||||
|
MouseGesture *g = NULL;
|
||||||
|
if((g = g_new(MouseGesture, 1)) == NULL)
|
||||||
|
return(NULL);
|
||||||
|
mouse_gesture_clear(g);
|
||||||
|
return(g);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean mouse_gestures_handle_events(GtkWidget *widget, GdkEvent *event, MidoriBrowser *browser)
|
||||||
|
{
|
||||||
|
if(event->type == GDK_BUTTON_PRESS) // a button was pressed
|
||||||
|
{
|
||||||
|
if(gesture->last == MOUSE_BUTTON_UNSET) // if the gesture was previously cleaned -> new gesture -> new start coordinates
|
||||||
|
{
|
||||||
|
gesture->start.x = event->button.x;
|
||||||
|
gesture->start.y = event->button.y;
|
||||||
|
gesture->last = event->button.button;
|
||||||
|
}
|
||||||
|
return(TRUE);
|
||||||
|
}
|
||||||
|
else if(event->type == GDK_MOTION_NOTIFY) // the mouse was moved
|
||||||
|
{
|
||||||
|
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) ||
|
||||||
|
(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) ||
|
||||||
|
(gesture->middle.y - y < DEVIANCE && gesture->middle.y - y > -DEVIANCE))
|
||||||
|
{
|
||||||
|
gesture->end.x = x;
|
||||||
|
gesture->end.y = y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(TRUE);
|
||||||
|
}
|
||||||
|
else if(event->type == GDK_BUTTON_RELEASE)
|
||||||
|
{
|
||||||
|
if(gesture->last == MOUSE_BUTTON_MIDDLE) // all mouse gestures will use the middle mouse button
|
||||||
|
{
|
||||||
|
// middle mouse button has been released
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
// 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)
|
||||||
|
{
|
||||||
|
// 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
|
||||||
|
}
|
||||||
|
else 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 left) -> reload
|
||||||
|
midori_browser_activate_action(browser, "Reload");
|
||||||
|
#ifdef __MOUSE_GESTURES_DEBUG__
|
||||||
|
g_print("Reload gesture\n");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(gesture->middle.y < gesture->start.y - MINLENGTH)
|
||||||
|
{
|
||||||
|
// StartNode to MiddleNode is drawn upwards
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
// the line was drawn from left to right
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(gesture->middle.x < gesture->start.x - MINLENGTH)
|
||||||
|
{
|
||||||
|
// the line was drawn from right to left
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mouse_gesture_clear(gesture); // gesture finished, clear it
|
||||||
|
return(TRUE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return(FALSE); // this event is supposed to be handled again (by someone else's code) since it was irrelevant to us
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mouse_gestures_tab_cb(MidoriBrowser* browser, GtkWidget *view) // this is performed when a new tab is created
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mouse_gestures_browser_cb(MidoriApp *app, MidoriBrowser *browser) // this is performed when ever a new window is created
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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)
|
||||||
|
{
|
||||||
|
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
|
||||||
|
{
|
||||||
|
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
|
||||||
|
|
||||||
|
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
|
||||||
|
{
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g_free(gesture); // free the structure that contains the gesture information
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mouse_gestures_activate(MidoriExtension *extension, MidoriApp *app) // this is performed on extension-activation
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
MidoriExtension* extension_init(void)
|
||||||
|
{
|
||||||
|
MidoriExtension* extension = NULL;
|
||||||
|
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);
|
||||||
|
}
|
37
extensions/mouse-gestures/mouse-gestures.h
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2009 Matthias Kruk <mkruk@matthiaskruk.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 __MOUSE_GESTURES_H__
|
||||||
|
#define __MOUSE_GESTURES_H__
|
||||||
|
|
||||||
|
typedef struct _MouseGesture MouseGesture;
|
||||||
|
typedef enum _MouseButton MouseButton;
|
||||||
|
|
||||||
|
enum _MouseButton {
|
||||||
|
MOUSE_BUTTON_LEFT = 1,
|
||||||
|
MOUSE_BUTTON_RIGHT = 3,
|
||||||
|
MOUSE_BUTTON_MIDDLE = 2,
|
||||||
|
MOUSE_BUTTON_UNSET = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MouseGestureNode {
|
||||||
|
double x;
|
||||||
|
double y;
|
||||||
|
} MouseGestureNode_t;
|
||||||
|
|
||||||
|
struct _MouseGesture {
|
||||||
|
struct MouseGestureNode start;
|
||||||
|
struct MouseGestureNode middle;
|
||||||
|
struct MouseGestureNode end;
|
||||||
|
MouseButton last;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
187
extensions/page-holder.c
Normal file
|
@ -0,0 +1,187 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2008 Christian Dywan <christian@twotoasts.de>
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
See the file COPYING for the full license text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <midori/midori.h>
|
||||||
|
|
||||||
|
#define STOCK_PAGE_HOLDER "page-holder"
|
||||||
|
|
||||||
|
static void
|
||||||
|
page_holder_app_add_browser_cb (MidoriApp* app,
|
||||||
|
MidoriBrowser* browser,
|
||||||
|
MidoriExtension* extension);
|
||||||
|
|
||||||
|
static gint
|
||||||
|
page_holder_notebook_append_view (GtkWidget* notebook)
|
||||||
|
{
|
||||||
|
GtkWidget* view;
|
||||||
|
MidoriBrowser* browser;
|
||||||
|
MidoriWebSettings *settings;
|
||||||
|
GtkWidget* label;
|
||||||
|
|
||||||
|
view = midori_view_new (NULL);
|
||||||
|
browser = MIDORI_BROWSER (gtk_widget_get_toplevel (notebook));
|
||||||
|
settings = katze_object_get_object (browser, "settings");
|
||||||
|
midori_view_set_settings (MIDORI_VIEW (view), settings);
|
||||||
|
g_object_unref (settings);
|
||||||
|
gtk_widget_show (view);
|
||||||
|
label = midori_view_get_proxy_tab_label (MIDORI_VIEW (view));
|
||||||
|
return gtk_notebook_append_page (GTK_NOTEBOOK (notebook), view, label);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
page_holder_button_jump_to_clicked_cb (GtkWidget* button,
|
||||||
|
GtkWidget* notebook)
|
||||||
|
{
|
||||||
|
gint n;
|
||||||
|
MidoriBrowser* browser;
|
||||||
|
const gchar* uri;
|
||||||
|
GtkWidget* view;
|
||||||
|
|
||||||
|
n = gtk_notebook_get_current_page (GTK_NOTEBOOK (notebook));
|
||||||
|
if (n < 0)
|
||||||
|
n = page_holder_notebook_append_view (notebook);
|
||||||
|
|
||||||
|
browser = MIDORI_BROWSER (gtk_widget_get_toplevel (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);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
page_holder_button_add_clicked_cb (GtkWidget* button,
|
||||||
|
GtkWidget* notebook)
|
||||||
|
{
|
||||||
|
gint n;
|
||||||
|
GtkWidget* view;
|
||||||
|
MidoriBrowser* browser;
|
||||||
|
const gchar* uri;
|
||||||
|
|
||||||
|
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));
|
||||||
|
uri = midori_browser_get_current_uri (browser);
|
||||||
|
midori_view_set_uri (MIDORI_VIEW (view), uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
page_holder_deactivate_cb (MidoriExtension* extension,
|
||||||
|
GtkWidget* notebook)
|
||||||
|
{
|
||||||
|
MidoriApp* app = midori_extension_get_app (extension);
|
||||||
|
|
||||||
|
gtk_widget_destroy (notebook);
|
||||||
|
g_signal_handlers_disconnect_by_func (
|
||||||
|
extension, page_holder_deactivate_cb, notebook);
|
||||||
|
g_signal_handlers_disconnect_by_func (
|
||||||
|
app, page_holder_app_add_browser_cb, extension);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
page_holder_app_add_browser_cb (MidoriApp* app,
|
||||||
|
MidoriBrowser* browser,
|
||||||
|
MidoriExtension* extension)
|
||||||
|
{
|
||||||
|
GtkWidget* panel;
|
||||||
|
GtkWidget* notebook;
|
||||||
|
GtkWidget* toolbar;
|
||||||
|
GtkToolItem* toolitem;
|
||||||
|
|
||||||
|
panel = katze_object_get_object (browser, "panel");
|
||||||
|
notebook = gtk_notebook_new ();
|
||||||
|
gtk_notebook_set_tab_pos (GTK_NOTEBOOK (notebook), GTK_POS_RIGHT);
|
||||||
|
gtk_notebook_set_scrollable (GTK_NOTEBOOK (notebook), TRUE);
|
||||||
|
gtk_widget_show (notebook);
|
||||||
|
toolbar = gtk_toolbar_new ();
|
||||||
|
gtk_toolbar_set_style (GTK_TOOLBAR (toolbar), GTK_TOOLBAR_BOTH_HORIZ);
|
||||||
|
gtk_toolbar_set_icon_size (GTK_TOOLBAR (toolbar), GTK_ICON_SIZE_BUTTON);
|
||||||
|
gtk_widget_show (toolbar);
|
||||||
|
|
||||||
|
toolitem = gtk_tool_button_new_from_stock (GTK_STOCK_JUMP_TO);
|
||||||
|
gtk_tool_item_set_is_important (toolitem, TRUE);
|
||||||
|
g_signal_connect (toolitem, "clicked",
|
||||||
|
G_CALLBACK (page_holder_button_jump_to_clicked_cb), notebook);
|
||||||
|
gtk_widget_show (GTK_WIDGET (toolitem));
|
||||||
|
gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1);
|
||||||
|
|
||||||
|
toolitem = gtk_separator_tool_item_new ();
|
||||||
|
gtk_separator_tool_item_set_draw (GTK_SEPARATOR_TOOL_ITEM (toolitem), FALSE);
|
||||||
|
gtk_tool_item_set_expand (toolitem, TRUE);
|
||||||
|
gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1);
|
||||||
|
gtk_widget_show (GTK_WIDGET (toolitem));
|
||||||
|
|
||||||
|
toolitem = gtk_tool_button_new_from_stock (GTK_STOCK_ADD);
|
||||||
|
gtk_tool_item_set_is_important (toolitem, TRUE);
|
||||||
|
g_signal_connect (toolitem, "clicked",
|
||||||
|
G_CALLBACK (page_holder_button_add_clicked_cb), notebook);
|
||||||
|
gtk_widget_show (GTK_WIDGET (toolitem));
|
||||||
|
gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1);
|
||||||
|
|
||||||
|
midori_panel_append_widget (MIDORI_PANEL (panel), notebook,
|
||||||
|
/* i18n: A panel showing a user specified web page */
|
||||||
|
STOCK_PAGE_HOLDER, _("Pageholder"), toolbar);
|
||||||
|
g_signal_connect (extension, "deactivate",
|
||||||
|
G_CALLBACK (page_holder_deactivate_cb), notebook);
|
||||||
|
|
||||||
|
g_object_unref (panel);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
page_holder_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++)))
|
||||||
|
page_holder_app_add_browser_cb (app, browser, extension);
|
||||||
|
g_object_unref (browsers);
|
||||||
|
g_signal_connect (app, "add-browser",
|
||||||
|
G_CALLBACK (page_holder_app_add_browser_cb), extension);
|
||||||
|
}
|
||||||
|
|
||||||
|
MidoriExtension*
|
||||||
|
extension_init (void)
|
||||||
|
{
|
||||||
|
GtkIconFactory* factory;
|
||||||
|
GtkIconSource* icon_source;
|
||||||
|
GtkIconSet* icon_set;
|
||||||
|
static GtkStockItem items[] =
|
||||||
|
{
|
||||||
|
{ STOCK_PAGE_HOLDER, N_("_Pageholder"), 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_ORIENTATION_PORTRAIT);
|
||||||
|
gtk_icon_set_add_source (icon_set, icon_source);
|
||||||
|
gtk_icon_source_free (icon_source);
|
||||||
|
gtk_icon_factory_add (factory, STOCK_PAGE_HOLDER, icon_set);
|
||||||
|
gtk_icon_set_unref (icon_set);
|
||||||
|
gtk_icon_factory_add_default (factory);
|
||||||
|
g_object_unref (factory);
|
||||||
|
|
||||||
|
MidoriExtension* extension = g_object_new (MIDORI_TYPE_EXTENSION,
|
||||||
|
"name", _("Pageholder"),
|
||||||
|
"description", "",
|
||||||
|
"version", "0.1",
|
||||||
|
"authors", "Christian Dywan <christian@twotoasts.de>",
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
g_signal_connect (extension, "activate",
|
||||||
|
G_CALLBACK (page_holder_activate_cb), NULL);
|
||||||
|
|
||||||
|
return extension;
|
||||||
|
}
|
114
extensions/statusbar-features.c
Normal file
|
@ -0,0 +1,114 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2008 Christian Dywan <christian@twotoasts.de>
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
See the file COPYING for the full license text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <midori/midori.h>
|
||||||
|
|
||||||
|
static void
|
||||||
|
statusbar_features_app_add_browser_cb (MidoriApp* app,
|
||||||
|
MidoriBrowser* browser,
|
||||||
|
MidoriExtension* extension);
|
||||||
|
|
||||||
|
static void
|
||||||
|
statusbar_features_deactivate_cb (MidoriExtension* extension,
|
||||||
|
GtkWidget* bbox)
|
||||||
|
{
|
||||||
|
MidoriApp* app = midori_extension_get_app (extension);
|
||||||
|
|
||||||
|
gtk_widget_destroy (bbox);
|
||||||
|
g_signal_handlers_disconnect_by_func (
|
||||||
|
extension, statusbar_features_deactivate_cb, bbox);
|
||||||
|
g_signal_handlers_disconnect_by_func (
|
||||||
|
app, statusbar_features_app_add_browser_cb, extension);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
statusbar_features_app_add_browser_cb (MidoriApp* app,
|
||||||
|
MidoriBrowser* browser,
|
||||||
|
MidoriExtension* extension)
|
||||||
|
{
|
||||||
|
GtkWidget* statusbar;
|
||||||
|
GtkWidget* bbox;
|
||||||
|
MidoriWebSettings* settings;
|
||||||
|
GtkWidget* button;
|
||||||
|
GtkWidget* image;
|
||||||
|
|
||||||
|
/* FIXME: Monitor each view and modify its settings individually
|
||||||
|
instead of merely replicating the global preferences. */
|
||||||
|
|
||||||
|
statusbar = katze_object_get_object (browser, "statusbar");
|
||||||
|
bbox = gtk_hbox_new (FALSE, 0);
|
||||||
|
settings = katze_object_get_object (browser, "settings");
|
||||||
|
button = katze_property_proxy (settings, "auto-load-images", "toggle");
|
||||||
|
image = gtk_image_new_from_stock (STOCK_IMAGE, GTK_ICON_SIZE_MENU);
|
||||||
|
gtk_widget_show (image);
|
||||||
|
gtk_container_add (GTK_CONTAINER (button), image);
|
||||||
|
#if GTK_CHECK_VERSION(2, 12, 0)
|
||||||
|
gtk_widget_set_tooltip_text (button, _("Load images automatically"));
|
||||||
|
#endif
|
||||||
|
gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, FALSE, 2);
|
||||||
|
gtk_widget_show (button);
|
||||||
|
button = katze_property_proxy (settings, "enable-scripts", "toggle");
|
||||||
|
image = gtk_image_new_from_stock (STOCK_SCRIPTS, GTK_ICON_SIZE_MENU);
|
||||||
|
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 scripts"));
|
||||||
|
#endif
|
||||||
|
gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, FALSE, 2);
|
||||||
|
gtk_widget_show (button);
|
||||||
|
button = katze_property_proxy (settings, "enable-plugins", "toggle");
|
||||||
|
image = gtk_image_new_from_stock (STOCK_PLUGINS, GTK_ICON_SIZE_MENU);
|
||||||
|
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"));
|
||||||
|
#endif
|
||||||
|
gtk_box_pack_start (GTK_BOX (bbox), button, FALSE, FALSE, 2);
|
||||||
|
gtk_widget_show (button);
|
||||||
|
gtk_widget_show (bbox);
|
||||||
|
gtk_box_pack_start (GTK_BOX (statusbar), bbox, FALSE, FALSE, 3);
|
||||||
|
g_object_unref (settings);
|
||||||
|
|
||||||
|
g_signal_connect (extension, "deactivate",
|
||||||
|
G_CALLBACK (statusbar_features_deactivate_cb), bbox);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
statusbar_features_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++)))
|
||||||
|
statusbar_features_app_add_browser_cb (app, browser, extension);
|
||||||
|
g_signal_connect (app, "add-browser",
|
||||||
|
G_CALLBACK (statusbar_features_app_add_browser_cb), extension);
|
||||||
|
}
|
||||||
|
|
||||||
|
MidoriExtension*
|
||||||
|
extension_init (void)
|
||||||
|
{
|
||||||
|
MidoriExtension* extension = g_object_new (MIDORI_TYPE_EXTENSION,
|
||||||
|
"name", "Statusbar Features",
|
||||||
|
"description", "",
|
||||||
|
"version", "0.1",
|
||||||
|
"authors", "Christian Dywan <christian@twotoasts.de>",
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
g_signal_connect (extension, "activate",
|
||||||
|
G_CALLBACK (statusbar_features_activate_cb), NULL);
|
||||||
|
|
||||||
|
return extension;
|
||||||
|
}
|
77
extensions/tab-panel/main.c
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2008 Christian Dywan <christian@twotoasts.de>
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
See the file COPYING for the full license text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "tab-panel-extension.h"
|
||||||
|
|
||||||
|
#include <midori/midori.h>
|
||||||
|
|
||||||
|
#define STOCK_TAB_PANEL "tab-panel"
|
||||||
|
|
||||||
|
static void
|
||||||
|
tab_panel_app_add_browser_cb (MidoriApp* app,
|
||||||
|
MidoriBrowser* browser)
|
||||||
|
{
|
||||||
|
GtkWidget* panel;
|
||||||
|
GtkWidget* child;
|
||||||
|
|
||||||
|
/* FIXME: Actually provide a tree view listing all views. */
|
||||||
|
|
||||||
|
panel = katze_object_get_object (browser, "panel");
|
||||||
|
child = midori_view_new (NULL);
|
||||||
|
gtk_widget_show (child);
|
||||||
|
midori_panel_append_widget (MIDORI_PANEL (panel), child,
|
||||||
|
STOCK_TAB_PANEL, _("Tab Panel"), NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
tab_panel_activate_cb (MidoriExtension* extension,
|
||||||
|
MidoriApp* app)
|
||||||
|
{
|
||||||
|
g_signal_connect (app, "add-browser",
|
||||||
|
G_CALLBACK (tab_panel_app_add_browser_cb), NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
MidoriExtension*
|
||||||
|
extension_init (void)
|
||||||
|
{
|
||||||
|
MidoriExtension* extension;
|
||||||
|
GtkIconFactory* factory;
|
||||||
|
GtkIconSource* icon_source;
|
||||||
|
GtkIconSet* icon_set;
|
||||||
|
static GtkStockItem items[] =
|
||||||
|
{
|
||||||
|
{ STOCK_TAB_PANEL, N_("T_ab Panel"), 0, 0, NULL },
|
||||||
|
};
|
||||||
|
|
||||||
|
factory = gtk_icon_factory_new ();
|
||||||
|
gtk_stock_add (items, G_N_ELEMENTS (items));
|
||||||
|
icon_set = gtk_icon_set_new ();
|
||||||
|
icon_source = gtk_icon_source_new ();
|
||||||
|
gtk_icon_source_set_icon_name (icon_source, GTK_STOCK_INDEX);
|
||||||
|
gtk_icon_set_add_source (icon_set, icon_source);
|
||||||
|
gtk_icon_source_free (icon_source);
|
||||||
|
gtk_icon_factory_add (factory, STOCK_TAB_PANEL, icon_set);
|
||||||
|
gtk_icon_set_unref (icon_set);
|
||||||
|
gtk_icon_factory_add_default (factory);
|
||||||
|
g_object_unref (factory);
|
||||||
|
|
||||||
|
extension = g_object_new (TAB_PANEL_TYPE_EXTENSION,
|
||||||
|
"name", _("Tab Panel"),
|
||||||
|
"description", "",
|
||||||
|
"version", "0.1",
|
||||||
|
"authors", "Christian Dywan <christian@twotoasts.de>",
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
g_signal_connect (extension, "activate",
|
||||||
|
G_CALLBACK (tab_panel_activate_cb), NULL);
|
||||||
|
|
||||||
|
return extension;
|
||||||
|
}
|
38
extensions/tab-panel/tab-panel-extension.c
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2008 Christian Dywan <christian@twotoasts.de>
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
See the file COPYING for the full license text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "tab-panel-extension.h"
|
||||||
|
|
||||||
|
#include <midori/midori.h>
|
||||||
|
|
||||||
|
struct _TabPanelExtension
|
||||||
|
{
|
||||||
|
MidoriExtension parent_instance;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _TabPanelExtensionClass
|
||||||
|
{
|
||||||
|
MidoriExtensionClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (TabPanelExtension, tab_panel_extension, MIDORI_TYPE_EXTENSION);
|
||||||
|
|
||||||
|
static void
|
||||||
|
tab_panel_extension_class_init (TabPanelExtensionClass* class)
|
||||||
|
{
|
||||||
|
/* Nothing to do. */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
tab_panel_extension_init (TabPanelExtension* extension)
|
||||||
|
{
|
||||||
|
/* Nothing to do. */
|
||||||
|
}
|
43
extensions/tab-panel/tab-panel-extension.h
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2008 Christian Dywan <christian@twotoasts.de>
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
See the file COPYING for the full license text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __TAB_PANEL_EXTENSION_H__
|
||||||
|
#define __TAB_PANEL_EXTENSION_H__
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define TAB_PANEL_TYPE_EXTENSION \
|
||||||
|
(midori_extension_get_type ())
|
||||||
|
#define TAB_PANEL_EXTENSION(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_CAST ((obj), TAB_PANEL_TYPE_EXTENSION, TabPanelExtension))
|
||||||
|
#define TAB_PANEL_EXTENSION_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_CAST ((klass), TAB_PANEL_TYPE_EXTENSION, TabPanelExtensionClass))
|
||||||
|
#define TAB_PANEL_IS_EXTENSION(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), TAB_PANEL_TYPE_EXTENSION))
|
||||||
|
#define TAB_PANEL_IS_EXTENSION_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_TYPE ((klass), TAB_PANEL_TYPE_EXTENSION))
|
||||||
|
#define TAB_PANEL_EXTENSION_GET_CLASS(obj) \
|
||||||
|
(G_TYPE_INSTANCE_GET_CLASS ((obj), TAB_PANEL_TYPE_EXTENSION, TabPanelExtensionClass))
|
||||||
|
|
||||||
|
typedef struct _TabPanelExtension TabPanelExtension;
|
||||||
|
typedef struct _TabPanelExtensionClass TabPanelExtensionClass;
|
||||||
|
|
||||||
|
GType
|
||||||
|
tab_panel_extension_get_type (void);
|
||||||
|
|
||||||
|
/* There is no API for TabPanelExtension. Please use the
|
||||||
|
available properties and signals. */
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __TAB_PANEL_EXTENSION_H__ */
|
32
extensions/wscript_build
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
#! /usr/bin/env python
|
||||||
|
# WAF build script for midori
|
||||||
|
# This file is licensed under the terms of the expat license, see the file EXPAT.
|
||||||
|
|
||||||
|
extensions = os.listdir ('extensions')
|
||||||
|
for extension in extensions:
|
||||||
|
# Tab Panel isn't useful at this point
|
||||||
|
if extension == 'tab-panel':
|
||||||
|
continue
|
||||||
|
folder = 'extensions' + os.sep + extension
|
||||||
|
if os.path.isdir (folder):
|
||||||
|
files = os.listdir (folder)
|
||||||
|
target = extension
|
||||||
|
source = ''
|
||||||
|
for fila in files:
|
||||||
|
if fila[-2:] == '.c':
|
||||||
|
source += ' ' + extension + os.sep + fila
|
||||||
|
if not source:
|
||||||
|
Utils.pprint ('RED', folder + ': No source files found')
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
if extension[-2:] != '.c':
|
||||||
|
continue
|
||||||
|
target = extension[:-2]
|
||||||
|
source = extension
|
||||||
|
|
||||||
|
obj = bld.new_task_gen ('cc', 'shlib')
|
||||||
|
obj.target = target
|
||||||
|
obj.includes = '..'
|
||||||
|
obj.source = source
|
||||||
|
obj.uselib = 'UNIQUE LIBSOUP GIO GTK SQLITE WEBKIT LIBXML'
|
||||||
|
obj.install_path = '${LIBDIR}/midori'
|
BIN
icons/16x16/extension.png
Normal file
After Width: | Height: | Size: 780 B |
BIN
icons/16x16/midori.png
Normal file
After Width: | Height: | Size: 937 B |
BIN
icons/16x16/news-feed.png
Normal file
After Width: | Height: | Size: 832 B |
BIN
icons/22x22/extension.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
icons/22x22/midori.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
icons/22x22/news-feed.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
199
icons/scalable/extension.svg
Normal file
|
@ -0,0 +1,199 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="48"
|
||||||
|
height="48"
|
||||||
|
id="svg2"
|
||||||
|
sodipodi:version="0.32"
|
||||||
|
inkscape:version="0.46"
|
||||||
|
version="1.0"
|
||||||
|
sodipodi:docname="puzzle.svg"
|
||||||
|
inkscape:output_extension="org.inkscape.output.svg.inkscape">
|
||||||
|
<defs
|
||||||
|
id="defs4">
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
id="linearGradient3301">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#888a85;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop3303" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#888a85;stop-opacity:0;"
|
||||||
|
offset="1"
|
||||||
|
id="stop3305" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient3259">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#254109;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop3261" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#c1f093;stop-opacity:0;"
|
||||||
|
offset="1"
|
||||||
|
id="stop3263" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient3229">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#6fcb15;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop3231" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#73d216;stop-opacity:0;"
|
||||||
|
offset="1"
|
||||||
|
id="stop3233" />
|
||||||
|
</linearGradient>
|
||||||
|
<inkscape:perspective
|
||||||
|
sodipodi:type="inkscape:persp3d"
|
||||||
|
inkscape:vp_x="0 : 526.18109 : 1"
|
||||||
|
inkscape:vp_y="0 : 1000 : 0"
|
||||||
|
inkscape:vp_z="744.09448 : 526.18109 : 1"
|
||||||
|
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
|
||||||
|
id="perspective10" />
|
||||||
|
<inkscape:perspective
|
||||||
|
id="perspective2447"
|
||||||
|
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
|
||||||
|
inkscape:vp_z="744.09448 : 526.18109 : 1"
|
||||||
|
inkscape:vp_y="0 : 1000 : 0"
|
||||||
|
inkscape:vp_x="0 : 526.18109 : 1"
|
||||||
|
sodipodi:type="inkscape:persp3d" />
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient3229"
|
||||||
|
id="linearGradient3235"
|
||||||
|
x1="371.78729"
|
||||||
|
y1="555.55804"
|
||||||
|
x2="320.8378"
|
||||||
|
y2="501.43228"
|
||||||
|
gradientUnits="userSpaceOnUse" />
|
||||||
|
<filter
|
||||||
|
inkscape:collect="always"
|
||||||
|
id="filter3287"
|
||||||
|
x="-0.013903426"
|
||||||
|
width="1.0278069"
|
||||||
|
y="-0.11628319"
|
||||||
|
height="1.2325664">
|
||||||
|
<feGaussianBlur
|
||||||
|
inkscape:collect="always"
|
||||||
|
stdDeviation="0.20189084"
|
||||||
|
id="feGaussianBlur3289" />
|
||||||
|
</filter>
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient3229"
|
||||||
|
id="linearGradient3299"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="371.78729"
|
||||||
|
y1="555.55804"
|
||||||
|
x2="320.8378"
|
||||||
|
y2="501.43228" />
|
||||||
|
<radialGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient3301"
|
||||||
|
id="radialGradient3307"
|
||||||
|
cx="17.704134"
|
||||||
|
cy="44.27507"
|
||||||
|
fx="17.704134"
|
||||||
|
fy="44.27507"
|
||||||
|
r="17.425131"
|
||||||
|
gradientTransform="matrix(1.4191617,0,0,0.1195652,-7.4208958,38.981304)"
|
||||||
|
gradientUnits="userSpaceOnUse" />
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient3229"
|
||||||
|
id="linearGradient3310"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="371.78729"
|
||||||
|
y1="555.55804"
|
||||||
|
x2="307.07446"
|
||||||
|
y2="483.37579"
|
||||||
|
gradientTransform="translate(0.1262691,0)" />
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="7.9195959"
|
||||||
|
inkscape:cx="-31.755352"
|
||||||
|
inkscape:cy="29.67997"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="true"
|
||||||
|
inkscape:snap-global="false"
|
||||||
|
inkscape:window-width="997"
|
||||||
|
inkscape:window-height="795"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="0">
|
||||||
|
<inkscape:grid
|
||||||
|
type="xygrid"
|
||||||
|
id="grid2455"
|
||||||
|
visible="true"
|
||||||
|
enabled="true" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<metadata
|
||||||
|
id="metadata7">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:creator>
|
||||||
|
<cc:Agent>
|
||||||
|
<dc:title>Nancy Runge</dc:title>
|
||||||
|
</cc:Agent>
|
||||||
|
</dc:creator>
|
||||||
|
<dc:rights>
|
||||||
|
<cc:Agent>
|
||||||
|
<dc:title>licenced under LGPL</dc:title>
|
||||||
|
</cc:Agent>
|
||||||
|
</dc:rights>
|
||||||
|
<dc:title>Extensions</dc:title>
|
||||||
|
<dc:publisher>
|
||||||
|
<cc:Agent>
|
||||||
|
<dc:title>http://www.twotoasts.de</dc:title>
|
||||||
|
</cc:Agent>
|
||||||
|
</dc:publisher>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="Ebene 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1"
|
||||||
|
transform="translate(-334.84263,-513.45087)">
|
||||||
|
<path
|
||||||
|
sodipodi:type="arc"
|
||||||
|
style="opacity:0.52803034;fill:url(#radialGradient3307);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter3287)"
|
||||||
|
id="path3257"
|
||||||
|
sodipodi:cx="20.834396"
|
||||||
|
sodipodi:cy="44.275063"
|
||||||
|
sodipodi:rx="17.425131"
|
||||||
|
sodipodi:ry="2.0834396"
|
||||||
|
d="M 38.259527,44.275063 A 17.425131,2.0834396 0 1 1 3.4092655,44.275063 A 17.425131,2.0834396 0 1 1 38.259527,44.275063 z"
|
||||||
|
transform="matrix(1.2065218,0,0,1.6363637,333.12839,482.68731)" />
|
||||||
|
<path
|
||||||
|
style="fill:#c1f093;fill-opacity:1;fill-rule:evenodd;stroke:#499402;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
|
||||||
|
d="M 337.59808,522.17297 L 337.72435,533.84844 C 339.47847,534.10639 341.10631,535.92142 342.86043,535.22887 C 354.484,532.75774 350.70132,551.41563 342.10964,542.50639 C 340.64788,541.6646 339.18611,542.12627 337.72435,542.15558 L 337.67073,553.72581 L 353.23389,553.73869 C 354.05552,552.4318 354.72796,551.87106 354.60115,550.08995 C 351.64196,539.72544 369.94217,539.26102 360.04106,550.78887 C 359.83384,551.92692 361.24191,552.43363 361.98031,553.57168 L 369.96412,553.44765 L 369.96412,540.88184 C 370.96339,539.9698 371.96266,540.18833 372.96193,540.17836 C 384.45308,546.41513 382.69169,524.21109 372.50653,532.25474 C 371.79768,532.78933 371.04359,533.05251 370.0988,532.17145 L 370.0988,521.99757 L 362.85737,521.99757 C 361.30432,524.66021 361.13738,525.26649 361.37766,526.1182 C 368.03927,535.17088 347.04741,536.92703 352.54122,528.11641 C 354.21415,526.75748 354.49233,523.14925 354.4376,521.99756 L 337.57862,522.11095"
|
||||||
|
id="path2453"
|
||||||
|
sodipodi:nodetypes="ccccccccccccccccccccc" />
|
||||||
|
<path
|
||||||
|
style="fill:url(#linearGradient3310);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.87325984000000001;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1"
|
||||||
|
d="M 339.0736,523.88908 L 339.37844,532.79484 C 340.92793,533.01753 342.49273,534.03344 344.04222,533.43557 C 356.8745,532.10371 351.782,552.26286 342.62716,544.9362 C 341.58846,543.57814 340.36483,543.48432 339.0736,543.50962 L 339.13777,552.19979 L 352.02889,552.1019 C 352.95857,551.13679 354.00081,551.05253 352.57409,548.46314 C 352.71994,537.89846 369.3947,537.1685 362.99814,549.56575 C 362.81509,550.54821 362.19137,550.54855 362.84363,551.53102 L 368.46752,551.51322 L 368.46752,540.12957 C 369.78113,538.48037 371.66756,538.44729 372.54418,538.45083 C 381.58291,544.2191 381.40416,527.19794 373.12406,533.66401 C 372.91206,535.1722 368.70591,534.44374 368.40791,532.60997 L 368.40791,523.55909 L 363.61838,523.64838 C 362.51436,525.85772 363.34904,526.38112 363.56129,527.11639 C 368.40591,536.59135 346.45266,539.32394 350.48782,528.03786 C 351.96559,526.86471 353.37203,524.01762 352.60941,523.55908 L 338.78855,523.65697"
|
||||||
|
id="path3227"
|
||||||
|
sodipodi:nodetypes="ccccccccccccccccccccc" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 8.1 KiB |
230
icons/scalable/midori.svg
Normal file
|
@ -0,0 +1,230 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="48"
|
||||||
|
height="48"
|
||||||
|
id="svg3612"
|
||||||
|
sodipodi:version="0.32"
|
||||||
|
inkscape:version="0.46"
|
||||||
|
version="1.0"
|
||||||
|
sodipodi:docname="drawing-1.svg"
|
||||||
|
inkscape:output_extension="org.inkscape.output.svg.inkscape">
|
||||||
|
<defs
|
||||||
|
id="defs3614">
|
||||||
|
<inkscape:perspective
|
||||||
|
sodipodi:type="inkscape:persp3d"
|
||||||
|
inkscape:vp_x="0 : 19.696583 : 1"
|
||||||
|
inkscape:vp_y="0 : 1000 : 0"
|
||||||
|
inkscape:vp_z="34.692669 : 19.696583 : 1"
|
||||||
|
inkscape:persp3d-origin="17.346334 : 13.131055 : 1"
|
||||||
|
id="perspective42" />
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient3412">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#ffffff;stop-opacity:0.59836066;"
|
||||||
|
offset="0"
|
||||||
|
id="stop3414" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#4e9a06;stop-opacity:0;"
|
||||||
|
offset="1"
|
||||||
|
id="stop3416" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient3458">
|
||||||
|
<stop
|
||||||
|
style="stop-color:#41a100;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop3460" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#ffffff;stop-opacity:0;"
|
||||||
|
offset="1"
|
||||||
|
id="stop3462" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient3412"
|
||||||
|
id="linearGradient2416"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="matrix(1.1626866,0.3285437,-0.3285437,1.1626866,325.6313,407.16081)"
|
||||||
|
x1="13"
|
||||||
|
y1="11"
|
||||||
|
x2="40"
|
||||||
|
y2="19" />
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient3458"
|
||||||
|
id="linearGradient2427"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="matrix(1.1626866,0.3285437,-0.3285437,1.1626866,327.75135,406.92561)"
|
||||||
|
x1="33"
|
||||||
|
y1="33"
|
||||||
|
x2="4"
|
||||||
|
y2="5" />
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
gridtolerance="10000"
|
||||||
|
guidetolerance="10"
|
||||||
|
objecttolerance="10"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="11.2"
|
||||||
|
inkscape:cx="-2.4112669"
|
||||||
|
inkscape:cy="21.831798"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="true"
|
||||||
|
showguides="true"
|
||||||
|
inkscape:guide-bbox="true"
|
||||||
|
inkscape:window-width="1443"
|
||||||
|
inkscape:window-height="766"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="22"
|
||||||
|
inkscape:snap-global="false">
|
||||||
|
<inkscape:grid
|
||||||
|
type="xygrid"
|
||||||
|
id="grid3623"
|
||||||
|
visible="true"
|
||||||
|
enabled="true" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="0,1"
|
||||||
|
position="-24.285714,35.982143"
|
||||||
|
id="guide3782" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="0,1"
|
||||||
|
position="10.535714,-15.357143"
|
||||||
|
id="guide3784" />
|
||||||
|
<sodipodi:guide
|
||||||
|
orientation="1,0"
|
||||||
|
position="8.3928572,12.321429"
|
||||||
|
id="guide3786" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<metadata
|
||||||
|
id="metadata3617">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1"
|
||||||
|
transform="translate(-322.76854,-423.39033)">
|
||||||
|
<g
|
||||||
|
transform="matrix(1.1626866,0.3285437,-0.3285437,1.1626866,327.85931,406.67587)"
|
||||||
|
style="stroke:none"
|
||||||
|
id="g3562">
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="ccsssscssccc"
|
||||||
|
id="path3564"
|
||||||
|
d="M 32.62692,6.6695339 C 28.943103,10.347154 11.111941,12.664469 9,33 C 9.3414198,38.11565 11.750163,44.619293 16.499797,43.597643 C 17.482576,43.386246 18.538501,43.794446 19.203605,44.407481 C 23.555343,48.418538 27.732345,46.782233 28.855024,43.962447 C 29.070261,43.421846 29.754997,43.365614 30.315916,43.589557 C 36.857006,46.201039 38.613158,38.645886 39,33 C 39.096949,30.551387 37.800853,11.942617 35.822153,10.473066 C 35.232485,10.035129 33.801652,12.187441 32.644545,14.379307 C 23.397466,31.895713 11.762403,24.057082 32.238499,7.1548098 L 32.4735,6.6276491 L 32.744417,6.6586341"
|
||||||
|
style="fill:#c5f199;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1" />
|
||||||
|
<g
|
||||||
|
style="fill:#c5f199;fill-opacity:1;stroke:none;stroke-linecap:round;stroke-linejoin:bevel;stroke-opacity:1"
|
||||||
|
id="g3566">
|
||||||
|
<path
|
||||||
|
style="fill:#c5f199;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:round;stroke-linejoin:bevel;stroke-opacity:1"
|
||||||
|
d="M 24,45 L 24,33"
|
||||||
|
id="path3568" />
|
||||||
|
<path
|
||||||
|
style="fill:#c5f199;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:round;stroke-linejoin:bevel;stroke-opacity:1"
|
||||||
|
d="M 15,42 L 15,35"
|
||||||
|
id="path3570" />
|
||||||
|
<path
|
||||||
|
style="fill:#c5f199;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:round;stroke-linejoin:bevel;stroke-opacity:1"
|
||||||
|
d="M 33,42 L 33,35"
|
||||||
|
id="path3572" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
transform="matrix(1.1626866,0.3285437,-0.3285437,1.1626866,327.85931,406.67587)"
|
||||||
|
id="g3574"
|
||||||
|
style="fill:#73d216;fill-opacity:1;stroke:none">
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="csccsssscc"
|
||||||
|
id="path3576"
|
||||||
|
d="M 35.234589,13.724224 C 31.496538,21.805793 21.999895,29.946967 19.494746,24.633171 C 18.259214,22.012423 20.444587,17.339475 24.970511,12.046117 C 19.052984,15.684909 9.0048605,24.657969 10.614085,33.891165 C 10.240096,37.730699 13.217584,44.854617 17.074704,42.528018 C 18.102914,41.907806 19.832336,42.804046 20.452936,43.859693 C 21.771483,46.102557 26.565305,45.447239 27.607052,44.011061 C 28.374886,42.952509 29.980607,42.339501 31.245483,42.634122 C 36.778838,43.922978 37.16615,36.508792 37.142809,33.588177 C 38.771623,22.841659 35.355682,17.704462 35.234589,13.724224 z"
|
||||||
|
style="fill:#73d216;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1" />
|
||||||
|
<g
|
||||||
|
style="fill:#73d216;fill-opacity:1;stroke:none;stroke-linecap:round;stroke-linejoin:bevel;stroke-opacity:1"
|
||||||
|
id="g3578">
|
||||||
|
<path
|
||||||
|
style="fill:#73d216;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:round;stroke-linejoin:bevel;stroke-opacity:1"
|
||||||
|
d="M 33,42 L 33,35"
|
||||||
|
id="path3580" />
|
||||||
|
<path
|
||||||
|
style="fill:#73d216;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:round;stroke-linejoin:bevel;stroke-opacity:1"
|
||||||
|
d="M 24,45 L 24,33"
|
||||||
|
id="path3582" />
|
||||||
|
<path
|
||||||
|
style="fill:#73d216;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:round;stroke-linejoin:bevel;stroke-opacity:1"
|
||||||
|
d="M 15,42 L 15,35"
|
||||||
|
id="path3584" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="cccsscsc"
|
||||||
|
id="path3586"
|
||||||
|
d="M 329.51073,447.61372 C 332.22018,442.31643 337.23637,442.25529 346.02247,445.13278 C 351.85692,445.13277 359.69811,439.61104 364.13235,434.66153 C 365.12684,453.86745 356.57278,473.21027 348.95566,465.678 C 347.93716,464.67086 347.17038,465.7736 345.66657,466.61478 C 344.22635,467.4204 343.53424,467.54511 341.98051,467.14292 C 336.85873,467.46725 335.86518,459.21391 333.59195,460.87858 C 329.28077,464.03562 327.73041,455.09453 329.51073,447.61372 z"
|
||||||
|
style="fill:url(#linearGradient2427);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="cc"
|
||||||
|
id="path3590"
|
||||||
|
d="M 334.53834,462.27896 C 334.2078,459.40748 333.844,454.00043 336.35842,450.8616"
|
||||||
|
style="fill:none;fill-rule:evenodd;stroke:#c5f199;stroke-width:3.6246419;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="ccccc"
|
||||||
|
id="path3592"
|
||||||
|
d="M 347.26802,454.03922 C 344.36973,461.6067 346.25402,462.8854 347.66323,466.99966 L 347.66323,466.99966 L 347.66323,466.99966 L 347.48466,466.37466"
|
||||||
|
style="fill:none;fill-rule:evenodd;stroke:#c5f199;stroke-width:3.6246419;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||||
|
<g
|
||||||
|
transform="matrix(1.1626866,0.3285437,-0.3285437,1.1626866,300.43486,392.47027)"
|
||||||
|
id="g3596">
|
||||||
|
<path
|
||||||
|
style="fill:none;fill-opacity:1;fill-rule:nonzero;stroke:#204c00;stroke-width:0.82766795;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="M 58.836696,11.191679 C 54.60152,13.283618 34.371877,21.539565 34.111956,38.37916 C 34.23937,44.016827 37.022977,50.949008 42.995777,48.976423 C 43.419099,48.836853 43.503143,48.965524 43.757523,49.283134 C 47.911767,54.469973 53.736445,51.666736 54.462077,48.968721 C 54.565425,48.584458 54.107103,48.849125 54.462077,48.968721 C 61.90878,51.477628 63.638909,44.604122 64.115394,38.779293 C 65.224194,33.529058 61.312968,14.079248 60.37612,15.673393 C 44.414802,42.833251 39.236631,24.348064 58.836696,11.191679"
|
||||||
|
id="path3598"
|
||||||
|
sodipodi:nodetypes="ccsssscsc" />
|
||||||
|
<g
|
||||||
|
id="g3600"
|
||||||
|
style="fill:none;fill-opacity:1;stroke:#306600;stroke-width:0.82766795;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
transform="translate(25,5)">
|
||||||
|
<g
|
||||||
|
style="stroke:#204c00;stroke-width:0.82766795;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="g3602">
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="cc"
|
||||||
|
style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#204c00;stroke-width:0.82766795;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="M 18.645566,43.903974 C 15.051587,37.187354 16.540541,35.406359 16.713974,33.280216"
|
||||||
|
id="path3606" />
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="cc"
|
||||||
|
style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#204c00;stroke-width:0.82766795;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="M 29.35012,43.828988 C 26.087374,40.085035 25.418677,36.423326 26.118423,33.355781"
|
||||||
|
id="path3608" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="ccccccc"
|
||||||
|
id="path3610"
|
||||||
|
d="M 351.92318,429.5918 C 352.10808,427.28792 329.31466,436.91697 329.60494,447.76046 C 333.57302,442.60412 337.42833,442.17904 343.75497,444.76136 C 348.36775,449.06988 334.57289,441.21352 351.92318,429.5918 L 351.92318,429.5918 L 351.92318,429.5918 L 351.92318,429.5918 z"
|
||||||
|
style="fill:url(#linearGradient2416);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:round;stroke-opacity:1" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 11 KiB |
280
icons/scalable/news-feed.svg
Normal file
|
@ -0,0 +1,280 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
id="svg2"
|
||||||
|
sodipodi:version="0.32"
|
||||||
|
inkscape:version="0.46"
|
||||||
|
width="48"
|
||||||
|
height="48"
|
||||||
|
xml:space="preserve"
|
||||||
|
sodipodi:docname="tango-rss.svg"
|
||||||
|
version="1.0"
|
||||||
|
inkscape:output_extension="org.inkscape.output.svg.inkscape"><metadata
|
||||||
|
id="metadata7"><rdf:RDF><cc:Work
|
||||||
|
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
|
||||||
|
id="defs5"><linearGradient
|
||||||
|
id="linearGradient3300"><stop
|
||||||
|
style="stop-color:#ce5c00;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop3302" /><stop
|
||||||
|
style="stop-color:#893d00;stop-opacity:1;"
|
||||||
|
offset="1"
|
||||||
|
id="stop3304" /></linearGradient><linearGradient
|
||||||
|
id="linearGradient3275"><stop
|
||||||
|
style="stop-color:#ffffff;stop-opacity:1;"
|
||||||
|
offset="0"
|
||||||
|
id="stop3277" /><stop
|
||||||
|
style="stop-color:#f57900;stop-opacity:0;"
|
||||||
|
offset="1"
|
||||||
|
id="stop3279" /></linearGradient><inkscape:perspective
|
||||||
|
sodipodi:type="inkscape:persp3d"
|
||||||
|
inkscape:vp_x="0 : 526.18109 : 1"
|
||||||
|
inkscape:vp_y="0 : 1000 : 0"
|
||||||
|
inkscape:vp_z="744.09448 : 526.18109 : 1"
|
||||||
|
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
|
||||||
|
id="perspective9" /><clipPath
|
||||||
|
clipPathUnits="userSpaceOnUse"
|
||||||
|
id="clipPath17"><path
|
||||||
|
d="M 0,128 L 128,128 L 128,0 L 0,0 L 0,128 z"
|
||||||
|
id="path19" /></clipPath><linearGradient
|
||||||
|
x1="0"
|
||||||
|
y1="0"
|
||||||
|
x2="1"
|
||||||
|
y2="0"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="matrix(-104.01236,104.01237,104.01237,104.01237,116.00586,11.994141)"
|
||||||
|
spreadMethod="pad"
|
||||||
|
id="linearGradient37"><stop
|
||||||
|
style="stop-opacity:1;stop-color:#d95b29"
|
||||||
|
offset="0"
|
||||||
|
id="stop39" /><stop
|
||||||
|
style="stop-opacity:1;stop-color:#fb9e3a"
|
||||||
|
offset="0.5"
|
||||||
|
id="stop41" /><stop
|
||||||
|
style="stop-opacity:1;stop-color:#e3702d"
|
||||||
|
offset="1"
|
||||||
|
id="stop43" /></linearGradient><linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient3275"
|
||||||
|
id="linearGradient3281"
|
||||||
|
x1="28.140682"
|
||||||
|
y1="59.007069"
|
||||||
|
x2="123.56256"
|
||||||
|
y2="64.008011"
|
||||||
|
gradientUnits="userSpaceOnUse" /><linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient3275"
|
||||||
|
id="linearGradient3283"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="-22.962652"
|
||||||
|
y1="-26.856916"
|
||||||
|
x2="113.12444"
|
||||||
|
y2="103.36325" /><linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient3275"
|
||||||
|
id="linearGradient3285"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="4.4374332"
|
||||||
|
y1="64.008011"
|
||||||
|
x2="123.56256"
|
||||||
|
y2="64.008011" /><linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient3275"
|
||||||
|
id="linearGradient3287"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="4.4374332"
|
||||||
|
y1="64.008011"
|
||||||
|
x2="123.56256"
|
||||||
|
y2="64.008011" /><linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient3300"
|
||||||
|
id="linearGradient3306"
|
||||||
|
x1="-0.98719376"
|
||||||
|
y1="119.27105"
|
||||||
|
x2="39.936729"
|
||||||
|
y2="88.299164"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="matrix(0.9961613,0,0,1.0000405,6.8742977e-4,-4.4021459e-3)" /><linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient3300"
|
||||||
|
id="linearGradient3351"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="matrix(0.9961613,0,0,1.0000405,6.8742977e-4,-4.4021459e-3)"
|
||||||
|
x1="-0.98719376"
|
||||||
|
y1="119.27105"
|
||||||
|
x2="39.936729"
|
||||||
|
y2="88.299164" /><linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient3275"
|
||||||
|
id="linearGradient3353"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="-22.962652"
|
||||||
|
y1="-26.856916"
|
||||||
|
x2="113.12444"
|
||||||
|
y2="103.36325" /><linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient3275"
|
||||||
|
id="linearGradient3355"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="4.4374332"
|
||||||
|
y1="64.008011"
|
||||||
|
x2="123.56256"
|
||||||
|
y2="64.008011" /><linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient3275"
|
||||||
|
id="linearGradient3357"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="4.4374332"
|
||||||
|
y1="64.008011"
|
||||||
|
x2="123.56256"
|
||||||
|
y2="64.008011" /><linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient3275"
|
||||||
|
id="linearGradient3359"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="28.140682"
|
||||||
|
y1="59.007069"
|
||||||
|
x2="123.56256"
|
||||||
|
y2="64.008011" /><linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient3300"
|
||||||
|
id="linearGradient3209"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="matrix(0.9961613,0,0,1.0000405,6.8742977e-4,-4.4021459e-3)"
|
||||||
|
x1="-0.98719376"
|
||||||
|
y1="119.27105"
|
||||||
|
x2="39.936729"
|
||||||
|
y2="88.299164" /><linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient3275"
|
||||||
|
id="linearGradient3211"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="-22.962652"
|
||||||
|
y1="-26.856916"
|
||||||
|
x2="113.12444"
|
||||||
|
y2="103.36325" /><linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient3275"
|
||||||
|
id="linearGradient3213"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="4.4374332"
|
||||||
|
y1="64.008011"
|
||||||
|
x2="123.56256"
|
||||||
|
y2="64.008011" /><linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient3275"
|
||||||
|
id="linearGradient3215"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="4.4374332"
|
||||||
|
y1="64.008011"
|
||||||
|
x2="123.56256"
|
||||||
|
y2="64.008011" /><linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient3275"
|
||||||
|
id="linearGradient3217"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="28.140682"
|
||||||
|
y1="59.007069"
|
||||||
|
x2="123.56256"
|
||||||
|
y2="64.008011" /><linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient3300"
|
||||||
|
id="linearGradient3232"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
gradientTransform="matrix(0.9961613,0,0,1.0000405,6.4944458e-2,-4.4021459e-3)"
|
||||||
|
x1="-0.98719376"
|
||||||
|
y1="119.27105"
|
||||||
|
x2="39.936729"
|
||||||
|
y2="88.299164" /><linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient3275"
|
||||||
|
id="linearGradient3234"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
x1="-17.119463"
|
||||||
|
y1="-35.774288"
|
||||||
|
x2="113.12444"
|
||||||
|
y2="103.36325" /></defs><sodipodi:namedview
|
||||||
|
inkscape:window-height="720"
|
||||||
|
inkscape:window-width="888"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
guidetolerance="10.0"
|
||||||
|
gridtolerance="10.0"
|
||||||
|
objecttolerance="10.0"
|
||||||
|
borderopacity="1.0"
|
||||||
|
bordercolor="#666666"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
id="base"
|
||||||
|
showgrid="true"
|
||||||
|
inkscape:snap-global="false"
|
||||||
|
showguides="true"
|
||||||
|
inkscape:guide-bbox="true"
|
||||||
|
inkscape:zoom="8.8034794"
|
||||||
|
inkscape:cx="3.3324561"
|
||||||
|
inkscape:cy="40.010499"
|
||||||
|
inkscape:window-x="542"
|
||||||
|
inkscape:window-y="39"
|
||||||
|
inkscape:current-layer="g11"><inkscape:grid
|
||||||
|
type="xygrid"
|
||||||
|
id="grid2432"
|
||||||
|
visible="true"
|
||||||
|
enabled="true" /></sodipodi:namedview><g
|
||||||
|
id="g11"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
inkscape:label="feed-icon-legacy"
|
||||||
|
transform="matrix(1.25,0,0,-1.25,0,160)"><path
|
||||||
|
style="fill:#fcaf3e;fill-opacity:1;fill-rule:nonzero;stroke:url(#linearGradient3232);stroke-width:0.80048220999999986"
|
||||||
|
d="M 38.002169,119.5841 C 38.136627,124.13453 33.833799,128.04502 29.34011,127.60391 C 22.114004,127.57701 14.884487,127.65816 7.6605468,127.56249 C 3.374464,127.23569 0.043196567,123.0315 0.4796428,118.78629 C 0.50646108,111.58944 0.42554092,104.38919 0.52093827,97.194505 C 0.84590169,92.898821 5.0383763,89.557076 9.2743628,89.994993 C 16.456202,90.021864 23.641448,89.940771 30.821119,90.036395 C 35.107237,90.362998 38.438787,94.566998 38.002169,98.8123 C 38.002169,105.73624 38.002169,112.66018 38.002169,119.5841 z"
|
||||||
|
id="path21" /><g
|
||||||
|
id="g27"
|
||||||
|
transform="matrix(0.2954876,0,0,-0.2955267,0.3513908,127.60862)"
|
||||||
|
style="fill:#f57900;fill-opacity:1"><g
|
||||||
|
id="g33"
|
||||||
|
style="fill:#f57900;fill-opacity:1"><g
|
||||||
|
id="g35"
|
||||||
|
style="fill:#f57900;fill-opacity:1"><path
|
||||||
|
id="path45"
|
||||||
|
d="M 123.429,29.915001 C 123.85961,15.464801 110.11454,3.1099424 95.831258,4.571 C 72.994905,4.6555834 50.147792,4.4001008 27.318303,4.7018714 C 13.655392,5.7359945 3.1212452,19.154954 4.571,32.63029 C 4.6555615,55.310488 4.4001543,78.001434 4.701815,100.67478 C 5.732848,114.33766 19.14685,124.88003 32.62429,123.429 C 55.309345,123.34447 78.005156,123.59982 100.68335,123.29816 C 114.34614,122.26269 124.87863,108.84276 123.429,95.36771 C 123.429,73.55014 123.429,51.732571 123.429,29.915001 z"
|
||||||
|
style="fill:#f57900;fill-opacity:1;stroke:none" /></g></g></g><g
|
||||||
|
id="g3267"
|
||||||
|
transform="matrix(0.2954876,0,0,-0.2955267,0.3016452,127.60042)"
|
||||||
|
style="fill:url(#linearGradient3217);fill-opacity:1"><g
|
||||||
|
id="g3269"
|
||||||
|
style="fill:url(#linearGradient3215);fill-opacity:1"><g
|
||||||
|
id="g3271"
|
||||||
|
style="fill:url(#linearGradient3213);fill-opacity:1"><path
|
||||||
|
id="path3273"
|
||||||
|
d="M 120.35364,17.922673 C 115.55613,8.6998977 107.96179,4.6474204 95.831258,4.571 C 72.994905,4.6555834 50.147792,4.4001008 27.318303,4.7018714 C 13.655392,5.7359945 3.1212452,19.154954 4.571,32.63029 C 4.6555615,55.310488 4.4001543,80.768894 4.701815,103.44224 C 6.1143957,104.77002 9.3538134,119.64674 16.281216,115.55817 C 32.747299,105.83986 62.937668,76.829161 61.921742,67.38561 C 61.921742,45.56804 120.35364,39.740243 120.35364,17.922673 z"
|
||||||
|
style="fill:url(#linearGradient3234);fill-opacity:1;stroke:none"
|
||||||
|
sodipodi:nodetypes="cccccscc" /></g></g></g><g
|
||||||
|
id="g3295"
|
||||||
|
transform="translate(-0.7068273,-0.4497993)"
|
||||||
|
style="fill:#eeeeec;stroke:#eeeeec"><path
|
||||||
|
transform="matrix(0.8,0,0,-0.8,0,128)"
|
||||||
|
sodipodi:nodetypes="ccccc"
|
||||||
|
id="path3293"
|
||||||
|
d="M 8.7550201,7.1164658 C 27.144226,9.188466 39.179126,18.429426 40.883534,39.325301 L 35.180723,39.325301 C 33.384365,22.620491 23.902594,14.889021 8.8353414,13.381526 L 8.7550201,7.1164658 z"
|
||||||
|
style="fill:#eeeeec;fill-opacity:1;fill-rule:evenodd;stroke:#eeeeec;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /><path
|
||||||
|
sodipodi:nodetypes="ccccc"
|
||||||
|
transform="matrix(0.8,0,0,-0.8,0,128)"
|
||||||
|
id="path3291"
|
||||||
|
d="M 9.0763052,24.2249 C 18.841763,24.662007 23.0271,30.700076 23.935743,39.405622 L 29.879518,39.485944 C 28.300152,25.30521 20.281142,19.207838 9.0763052,18.120482 L 9.0763052,24.2249 z"
|
||||||
|
style="fill:#eeeeec;fill-opacity:1;fill-rule:evenodd;stroke:#eeeeec;stroke-width:1px;stroke-linecap:round;stroke-linejoin:round;stroke-opacity:1" /><path
|
||||||
|
transform="matrix(0.8,0,0,-0.8,0.8178584,128)"
|
||||||
|
d="M 16.290628,35.107368 A 4.3635263,4.3537817 0 1 1 7.5635757,35.107368 A 4.3635263,4.3537817 0 1 1 16.290628,35.107368 z"
|
||||||
|
sodipodi:ry="4.3537817"
|
||||||
|
sodipodi:rx="4.3635263"
|
||||||
|
sodipodi:cy="35.107368"
|
||||||
|
sodipodi:cx="11.927102"
|
||||||
|
id="path2493"
|
||||||
|
style="opacity:1;fill:#eeeeec;fill-opacity:1;fill-rule:evenodd;stroke:#eeeeec;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
sodipodi:type="arc" /></g></g></svg>
|
After Width: | Height: | Size: 12 KiB |
39
icons/wscript_build
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
#! /usr/bin/env python
|
||||||
|
# WAF build script for midori
|
||||||
|
# This file is licensed under the terms of the expat license, see the file EXPAT.
|
||||||
|
|
||||||
|
import Utils
|
||||||
|
|
||||||
|
def add_image (bld, category, name):
|
||||||
|
|
||||||
|
srcdir = os.getcwd ()
|
||||||
|
blddir = bld.bdir
|
||||||
|
|
||||||
|
rsvg_convert = bld.env['RSVG_CONVERT']
|
||||||
|
|
||||||
|
if rsvg_convert:
|
||||||
|
Utils.check_dir (blddir + '/icons')
|
||||||
|
|
||||||
|
for size in [16, 22, 32, 48]:
|
||||||
|
format = str (size) + 'x' + str (size)
|
||||||
|
if os.access (srcdir + '/icons/' + format + '/' + name + '.png', os.F_OK):
|
||||||
|
bld.install_files ('${DATADIR}/icons/hicolor/' + format + '/' + category,
|
||||||
|
srcdir + '/icons/' + format + '/' + name + '.png')
|
||||||
|
elif not rsvg_convert:
|
||||||
|
pass
|
||||||
|
elif os.access (srcdir + '/icons/scalable/' + name + '.svg', os.F_OK):
|
||||||
|
Utils.check_dir (blddir + '/icons/' + format)
|
||||||
|
command = rsvg_convert + ' -w ' + str(size) + \
|
||||||
|
' -h ' + str(size) + \
|
||||||
|
' -o ' + blddir + '/icons/' + format + '/' + name + '.png' + \
|
||||||
|
' ' + srcdir + '/icons/scalable/' + name + '.svg'
|
||||||
|
if not Utils.exec_command (command):
|
||||||
|
bld.install_files ('${DATADIR}/icons/hicolor/' + format + '/' + category,
|
||||||
|
blddir + '/icons/' + format + '/' + name + '.png')
|
||||||
|
else:
|
||||||
|
Utils.pprint ('BLUE', "Optimized icons could not be created.")
|
||||||
|
break
|
||||||
|
|
||||||
|
add_image (bld, 'categories', 'extension')
|
||||||
|
add_image (bld, 'apps', 'midori')
|
||||||
|
add_image (bld, 'status', 'news-feed')
|
439
katze/katze-array.c
Normal file
|
@ -0,0 +1,439 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2008-2009 Christian Dywan <christian@twotoasts.de>
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
See the file COPYING for the full license text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "katze-array.h"
|
||||||
|
|
||||||
|
#include "katze-utils.h"
|
||||||
|
#include "marshal.h"
|
||||||
|
|
||||||
|
#include <glib/gi18n.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SECTION:katze-array
|
||||||
|
* @short_description: A type aware item container
|
||||||
|
* @see_also: #KatzeList
|
||||||
|
*
|
||||||
|
* #KatzeArray is a type aware container for items.
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct _KatzeArray
|
||||||
|
{
|
||||||
|
KatzeItem parent_instance;
|
||||||
|
|
||||||
|
GType type;
|
||||||
|
GList* items;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _KatzeArrayClass
|
||||||
|
{
|
||||||
|
KatzeItemClass parent_class;
|
||||||
|
|
||||||
|
/* Signals */
|
||||||
|
void
|
||||||
|
(*add_item) (KatzeArray* array,
|
||||||
|
gpointer item);
|
||||||
|
void
|
||||||
|
(*remove_item) (KatzeArray* array,
|
||||||
|
gpointer item);
|
||||||
|
void
|
||||||
|
(*move_item) (KatzeArray* array,
|
||||||
|
gpointer item,
|
||||||
|
gint index);
|
||||||
|
void
|
||||||
|
(*clear) (KatzeArray* array);
|
||||||
|
};
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (KatzeArray, katze_array, KATZE_TYPE_ITEM);
|
||||||
|
|
||||||
|
enum {
|
||||||
|
ADD_ITEM,
|
||||||
|
REMOVE_ITEM,
|
||||||
|
MOVE_ITEM,
|
||||||
|
CLEAR,
|
||||||
|
|
||||||
|
LAST_SIGNAL
|
||||||
|
};
|
||||||
|
|
||||||
|
static guint signals[LAST_SIGNAL];
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_array_finalize (GObject* object);
|
||||||
|
|
||||||
|
static void
|
||||||
|
_katze_array_add_item (KatzeArray* array,
|
||||||
|
gpointer item)
|
||||||
|
{
|
||||||
|
if (katze_array_is_a (array, G_TYPE_OBJECT))
|
||||||
|
{
|
||||||
|
GType type = G_OBJECT_TYPE (item);
|
||||||
|
|
||||||
|
g_return_if_fail (katze_array_is_a (array, type));
|
||||||
|
g_object_ref (item);
|
||||||
|
if (g_type_is_a (type, KATZE_TYPE_ITEM))
|
||||||
|
katze_item_set_parent (item, array);
|
||||||
|
}
|
||||||
|
|
||||||
|
array->items = g_list_append (array->items, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_katze_array_remove_item (KatzeArray* array,
|
||||||
|
gpointer item)
|
||||||
|
{
|
||||||
|
array->items = g_list_remove (array->items, item);
|
||||||
|
|
||||||
|
if (katze_array_is_a (array, G_TYPE_OBJECT))
|
||||||
|
{
|
||||||
|
if (KATZE_IS_ITEM (item))
|
||||||
|
katze_item_set_parent (item, NULL);
|
||||||
|
g_object_unref (item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_katze_array_move_item (KatzeArray* array,
|
||||||
|
gpointer item,
|
||||||
|
gint position)
|
||||||
|
{
|
||||||
|
array->items = g_list_remove (array->items, item);
|
||||||
|
array->items = g_list_insert (array->items, item, position);
|
||||||
|
}
|
||||||
|
|
||||||
|
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)))
|
||||||
|
katze_array_remove_item (array, item);
|
||||||
|
}
|
||||||
|
g_list_free (array->items);
|
||||||
|
array->items = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_array_class_init (KatzeArrayClass* class)
|
||||||
|
{
|
||||||
|
GObjectClass* gobject_class;
|
||||||
|
|
||||||
|
gobject_class = G_OBJECT_CLASS (class);
|
||||||
|
gobject_class->finalize = katze_array_finalize;
|
||||||
|
|
||||||
|
signals[ADD_ITEM] = g_signal_new (
|
||||||
|
"add-item",
|
||||||
|
G_TYPE_FROM_CLASS (class),
|
||||||
|
(GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
|
||||||
|
G_STRUCT_OFFSET (KatzeArrayClass, add_item),
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
g_cclosure_marshal_VOID__POINTER,
|
||||||
|
G_TYPE_NONE, 1,
|
||||||
|
G_TYPE_POINTER);
|
||||||
|
|
||||||
|
signals[REMOVE_ITEM] = g_signal_new (
|
||||||
|
"remove-item",
|
||||||
|
G_TYPE_FROM_CLASS (class),
|
||||||
|
(GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
|
||||||
|
G_STRUCT_OFFSET (KatzeArrayClass, remove_item),
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
g_cclosure_marshal_VOID__POINTER,
|
||||||
|
G_TYPE_NONE, 1,
|
||||||
|
G_TYPE_POINTER);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* KatzeArray::move-item:
|
||||||
|
* @array: the object on which the signal is emitted
|
||||||
|
* @item: the item being moved
|
||||||
|
* @position: the new position of the item
|
||||||
|
*
|
||||||
|
* An item is moved to a new position.
|
||||||
|
*
|
||||||
|
* Since: 0.1.6
|
||||||
|
**/
|
||||||
|
signals[MOVE_ITEM] = g_signal_new (
|
||||||
|
"move-item",
|
||||||
|
G_TYPE_FROM_CLASS (class),
|
||||||
|
(GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
|
||||||
|
G_STRUCT_OFFSET (KatzeArrayClass, move_item),
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
katze_cclosure_marshal_VOID__POINTER_INT,
|
||||||
|
G_TYPE_NONE, 2,
|
||||||
|
G_TYPE_POINTER,
|
||||||
|
G_TYPE_INT);
|
||||||
|
|
||||||
|
signals[CLEAR] = g_signal_new (
|
||||||
|
"clear",
|
||||||
|
G_TYPE_FROM_CLASS (class),
|
||||||
|
(GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
|
||||||
|
G_STRUCT_OFFSET (KatzeArrayClass, clear),
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
g_cclosure_marshal_VOID__VOID,
|
||||||
|
G_TYPE_NONE, 0);
|
||||||
|
|
||||||
|
gobject_class = G_OBJECT_CLASS (class);
|
||||||
|
gobject_class->finalize = katze_array_finalize;
|
||||||
|
|
||||||
|
class->add_item = _katze_array_add_item;
|
||||||
|
class->remove_item = _katze_array_remove_item;
|
||||||
|
class->move_item = _katze_array_move_item;
|
||||||
|
class->clear = _katze_array_clear;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_array_init (KatzeArray* array)
|
||||||
|
{
|
||||||
|
array->type = G_TYPE_NONE;
|
||||||
|
array->items = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_array_finalize (GObject* object)
|
||||||
|
{
|
||||||
|
KatzeArray* array;
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
array = KATZE_ARRAY (object);
|
||||||
|
if (katze_array_is_a (array, G_TYPE_OBJECT))
|
||||||
|
{
|
||||||
|
gpointer item;
|
||||||
|
i = 0;
|
||||||
|
while ((item = g_list_nth_data (array->items, i++)))
|
||||||
|
g_object_unref (item);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_list_free (array->items);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (katze_array_parent_class)->finalize (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* katze_array_new:
|
||||||
|
* @type: the expected item type
|
||||||
|
*
|
||||||
|
* Creates a new #KatzeArray for @type items.
|
||||||
|
*
|
||||||
|
* You may only add items of the given type or inherited
|
||||||
|
* from it to this array *if* @type is an #GObject type.
|
||||||
|
* The array will keep a reference on each object until
|
||||||
|
* it is removed from the array.
|
||||||
|
*
|
||||||
|
* Return value: a new #KatzeArray
|
||||||
|
**/
|
||||||
|
KatzeArray*
|
||||||
|
katze_array_new (GType type)
|
||||||
|
{
|
||||||
|
KatzeArray* array = g_object_new (KATZE_TYPE_ARRAY, NULL);
|
||||||
|
array->type = type;
|
||||||
|
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* katze_array_is_a:
|
||||||
|
* @array: a #KatzeArray
|
||||||
|
* @is_a_type: type to compare with
|
||||||
|
*
|
||||||
|
* Checks whether the array is compatible
|
||||||
|
* with items of the specified type.
|
||||||
|
*
|
||||||
|
* Retur value: %TRUE if @array is compatible with @is_a_type
|
||||||
|
**/
|
||||||
|
gboolean
|
||||||
|
katze_array_is_a (KatzeArray* array,
|
||||||
|
GType is_a_type)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (KATZE_IS_ARRAY (array), FALSE);
|
||||||
|
|
||||||
|
return g_type_is_a (array->type, is_a_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* katze_array_add_item:
|
||||||
|
* @array: a #KatzeArray
|
||||||
|
* @item: an item
|
||||||
|
*
|
||||||
|
* Adds an item to the array.
|
||||||
|
*
|
||||||
|
* If @item is a #KatzeItem its parent is set accordingly.
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
katze_array_add_item (KatzeArray* array,
|
||||||
|
gpointer item)
|
||||||
|
{
|
||||||
|
g_return_if_fail (KATZE_IS_ARRAY (array));
|
||||||
|
|
||||||
|
g_signal_emit (array, signals[ADD_ITEM], 0, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* katze_array_remove_item:
|
||||||
|
* @array: a #KatzeArray
|
||||||
|
* @item: an item
|
||||||
|
*
|
||||||
|
* Removes an item from the array.
|
||||||
|
*
|
||||||
|
* If @item is a #KatzeItem its parent is unset accordingly.
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
katze_array_remove_item (KatzeArray* array,
|
||||||
|
gpointer item)
|
||||||
|
{
|
||||||
|
g_return_if_fail (KATZE_IS_ARRAY (array));
|
||||||
|
|
||||||
|
g_signal_emit (array, signals[REMOVE_ITEM], 0, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* katze_array_get_nth_item:
|
||||||
|
* @array: a #KatzeArray
|
||||||
|
* @n: an index in the array
|
||||||
|
*
|
||||||
|
* Retrieves the item in @array at the position @n.
|
||||||
|
*
|
||||||
|
* Return value: an item, or %NULL
|
||||||
|
**/
|
||||||
|
gpointer
|
||||||
|
katze_array_get_nth_item (KatzeArray* array,
|
||||||
|
guint n)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (KATZE_IS_ARRAY (array), NULL);
|
||||||
|
|
||||||
|
return g_list_nth_data (array->items, n);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* katze_array_is_empty:
|
||||||
|
* @array: a #KatzeArray
|
||||||
|
*
|
||||||
|
* Determines whether @array is empty.
|
||||||
|
*
|
||||||
|
* Return value: an item, or %NULL
|
||||||
|
**/
|
||||||
|
gboolean
|
||||||
|
katze_array_is_empty (KatzeArray* array)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (KATZE_IS_ARRAY (array), TRUE);
|
||||||
|
|
||||||
|
return !g_list_nth_data (array->items, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* katze_array_get_item_index:
|
||||||
|
* @array: a #KatzeArray
|
||||||
|
* @item: an item in the array
|
||||||
|
*
|
||||||
|
* Retrieves the index of the item in @array.
|
||||||
|
*
|
||||||
|
* Return value: an item, or -1
|
||||||
|
**/
|
||||||
|
gint
|
||||||
|
katze_array_get_item_index (KatzeArray* array,
|
||||||
|
gpointer item)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (KATZE_IS_ARRAY (array), -1);
|
||||||
|
|
||||||
|
return g_list_index (array->items, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* katze_array_find_token:
|
||||||
|
* @array: a #KatzeArray
|
||||||
|
* @token: a token string
|
||||||
|
*
|
||||||
|
* Looks up an item in the array which has the specified token.
|
||||||
|
*
|
||||||
|
* This function will silently fail if the type of the list
|
||||||
|
* is not based on #GObject and only #KatzeItem children
|
||||||
|
* are checked for their token, any other objects are skipped.
|
||||||
|
*
|
||||||
|
* Note that @token is by definition unique to one item.
|
||||||
|
*
|
||||||
|
* Return value: an item, or %NULL
|
||||||
|
**/
|
||||||
|
gpointer
|
||||||
|
katze_array_find_token (KatzeArray* array,
|
||||||
|
const gchar* token)
|
||||||
|
{
|
||||||
|
guint i;
|
||||||
|
gpointer item;
|
||||||
|
|
||||||
|
if (!katze_array_is_a (array, G_TYPE_OBJECT))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
while ((item = g_list_nth_data (array->items, i++)))
|
||||||
|
{
|
||||||
|
const gchar* found_token = katze_item_get_token ((KatzeItem*)item);
|
||||||
|
if (!g_strcmp0 (found_token, token))
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* katze_array_get_length:
|
||||||
|
* @array: a #KatzeArray
|
||||||
|
*
|
||||||
|
* Retrieves the number of items in @array.
|
||||||
|
*
|
||||||
|
* Return value: the length of the list
|
||||||
|
**/
|
||||||
|
guint
|
||||||
|
katze_array_get_length (KatzeArray* array)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (KATZE_IS_ARRAY (array), 0);
|
||||||
|
|
||||||
|
return g_list_length (array->items);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* katze_array_move_item:
|
||||||
|
* @array: a #KatzeArray
|
||||||
|
* @item: the item being moved
|
||||||
|
* @position: the new position of the item
|
||||||
|
*
|
||||||
|
* Moves @item to the position @position.
|
||||||
|
*
|
||||||
|
* Since: 0.1.6
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
katze_array_move_item (KatzeArray* array,
|
||||||
|
gpointer item,
|
||||||
|
gint position)
|
||||||
|
{
|
||||||
|
g_return_if_fail (KATZE_IS_ARRAY (array));
|
||||||
|
|
||||||
|
g_signal_emit (array, signals[MOVE_ITEM], 0, item, position);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* katze_array_clear:
|
||||||
|
* @array: a #KatzeArray
|
||||||
|
*
|
||||||
|
* Deletes all items currently contained in @array.
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
katze_array_clear (KatzeArray* array)
|
||||||
|
{
|
||||||
|
g_return_if_fail (KATZE_IS_ARRAY (array));
|
||||||
|
|
||||||
|
g_signal_emit (array, signals[CLEAR], 0);
|
||||||
|
}
|
81
katze/katze-array.h
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2008-2009 Christian Dywan <christian@twotoasts.de>
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
See the file COPYING for the full license text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __KATZE_ARRAY_H__
|
||||||
|
#define __KATZE_ARRAY_H__
|
||||||
|
|
||||||
|
#include <katze/katze-item.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define KATZE_TYPE_ARRAY \
|
||||||
|
(katze_array_get_type ())
|
||||||
|
#define KATZE_ARRAY(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_CAST ((obj), KATZE_TYPE_ARRAY, KatzeArray))
|
||||||
|
#define KATZE_ARRAY_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_CAST ((klass), KATZE_TYPE_ARRAY, KatzeArrayClass))
|
||||||
|
#define KATZE_IS_ARRAY(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), KATZE_TYPE_ARRAY))
|
||||||
|
#define KATZE_IS_ARRAY_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_TYPE ((klass), KATZE_TYPE_ARRAY))
|
||||||
|
#define KATZE_ARRAY_GET_CLASS(obj) \
|
||||||
|
(G_TYPE_INSTANCE_GET_CLASS ((obj), KATZE_TYPE_ARRAY, KatzeArrayClass))
|
||||||
|
|
||||||
|
typedef struct _KatzeArray KatzeArray;
|
||||||
|
typedef struct _KatzeArrayClass KatzeArrayClass;
|
||||||
|
|
||||||
|
GType
|
||||||
|
katze_array_get_type (void);
|
||||||
|
|
||||||
|
KatzeArray*
|
||||||
|
katze_array_new (GType type);
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
katze_array_is_a (KatzeArray* array,
|
||||||
|
GType is_a_type);
|
||||||
|
|
||||||
|
void
|
||||||
|
katze_array_add_item (KatzeArray* array,
|
||||||
|
gpointer item);
|
||||||
|
|
||||||
|
void
|
||||||
|
katze_array_remove_item (KatzeArray* array,
|
||||||
|
gpointer item);
|
||||||
|
|
||||||
|
gpointer
|
||||||
|
katze_array_get_nth_item (KatzeArray* array,
|
||||||
|
guint n);
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
katze_array_is_empty (KatzeArray* array);
|
||||||
|
|
||||||
|
gint
|
||||||
|
katze_array_get_item_index (KatzeArray* array,
|
||||||
|
gpointer item);
|
||||||
|
|
||||||
|
gpointer
|
||||||
|
katze_array_find_token (KatzeArray* array,
|
||||||
|
const gchar* token);
|
||||||
|
|
||||||
|
guint
|
||||||
|
katze_array_get_length (KatzeArray* array);
|
||||||
|
|
||||||
|
void
|
||||||
|
katze_array_move_item (KatzeArray* array,
|
||||||
|
gpointer item,
|
||||||
|
gint position);
|
||||||
|
|
||||||
|
void
|
||||||
|
katze_array_clear (KatzeArray* array);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __KATZE_ARRAY_H__ */
|
574
katze/katze-arrayaction.c
Normal file
|
@ -0,0 +1,574 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2008 Christian Dywan <christian@twotoasts.de>
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
See the file COPYING for the full license text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "katze-arrayaction.h"
|
||||||
|
|
||||||
|
#include "katze-net.h"
|
||||||
|
#include "katze-utils.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <glib/gi18n.h>
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
struct _KatzeArrayAction
|
||||||
|
{
|
||||||
|
GtkAction parent_instance;
|
||||||
|
|
||||||
|
KatzeArray* array;
|
||||||
|
KatzeNet* net;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _KatzeArrayActionClass
|
||||||
|
{
|
||||||
|
GtkActionClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (KatzeArrayAction, katze_array_action, GTK_TYPE_ACTION);
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
PROP_0,
|
||||||
|
|
||||||
|
PROP_ARRAY
|
||||||
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
POPULATE_POPUP,
|
||||||
|
ACTIVATE_ITEM,
|
||||||
|
LAST_SIGNAL
|
||||||
|
};
|
||||||
|
|
||||||
|
static guint signals[LAST_SIGNAL];
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_array_action_finalize (GObject* object);
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_array_action_set_property (GObject* object,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue* value,
|
||||||
|
GParamSpec* pspec);
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_array_action_get_property (GObject* object,
|
||||||
|
guint prop_id,
|
||||||
|
GValue* value,
|
||||||
|
GParamSpec* pspec);
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_array_action_activate (GtkAction* object);
|
||||||
|
|
||||||
|
static GtkWidget*
|
||||||
|
katze_array_action_create_tool_item (GtkAction* action);
|
||||||
|
|
||||||
|
static GtkWidget*
|
||||||
|
katze_array_action_create_menu_item (GtkAction* action);
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_array_action_connect_proxy (GtkAction* action,
|
||||||
|
GtkWidget* proxy);
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_array_action_disconnect_proxy (GtkAction* action,
|
||||||
|
GtkWidget* proxy);
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_array_action_class_init (KatzeArrayActionClass* class)
|
||||||
|
{
|
||||||
|
GObjectClass* gobject_class;
|
||||||
|
GtkActionClass* action_class;
|
||||||
|
|
||||||
|
signals[POPULATE_POPUP] = g_signal_new ("populate-popup",
|
||||||
|
G_TYPE_FROM_CLASS (class),
|
||||||
|
(GSignalFlags) (G_SIGNAL_RUN_LAST),
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
g_cclosure_marshal_VOID__OBJECT,
|
||||||
|
G_TYPE_NONE, 1,
|
||||||
|
GTK_TYPE_MENU);
|
||||||
|
|
||||||
|
signals[ACTIVATE_ITEM] = g_signal_new ("activate-item",
|
||||||
|
G_TYPE_FROM_CLASS (class),
|
||||||
|
(GSignalFlags) (G_SIGNAL_RUN_LAST),
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
g_cclosure_marshal_VOID__OBJECT,
|
||||||
|
G_TYPE_NONE, 1,
|
||||||
|
KATZE_TYPE_ITEM);
|
||||||
|
|
||||||
|
gobject_class = G_OBJECT_CLASS (class);
|
||||||
|
gobject_class->finalize = katze_array_action_finalize;
|
||||||
|
gobject_class->set_property = katze_array_action_set_property;
|
||||||
|
gobject_class->get_property = katze_array_action_get_property;
|
||||||
|
|
||||||
|
action_class = GTK_ACTION_CLASS (class);
|
||||||
|
action_class->activate = katze_array_action_activate;
|
||||||
|
action_class->create_menu_item = katze_array_action_create_menu_item;
|
||||||
|
action_class->create_tool_item = katze_array_action_create_tool_item;
|
||||||
|
action_class->connect_proxy = katze_array_action_connect_proxy;
|
||||||
|
action_class->disconnect_proxy = katze_array_action_disconnect_proxy;
|
||||||
|
|
||||||
|
g_object_class_install_property (gobject_class,
|
||||||
|
PROP_ARRAY,
|
||||||
|
g_param_spec_object (
|
||||||
|
"array",
|
||||||
|
"Array",
|
||||||
|
"The array the action represents",
|
||||||
|
KATZE_TYPE_ARRAY,
|
||||||
|
G_PARAM_READWRITE));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_array_action_init (KatzeArrayAction* array_action)
|
||||||
|
{
|
||||||
|
array_action->array = NULL;
|
||||||
|
array_action->net = katze_net_new ();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_array_action_finalize (GObject* object)
|
||||||
|
{
|
||||||
|
KatzeArrayAction* array_action = KATZE_ARRAY_ACTION (object);
|
||||||
|
|
||||||
|
katze_object_assign (array_action->array, NULL);
|
||||||
|
katze_object_assign (array_action->net, NULL);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (katze_array_action_parent_class)->finalize (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_array_action_set_property (GObject* object,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue* value,
|
||||||
|
GParamSpec* pspec)
|
||||||
|
{
|
||||||
|
KatzeArrayAction* array_action = KATZE_ARRAY_ACTION (object);
|
||||||
|
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_ARRAY:
|
||||||
|
katze_array_action_set_array (array_action, g_value_get_object (value));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_array_action_get_property (GObject* object,
|
||||||
|
guint prop_id,
|
||||||
|
GValue* value,
|
||||||
|
GParamSpec* pspec)
|
||||||
|
{
|
||||||
|
KatzeArrayAction* array_action = KATZE_ARRAY_ACTION (object);
|
||||||
|
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_ARRAY:
|
||||||
|
g_value_set_object (value, array_action->array);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_array_action_activate (GtkAction* action)
|
||||||
|
{
|
||||||
|
GSList* proxies;
|
||||||
|
|
||||||
|
proxies = gtk_action_get_proxies (action);
|
||||||
|
if (!proxies)
|
||||||
|
return;
|
||||||
|
|
||||||
|
do
|
||||||
|
if (GTK_IS_TOOL_ITEM (proxies->data))
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
while ((proxies = g_slist_next (proxies)));
|
||||||
|
|
||||||
|
if (GTK_ACTION_CLASS (katze_array_action_parent_class)->activate)
|
||||||
|
GTK_ACTION_CLASS (katze_array_action_parent_class)->activate (action);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_array_action_menu_item_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 void
|
||||||
|
katze_array_action_menu_item_select_cb (GtkWidget* proxy,
|
||||||
|
KatzeArrayAction* array_action);
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_array_action_generate_menu (KatzeArrayAction* array_action,
|
||||||
|
KatzeArray* array,
|
||||||
|
GtkWidget* menu,
|
||||||
|
GtkWidget* proxy)
|
||||||
|
{
|
||||||
|
guint i;
|
||||||
|
KatzeItem* item;
|
||||||
|
GtkWidget* menuitem;
|
||||||
|
const gchar* icon_name;
|
||||||
|
GdkPixbuf* icon;
|
||||||
|
GtkWidget* image;
|
||||||
|
GtkWidget* submenu;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
while ((item = katze_array_get_nth_item (array, i++)))
|
||||||
|
{
|
||||||
|
/* FIXME: The menu item should reflect changes to the item */
|
||||||
|
if (!KATZE_IS_ARRAY (item) && !katze_item_get_uri (item))
|
||||||
|
{
|
||||||
|
menuitem = gtk_separator_menu_item_new ();
|
||||||
|
gtk_widget_show (menuitem);
|
||||||
|
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
|
||||||
|
g_object_set_data (G_OBJECT (menuitem), "KatzeItem", item);
|
||||||
|
if (KATZE_IS_ARRAY (item))
|
||||||
|
{
|
||||||
|
submenu = gtk_menu_new ();
|
||||||
|
gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), submenu);
|
||||||
|
g_signal_connect (menuitem, "select",
|
||||||
|
G_CALLBACK (katze_array_action_menu_item_select_cb), array_action);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
g_signal_connect (menuitem, "activate",
|
||||||
|
G_CALLBACK (katze_array_action_menu_item_activate_cb), array_action);
|
||||||
|
gtk_widget_show (menuitem);
|
||||||
|
}
|
||||||
|
if (!i)
|
||||||
|
{
|
||||||
|
menuitem = gtk_image_menu_item_new_with_label (_("Empty"));
|
||||||
|
gtk_widget_set_sensitive (menuitem, FALSE);
|
||||||
|
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
|
||||||
|
gtk_widget_show (menuitem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_array_action_menu_item_select_cb (GtkWidget* proxy,
|
||||||
|
KatzeArrayAction* array_action)
|
||||||
|
{
|
||||||
|
GtkWidget* menu;
|
||||||
|
KatzeArray* array;
|
||||||
|
|
||||||
|
menu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (proxy));
|
||||||
|
gtk_container_foreach (GTK_CONTAINER (menu),
|
||||||
|
(GtkCallback)(gtk_widget_destroy), NULL);
|
||||||
|
|
||||||
|
array = g_object_get_data (G_OBJECT (proxy), "KatzeItem");
|
||||||
|
katze_array_action_generate_menu (array_action, array, menu, proxy);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_array_action_proxy_clicked_cb (GtkWidget* proxy,
|
||||||
|
KatzeArrayAction* array_action)
|
||||||
|
{
|
||||||
|
GtkWidget* menu;
|
||||||
|
KatzeArray* array;
|
||||||
|
|
||||||
|
if (GTK_IS_MENU_ITEM (proxy))
|
||||||
|
{
|
||||||
|
g_object_set_data (G_OBJECT (proxy), "KatzeItem", array_action->array);
|
||||||
|
katze_array_action_menu_item_select_cb (proxy, array_action);
|
||||||
|
g_signal_emit (array_action, signals[POPULATE_POPUP], 0,
|
||||||
|
gtk_menu_item_get_submenu (GTK_MENU_ITEM (proxy)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
menu = gtk_menu_new ();
|
||||||
|
|
||||||
|
array = (KatzeArray*)g_object_get_data (G_OBJECT (proxy), "KatzeArray");
|
||||||
|
if (!array)
|
||||||
|
array = array_action->array;
|
||||||
|
katze_array_action_generate_menu (array_action, array, menu, proxy);
|
||||||
|
|
||||||
|
/* populate-popup should only affect the main proxy */
|
||||||
|
if (array == array_action->array)
|
||||||
|
g_signal_emit (array_action, signals[POPULATE_POPUP], 0, menu);
|
||||||
|
|
||||||
|
katze_widget_popup (GTK_WIDGET (proxy), GTK_MENU (menu),
|
||||||
|
NULL, KATZE_MENU_POSITION_LEFT);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GtkWidget*
|
||||||
|
katze_array_action_create_menu_item (GtkAction* action)
|
||||||
|
{
|
||||||
|
GtkWidget* menuitem;
|
||||||
|
|
||||||
|
menuitem = gtk_menu_item_new ();
|
||||||
|
return menuitem;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GtkWidget*
|
||||||
|
katze_array_action_create_tool_item (GtkAction* action)
|
||||||
|
{
|
||||||
|
GtkWidget* toolitem;
|
||||||
|
|
||||||
|
toolitem = GTK_WIDGET (gtk_tool_button_new (NULL, NULL));
|
||||||
|
return toolitem;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_array_action_label_notify_cb (GtkToolButton* item,
|
||||||
|
GParamSpec* pspec,
|
||||||
|
GtkLabel* label)
|
||||||
|
{
|
||||||
|
const gchar* property;
|
||||||
|
const gchar* text;
|
||||||
|
|
||||||
|
if (!G_IS_PARAM_SPEC_STRING (pspec))
|
||||||
|
return;
|
||||||
|
|
||||||
|
property = g_param_spec_get_name (pspec);
|
||||||
|
if (!strcmp (property, "label"))
|
||||||
|
{
|
||||||
|
text = gtk_tool_button_get_label (item);
|
||||||
|
gtk_label_set_text (label, text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_array_action_item_notify_cb (KatzeItem* item,
|
||||||
|
GParamSpec* pspec,
|
||||||
|
GtkToolItem* toolitem)
|
||||||
|
{
|
||||||
|
KatzeArrayAction* array_action;
|
||||||
|
const gchar* property;
|
||||||
|
const gchar* title;
|
||||||
|
const gchar* desc;
|
||||||
|
GdkPixbuf* icon;
|
||||||
|
GtkWidget* image;
|
||||||
|
|
||||||
|
if (!G_IS_PARAM_SPEC_STRING (pspec))
|
||||||
|
return;
|
||||||
|
|
||||||
|
array_action = (KatzeArrayAction*)g_object_get_data (
|
||||||
|
G_OBJECT (toolitem), "KatzeArrayAction");
|
||||||
|
property = g_param_spec_get_name (pspec);
|
||||||
|
if (!strcmp (property, "name"))
|
||||||
|
{
|
||||||
|
title = katze_item_get_name (item);
|
||||||
|
if (title)
|
||||||
|
gtk_tool_button_set_label (GTK_TOOL_BUTTON (toolitem), title);
|
||||||
|
else
|
||||||
|
gtk_tool_button_set_label (GTK_TOOL_BUTTON (toolitem),
|
||||||
|
katze_item_get_uri (item));
|
||||||
|
}
|
||||||
|
else if (!strcmp (property, "text"))
|
||||||
|
{
|
||||||
|
desc = katze_item_get_text (item);
|
||||||
|
if (desc && *desc)
|
||||||
|
gtk_tool_item_set_tooltip_text (toolitem, desc);
|
||||||
|
else
|
||||||
|
gtk_tool_item_set_tooltip_text (toolitem,
|
||||||
|
katze_item_get_uri (item));
|
||||||
|
}
|
||||||
|
else if (!KATZE_IS_ARRAY (item) && !strcmp (property, "uri"))
|
||||||
|
{
|
||||||
|
icon = katze_net_load_icon (array_action->net, katze_item_get_uri (item),
|
||||||
|
NULL, GTK_WIDGET (toolitem), NULL);
|
||||||
|
image = gtk_image_new_from_pixbuf (icon);
|
||||||
|
g_object_unref (icon);
|
||||||
|
gtk_widget_show (image);
|
||||||
|
gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (toolitem), image);
|
||||||
|
}
|
||||||
|
else if (!strcmp (property, "icon"))
|
||||||
|
{
|
||||||
|
image = gtk_image_new_from_icon_name (katze_item_get_icon (item),
|
||||||
|
GTK_ICON_SIZE_MENU);
|
||||||
|
gtk_widget_show (image);
|
||||||
|
gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (toolitem), image);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* katze_array_action_create_tool_item_for:
|
||||||
|
* @array_action: a #KatzeArrayAction
|
||||||
|
* @item: a #KatzeItem
|
||||||
|
*
|
||||||
|
* Creates a tool item for a particular @item, that also
|
||||||
|
* reflects changes to its properties. In the case of
|
||||||
|
* an array, the item will create a popup menu with
|
||||||
|
* the contained items.
|
||||||
|
*
|
||||||
|
* Note that the label is reasonably ellipsized for you,
|
||||||
|
* much like katze_image_menu_item_new_ellipsized().
|
||||||
|
*
|
||||||
|
* Return value: a new tool item
|
||||||
|
**/
|
||||||
|
GtkToolItem*
|
||||||
|
katze_array_action_create_tool_item_for (KatzeArrayAction* array_action,
|
||||||
|
KatzeItem* item)
|
||||||
|
{
|
||||||
|
const gchar* title;
|
||||||
|
const gchar* uri;
|
||||||
|
const gchar* desc;
|
||||||
|
GtkToolItem* toolitem;
|
||||||
|
GdkPixbuf* icon;
|
||||||
|
GtkWidget* image;
|
||||||
|
GtkWidget* label;
|
||||||
|
|
||||||
|
title = katze_item_get_name (item);
|
||||||
|
uri = katze_item_get_uri (item);
|
||||||
|
desc = katze_item_get_text (item);
|
||||||
|
|
||||||
|
if (!KATZE_IS_ARRAY (item) && !uri)
|
||||||
|
return gtk_separator_tool_item_new ();
|
||||||
|
|
||||||
|
toolitem = gtk_tool_button_new (NULL, NULL);
|
||||||
|
if (KATZE_IS_ARRAY (item))
|
||||||
|
icon = gtk_widget_render_icon (GTK_WIDGET (toolitem),
|
||||||
|
GTK_STOCK_DIRECTORY, GTK_ICON_SIZE_MENU, NULL);
|
||||||
|
else
|
||||||
|
icon = katze_net_load_icon (array_action->net, uri,
|
||||||
|
NULL, GTK_WIDGET (toolitem), NULL);
|
||||||
|
image = gtk_image_new_from_pixbuf (icon);
|
||||||
|
g_object_unref (icon);
|
||||||
|
gtk_widget_show (image);
|
||||||
|
gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (toolitem), image);
|
||||||
|
label = gtk_label_new (NULL);
|
||||||
|
/* FIXME: Should text direction be respected here? */
|
||||||
|
gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.0);
|
||||||
|
gtk_label_set_max_width_chars (GTK_LABEL (label), 25);
|
||||||
|
gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_MIDDLE);
|
||||||
|
gtk_widget_show (label);
|
||||||
|
gtk_tool_button_set_label_widget (GTK_TOOL_BUTTON (toolitem), label);
|
||||||
|
/* GtkToolItem won't update our custom label, so we
|
||||||
|
apply a little bit of 'magic' to fix that. */
|
||||||
|
g_signal_connect (toolitem, "notify",
|
||||||
|
G_CALLBACK (katze_array_action_label_notify_cb), label);
|
||||||
|
if (title)
|
||||||
|
gtk_tool_button_set_label (GTK_TOOL_BUTTON (toolitem), title);
|
||||||
|
else
|
||||||
|
gtk_tool_button_set_label (GTK_TOOL_BUTTON (toolitem), uri);
|
||||||
|
gtk_tool_item_set_is_important (toolitem, TRUE);
|
||||||
|
if (desc && *desc)
|
||||||
|
gtk_tool_item_set_tooltip_text (toolitem, desc);
|
||||||
|
else
|
||||||
|
gtk_tool_item_set_tooltip_text (toolitem, uri);
|
||||||
|
if (KATZE_IS_ARRAY (item))
|
||||||
|
{
|
||||||
|
g_object_set_data (G_OBJECT (toolitem), "KatzeArray", item);
|
||||||
|
g_signal_connect (toolitem, "clicked",
|
||||||
|
G_CALLBACK (katze_array_action_proxy_clicked_cb), array_action);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_object_set_data (G_OBJECT (toolitem), "KatzeArrayAction", array_action);
|
||||||
|
g_signal_connect (item, "notify",
|
||||||
|
G_CALLBACK (katze_array_action_item_notify_cb), toolitem);
|
||||||
|
return toolitem;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_array_action_connect_proxy (GtkAction* action,
|
||||||
|
GtkWidget* proxy)
|
||||||
|
{
|
||||||
|
GTK_ACTION_CLASS (katze_array_action_parent_class)->connect_proxy (
|
||||||
|
action, proxy);
|
||||||
|
|
||||||
|
if (GTK_IS_TOOL_ITEM (proxy))
|
||||||
|
{
|
||||||
|
g_signal_connect (proxy, "clicked",
|
||||||
|
G_CALLBACK (katze_array_action_proxy_clicked_cb), action);
|
||||||
|
}
|
||||||
|
else if (GTK_IS_MENU_ITEM (proxy))
|
||||||
|
{
|
||||||
|
gtk_menu_item_set_submenu (GTK_MENU_ITEM (proxy), gtk_menu_new ());
|
||||||
|
/* FIXME: 'select' doesn't cover all ways of selection */
|
||||||
|
g_signal_connect (proxy, "select",
|
||||||
|
G_CALLBACK (katze_array_action_proxy_clicked_cb), action);
|
||||||
|
}
|
||||||
|
gtk_widget_set_sensitive (proxy, KATZE_ARRAY_ACTION (action)->array != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_array_action_disconnect_proxy (GtkAction* action,
|
||||||
|
GtkWidget* proxy)
|
||||||
|
{
|
||||||
|
g_signal_handlers_disconnect_by_func (proxy,
|
||||||
|
G_CALLBACK (katze_array_action_proxy_clicked_cb), action);
|
||||||
|
|
||||||
|
GTK_ACTION_CLASS (katze_array_action_parent_class)->disconnect_proxy
|
||||||
|
(action, proxy);
|
||||||
|
}
|
||||||
|
|
||||||
|
KatzeArray*
|
||||||
|
katze_array_action_get_array (KatzeArrayAction* array_action)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (KATZE_IS_ARRAY_ACTION (array_action), NULL);
|
||||||
|
|
||||||
|
return array_action->array;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
katze_array_action_set_array (KatzeArrayAction* array_action,
|
||||||
|
KatzeArray* array)
|
||||||
|
{
|
||||||
|
GSList* proxies;
|
||||||
|
|
||||||
|
g_return_if_fail (KATZE_IS_ARRAY_ACTION (array_action));
|
||||||
|
g_return_if_fail (!array || katze_array_is_a (array, KATZE_TYPE_ITEM));
|
||||||
|
|
||||||
|
/* FIXME: Disconnect old array */
|
||||||
|
|
||||||
|
if (array)
|
||||||
|
g_object_ref (array);
|
||||||
|
katze_object_assign (array_action->array, array);
|
||||||
|
|
||||||
|
/* FIXME: Add and remove items dynamically */
|
||||||
|
/*g_object_connect (array,
|
||||||
|
"signal-after::add-item",
|
||||||
|
katze_array_action_engines_add_item_cb, array_action,
|
||||||
|
"signal-after::remove-item",
|
||||||
|
katze_array_action_engines_remove_item_cb, array_action,
|
||||||
|
NULL);*/
|
||||||
|
|
||||||
|
g_object_notify (G_OBJECT (array_action), "array");
|
||||||
|
|
||||||
|
proxies = gtk_action_get_proxies (GTK_ACTION (array_action));
|
||||||
|
if (!proxies)
|
||||||
|
return;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
gtk_widget_set_sensitive (proxies->data, array != NULL);
|
||||||
|
}
|
||||||
|
while ((proxies = g_slist_next (proxies)));
|
||||||
|
}
|
53
katze/katze-arrayaction.h
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2008 Christian Dywan <christian@twotoasts.de>
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
See the file COPYING for the full license text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __KATZE_ARRAY_ACTION_H__
|
||||||
|
#define __KATZE_ARRAY_ACTION_H__
|
||||||
|
|
||||||
|
#include "katze-array.h"
|
||||||
|
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define KATZE_TYPE_ARRAY_ACTION \
|
||||||
|
(katze_array_action_get_type ())
|
||||||
|
#define KATZE_ARRAY_ACTION(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_CAST ((obj), KATZE_TYPE_ARRAY_ACTION, KatzeArrayAction))
|
||||||
|
#define KATZE_ARRAY_ACTION_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_CAST ((klass), KATZE_TYPE_ARRAY_ACTION, KatzeArrayActionClass))
|
||||||
|
#define KATZE_IS_ARRAY_ACTION(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), KATZE_TYPE_ARRAY_ACTION))
|
||||||
|
#define KATZE_IS_ARRAY_ACTION_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_TYPE ((klass), KATZE_TYPE_ARRAY_ACTION))
|
||||||
|
#define KATZE_ARRAY_ACTION_GET_CLASS(obj) \
|
||||||
|
(G_TYPE_INSTANCE_GET_CLASS ((obj), KATZE_TYPE_ARRAY_ACTION, KatzeArrayActionClass))
|
||||||
|
|
||||||
|
typedef struct _KatzeArrayAction KatzeArrayAction;
|
||||||
|
typedef struct _KatzeArrayActionClass KatzeArrayActionClass;
|
||||||
|
|
||||||
|
GType
|
||||||
|
katze_array_action_get_type (void);
|
||||||
|
|
||||||
|
KatzeArray*
|
||||||
|
katze_array_action_get_array (KatzeArrayAction* array_action);
|
||||||
|
|
||||||
|
void
|
||||||
|
katze_array_action_set_array (KatzeArrayAction* array_action,
|
||||||
|
KatzeArray* array);
|
||||||
|
|
||||||
|
GtkToolItem*
|
||||||
|
katze_array_action_create_tool_item_for (KatzeArrayAction* array_action,
|
||||||
|
KatzeItem* item);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __KATZE_ARRAY_ACTION_H__ */
|
212
katze/katze-http-auth.c
Normal file
|
@ -0,0 +1,212 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2008-2009 Christian Dywan <christian@twotoasts.de>
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
See the file COPYING for the full license text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "katze-http-auth.h"
|
||||||
|
|
||||||
|
#include <libsoup/soup.h>
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
#include <glib/gi18n.h>
|
||||||
|
|
||||||
|
struct _KatzeHttpAuth
|
||||||
|
{
|
||||||
|
GObject parent_instance;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _KatzeHttpAuthClass
|
||||||
|
{
|
||||||
|
GObjectClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_http_auth_session_feature_iface_init (SoupSessionFeatureInterface *iface,
|
||||||
|
gpointer data);
|
||||||
|
|
||||||
|
G_DEFINE_TYPE_WITH_CODE (KatzeHttpAuth, katze_http_auth, G_TYPE_OBJECT,
|
||||||
|
G_IMPLEMENT_INTERFACE (SOUP_TYPE_SESSION_FEATURE,
|
||||||
|
katze_http_auth_session_feature_iface_init));
|
||||||
|
|
||||||
|
static void
|
||||||
|
authentication_dialog_response_cb (GtkWidget* dialog,
|
||||||
|
gint response,
|
||||||
|
SoupAuth* auth)
|
||||||
|
{
|
||||||
|
GtkWidget* username;
|
||||||
|
GtkWidget* password;
|
||||||
|
SoupSession* session;
|
||||||
|
SoupMessage* msg;
|
||||||
|
|
||||||
|
if (response == GTK_RESPONSE_OK)
|
||||||
|
{
|
||||||
|
|
||||||
|
username = g_object_get_data (G_OBJECT (dialog), "username");
|
||||||
|
password = g_object_get_data (G_OBJECT (dialog), "password");
|
||||||
|
|
||||||
|
soup_auth_authenticate (auth,
|
||||||
|
gtk_entry_get_text (GTK_ENTRY (username)),
|
||||||
|
gtk_entry_get_text (GTK_ENTRY (password)));
|
||||||
|
}
|
||||||
|
|
||||||
|
session = g_object_get_data (G_OBJECT (dialog), "session");
|
||||||
|
msg = g_object_get_data (G_OBJECT (dialog), "msg");
|
||||||
|
gtk_widget_destroy (dialog);
|
||||||
|
if (g_object_get_data (G_OBJECT (msg), "paused"))
|
||||||
|
soup_session_unpause_message (session, msg);
|
||||||
|
g_object_unref (auth);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_http_auth_session_authenticate_cb (SoupSession* session,
|
||||||
|
SoupMessage* msg,
|
||||||
|
SoupAuth* auth,
|
||||||
|
gboolean retrying)
|
||||||
|
{
|
||||||
|
GtkWidget* dialog;
|
||||||
|
GtkSizeGroup* sizegroup;
|
||||||
|
GtkWidget* hbox;
|
||||||
|
GtkWidget* image;
|
||||||
|
GtkWidget* label;
|
||||||
|
GtkWidget* align;
|
||||||
|
GtkWidget* entry;
|
||||||
|
|
||||||
|
/* We want to ask for authentication exactly once, so we
|
||||||
|
enforce this with a tag. There might be a better way. */
|
||||||
|
if (!retrying && g_object_get_data (G_OBJECT (msg), "katze-session-tag"))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (soup_message_is_keepalive (msg))
|
||||||
|
{
|
||||||
|
/* We use another tag to indicate whether a message is paused.
|
||||||
|
There doesn't seem to be API in libSoup to find that out. */
|
||||||
|
soup_session_pause_message (session, msg);
|
||||||
|
g_object_set_data (G_OBJECT (msg), "paused", (void*)1);
|
||||||
|
}
|
||||||
|
g_object_set_data (G_OBJECT (msg), "katze-session-tag", (void*)1);
|
||||||
|
|
||||||
|
dialog = gtk_dialog_new_with_buttons (_("Authentication Required"),
|
||||||
|
NULL,
|
||||||
|
GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR,
|
||||||
|
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
||||||
|
GTK_STOCK_OK, GTK_RESPONSE_OK,
|
||||||
|
NULL);
|
||||||
|
gtk_window_set_icon_name (GTK_WINDOW (dialog),
|
||||||
|
GTK_STOCK_DIALOG_AUTHENTICATION);
|
||||||
|
gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
|
||||||
|
gtk_container_set_border_width (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), 5);
|
||||||
|
|
||||||
|
gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->vbox), 5);
|
||||||
|
hbox = gtk_hbox_new (FALSE, 6);
|
||||||
|
image = gtk_image_new_from_stock (GTK_STOCK_DIALOG_AUTHENTICATION,
|
||||||
|
GTK_ICON_SIZE_DIALOG);
|
||||||
|
gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0);
|
||||||
|
label = gtk_label_new (_("A username and a password are required\n"
|
||||||
|
"to open this location:"));
|
||||||
|
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
|
||||||
|
gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), hbox);
|
||||||
|
label = gtk_label_new (soup_auth_get_host (auth));
|
||||||
|
gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), label);
|
||||||
|
/* If the realm is merely the host, omit the realm label */
|
||||||
|
if (g_strcmp0 (soup_auth_get_host (auth), soup_auth_get_realm (auth)))
|
||||||
|
{
|
||||||
|
label = gtk_label_new (soup_auth_get_realm (auth));
|
||||||
|
gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), label);
|
||||||
|
}
|
||||||
|
sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
|
||||||
|
hbox = gtk_hbox_new (FALSE, 6);
|
||||||
|
label = gtk_label_new (_("Username"));
|
||||||
|
align = gtk_alignment_new (0, 0.5, 0, 0);
|
||||||
|
gtk_container_add (GTK_CONTAINER (align), label);
|
||||||
|
gtk_size_group_add_widget (sizegroup, align);
|
||||||
|
gtk_box_pack_start (GTK_BOX (hbox), align, TRUE, TRUE, 0);
|
||||||
|
entry = gtk_entry_new ();
|
||||||
|
gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
|
||||||
|
gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE);
|
||||||
|
g_object_set_data (G_OBJECT (dialog), "username", entry);
|
||||||
|
gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), hbox);
|
||||||
|
hbox = gtk_hbox_new (FALSE, 6);
|
||||||
|
label = gtk_label_new (_("Password"));
|
||||||
|
align = gtk_alignment_new (0, 0.5, 0, 0);
|
||||||
|
gtk_container_add (GTK_CONTAINER (align), label);
|
||||||
|
gtk_size_group_add_widget (sizegroup, align);
|
||||||
|
gtk_box_pack_start (GTK_BOX (hbox), align, TRUE, TRUE, 0);
|
||||||
|
entry = gtk_entry_new_with_max_length (32);
|
||||||
|
gtk_entry_set_visibility (GTK_ENTRY (entry), FALSE);
|
||||||
|
gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
|
||||||
|
gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE);
|
||||||
|
g_object_set_data (G_OBJECT (dialog), "password", entry);
|
||||||
|
gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), hbox);
|
||||||
|
gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
|
||||||
|
gtk_widget_show_all (GTK_DIALOG (dialog)->vbox);
|
||||||
|
|
||||||
|
g_object_set_data (G_OBJECT (dialog), "session", session);
|
||||||
|
g_object_set_data (G_OBJECT (dialog), "msg", msg);
|
||||||
|
g_signal_connect (dialog, "response",
|
||||||
|
G_CALLBACK (authentication_dialog_response_cb), g_object_ref (auth));
|
||||||
|
gtk_widget_show (dialog);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_http_auth_session_request_queued_cb (SoupSession* session,
|
||||||
|
SoupMessage* msg,
|
||||||
|
gpointer data)
|
||||||
|
{
|
||||||
|
/* WebKit has its own authentication dialog in recent versions.
|
||||||
|
We want only one, and we choose our own to have localization. */
|
||||||
|
GType type = g_type_from_name ("WebKitSoupAuthDialog");
|
||||||
|
if (type)
|
||||||
|
soup_session_remove_feature_by_type (session, type);
|
||||||
|
|
||||||
|
g_signal_connect (session, "authenticate",
|
||||||
|
G_CALLBACK (katze_http_auth_session_authenticate_cb), NULL);
|
||||||
|
g_signal_handlers_disconnect_by_func (session,
|
||||||
|
katze_http_auth_session_request_queued_cb, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_http_auth_attach (SoupSessionFeature* feature,
|
||||||
|
SoupSession* session)
|
||||||
|
{
|
||||||
|
g_signal_connect (session, "request-queued",
|
||||||
|
G_CALLBACK (katze_http_auth_session_request_queued_cb), NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_http_auth_detach (SoupSessionFeature* feature,
|
||||||
|
SoupSession* session)
|
||||||
|
{
|
||||||
|
g_signal_handlers_disconnect_by_func (session,
|
||||||
|
katze_http_auth_session_authenticate_cb, NULL);
|
||||||
|
g_signal_handlers_disconnect_by_func (session,
|
||||||
|
katze_http_auth_session_request_queued_cb, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_http_auth_session_feature_iface_init (SoupSessionFeatureInterface *iface,
|
||||||
|
gpointer data)
|
||||||
|
{
|
||||||
|
iface->attach = katze_http_auth_attach;
|
||||||
|
iface->detach = katze_http_auth_detach;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_http_auth_class_init (KatzeHttpAuthClass* class)
|
||||||
|
{
|
||||||
|
/* Nothing to do. */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_http_auth_init (KatzeHttpAuth* http_auth)
|
||||||
|
{
|
||||||
|
/* Nothing to do. */
|
||||||
|
}
|
42
katze/katze-http-auth.h
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2009 Christian Dywan <christian@twotoasts.de>
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
See the file COPYING for the full license text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __KATZE_HTTP_AUTH_H__
|
||||||
|
#define __KATZE_HTTP_AUTH_H__
|
||||||
|
|
||||||
|
#include "katze-utils.h"
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define KATZE_TYPE_HTTP_AUTH \
|
||||||
|
(katze_http_auth_get_type ())
|
||||||
|
#define KATZE_HTTP_AUTH(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_CAST ((obj), KATZE_TYPE_HTTP_AUTH, KatzeHttpAuth))
|
||||||
|
#define KATZE_HTTP_AUTH_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_CAST ((klass), KATZE_TYPE_HTTP_AUTH, KatzeHttpAuthClass))
|
||||||
|
#define KATZE_IS_HTTP_AUTH(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), KATZE_TYPE_HTTP_AUTH))
|
||||||
|
#define KATZE_IS_HTTP_AUTH_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_TYPE ((klass), KATZE_TYPE_HTTP_AUTH))
|
||||||
|
#define KATZE_HTTP_AUTH_GET_CLASS(obj) \
|
||||||
|
(G_TYPE_INSTANCE_GET_CLASS ((obj), KATZE_TYPE_HTTP_AUTH, KatzeHttpAuthClass))
|
||||||
|
|
||||||
|
typedef struct _KatzeHttpAuth KatzeHttpAuth;
|
||||||
|
typedef struct _KatzeHttpAuthClass KatzeHttpAuthClass;
|
||||||
|
|
||||||
|
GType
|
||||||
|
katze_http_auth_get_type (void);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __KATZE_HTTP_AUTH_H__ */
|
300
katze/katze-http-cookies.c
Normal file
|
@ -0,0 +1,300 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2008-2009 Christian Dywan <christian@twotoasts.de>
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
See the file COPYING for the full license text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "katze-http-cookies.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <glib/gi18n.h>
|
||||||
|
#include <libsoup/soup.h>
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
struct _KatzeHttpCookies
|
||||||
|
{
|
||||||
|
GObject parent_instance;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _KatzeHttpCookiesClass
|
||||||
|
{
|
||||||
|
GObjectClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_http_cookies_session_feature_iface_init (SoupSessionFeatureInterface *iface,
|
||||||
|
gpointer data);
|
||||||
|
|
||||||
|
G_DEFINE_TYPE_WITH_CODE (KatzeHttpCookies, katze_http_cookies, G_TYPE_OBJECT,
|
||||||
|
G_IMPLEMENT_INTERFACE (SOUP_TYPE_SESSION_FEATURE,
|
||||||
|
katze_http_cookies_session_feature_iface_init));
|
||||||
|
|
||||||
|
/* Cookie jar saving to Mozilla format
|
||||||
|
Copyright (C) 2008 Xan Lopez <xan@gnome.org>
|
||||||
|
Copyright (C) 2008 Dan Winship <danw@gnome.org>
|
||||||
|
Mostly copied from libSoup 2.24, coding style adjusted */
|
||||||
|
static SoupCookie*
|
||||||
|
parse_cookie (gchar* line,
|
||||||
|
time_t now)
|
||||||
|
{
|
||||||
|
gchar** result;
|
||||||
|
SoupCookie *cookie = NULL;
|
||||||
|
gboolean http_only;
|
||||||
|
time_t max_age;
|
||||||
|
gchar* host/*, *is_domain*/, *path, *secure, *expires, *name, *value;
|
||||||
|
|
||||||
|
if (g_str_has_prefix (line, "#HttpOnly_"))
|
||||||
|
{
|
||||||
|
http_only = TRUE;
|
||||||
|
line += strlen ("#HttpOnly_");
|
||||||
|
}
|
||||||
|
else if (*line == '#' || g_ascii_isspace (*line))
|
||||||
|
return cookie;
|
||||||
|
else
|
||||||
|
http_only = FALSE;
|
||||||
|
|
||||||
|
result = g_strsplit (line, "\t", -1);
|
||||||
|
if (g_strv_length (result) != 7)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
/* Check this first */
|
||||||
|
expires = result[4];
|
||||||
|
max_age = strtoul (expires, NULL, 10) - now;
|
||||||
|
if (max_age <= 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
host = result[0];
|
||||||
|
/* is_domain = result[1]; */
|
||||||
|
path = result[2];
|
||||||
|
secure = result[3];
|
||||||
|
|
||||||
|
name = result[5];
|
||||||
|
value = result[6];
|
||||||
|
|
||||||
|
cookie = soup_cookie_new (name, value, host, path, max_age);
|
||||||
|
|
||||||
|
if (strcmp (secure, "FALSE"))
|
||||||
|
soup_cookie_set_secure (cookie, TRUE);
|
||||||
|
if (http_only)
|
||||||
|
soup_cookie_set_http_only (cookie, TRUE);
|
||||||
|
|
||||||
|
out:
|
||||||
|
g_strfreev (result);
|
||||||
|
|
||||||
|
return cookie;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Cookie jar saving to Mozilla format
|
||||||
|
Copyright (C) 2008 Xan Lopez <xan@gnome.org>
|
||||||
|
Copyright (C) 2008 Dan Winship <danw@gnome.org>
|
||||||
|
Mostly copied from libSoup 2.24, coding style adjusted */
|
||||||
|
static void
|
||||||
|
parse_line (SoupCookieJar* jar,
|
||||||
|
gchar* line,
|
||||||
|
time_t now)
|
||||||
|
{
|
||||||
|
SoupCookie* cookie;
|
||||||
|
|
||||||
|
if ((cookie = parse_cookie (line, now)))
|
||||||
|
soup_cookie_jar_add_cookie (jar, cookie);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Cookie jar saving to Mozilla format
|
||||||
|
Copyright (C) 2008 Xan Lopez <xan@gnome.org>
|
||||||
|
Copyright (C) 2008 Dan Winship <danw@gnome.org>
|
||||||
|
Mostly copied from libSoup 2.24, coding style adjusted */
|
||||||
|
static void
|
||||||
|
cookie_jar_load (SoupCookieJar* jar,
|
||||||
|
const gchar* filename)
|
||||||
|
{
|
||||||
|
char* contents = NULL;
|
||||||
|
gchar* line;
|
||||||
|
gchar* p;
|
||||||
|
gsize length = 0;
|
||||||
|
time_t now = time (NULL);
|
||||||
|
|
||||||
|
if (!g_file_get_contents (filename, &contents, &length, NULL))
|
||||||
|
return;
|
||||||
|
|
||||||
|
line = contents;
|
||||||
|
for (p = contents; *p; p++)
|
||||||
|
{
|
||||||
|
/* \r\n comes out as an extra empty line and gets ignored */
|
||||||
|
if (*p == '\r' || *p == '\n')
|
||||||
|
{
|
||||||
|
*p = '\0';
|
||||||
|
parse_line (jar, line, now);
|
||||||
|
line = p + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
parse_line (jar, line, now);
|
||||||
|
|
||||||
|
g_free (contents);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Cookie jar saving to Mozilla format
|
||||||
|
Copyright (C) 2008 Xan Lopez <xan@gnome.org>
|
||||||
|
Copyright (C) 2008 Dan Winship <danw@gnome.org>
|
||||||
|
Copied from libSoup 2.24, coding style preserved */
|
||||||
|
static void
|
||||||
|
write_cookie (FILE *out, SoupCookie *cookie)
|
||||||
|
{
|
||||||
|
fseek (out, 0, SEEK_END);
|
||||||
|
|
||||||
|
fprintf (out, "%s%s\t%s\t%s\t%s\t%lu\t%s\t%s\n",
|
||||||
|
cookie->http_only ? "#HttpOnly_" : "",
|
||||||
|
cookie->domain,
|
||||||
|
*cookie->domain == '.' ? "TRUE" : "FALSE",
|
||||||
|
cookie->path,
|
||||||
|
cookie->secure ? "TRUE" : "FALSE",
|
||||||
|
(gulong)soup_date_to_time_t (cookie->expires),
|
||||||
|
cookie->name,
|
||||||
|
cookie->value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Cookie jar saving to Mozilla format
|
||||||
|
Copyright (C) 2008 Xan Lopez <xan@gnome.org>
|
||||||
|
Copyright (C) 2008 Dan Winship <danw@gnome.org>
|
||||||
|
Copied from libSoup 2.24, coding style preserved */
|
||||||
|
static void
|
||||||
|
delete_cookie (const char *filename, SoupCookie *cookie)
|
||||||
|
{
|
||||||
|
char *contents = NULL, *line, *p;
|
||||||
|
gsize length = 0;
|
||||||
|
FILE *f;
|
||||||
|
SoupCookie *c;
|
||||||
|
time_t now = time (NULL);
|
||||||
|
|
||||||
|
if (!g_file_get_contents (filename, &contents, &length, NULL))
|
||||||
|
return;
|
||||||
|
|
||||||
|
f = fopen (filename, "w");
|
||||||
|
if (!f) {
|
||||||
|
g_free (contents);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
line = contents;
|
||||||
|
for (p = contents; *p; p++) {
|
||||||
|
/* \r\n comes out as an extra empty line and gets ignored */
|
||||||
|
if (*p == '\r' || *p == '\n') {
|
||||||
|
*p = '\0';
|
||||||
|
c = parse_cookie (line, now);
|
||||||
|
if (!c)
|
||||||
|
continue;
|
||||||
|
if (!soup_cookie_equal (cookie, c))
|
||||||
|
write_cookie (f, c);
|
||||||
|
line = p + 1;
|
||||||
|
soup_cookie_free (c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c = parse_cookie (line, now);
|
||||||
|
if (c) {
|
||||||
|
if (!soup_cookie_equal (cookie, c))
|
||||||
|
write_cookie (f, c);
|
||||||
|
soup_cookie_free (c);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free (contents);
|
||||||
|
fclose (f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Cookie jar saving to Mozilla format
|
||||||
|
Copyright (C) 2008 Xan Lopez <xan@gnome.org>
|
||||||
|
Copyright (C) 2008 Dan Winship <danw@gnome.org>
|
||||||
|
Mostly copied from libSoup 2.24, coding style adjusted */
|
||||||
|
static void
|
||||||
|
cookie_jar_changed_cb (SoupCookieJar* jar,
|
||||||
|
SoupCookie* old_cookie,
|
||||||
|
SoupCookie* new_cookie,
|
||||||
|
gchar* filename)
|
||||||
|
{
|
||||||
|
GObject* settings;
|
||||||
|
guint accept_cookies;
|
||||||
|
|
||||||
|
if (old_cookie)
|
||||||
|
delete_cookie (filename, old_cookie);
|
||||||
|
|
||||||
|
if (new_cookie)
|
||||||
|
{
|
||||||
|
FILE *out;
|
||||||
|
|
||||||
|
settings = g_object_get_data (G_OBJECT (jar), "midori-settings");
|
||||||
|
accept_cookies = katze_object_get_enum (settings, "accept-cookies");
|
||||||
|
if (accept_cookies == 2 /* MIDORI_ACCEPT_COOKIES_NONE */)
|
||||||
|
{
|
||||||
|
soup_cookie_jar_delete_cookie (jar, new_cookie);
|
||||||
|
}
|
||||||
|
else if (accept_cookies == 1 /* MIDORI_ACCEPT_COOKIES_SESSION */
|
||||||
|
&& new_cookie->expires)
|
||||||
|
{
|
||||||
|
soup_cookie_jar_delete_cookie (jar, new_cookie);
|
||||||
|
}
|
||||||
|
else if (new_cookie->expires)
|
||||||
|
{
|
||||||
|
gint age = katze_object_get_int (settings, "maximum-cookie-age");
|
||||||
|
soup_cookie_set_max_age (new_cookie,
|
||||||
|
age * SOUP_COOKIE_MAX_AGE_ONE_DAY);
|
||||||
|
|
||||||
|
if (!(out = fopen (filename, "a")))
|
||||||
|
return;
|
||||||
|
write_cookie (out, new_cookie);
|
||||||
|
if (fclose (out) != 0)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_http_cookies_attach (SoupSessionFeature* feature,
|
||||||
|
SoupSession* session)
|
||||||
|
{
|
||||||
|
SoupSessionFeature* cookie_jar;
|
||||||
|
gchar* filename;
|
||||||
|
|
||||||
|
cookie_jar = soup_session_get_feature (session, SOUP_TYPE_COOKIE_JAR);
|
||||||
|
g_return_if_fail (cookie_jar != NULL);
|
||||||
|
filename = g_object_get_data (G_OBJECT (feature), "filename");
|
||||||
|
g_return_if_fail (filename != NULL);
|
||||||
|
cookie_jar_load (SOUP_COOKIE_JAR (cookie_jar), filename);
|
||||||
|
g_signal_connect_data (cookie_jar, "changed",
|
||||||
|
G_CALLBACK (cookie_jar_changed_cb), g_strdup (filename),
|
||||||
|
(GClosureNotify)g_free, 0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_http_cookies_detach (SoupSessionFeature* feature,
|
||||||
|
SoupSession* session)
|
||||||
|
{
|
||||||
|
/* Nothing to do. */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_http_cookies_session_feature_iface_init (SoupSessionFeatureInterface *iface,
|
||||||
|
gpointer data)
|
||||||
|
{
|
||||||
|
iface->attach = katze_http_cookies_attach;
|
||||||
|
iface->detach = katze_http_cookies_detach;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_http_cookies_class_init (KatzeHttpCookiesClass* class)
|
||||||
|
{
|
||||||
|
/* Nothing to do. */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_http_cookies_init (KatzeHttpCookies* http_cookies)
|
||||||
|
{
|
||||||
|
/* Nothing to do. */
|
||||||
|
}
|
42
katze/katze-http-cookies.h
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2009 Christian Dywan <christian@twotoasts.de>
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
See the file COPYING for the full license text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __KATZE_HTTP_COOKIES_H__
|
||||||
|
#define __KATZE_HTTP_COOKIES_H__
|
||||||
|
|
||||||
|
#include "katze-utils.h"
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define KATZE_TYPE_HTTP_COOKIES \
|
||||||
|
(katze_http_cookies_get_type ())
|
||||||
|
#define KATZE_HTTP_COOKIES(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_CAST ((obj), KATZE_TYPE_HTTP_COOKIES, KatzeHttpCookies))
|
||||||
|
#define KATZE_HTTP_COOKIES_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_CAST ((klass), KATZE_TYPE_HTTP_COOKIES, KatzeHttpCookiesClass))
|
||||||
|
#define KATZE_IS_HTTP_COOKIES(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), KATZE_TYPE_HTTP_COOKIES))
|
||||||
|
#define KATZE_IS_HTTP_COOKIES_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_TYPE ((klass), KATZE_TYPE_HTTP_COOKIES))
|
||||||
|
#define KATZE_HTTP_COOKIES_GET_CLASS(obj) \
|
||||||
|
(G_TYPE_INSTANCE_GET_CLASS ((obj), KATZE_TYPE_HTTP_COOKIES, KatzeHttpCookiesClass))
|
||||||
|
|
||||||
|
typedef struct _KatzeHttpCookies KatzeHttpCookies;
|
||||||
|
typedef struct _KatzeHttpCookiesClass KatzeHttpCookiesClass;
|
||||||
|
|
||||||
|
GType
|
||||||
|
katze_http_cookies_get_type (void);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __KATZE_HTTP_COOKIES_H__ */
|
530
katze/katze-item.c
Normal file
|
@ -0,0 +1,530 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2008 Christian Dywan <christian@twotoasts.de>
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
See the file COPYING for the full license text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "katze-item.h"
|
||||||
|
|
||||||
|
#include "katze-utils.h"
|
||||||
|
|
||||||
|
#include <glib/gi18n.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SECTION:katze-item
|
||||||
|
* @short_description: A useful item
|
||||||
|
* @see_also: #KatzeArray
|
||||||
|
*
|
||||||
|
* #KatzeItem is a particularly useful item that provides
|
||||||
|
* several commonly needed properties.
|
||||||
|
*/
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (KatzeItem, katze_item, G_TYPE_OBJECT)
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
PROP_0,
|
||||||
|
|
||||||
|
PROP_NAME,
|
||||||
|
PROP_TEXT,
|
||||||
|
PROP_URI,
|
||||||
|
PROP_ICON,
|
||||||
|
PROP_TOKEN,
|
||||||
|
PROP_ADDED,
|
||||||
|
PROP_PARENT
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_item_finalize (GObject* object);
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_item_set_property (GObject* object,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue* value,
|
||||||
|
GParamSpec* pspec);
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_item_get_property (GObject* object,
|
||||||
|
guint prop_id,
|
||||||
|
GValue* value,
|
||||||
|
GParamSpec* pspec);
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_item_class_init (KatzeItemClass* class)
|
||||||
|
{
|
||||||
|
GObjectClass* gobject_class;
|
||||||
|
GParamFlags flags;
|
||||||
|
|
||||||
|
gobject_class = G_OBJECT_CLASS (class);
|
||||||
|
gobject_class->finalize = katze_item_finalize;
|
||||||
|
gobject_class->set_property = katze_item_set_property;
|
||||||
|
gobject_class->get_property = katze_item_get_property;
|
||||||
|
|
||||||
|
flags = G_PARAM_READWRITE | G_PARAM_CONSTRUCT;
|
||||||
|
|
||||||
|
g_object_class_install_property (gobject_class,
|
||||||
|
PROP_NAME,
|
||||||
|
g_param_spec_string (
|
||||||
|
"name",
|
||||||
|
"Name",
|
||||||
|
"The name of the item",
|
||||||
|
NULL,
|
||||||
|
flags));
|
||||||
|
|
||||||
|
g_object_class_install_property (gobject_class,
|
||||||
|
PROP_TEXT,
|
||||||
|
g_param_spec_string (
|
||||||
|
"text",
|
||||||
|
"Text",
|
||||||
|
"The descriptive text of the item",
|
||||||
|
NULL,
|
||||||
|
flags));
|
||||||
|
|
||||||
|
g_object_class_install_property (gobject_class,
|
||||||
|
PROP_URI,
|
||||||
|
g_param_spec_string (
|
||||||
|
"uri",
|
||||||
|
"URI",
|
||||||
|
"The URI of the item",
|
||||||
|
NULL,
|
||||||
|
flags));
|
||||||
|
|
||||||
|
g_object_class_install_property (gobject_class,
|
||||||
|
PROP_ICON,
|
||||||
|
g_param_spec_string (
|
||||||
|
"icon",
|
||||||
|
"Icon",
|
||||||
|
"The icon of the item",
|
||||||
|
NULL,
|
||||||
|
flags));
|
||||||
|
|
||||||
|
g_object_class_install_property (gobject_class,
|
||||||
|
PROP_TOKEN,
|
||||||
|
g_param_spec_string (
|
||||||
|
"token",
|
||||||
|
"Token",
|
||||||
|
"The token of the item",
|
||||||
|
NULL,
|
||||||
|
flags));
|
||||||
|
|
||||||
|
g_object_class_install_property (gobject_class,
|
||||||
|
PROP_ADDED,
|
||||||
|
g_param_spec_int64 (
|
||||||
|
"added",
|
||||||
|
"Added",
|
||||||
|
"When the item was added",
|
||||||
|
G_MININT64,
|
||||||
|
G_MAXINT64,
|
||||||
|
0,
|
||||||
|
flags));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* KatzeItem:parent:
|
||||||
|
*
|
||||||
|
* The parent of the item.
|
||||||
|
*
|
||||||
|
* Since: 0.1.2
|
||||||
|
*/
|
||||||
|
g_object_class_install_property (gobject_class,
|
||||||
|
PROP_PARENT,
|
||||||
|
g_param_spec_object (
|
||||||
|
"parent",
|
||||||
|
"Parent",
|
||||||
|
"The parent of the item",
|
||||||
|
G_TYPE_OBJECT,
|
||||||
|
flags));
|
||||||
|
|
||||||
|
class->copy = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_item_init (KatzeItem* item)
|
||||||
|
{
|
||||||
|
/* Nothing to do here */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_item_finalize (GObject* object)
|
||||||
|
{
|
||||||
|
KatzeItem* item = KATZE_ITEM (object);
|
||||||
|
|
||||||
|
g_free (item->name);
|
||||||
|
g_free (item->text);
|
||||||
|
g_free (item->uri);
|
||||||
|
g_free (item->icon);
|
||||||
|
g_free (item->token);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (katze_item_parent_class)->finalize (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_item_set_property (GObject* object,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue* value,
|
||||||
|
GParamSpec* pspec)
|
||||||
|
{
|
||||||
|
KatzeItem* item = KATZE_ITEM (object);
|
||||||
|
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_NAME:
|
||||||
|
katze_assign (item->name, g_value_dup_string (value));
|
||||||
|
break;
|
||||||
|
case PROP_TEXT:
|
||||||
|
katze_assign (item->text, g_value_dup_string (value));
|
||||||
|
break;
|
||||||
|
case PROP_URI:
|
||||||
|
katze_assign (item->uri, g_value_dup_string (value));
|
||||||
|
break;
|
||||||
|
case PROP_ICON:
|
||||||
|
katze_assign (item->icon, g_value_dup_string (value));
|
||||||
|
break;
|
||||||
|
case PROP_TOKEN:
|
||||||
|
katze_assign (item->token, g_value_dup_string (value));
|
||||||
|
break;
|
||||||
|
case PROP_ADDED:
|
||||||
|
item->added = g_value_get_int64 (value);
|
||||||
|
break;
|
||||||
|
case PROP_PARENT:
|
||||||
|
katze_item_set_parent (item, g_value_get_object (value));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_item_get_property (GObject* object,
|
||||||
|
guint prop_id,
|
||||||
|
GValue* value,
|
||||||
|
GParamSpec* pspec)
|
||||||
|
{
|
||||||
|
KatzeItem* item = KATZE_ITEM (object);
|
||||||
|
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_NAME:
|
||||||
|
g_value_set_string (value, item->name);
|
||||||
|
break;
|
||||||
|
case PROP_TEXT:
|
||||||
|
g_value_set_string (value, item->text);
|
||||||
|
break;
|
||||||
|
case PROP_URI:
|
||||||
|
g_value_set_string (value, item->uri);
|
||||||
|
break;
|
||||||
|
case PROP_ICON:
|
||||||
|
g_value_set_string (value, item->icon);
|
||||||
|
break;
|
||||||
|
case PROP_TOKEN:
|
||||||
|
g_value_set_string (value, item->token);
|
||||||
|
break;
|
||||||
|
case PROP_ADDED:
|
||||||
|
g_value_set_int64 (value, item->added);
|
||||||
|
break;
|
||||||
|
case PROP_PARENT:
|
||||||
|
g_value_set_object (value, item->parent);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* katze_item_new:
|
||||||
|
*
|
||||||
|
* Creates a new #KatzeItem.
|
||||||
|
*
|
||||||
|
* Return value: a new #KatzeItem
|
||||||
|
**/
|
||||||
|
KatzeItem*
|
||||||
|
katze_item_new (void)
|
||||||
|
{
|
||||||
|
KatzeItem* item = g_object_new (KATZE_TYPE_ITEM, NULL);
|
||||||
|
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* katze_item_get_name:
|
||||||
|
* @item: a #KatzeItem
|
||||||
|
*
|
||||||
|
* Retrieves the name of @item.
|
||||||
|
*
|
||||||
|
* Return value: the name of the item
|
||||||
|
**/
|
||||||
|
const gchar*
|
||||||
|
katze_item_get_name (KatzeItem* item)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (KATZE_IS_ITEM (item), NULL);
|
||||||
|
|
||||||
|
return item->name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* katze_item_set_name:
|
||||||
|
* @item: a #KatzeItem
|
||||||
|
* @name: a string
|
||||||
|
*
|
||||||
|
* Sets the name of @item.
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
katze_item_set_name (KatzeItem* item,
|
||||||
|
const gchar* name)
|
||||||
|
{
|
||||||
|
g_return_if_fail (KATZE_IS_ITEM (item));
|
||||||
|
|
||||||
|
katze_assign (item->name, g_strdup (name));
|
||||||
|
g_object_notify (G_OBJECT (item), "name");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* katze_item_get_text:
|
||||||
|
* @item: a #KatzeItem
|
||||||
|
*
|
||||||
|
* Retrieves the descriptive text of @item.
|
||||||
|
*
|
||||||
|
* Return value: the text of the item
|
||||||
|
**/
|
||||||
|
const gchar*
|
||||||
|
katze_item_get_text (KatzeItem* item)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (KATZE_IS_ITEM (item), NULL);
|
||||||
|
|
||||||
|
return item->text;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* katze_item_set_text:
|
||||||
|
* @item: a #KatzeItem
|
||||||
|
* @description: a string
|
||||||
|
*
|
||||||
|
* Sets the descriptive text of @item.
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
katze_item_set_text (KatzeItem* item,
|
||||||
|
const gchar* text)
|
||||||
|
{
|
||||||
|
g_return_if_fail (KATZE_IS_ITEM (item));
|
||||||
|
|
||||||
|
katze_assign (item->text, g_strdup (text));
|
||||||
|
g_object_notify (G_OBJECT (item), "text");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* katze_item_get_uri:
|
||||||
|
* @item: a #KatzeItem
|
||||||
|
*
|
||||||
|
* Retrieves the URI of @item.
|
||||||
|
*
|
||||||
|
* Return value: the URI of the item
|
||||||
|
**/
|
||||||
|
const gchar*
|
||||||
|
katze_item_get_uri (KatzeItem* item)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (KATZE_IS_ITEM (item), NULL);
|
||||||
|
|
||||||
|
return item->uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* katze_item_set_uri:
|
||||||
|
* @item: a #KatzeItem
|
||||||
|
* @uri: a string
|
||||||
|
*
|
||||||
|
* Sets the URI of @item.
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
katze_item_set_uri (KatzeItem* item,
|
||||||
|
const gchar* uri)
|
||||||
|
{
|
||||||
|
g_return_if_fail (KATZE_IS_ITEM (item));
|
||||||
|
|
||||||
|
katze_assign (item->uri, g_strdup (uri));
|
||||||
|
g_object_notify (G_OBJECT (item), "uri");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* katze_item_get_icon:
|
||||||
|
* @item: a #KatzeItem
|
||||||
|
*
|
||||||
|
* Retrieves the icon of @item.
|
||||||
|
*
|
||||||
|
* Return value: the icon of the item
|
||||||
|
**/
|
||||||
|
const gchar*
|
||||||
|
katze_item_get_icon (KatzeItem* item)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (KATZE_IS_ITEM (item), NULL);
|
||||||
|
|
||||||
|
return item->icon;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* katze_item_set_icon:
|
||||||
|
* @item: a #KatzeItem
|
||||||
|
* @icon: a string
|
||||||
|
*
|
||||||
|
* Sets the icon of @item.
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
katze_item_set_icon (KatzeItem* item,
|
||||||
|
const gchar* icon)
|
||||||
|
{
|
||||||
|
g_return_if_fail (KATZE_IS_ITEM (item));
|
||||||
|
|
||||||
|
katze_assign (item->icon, g_strdup (icon));
|
||||||
|
g_object_notify (G_OBJECT (item), "icon");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* katze_item_get_token:
|
||||||
|
* @item: a #KatzeItem
|
||||||
|
*
|
||||||
|
* Retrieves the token of @item.
|
||||||
|
*
|
||||||
|
* Return value: the token of the item
|
||||||
|
**/
|
||||||
|
const gchar*
|
||||||
|
katze_item_get_token (KatzeItem* item)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (KATZE_IS_ITEM (item), NULL);
|
||||||
|
|
||||||
|
return item->token;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* katze_item_set_token:
|
||||||
|
* @item: a #KatzeItem
|
||||||
|
* @token: a string
|
||||||
|
*
|
||||||
|
* Sets the token of @item.
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
katze_item_set_token (KatzeItem* item,
|
||||||
|
const gchar* token)
|
||||||
|
{
|
||||||
|
g_return_if_fail (KATZE_IS_ITEM (item));
|
||||||
|
|
||||||
|
katze_assign (item->token, g_strdup (token));
|
||||||
|
g_object_notify (G_OBJECT (item), "token");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* katze_item_get_added:
|
||||||
|
* @item: a #KatzeItem
|
||||||
|
*
|
||||||
|
* Determines when @item was added.
|
||||||
|
*
|
||||||
|
* Return value: a timestamp
|
||||||
|
**/
|
||||||
|
gint64
|
||||||
|
katze_item_get_added (KatzeItem* item)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (KATZE_IS_ITEM (item), 0);
|
||||||
|
|
||||||
|
return item->added;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* katze_item_set_added:
|
||||||
|
* @item: a #KatzeItem
|
||||||
|
* @added: a timestamp
|
||||||
|
*
|
||||||
|
* Sets when @item was added.
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
katze_item_set_added (KatzeItem* item,
|
||||||
|
gint64 added)
|
||||||
|
{
|
||||||
|
g_return_if_fail (KATZE_IS_ITEM (item));
|
||||||
|
|
||||||
|
item->added = added;
|
||||||
|
g_object_notify (G_OBJECT (item), "added");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* katze_item_get_parent:
|
||||||
|
* @item: a #KatzeItem
|
||||||
|
*
|
||||||
|
* Determines the parent of @item.
|
||||||
|
*
|
||||||
|
* Since 0.1.2 you can monitor the "parent" property.
|
||||||
|
*
|
||||||
|
* Return value: the parent of the item
|
||||||
|
**/
|
||||||
|
gpointer
|
||||||
|
katze_item_get_parent (KatzeItem* item)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (KATZE_IS_ITEM (item), NULL);
|
||||||
|
|
||||||
|
return item->parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* katze_item_set_parent:
|
||||||
|
* @item: a #KatzeItem
|
||||||
|
* @parent: the new parent
|
||||||
|
*
|
||||||
|
* Sets the parent of @item.
|
||||||
|
*
|
||||||
|
* This is intended for item container implementations. Notably
|
||||||
|
* the new parent will not be notified of the change.
|
||||||
|
*
|
||||||
|
* Since 0.1.2 you can monitor the "parent" property, so unsetting
|
||||||
|
* the parent is actually safe if the parent supports it.
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
katze_item_set_parent (KatzeItem* item,
|
||||||
|
gpointer parent)
|
||||||
|
{
|
||||||
|
g_return_if_fail (KATZE_IS_ITEM (item));
|
||||||
|
g_return_if_fail (!parent || G_IS_OBJECT (parent));
|
||||||
|
|
||||||
|
if (parent)
|
||||||
|
g_object_ref (parent);
|
||||||
|
katze_object_assign (item->parent, parent);
|
||||||
|
g_object_notify (G_OBJECT (item), "parent");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* katze_item_copy:
|
||||||
|
* @item: a #KatzeItem
|
||||||
|
*
|
||||||
|
* Creates an exact copy of @item.
|
||||||
|
*
|
||||||
|
* Note that subclass specific features will only
|
||||||
|
* be preserved if the class implements it.
|
||||||
|
*
|
||||||
|
* Return value: a new #KatzeItem
|
||||||
|
*
|
||||||
|
* Since: 0.1.3
|
||||||
|
**/
|
||||||
|
KatzeItem*
|
||||||
|
katze_item_copy (KatzeItem* item)
|
||||||
|
{
|
||||||
|
KatzeItem* copy;
|
||||||
|
KatzeItemClass* class;
|
||||||
|
|
||||||
|
g_return_val_if_fail (KATZE_IS_ITEM (item), NULL);
|
||||||
|
|
||||||
|
copy = g_object_new (G_OBJECT_TYPE (item),
|
||||||
|
"name", item->name,
|
||||||
|
"text", item->text,
|
||||||
|
"uri", item->uri,
|
||||||
|
"icon", item->icon,
|
||||||
|
"token", item->token,
|
||||||
|
"added", item->added,
|
||||||
|
"parent", item->parent,
|
||||||
|
NULL);
|
||||||
|
class = KATZE_ITEM_GET_CLASS (item);
|
||||||
|
return class->copy ? class->copy (copy) : copy;
|
||||||
|
}
|
117
katze/katze-item.h
Normal file
|
@ -0,0 +1,117 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2008 Christian Dywan <christian@twotoasts.de>
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
See the file COPYING for the full license text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __KATZE_ITEM_H__
|
||||||
|
#define __KATZE_ITEM_H__
|
||||||
|
|
||||||
|
#include <glib-object.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define KATZE_TYPE_ITEM \
|
||||||
|
(katze_item_get_type ())
|
||||||
|
#define KATZE_ITEM(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_CAST ((obj), KATZE_TYPE_ITEM, KatzeItem))
|
||||||
|
#define KATZE_ITEM_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_CAST ((klass), KATZE_TYPE_ITEM, KatzeItemClass))
|
||||||
|
#define KATZE_IS_ITEM(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), KATZE_TYPE_ITEM))
|
||||||
|
#define KATZE_IS_ITEM_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_TYPE ((klass), KATZE_TYPE_ITEM))
|
||||||
|
#define KATZE_ITEM_GET_CLASS(obj) \
|
||||||
|
(G_TYPE_INSTANCE_GET_CLASS ((obj), KATZE_TYPE_ITEM, KatzeItemClass))
|
||||||
|
|
||||||
|
typedef struct _KatzeItem KatzeItem;
|
||||||
|
typedef struct _KatzeItemClass KatzeItemClass;
|
||||||
|
|
||||||
|
struct _KatzeItem
|
||||||
|
{
|
||||||
|
GObject parent_instance;
|
||||||
|
|
||||||
|
gchar* name;
|
||||||
|
gchar* text;
|
||||||
|
gchar* uri;
|
||||||
|
gchar* icon;
|
||||||
|
gchar* token;
|
||||||
|
gint64 added;
|
||||||
|
|
||||||
|
KatzeItem* parent;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _KatzeItemClass
|
||||||
|
{
|
||||||
|
GObjectClass parent_class;
|
||||||
|
|
||||||
|
gpointer
|
||||||
|
(*copy) (KatzeItem* item);
|
||||||
|
};
|
||||||
|
|
||||||
|
GType
|
||||||
|
katze_item_get_type (void);
|
||||||
|
|
||||||
|
KatzeItem*
|
||||||
|
katze_item_new (void);
|
||||||
|
|
||||||
|
const gchar*
|
||||||
|
katze_item_get_name (KatzeItem* item);
|
||||||
|
|
||||||
|
void
|
||||||
|
katze_item_set_name (KatzeItem* item,
|
||||||
|
const gchar* name);
|
||||||
|
|
||||||
|
const gchar*
|
||||||
|
katze_item_get_text (KatzeItem* item);
|
||||||
|
|
||||||
|
void
|
||||||
|
katze_item_set_text (KatzeItem* item,
|
||||||
|
const gchar* text);
|
||||||
|
|
||||||
|
const gchar*
|
||||||
|
katze_item_get_uri (KatzeItem* item);
|
||||||
|
|
||||||
|
void
|
||||||
|
katze_item_set_uri (KatzeItem* item,
|
||||||
|
const gchar* uri);
|
||||||
|
|
||||||
|
const gchar*
|
||||||
|
katze_item_get_icon (KatzeItem* item);
|
||||||
|
|
||||||
|
void
|
||||||
|
katze_item_set_icon (KatzeItem* item,
|
||||||
|
const gchar* icon);
|
||||||
|
|
||||||
|
const gchar*
|
||||||
|
katze_item_get_token (KatzeItem* item);
|
||||||
|
|
||||||
|
void
|
||||||
|
katze_item_set_token (KatzeItem* item,
|
||||||
|
const gchar* token);
|
||||||
|
|
||||||
|
gint64
|
||||||
|
katze_item_get_added (KatzeItem* item);
|
||||||
|
|
||||||
|
void
|
||||||
|
katze_item_set_added (KatzeItem* item,
|
||||||
|
gint64 added);
|
||||||
|
|
||||||
|
gpointer
|
||||||
|
katze_item_get_parent (KatzeItem* item);
|
||||||
|
|
||||||
|
void
|
||||||
|
katze_item_set_parent (KatzeItem* item,
|
||||||
|
gpointer parent);
|
||||||
|
|
||||||
|
KatzeItem*
|
||||||
|
katze_item_copy (KatzeItem* item);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __MIDORI_WEB_ITEM_H__ */
|
598
katze/katze-net.c
Normal file
|
@ -0,0 +1,598 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2008-2009 Christian Dywan <christian@twotoasts.de>
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
See the file COPYING for the full license text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "katze-net.h"
|
||||||
|
|
||||||
|
#include <libsoup/soup.h>
|
||||||
|
#include <webkit/webkit.h>
|
||||||
|
|
||||||
|
struct _KatzeNet
|
||||||
|
{
|
||||||
|
GObject parent_instance;
|
||||||
|
|
||||||
|
GHashTable* memory;
|
||||||
|
gchar* cache_path;
|
||||||
|
guint cache_size;
|
||||||
|
|
||||||
|
SoupSession* session;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _KatzeNetClass
|
||||||
|
{
|
||||||
|
GObjectClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (KatzeNet, katze_net, G_TYPE_OBJECT)
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_net_finalize (GObject* object);
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_net_class_init (KatzeNetClass* class)
|
||||||
|
{
|
||||||
|
GObjectClass* gobject_class;
|
||||||
|
|
||||||
|
gobject_class = G_OBJECT_CLASS (class);
|
||||||
|
gobject_class->finalize = katze_net_finalize;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_net_object_maybe_unref (gpointer object)
|
||||||
|
{
|
||||||
|
if (object)
|
||||||
|
g_object_unref (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_net_init (KatzeNet* net)
|
||||||
|
{
|
||||||
|
net->memory = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||||
|
g_free, katze_net_object_maybe_unref);
|
||||||
|
net->cache_path = g_build_filename (g_get_user_cache_dir (),
|
||||||
|
PACKAGE_NAME, NULL);
|
||||||
|
|
||||||
|
net->session = webkit_get_default_session ();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_net_finalize (GObject* object)
|
||||||
|
{
|
||||||
|
KatzeNet* net = KATZE_NET (object);
|
||||||
|
|
||||||
|
g_hash_table_destroy (net->memory);
|
||||||
|
katze_assign (net->cache_path, NULL);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (katze_net_parent_class)->finalize (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* katze_net_new:
|
||||||
|
*
|
||||||
|
* Instantiates a new #KatzeNet instance.
|
||||||
|
*
|
||||||
|
* Return value: a new #KatzeNet
|
||||||
|
**/
|
||||||
|
KatzeNet*
|
||||||
|
katze_net_new (void)
|
||||||
|
{
|
||||||
|
static KatzeNet* net = NULL;
|
||||||
|
|
||||||
|
if (!net)
|
||||||
|
{
|
||||||
|
net = g_object_new (KATZE_TYPE_NET, NULL);
|
||||||
|
/* Since this is a "singleton", keep an extra reference */
|
||||||
|
g_object_ref (net);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
g_object_ref (net);
|
||||||
|
|
||||||
|
return net;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* katze_net_get_session:
|
||||||
|
*
|
||||||
|
* Retrieves the session of the net.
|
||||||
|
*
|
||||||
|
* Return value: a session, or %NULL
|
||||||
|
*
|
||||||
|
* Since: 0.1.3
|
||||||
|
**/
|
||||||
|
gpointer
|
||||||
|
katze_net_get_session (KatzeNet* net)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (KATZE_IS_NET (net), NULL);
|
||||||
|
|
||||||
|
return net->session;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
KatzeNet* net;
|
||||||
|
KatzeNetStatusCb status_cb;
|
||||||
|
KatzeNetTransferCb transfer_cb;
|
||||||
|
gpointer user_data;
|
||||||
|
KatzeNetRequest* request;
|
||||||
|
} KatzeNetPriv;
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_net_priv_free (KatzeNetPriv* priv)
|
||||||
|
{
|
||||||
|
KatzeNetRequest* request;
|
||||||
|
|
||||||
|
request = priv->request;
|
||||||
|
|
||||||
|
g_free (request->uri);
|
||||||
|
g_free (request->mime_type);
|
||||||
|
g_free (request->data);
|
||||||
|
|
||||||
|
g_free (request);
|
||||||
|
g_free (priv);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gchar*
|
||||||
|
katze_net_get_cached_path (KatzeNet* net,
|
||||||
|
const gchar* uri,
|
||||||
|
const gchar* subfolder)
|
||||||
|
{
|
||||||
|
gchar* cache_path;
|
||||||
|
gchar* checksum;
|
||||||
|
gchar* extension;
|
||||||
|
gchar* cached_filename;
|
||||||
|
gchar* cached_path;
|
||||||
|
|
||||||
|
if (subfolder)
|
||||||
|
cache_path = g_build_filename (net->cache_path, subfolder, NULL);
|
||||||
|
else
|
||||||
|
cache_path = net->cache_path;
|
||||||
|
g_mkdir_with_parents (cache_path, 0700);
|
||||||
|
checksum = g_compute_checksum_for_string (G_CHECKSUM_MD5, uri, -1);
|
||||||
|
|
||||||
|
extension = g_strrstr (uri, ".");
|
||||||
|
cached_filename = g_strdup_printf ("%s%s", checksum,
|
||||||
|
extension ? extension : "");
|
||||||
|
g_free (checksum);
|
||||||
|
cached_path = g_build_filename (cache_path, cached_filename, NULL);
|
||||||
|
g_free (cached_filename);
|
||||||
|
if (subfolder)
|
||||||
|
g_free (cache_path);
|
||||||
|
return cached_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_net_got_body_cb (SoupMessage* msg,
|
||||||
|
KatzeNetPriv* priv);
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_net_got_headers_cb (SoupMessage* msg,
|
||||||
|
KatzeNetPriv* priv)
|
||||||
|
{
|
||||||
|
KatzeNetRequest* request;
|
||||||
|
|
||||||
|
request = priv->request;
|
||||||
|
|
||||||
|
switch (msg->status_code)
|
||||||
|
{
|
||||||
|
case 200:
|
||||||
|
request->status = KATZE_NET_VERIFIED;
|
||||||
|
break;
|
||||||
|
case 301:
|
||||||
|
request->status = KATZE_NET_MOVED;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
request->status = KATZE_NET_NOT_FOUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!priv->status_cb (request, priv->user_data))
|
||||||
|
{
|
||||||
|
g_signal_handlers_disconnect_by_func (msg, katze_net_got_headers_cb, priv);
|
||||||
|
g_signal_handlers_disconnect_by_func (msg, katze_net_got_body_cb, priv);
|
||||||
|
soup_session_cancel_message (priv->net->session, msg, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_net_got_body_cb (SoupMessage* msg,
|
||||||
|
KatzeNetPriv* priv)
|
||||||
|
{
|
||||||
|
KatzeNetRequest* request;
|
||||||
|
#if 0
|
||||||
|
gchar* filename;
|
||||||
|
FILE* fp;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
request = priv->request;
|
||||||
|
|
||||||
|
if (msg->response_body->length > 0)
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
/* FIXME: Caching */
|
||||||
|
filename = katze_net_get_cached_path (net, request->uri, NULL);
|
||||||
|
if ((fp = fopen (filename, "wb")))
|
||||||
|
{
|
||||||
|
fwrite (msg->response_body->data,
|
||||||
|
1, msg->response_body->length, fp);
|
||||||
|
fclose (fp);
|
||||||
|
}
|
||||||
|
g_free (filename);
|
||||||
|
#endif
|
||||||
|
request->data = g_memdup (msg->response_body->data,
|
||||||
|
msg->response_body->length);
|
||||||
|
request->length = msg->response_body->length;
|
||||||
|
}
|
||||||
|
|
||||||
|
priv->transfer_cb (request, priv->user_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_net_finished_cb (SoupMessage* msg,
|
||||||
|
KatzeNetPriv* priv)
|
||||||
|
{
|
||||||
|
katze_net_priv_free (priv);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
katze_net_local_cb (KatzeNetPriv* priv)
|
||||||
|
{
|
||||||
|
KatzeNetRequest* request;
|
||||||
|
gchar* filename;
|
||||||
|
gchar* contents;
|
||||||
|
gsize length;
|
||||||
|
|
||||||
|
request = priv->request;
|
||||||
|
filename = g_filename_from_uri (request->uri, NULL, NULL);
|
||||||
|
|
||||||
|
if (!filename || !g_file_test (filename, G_FILE_TEST_EXISTS))
|
||||||
|
{
|
||||||
|
request->status = KATZE_NET_NOT_FOUND;
|
||||||
|
if (priv->status_cb)
|
||||||
|
priv->status_cb (request, priv->user_data);
|
||||||
|
katze_net_priv_free (priv);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
request->status = KATZE_NET_VERIFIED;
|
||||||
|
if (priv->status_cb && !priv->status_cb (request, priv->user_data))
|
||||||
|
{
|
||||||
|
katze_net_priv_free (priv);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!priv->transfer_cb)
|
||||||
|
{
|
||||||
|
katze_net_priv_free (priv);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
contents = NULL;
|
||||||
|
if (!g_file_get_contents (filename, &contents, &length, NULL))
|
||||||
|
{
|
||||||
|
request->status = KATZE_NET_FAILED;
|
||||||
|
priv->transfer_cb (request, priv->user_data);
|
||||||
|
katze_net_priv_free (priv);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
request->status = KATZE_NET_DONE;
|
||||||
|
request->data = contents;
|
||||||
|
request->length = length;
|
||||||
|
priv->transfer_cb (request, priv->user_data);
|
||||||
|
katze_net_priv_free (priv);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
katze_net_default_cb (KatzeNetPriv* priv)
|
||||||
|
{
|
||||||
|
KatzeNetRequest* request;
|
||||||
|
|
||||||
|
request = priv->request;
|
||||||
|
request->status = KATZE_NET_NOT_FOUND;
|
||||||
|
if (priv->status_cb)
|
||||||
|
priv->status_cb (request, priv->user_data);
|
||||||
|
katze_net_priv_free (priv);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* katze_net_load_uri:
|
||||||
|
* @net: a #KatzeNet
|
||||||
|
* @uri: an URI string
|
||||||
|
* @status_cb: function to call for status information
|
||||||
|
* @transfer_cb: function to call upon transfer
|
||||||
|
* @user_data: data to pass to the callback
|
||||||
|
*
|
||||||
|
* Requests a transfer of @uri.
|
||||||
|
*
|
||||||
|
* @status_cb will be called when the status of @uri
|
||||||
|
* is verified. The specified callback may be called
|
||||||
|
* multiple times unless cancelled.
|
||||||
|
*
|
||||||
|
* @transfer_cb will be called when the data @uri is
|
||||||
|
* pointing to was transferred. Note that even a failed
|
||||||
|
* transfer may transfer data.
|
||||||
|
*
|
||||||
|
* @status_cb will always to be called at least once.
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
katze_net_load_uri (KatzeNet* net,
|
||||||
|
const gchar* uri,
|
||||||
|
KatzeNetStatusCb status_cb,
|
||||||
|
KatzeNetTransferCb transfer_cb,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
KatzeNetRequest* request;
|
||||||
|
KatzeNetPriv* priv;
|
||||||
|
SoupMessage* msg;
|
||||||
|
|
||||||
|
g_return_if_fail (KATZE_IS_NET (net));
|
||||||
|
g_return_if_fail (uri != NULL);
|
||||||
|
|
||||||
|
if (!status_cb && !transfer_cb)
|
||||||
|
return;
|
||||||
|
|
||||||
|
request = g_new0 (KatzeNetRequest, 1);
|
||||||
|
request->uri = g_strdup (uri);
|
||||||
|
request->mime_type = NULL;
|
||||||
|
request->data = NULL;
|
||||||
|
|
||||||
|
priv = g_new0 (KatzeNetPriv, 1);
|
||||||
|
priv->net = net;
|
||||||
|
priv->status_cb = status_cb;
|
||||||
|
priv->transfer_cb = transfer_cb;
|
||||||
|
priv->user_data = user_data;
|
||||||
|
priv->request = request;
|
||||||
|
|
||||||
|
if (g_str_has_prefix (uri, "http://") || g_str_has_prefix (uri, "https://"))
|
||||||
|
{
|
||||||
|
msg = soup_message_new ("GET", uri);
|
||||||
|
if (status_cb)
|
||||||
|
g_signal_connect (msg, "got-headers",
|
||||||
|
G_CALLBACK (katze_net_got_headers_cb), priv);
|
||||||
|
if (transfer_cb)
|
||||||
|
g_signal_connect (msg, "got-body",
|
||||||
|
G_CALLBACK (katze_net_got_body_cb), priv);
|
||||||
|
g_signal_connect (msg, "finished",
|
||||||
|
G_CALLBACK (katze_net_finished_cb), priv);
|
||||||
|
soup_session_queue_message (net->session, msg, NULL, NULL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_str_has_prefix (uri, "file://"))
|
||||||
|
{
|
||||||
|
g_idle_add ((GSourceFunc)katze_net_local_cb, priv);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_idle_add ((GSourceFunc)katze_net_default_cb, priv);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
KatzeNet* net;
|
||||||
|
gchar* icon_file;
|
||||||
|
KatzeNetIconCb icon_cb;
|
||||||
|
GtkWidget* widget;
|
||||||
|
gpointer user_data;
|
||||||
|
} KatzeNetIconPriv;
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_net_icon_priv_free (KatzeNetIconPriv* priv)
|
||||||
|
{
|
||||||
|
g_free (priv->icon_file);
|
||||||
|
if (priv->widget)
|
||||||
|
g_object_unref (priv->widget);
|
||||||
|
g_free (priv);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
katze_net_icon_status_cb (KatzeNetRequest* request,
|
||||||
|
KatzeNetIconPriv* priv)
|
||||||
|
{
|
||||||
|
switch (request->status)
|
||||||
|
{
|
||||||
|
case KATZE_NET_VERIFIED:
|
||||||
|
if (request->mime_type &&
|
||||||
|
!g_str_has_prefix (request->mime_type, "image/"))
|
||||||
|
{
|
||||||
|
katze_net_icon_priv_free (priv);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case KATZE_NET_MOVED:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
katze_net_icon_priv_free (priv);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_net_icon_transfer_cb (KatzeNetRequest* request,
|
||||||
|
KatzeNetIconPriv* priv)
|
||||||
|
{
|
||||||
|
GdkPixbuf* pixbuf;
|
||||||
|
FILE* fp;
|
||||||
|
GdkPixbuf* pixbuf_scaled;
|
||||||
|
gint icon_width, icon_height;
|
||||||
|
size_t ret;
|
||||||
|
|
||||||
|
if (request->status == KATZE_NET_MOVED)
|
||||||
|
return;
|
||||||
|
|
||||||
|
pixbuf = NULL;
|
||||||
|
if (request->data)
|
||||||
|
{
|
||||||
|
if ((fp = fopen (priv->icon_file, "wb")))
|
||||||
|
{
|
||||||
|
ret = fwrite (request->data, 1, request->length, fp);
|
||||||
|
fclose (fp);
|
||||||
|
if ((ret - request->length) != 0)
|
||||||
|
{
|
||||||
|
g_warning ("Error writing to file %s "
|
||||||
|
"in katze_net_icon_transfer_cb()", priv->icon_file);
|
||||||
|
}
|
||||||
|
pixbuf = gdk_pixbuf_new_from_file (priv->icon_file, NULL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
pixbuf = katze_pixbuf_new_from_buffer ((guchar*)request->data,
|
||||||
|
request->length, request->mime_type, NULL);
|
||||||
|
if (pixbuf)
|
||||||
|
g_object_ref (pixbuf);
|
||||||
|
g_hash_table_insert (priv->net->memory,
|
||||||
|
g_strdup (priv->icon_file), pixbuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!priv->icon_cb)
|
||||||
|
{
|
||||||
|
katze_net_icon_priv_free (priv);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pixbuf)
|
||||||
|
{
|
||||||
|
if (priv->widget)
|
||||||
|
pixbuf = gtk_widget_render_icon (priv->widget,
|
||||||
|
GTK_STOCK_FILE, GTK_ICON_SIZE_MENU, NULL);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
priv->icon_cb (NULL, priv->user_data);
|
||||||
|
katze_net_icon_priv_free (priv);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &icon_width, &icon_height);
|
||||||
|
pixbuf_scaled = gdk_pixbuf_scale_simple (pixbuf, icon_width, icon_height,
|
||||||
|
GDK_INTERP_BILINEAR);
|
||||||
|
g_object_unref (pixbuf);
|
||||||
|
|
||||||
|
priv->icon_cb (pixbuf_scaled, priv->user_data);
|
||||||
|
katze_net_icon_priv_free (priv);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* katze_net_load_icon:
|
||||||
|
* @net: a #KatzeNet
|
||||||
|
* @uri: an URI string, or %NULL
|
||||||
|
* @icon_cb: function to call upon completion
|
||||||
|
* @widget: a related #GtkWidget, or %NULL
|
||||||
|
* @user_data: data to pass to the callback
|
||||||
|
*
|
||||||
|
* Requests a transfer of an icon for @uri. This is
|
||||||
|
* implemented by looking for a favicon.ico, an
|
||||||
|
* image according to the file type or even a
|
||||||
|
* generated icon. The provided icon is intended
|
||||||
|
* for user interfaces and not guaranteed to be
|
||||||
|
* the same over multiple requests, plus it may
|
||||||
|
* be scaled to fit the menu icon size.
|
||||||
|
*
|
||||||
|
* Pass a valid #GtkWidget to @widget if you want
|
||||||
|
* a themed default icon in case of a missing icon,
|
||||||
|
* otherwise %NULL will be returned in that case.
|
||||||
|
*
|
||||||
|
* The caller is expected to use the returned icon
|
||||||
|
* and update it if @icon_cb is called.
|
||||||
|
*
|
||||||
|
* Depending on whether the icon was previously
|
||||||
|
* cached or @uri is a local resource, the returned
|
||||||
|
* icon may already be the final one.
|
||||||
|
*
|
||||||
|
* Note that both the returned #GdkPixbuf and the
|
||||||
|
* icon passed to @icon_cb are newly allocated and
|
||||||
|
* the caller owns the reference.
|
||||||
|
*
|
||||||
|
* Since 0.1.2 @widget can be %NULL.
|
||||||
|
*
|
||||||
|
* Return value: a #GdkPixbuf, or %NULL
|
||||||
|
**/
|
||||||
|
GdkPixbuf*
|
||||||
|
katze_net_load_icon (KatzeNet* net,
|
||||||
|
const gchar* uri,
|
||||||
|
KatzeNetIconCb icon_cb,
|
||||||
|
GtkWidget* widget,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
guint i;
|
||||||
|
KatzeNetIconPriv* priv;
|
||||||
|
gchar* icon_uri;
|
||||||
|
gchar* icon_file;
|
||||||
|
GdkPixbuf* pixbuf;
|
||||||
|
gint icon_width, icon_height;
|
||||||
|
GdkPixbuf* pixbuf_scaled;
|
||||||
|
|
||||||
|
g_return_val_if_fail (KATZE_IS_NET (net), NULL);
|
||||||
|
g_return_val_if_fail (!widget || GTK_IS_WIDGET (widget), NULL);
|
||||||
|
|
||||||
|
pixbuf = NULL;
|
||||||
|
if (uri && (g_str_has_prefix (uri, "http://") ||
|
||||||
|
g_str_has_prefix (uri, "https://")))
|
||||||
|
{
|
||||||
|
i = 8;
|
||||||
|
while (uri[i] != '\0' && uri[i] != '/')
|
||||||
|
i++;
|
||||||
|
if (uri[i] == '/')
|
||||||
|
{
|
||||||
|
icon_uri = g_strdup (uri);
|
||||||
|
icon_uri[i] = '\0';
|
||||||
|
icon_uri = g_strdup_printf ("%s/favicon.ico", icon_uri);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
icon_uri = g_strdup_printf ("%s/favicon.ico", uri);
|
||||||
|
|
||||||
|
icon_file = katze_net_get_cached_path (net, icon_uri, "icons");
|
||||||
|
|
||||||
|
if (g_hash_table_lookup_extended (net->memory,
|
||||||
|
icon_file, NULL, (gpointer)&pixbuf))
|
||||||
|
{
|
||||||
|
g_free (icon_file);
|
||||||
|
if (pixbuf)
|
||||||
|
g_object_ref (pixbuf);
|
||||||
|
}
|
||||||
|
else if ((pixbuf = gdk_pixbuf_new_from_file (icon_file, NULL)))
|
||||||
|
g_free (icon_file);
|
||||||
|
/* If the called doesn't provide an icon callback,
|
||||||
|
we assume there is no interest in loading an un-cached icon. */
|
||||||
|
else if (icon_cb)
|
||||||
|
{
|
||||||
|
priv = g_new0 (KatzeNetIconPriv, 1);
|
||||||
|
priv->net = net;
|
||||||
|
priv->icon_file = icon_file;
|
||||||
|
priv->icon_cb = icon_cb;
|
||||||
|
priv->widget = widget ? g_object_ref (widget) : NULL;
|
||||||
|
priv->user_data = user_data;
|
||||||
|
|
||||||
|
katze_net_load_uri (net, icon_uri,
|
||||||
|
(KatzeNetStatusCb)katze_net_icon_status_cb,
|
||||||
|
(KatzeNetTransferCb)katze_net_icon_transfer_cb, priv);
|
||||||
|
}
|
||||||
|
g_free (icon_uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pixbuf)
|
||||||
|
{
|
||||||
|
if (widget)
|
||||||
|
pixbuf = gtk_widget_render_icon (widget,
|
||||||
|
GTK_STOCK_FILE, GTK_ICON_SIZE_MENU, NULL);
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &icon_width, &icon_height);
|
||||||
|
pixbuf_scaled = gdk_pixbuf_scale_simple (pixbuf, icon_width, icon_height,
|
||||||
|
GDK_INTERP_BILINEAR);
|
||||||
|
g_object_unref (pixbuf);
|
||||||
|
|
||||||
|
return pixbuf_scaled;
|
||||||
|
}
|
89
katze/katze-net.h
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2008 Christian Dywan <christian@twotoasts.de>
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
See the file COPYING for the full license text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __KATZE_NET_H__
|
||||||
|
#define __KATZE_NET_H__
|
||||||
|
|
||||||
|
#include "katze-utils.h"
|
||||||
|
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define KATZE_TYPE_NET \
|
||||||
|
(katze_net_get_type ())
|
||||||
|
#define KATZE_NET(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_CAST ((obj), KATZE_TYPE_NET, KatzeNet))
|
||||||
|
#define KATZE_NET_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_CAST ((klass), KATZE_TYPE_NET, KatzeNetClass))
|
||||||
|
#define KATZE_IS_NET(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), KATZE_TYPE_NET))
|
||||||
|
#define KATZE_IS_NET_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_TYPE ((klass), KATZE_TYPE_NET))
|
||||||
|
#define KATZE_NET_GET_CLASS(obj) \
|
||||||
|
(G_TYPE_INSTANCE_GET_CLASS ((obj), KATZE_TYPE_NET, KatzeNetClass))
|
||||||
|
|
||||||
|
typedef struct _KatzeNet KatzeNet;
|
||||||
|
typedef struct _KatzeNetClass KatzeNetClass;
|
||||||
|
|
||||||
|
GType
|
||||||
|
katze_net_get_type (void);
|
||||||
|
|
||||||
|
KatzeNet*
|
||||||
|
katze_net_new (void);
|
||||||
|
|
||||||
|
gpointer
|
||||||
|
katze_net_get_session (KatzeNet* net);
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
KATZE_NET_VERIFIED,
|
||||||
|
KATZE_NET_MOVED,
|
||||||
|
KATZE_NET_NOT_FOUND,
|
||||||
|
KATZE_NET_FAILED,
|
||||||
|
KATZE_NET_DONE
|
||||||
|
} KatzeNetStatus;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
gchar* uri;
|
||||||
|
KatzeNetStatus status;
|
||||||
|
gchar* mime_type;
|
||||||
|
gchar* data;
|
||||||
|
gint64 length;
|
||||||
|
} KatzeNetRequest;
|
||||||
|
|
||||||
|
typedef gboolean (*KatzeNetStatusCb) (KatzeNetRequest* request,
|
||||||
|
gpointer user_data);
|
||||||
|
|
||||||
|
typedef void (*KatzeNetTransferCb) (KatzeNetRequest* request,
|
||||||
|
gpointer user_data);
|
||||||
|
|
||||||
|
void
|
||||||
|
katze_net_load_uri (KatzeNet* net,
|
||||||
|
const gchar* uri,
|
||||||
|
KatzeNetStatusCb status_cb,
|
||||||
|
KatzeNetTransferCb transfer_cb,
|
||||||
|
gpointer user_data);
|
||||||
|
|
||||||
|
typedef void (*KatzeNetIconCb) (GdkPixbuf* icon,
|
||||||
|
gpointer user_data);
|
||||||
|
|
||||||
|
GdkPixbuf*
|
||||||
|
katze_net_load_icon (KatzeNet* net,
|
||||||
|
const gchar* uri,
|
||||||
|
KatzeNetIconCb icon_cb,
|
||||||
|
GtkWidget* widget,
|
||||||
|
gpointer user_data);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __KATZE_NET_H__ */
|
134
katze/katze-separatoraction.c
Normal file
|
@ -0,0 +1,134 @@
|
||||||
|
/*
|
||||||
|
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 "katze-separatoraction.h"
|
||||||
|
|
||||||
|
struct _KatzeSeparatorAction
|
||||||
|
{
|
||||||
|
GtkAction parent_instance;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _KatzeSeparatorActionClass
|
||||||
|
{
|
||||||
|
GtkActionClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (KatzeSeparatorAction, katze_separator_action, GTK_TYPE_ACTION);
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_separator_action_finalize (GObject* object);
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_separator_action_activate (GtkAction* object);
|
||||||
|
|
||||||
|
static GtkWidget*
|
||||||
|
katze_separator_action_create_tool_item (GtkAction* action);
|
||||||
|
|
||||||
|
static GtkWidget*
|
||||||
|
katze_separator_action_create_menu_item (GtkAction* action);
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_separator_action_connect_proxy (GtkAction* action,
|
||||||
|
GtkWidget* proxy);
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_separator_action_disconnect_proxy (GtkAction* action,
|
||||||
|
GtkWidget* proxy);
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_separator_action_class_init (KatzeSeparatorActionClass* class)
|
||||||
|
{
|
||||||
|
GObjectClass* gobject_class;
|
||||||
|
GtkActionClass* action_class;
|
||||||
|
|
||||||
|
gobject_class = G_OBJECT_CLASS (class);
|
||||||
|
gobject_class->finalize = katze_separator_action_finalize;
|
||||||
|
|
||||||
|
action_class = GTK_ACTION_CLASS (class);
|
||||||
|
action_class->activate = katze_separator_action_activate;
|
||||||
|
action_class->create_menu_item = katze_separator_action_create_menu_item;
|
||||||
|
action_class->create_tool_item = katze_separator_action_create_tool_item;
|
||||||
|
action_class->connect_proxy = katze_separator_action_connect_proxy;
|
||||||
|
action_class->disconnect_proxy = katze_separator_action_disconnect_proxy;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_separator_action_init (KatzeSeparatorAction* separator_action)
|
||||||
|
{
|
||||||
|
/* Nothing to do. */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_separator_action_finalize (GObject* object)
|
||||||
|
{
|
||||||
|
G_OBJECT_CLASS (katze_separator_action_parent_class)->finalize (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_separator_action_activate (GtkAction* action)
|
||||||
|
{
|
||||||
|
GSList* proxies;
|
||||||
|
|
||||||
|
proxies = gtk_action_get_proxies (action);
|
||||||
|
if (!proxies)
|
||||||
|
return;
|
||||||
|
|
||||||
|
do
|
||||||
|
if (GTK_IS_TOOL_ITEM (proxies->data))
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
while ((proxies = g_slist_next (proxies)));
|
||||||
|
|
||||||
|
if (GTK_ACTION_CLASS (katze_separator_action_parent_class)->activate)
|
||||||
|
GTK_ACTION_CLASS (katze_separator_action_parent_class)->activate (action);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GtkWidget*
|
||||||
|
katze_separator_action_create_menu_item (GtkAction* action)
|
||||||
|
{
|
||||||
|
GtkWidget* menuitem;
|
||||||
|
|
||||||
|
menuitem = gtk_separator_menu_item_new ();
|
||||||
|
return menuitem;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GtkWidget*
|
||||||
|
katze_separator_action_create_tool_item (GtkAction* action)
|
||||||
|
{
|
||||||
|
GtkWidget* toolitem;
|
||||||
|
|
||||||
|
toolitem = GTK_WIDGET (gtk_separator_tool_item_new ());
|
||||||
|
return toolitem;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_separator_action_connect_proxy (GtkAction* action,
|
||||||
|
GtkWidget* proxy)
|
||||||
|
{
|
||||||
|
GTK_ACTION_CLASS (katze_separator_action_parent_class)->connect_proxy (
|
||||||
|
action, proxy);
|
||||||
|
|
||||||
|
if (GTK_IS_TOOL_ITEM (proxy))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
else if (GTK_IS_MENU_ITEM (proxy))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_separator_action_disconnect_proxy (GtkAction* action,
|
||||||
|
GtkWidget* proxy)
|
||||||
|
{
|
||||||
|
GTK_ACTION_CLASS (katze_separator_action_parent_class)->disconnect_proxy
|
||||||
|
(action, proxy);
|
||||||
|
}
|
43
katze/katze-separatoraction.h
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2009 Christian Dywan <christian@twotoasts.de>
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
See the file COPYING for the full license text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __KATZE_SEPARATOR_ACTION_H__
|
||||||
|
#define __KATZE_SEPARATOR_ACTION_H__
|
||||||
|
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define KATZE_TYPE_SEPARATOR_ACTION \
|
||||||
|
(katze_separator_action_get_type ())
|
||||||
|
#define KATZE_SEPARATOR_ACTION(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_CAST ((obj), KATZE_TYPE_SEPARATOR_ACTION, \
|
||||||
|
KatzeSeparatorAction))
|
||||||
|
#define KATZE_SEPARATOR_ACTION_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_CAST ((klass), KATZE_TYPE_SEPARATOR_ACTION, \
|
||||||
|
KatzeSeparatorActionClass))
|
||||||
|
#define KATZE_IS_SEPARATOR_ACTION(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), KATZE_TYPE_SEPARATOR_ACTION))
|
||||||
|
#define KATZE_IS_SEPARATOR_ACTION_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_TYPE ((klass), KATZE_TYPE_SEPARATOR_ACTION))
|
||||||
|
#define KATZE_SEPARATOR_ACTION_GET_CLASS(obj) \
|
||||||
|
(G_TYPE_INSTANCE_GET_CLASS ((obj), KATZE_TYPE_SEPARATOR_ACTION, \
|
||||||
|
KatzeSeparatorActionClass))
|
||||||
|
|
||||||
|
typedef struct _KatzeSeparatorAction KatzeSeparatorAction;
|
||||||
|
typedef struct _KatzeSeparatorActionClass KatzeSeparatorActionClass;
|
||||||
|
|
||||||
|
GType
|
||||||
|
katze_separator_action_get_type (void);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __KATZE_SEPARATOR_ACTION_H__ */
|
919
katze/katze-throbber.c
Normal file
|
@ -0,0 +1,919 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2007-2008 Christian Dywan <christian@twotoasts.de>
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
See the file COPYING for the full license text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "katze-throbber.h"
|
||||||
|
|
||||||
|
#include "katze-utils.h"
|
||||||
|
|
||||||
|
#include <glib/gi18n.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
struct _KatzeThrobber
|
||||||
|
{
|
||||||
|
GtkMisc parent_instance;
|
||||||
|
|
||||||
|
GtkIconSize icon_size;
|
||||||
|
gchar* icon_name;
|
||||||
|
GdkPixbuf* pixbuf;
|
||||||
|
gchar* stock_id;
|
||||||
|
gboolean animated;
|
||||||
|
gchar* static_icon_name;
|
||||||
|
GdkPixbuf* static_pixbuf;
|
||||||
|
gchar* static_stock_id;
|
||||||
|
|
||||||
|
gint index;
|
||||||
|
gint timer_id;
|
||||||
|
gint width;
|
||||||
|
gint height;
|
||||||
|
};
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (KatzeThrobber, katze_throbber, GTK_TYPE_MISC);
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
PROP_0,
|
||||||
|
|
||||||
|
PROP_ICON_SIZE,
|
||||||
|
PROP_ICON_NAME,
|
||||||
|
PROP_PIXBUF,
|
||||||
|
PROP_ANIMATED,
|
||||||
|
PROP_STATIC_ICON_NAME,
|
||||||
|
PROP_STATIC_PIXBUF,
|
||||||
|
PROP_STATIC_STOCK_ID
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_throbber_dispose (GObject* object);
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_throbber_set_property (GObject* object,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue* value,
|
||||||
|
GParamSpec* pspec);
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_throbber_get_property (GObject* object,
|
||||||
|
guint prop_id,
|
||||||
|
GValue* value,
|
||||||
|
GParamSpec* pspec);
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_throbber_destroy (GtkObject* object);
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_throbber_realize (GtkWidget* widget);
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_throbber_unrealize (GtkWidget* widget);
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_throbber_map (GtkWidget* widget);
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_throbber_unmap (GtkWidget* widget);
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_throbber_style_set (GtkWidget* widget,
|
||||||
|
GtkStyle* style);
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_throbber_screen_changed (GtkWidget* widget,
|
||||||
|
GdkScreen* screen_prev);
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_throbber_size_request (GtkWidget* widget,
|
||||||
|
GtkRequisition* requisition);
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
katze_throbber_expose_event (GtkWidget* widget,
|
||||||
|
GdkEventExpose* event);
|
||||||
|
|
||||||
|
static void
|
||||||
|
icon_theme_changed (KatzeThrobber* throbber);
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
katze_throbber_timeout (KatzeThrobber* throbber);
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_throbber_timeout_destroy (KatzeThrobber* throbber);
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_throbber_class_init (KatzeThrobberClass* class)
|
||||||
|
{
|
||||||
|
GObjectClass* gobject_class = G_OBJECT_CLASS (class);
|
||||||
|
gobject_class->dispose = katze_throbber_dispose;
|
||||||
|
gobject_class->set_property = katze_throbber_set_property;
|
||||||
|
gobject_class->get_property = katze_throbber_get_property;
|
||||||
|
|
||||||
|
GtkObjectClass* object_class = GTK_OBJECT_CLASS (class);
|
||||||
|
object_class->destroy = katze_throbber_destroy;
|
||||||
|
|
||||||
|
GtkWidgetClass* widget_class = GTK_WIDGET_CLASS (class);
|
||||||
|
widget_class->realize = katze_throbber_realize;
|
||||||
|
widget_class->unrealize = katze_throbber_unrealize;
|
||||||
|
widget_class->map = katze_throbber_map;
|
||||||
|
widget_class->unmap = katze_throbber_unmap;
|
||||||
|
widget_class->style_set = katze_throbber_style_set;
|
||||||
|
widget_class->screen_changed = katze_throbber_screen_changed;
|
||||||
|
widget_class->size_request = katze_throbber_size_request;
|
||||||
|
widget_class->expose_event = katze_throbber_expose_event;
|
||||||
|
|
||||||
|
GParamFlags flags = G_PARAM_READWRITE | G_PARAM_CONSTRUCT;
|
||||||
|
|
||||||
|
g_object_class_install_property (gobject_class,
|
||||||
|
PROP_ICON_SIZE,
|
||||||
|
g_param_spec_int (
|
||||||
|
"icon-size",
|
||||||
|
"Icon size",
|
||||||
|
"Symbolic size to use for the animation",
|
||||||
|
0, G_MAXINT, GTK_ICON_SIZE_MENU,
|
||||||
|
flags));
|
||||||
|
|
||||||
|
g_object_class_install_property (gobject_class,
|
||||||
|
PROP_ICON_NAME,
|
||||||
|
g_param_spec_string (
|
||||||
|
"icon-name",
|
||||||
|
"Icon Name",
|
||||||
|
"The name of an icon containing animation frames",
|
||||||
|
"process-working",
|
||||||
|
flags));
|
||||||
|
|
||||||
|
g_object_class_install_property (gobject_class,
|
||||||
|
PROP_PIXBUF,
|
||||||
|
g_param_spec_object (
|
||||||
|
"pixbuf",
|
||||||
|
"Pixbuf",
|
||||||
|
"A GdkPixbuf containing animation frames",
|
||||||
|
GDK_TYPE_PIXBUF,
|
||||||
|
G_PARAM_READWRITE));
|
||||||
|
|
||||||
|
g_object_class_install_property (gobject_class,
|
||||||
|
PROP_ANIMATED,
|
||||||
|
g_param_spec_boolean (
|
||||||
|
"animated",
|
||||||
|
"Animated",
|
||||||
|
"Whether the throbber should be animated",
|
||||||
|
FALSE,
|
||||||
|
flags));
|
||||||
|
|
||||||
|
g_object_class_install_property (gobject_class,
|
||||||
|
PROP_STATIC_ICON_NAME,
|
||||||
|
g_param_spec_string (
|
||||||
|
"static-icon-name",
|
||||||
|
"Static Icon Name",
|
||||||
|
"The name of an icon to be used as the static image",
|
||||||
|
NULL,
|
||||||
|
flags));
|
||||||
|
|
||||||
|
g_object_class_install_property (gobject_class,
|
||||||
|
PROP_PIXBUF,
|
||||||
|
g_param_spec_object (
|
||||||
|
"static-pixbuf",
|
||||||
|
"Static Pixbuf",
|
||||||
|
"A GdkPixbuf to be used as the static image",
|
||||||
|
GDK_TYPE_PIXBUF,
|
||||||
|
G_PARAM_READWRITE));
|
||||||
|
|
||||||
|
g_object_class_install_property (gobject_class,
|
||||||
|
PROP_STATIC_STOCK_ID,
|
||||||
|
g_param_spec_string (
|
||||||
|
"static-stock-id",
|
||||||
|
"Static Stock ID",
|
||||||
|
"The stock ID of an icon to be used as the static image",
|
||||||
|
NULL,
|
||||||
|
flags));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_throbber_init (KatzeThrobber *throbber)
|
||||||
|
{
|
||||||
|
GTK_WIDGET_SET_FLAGS (throbber, GTK_NO_WINDOW);
|
||||||
|
|
||||||
|
throbber->timer_id = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_throbber_dispose (GObject* object)
|
||||||
|
{
|
||||||
|
KatzeThrobber* throbber = KATZE_THROBBER (object);
|
||||||
|
|
||||||
|
if (G_UNLIKELY (throbber->timer_id >= 0))
|
||||||
|
g_source_remove (throbber->timer_id);
|
||||||
|
|
||||||
|
(*G_OBJECT_CLASS (katze_throbber_parent_class)->dispose) (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_throbber_destroy (GtkObject* object)
|
||||||
|
{
|
||||||
|
KatzeThrobber* throbber = KATZE_THROBBER (object);
|
||||||
|
|
||||||
|
katze_assign (throbber->icon_name, NULL);
|
||||||
|
katze_object_assign (throbber->pixbuf, NULL);
|
||||||
|
katze_assign (throbber->static_icon_name, NULL);
|
||||||
|
katze_object_assign (throbber->static_pixbuf, NULL);
|
||||||
|
katze_assign (throbber->static_stock_id, NULL);
|
||||||
|
|
||||||
|
GTK_OBJECT_CLASS (katze_throbber_parent_class)->destroy (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_throbber_set_property (GObject* object,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue* value,
|
||||||
|
GParamSpec* pspec)
|
||||||
|
{
|
||||||
|
KatzeThrobber* throbber = KATZE_THROBBER (object);
|
||||||
|
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_ICON_SIZE:
|
||||||
|
katze_throbber_set_icon_size (throbber, g_value_get_int (value));
|
||||||
|
break;
|
||||||
|
case PROP_ICON_NAME:
|
||||||
|
katze_throbber_set_icon_name (throbber, g_value_get_string (value));
|
||||||
|
break;
|
||||||
|
case PROP_PIXBUF:
|
||||||
|
katze_throbber_set_pixbuf (throbber, g_value_get_object (value));
|
||||||
|
break;
|
||||||
|
case PROP_ANIMATED:
|
||||||
|
katze_throbber_set_animated (throbber, g_value_get_boolean (value));
|
||||||
|
break;
|
||||||
|
case PROP_STATIC_ICON_NAME:
|
||||||
|
katze_throbber_set_static_icon_name (throbber, g_value_get_string (value));
|
||||||
|
break;
|
||||||
|
case PROP_STATIC_PIXBUF:
|
||||||
|
katze_throbber_set_static_pixbuf (throbber, g_value_get_object (value));
|
||||||
|
break;
|
||||||
|
case PROP_STATIC_STOCK_ID:
|
||||||
|
katze_throbber_set_static_stock_id (throbber, g_value_get_string (value));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_throbber_get_property (GObject* object,
|
||||||
|
guint prop_id,
|
||||||
|
GValue* value,
|
||||||
|
GParamSpec* pspec)
|
||||||
|
{
|
||||||
|
KatzeThrobber* throbber = KATZE_THROBBER (object);
|
||||||
|
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_ICON_SIZE:
|
||||||
|
g_value_set_int (value, katze_throbber_get_icon_size (throbber));
|
||||||
|
break;
|
||||||
|
case PROP_ICON_NAME:
|
||||||
|
g_value_set_string (value, katze_throbber_get_icon_name (throbber));
|
||||||
|
break;
|
||||||
|
case PROP_PIXBUF:
|
||||||
|
g_value_set_object (value, katze_throbber_get_pixbuf (throbber));
|
||||||
|
break;
|
||||||
|
case PROP_ANIMATED:
|
||||||
|
g_value_set_boolean (value, katze_throbber_get_animated (throbber));
|
||||||
|
break;
|
||||||
|
case PROP_STATIC_ICON_NAME:
|
||||||
|
g_value_set_string (value, katze_throbber_get_static_icon_name (throbber));
|
||||||
|
break;
|
||||||
|
case PROP_STATIC_PIXBUF:
|
||||||
|
g_value_set_object (value, katze_throbber_get_static_pixbuf (throbber));
|
||||||
|
break;
|
||||||
|
case PROP_STATIC_STOCK_ID:
|
||||||
|
g_value_set_string (value, katze_throbber_get_static_stock_id (throbber));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* katze_throbber_new:
|
||||||
|
*
|
||||||
|
* Creates a new throbber widget.
|
||||||
|
*
|
||||||
|
* Return value: a new #KatzeThrobber
|
||||||
|
**/
|
||||||
|
GtkWidget*
|
||||||
|
katze_throbber_new (void)
|
||||||
|
{
|
||||||
|
KatzeThrobber* throbber = g_object_new (KATZE_TYPE_THROBBER,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
return GTK_WIDGET (throbber);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* katze_throbber_set_icon_size:
|
||||||
|
* @throbber: a #KatzeThrobber
|
||||||
|
* @icon_size: the new icon size
|
||||||
|
*
|
||||||
|
* Sets the desired size of the throbber image. The animation and static image
|
||||||
|
* will be displayed in this size. If a pixbuf is used for the animation every
|
||||||
|
* single frame is assumed to have this size.
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
katze_throbber_set_icon_size (KatzeThrobber* throbber,
|
||||||
|
GtkIconSize icon_size)
|
||||||
|
{
|
||||||
|
GtkSettings* gtk_settings;
|
||||||
|
|
||||||
|
g_return_if_fail (KATZE_IS_THROBBER (throbber));
|
||||||
|
gtk_settings = gtk_widget_get_settings (GTK_WIDGET (throbber));
|
||||||
|
g_return_if_fail (gtk_icon_size_lookup_for_settings (gtk_settings,
|
||||||
|
icon_size,
|
||||||
|
&throbber->width,
|
||||||
|
&throbber->height));
|
||||||
|
|
||||||
|
throbber->icon_size = icon_size;
|
||||||
|
|
||||||
|
g_object_notify (G_OBJECT (throbber), "icon-size");
|
||||||
|
|
||||||
|
gtk_widget_queue_draw (GTK_WIDGET (throbber));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* katze_throbber_set_icon_name:
|
||||||
|
* @throbber: a #KatzeThrobber
|
||||||
|
* @icon_name: an icon name or %NULL
|
||||||
|
*
|
||||||
|
* Sets the name of an icon that should provide the animation frames.
|
||||||
|
*
|
||||||
|
* The pixbuf is automatically invalidated.
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
katze_throbber_set_icon_name (KatzeThrobber* throbber,
|
||||||
|
const gchar* icon_name)
|
||||||
|
{
|
||||||
|
g_return_if_fail (KATZE_IS_THROBBER (throbber));
|
||||||
|
|
||||||
|
katze_assign (throbber->icon_name, g_strdup (icon_name));
|
||||||
|
|
||||||
|
if (icon_name)
|
||||||
|
icon_theme_changed (throbber);
|
||||||
|
|
||||||
|
g_object_notify (G_OBJECT (throbber), "icon-name");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* katze_throbber_set_pixbuf:
|
||||||
|
* @throbber: a #KatzeThrobber
|
||||||
|
* @pixbuf: a #GdkPixbuf or %NULL
|
||||||
|
*
|
||||||
|
* Sets the pixbuf that should provide the animation frames. Every frame
|
||||||
|
* is assumed to have the icon size of the throbber, which can be specified
|
||||||
|
* with katze_throbber_set_icon_size ().
|
||||||
|
*
|
||||||
|
* The icon name is automatically invalidated.
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
katze_throbber_set_pixbuf (KatzeThrobber* throbber,
|
||||||
|
GdkPixbuf* pixbuf)
|
||||||
|
{
|
||||||
|
g_return_if_fail (KATZE_IS_THROBBER (throbber));
|
||||||
|
g_return_if_fail (!pixbuf || GDK_IS_PIXBUF (pixbuf));
|
||||||
|
|
||||||
|
katze_object_assign (throbber->pixbuf, pixbuf);
|
||||||
|
|
||||||
|
g_object_freeze_notify (G_OBJECT (throbber));
|
||||||
|
|
||||||
|
if (pixbuf)
|
||||||
|
{
|
||||||
|
g_object_ref (pixbuf);
|
||||||
|
|
||||||
|
katze_assign (throbber->icon_name, NULL);
|
||||||
|
g_object_notify (G_OBJECT (throbber), "icon-name");
|
||||||
|
}
|
||||||
|
|
||||||
|
gtk_widget_queue_draw (GTK_WIDGET (throbber));
|
||||||
|
|
||||||
|
g_object_notify (G_OBJECT (throbber), "pixbuf");
|
||||||
|
g_object_thaw_notify (G_OBJECT (throbber));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* katze_throbber_set_animated:
|
||||||
|
* @throbber: a #KatzeThrobber
|
||||||
|
* @animated: %TRUE to animate the throbber
|
||||||
|
*
|
||||||
|
* Sets the animation state of the throbber.
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
katze_throbber_set_animated (KatzeThrobber* throbber,
|
||||||
|
gboolean animated)
|
||||||
|
{
|
||||||
|
g_return_if_fail (KATZE_IS_THROBBER (throbber));
|
||||||
|
|
||||||
|
if (G_UNLIKELY (throbber->animated == animated))
|
||||||
|
return;
|
||||||
|
|
||||||
|
throbber->animated = animated;
|
||||||
|
|
||||||
|
if (animated && (throbber->timer_id < 0))
|
||||||
|
throbber->timer_id = g_timeout_add_full (
|
||||||
|
G_PRIORITY_LOW, 50,
|
||||||
|
(GSourceFunc)katze_throbber_timeout,
|
||||||
|
throbber,
|
||||||
|
(GDestroyNotify)katze_throbber_timeout_destroy);
|
||||||
|
|
||||||
|
gtk_widget_queue_draw (GTK_WIDGET (throbber));
|
||||||
|
|
||||||
|
g_object_notify (G_OBJECT (throbber), "animated");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* katze_throbber_set_static_icon_name:
|
||||||
|
* @throbber: a #KatzeThrobber
|
||||||
|
* @icon_name: an icon name or %NULL
|
||||||
|
*
|
||||||
|
* Sets the name of an icon that should provide the static image.
|
||||||
|
*
|
||||||
|
* The static pixbuf and stock ID are automatically invalidated.
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
katze_throbber_set_static_icon_name (KatzeThrobber* throbber,
|
||||||
|
const gchar* icon_name)
|
||||||
|
{
|
||||||
|
g_return_if_fail (KATZE_IS_THROBBER (throbber));
|
||||||
|
|
||||||
|
katze_assign (throbber->static_icon_name, g_strdup (icon_name));
|
||||||
|
|
||||||
|
g_object_freeze_notify (G_OBJECT (throbber));
|
||||||
|
|
||||||
|
if (icon_name)
|
||||||
|
{
|
||||||
|
katze_assign (throbber->static_stock_id, NULL);
|
||||||
|
|
||||||
|
icon_theme_changed (throbber);
|
||||||
|
|
||||||
|
g_object_notify (G_OBJECT (throbber), "static-pixbuf");
|
||||||
|
g_object_notify (G_OBJECT (throbber), "static-stock-id");
|
||||||
|
}
|
||||||
|
|
||||||
|
g_object_notify (G_OBJECT (throbber), "static-icon-name");
|
||||||
|
g_object_thaw_notify (G_OBJECT (throbber));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* katze_throbber_set_static_pixbuf:
|
||||||
|
* @throbber: a #KatzeThrobber
|
||||||
|
* @pixbuf: a #GdkPixbuf or %NULL
|
||||||
|
*
|
||||||
|
* Sets the pixbuf that should provide the static image. The pixbuf is
|
||||||
|
* assumed to have the icon size of the throbber, which can be specified
|
||||||
|
* with katze_throbber_set_icon_size ().
|
||||||
|
*
|
||||||
|
* The static icon name and stock ID are automatically invalidated.
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
katze_throbber_set_static_pixbuf (KatzeThrobber* throbber,
|
||||||
|
GdkPixbuf* pixbuf)
|
||||||
|
{
|
||||||
|
g_return_if_fail (KATZE_IS_THROBBER (throbber));
|
||||||
|
g_return_if_fail (pixbuf == NULL || GDK_IS_PIXBUF (pixbuf));
|
||||||
|
|
||||||
|
katze_object_assign (throbber->static_pixbuf, pixbuf);
|
||||||
|
|
||||||
|
g_object_freeze_notify (G_OBJECT (throbber));
|
||||||
|
|
||||||
|
if (pixbuf)
|
||||||
|
{
|
||||||
|
g_object_ref (pixbuf);
|
||||||
|
|
||||||
|
katze_assign (throbber->static_icon_name, NULL);
|
||||||
|
katze_assign (throbber->static_stock_id, NULL);
|
||||||
|
|
||||||
|
gtk_widget_queue_draw (GTK_WIDGET (throbber));
|
||||||
|
|
||||||
|
g_object_notify (G_OBJECT (throbber), "static-icon-name");
|
||||||
|
g_object_notify (G_OBJECT (throbber), "static-stock-id");
|
||||||
|
}
|
||||||
|
|
||||||
|
g_object_notify (G_OBJECT (throbber), "static-pixbuf");
|
||||||
|
g_object_thaw_notify (G_OBJECT (throbber));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* katze_throbber_set_static_stock_id:
|
||||||
|
* @throbber: a #KatzeThrobber
|
||||||
|
* @stock_id: a stock ID or %NULL
|
||||||
|
*
|
||||||
|
* Sets the stock ID of an icon that should provide the static image.
|
||||||
|
*
|
||||||
|
* The static icon name and pixbuf are automatically invalidated.
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
katze_throbber_set_static_stock_id (KatzeThrobber* throbber,
|
||||||
|
const gchar* stock_id)
|
||||||
|
{
|
||||||
|
g_return_if_fail (KATZE_IS_THROBBER (throbber));
|
||||||
|
|
||||||
|
g_object_freeze_notify (G_OBJECT (throbber));
|
||||||
|
|
||||||
|
if (stock_id)
|
||||||
|
{
|
||||||
|
GtkStockItem stock_item;
|
||||||
|
g_return_if_fail (gtk_stock_lookup (stock_id, &stock_item));
|
||||||
|
|
||||||
|
g_object_notify (G_OBJECT (throbber), "static-icon-name");
|
||||||
|
g_object_notify (G_OBJECT (throbber), "static-pixbuf");
|
||||||
|
}
|
||||||
|
|
||||||
|
katze_assign (throbber->static_stock_id, g_strdup (stock_id));
|
||||||
|
|
||||||
|
if (stock_id)
|
||||||
|
icon_theme_changed (throbber);
|
||||||
|
|
||||||
|
g_object_notify (G_OBJECT (throbber), "static-stock-id");
|
||||||
|
g_object_thaw_notify (G_OBJECT (throbber));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* katze_throbber_get_icon_size:
|
||||||
|
* @throbber: a #KatzeThrobber
|
||||||
|
*
|
||||||
|
* Retrieves the size of the throbber.
|
||||||
|
*
|
||||||
|
* Return value: the size of the throbber
|
||||||
|
**/
|
||||||
|
GtkIconSize
|
||||||
|
katze_throbber_get_icon_size (KatzeThrobber* throbber)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (KATZE_IS_THROBBER (throbber), GTK_ICON_SIZE_INVALID);
|
||||||
|
|
||||||
|
return throbber->icon_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* katze_throbber_get_icon_name:
|
||||||
|
* @throbber: a #KatzeThrobber
|
||||||
|
*
|
||||||
|
* Retrieves the name of the icon providing the animation frames.
|
||||||
|
*
|
||||||
|
* Return value: the name of the icon providing the animation frames, or %NULL
|
||||||
|
**/
|
||||||
|
const gchar*
|
||||||
|
katze_throbber_get_icon_name (KatzeThrobber* throbber)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (KATZE_IS_THROBBER (throbber), NULL);
|
||||||
|
|
||||||
|
return throbber->icon_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* katze_throbber_get_pixbuf:
|
||||||
|
* @throbber: a #KatzeThrobber
|
||||||
|
*
|
||||||
|
* Retrieves the #GdkPixbuf providing the animation frames if an icon name
|
||||||
|
* or pixbuf is available. The caller of this function does not own a
|
||||||
|
* reference to the returned pixbuf.
|
||||||
|
*
|
||||||
|
* Return value: the pixbuf providing the animation frames, or %NULL
|
||||||
|
**/
|
||||||
|
GdkPixbuf*
|
||||||
|
katze_throbber_get_pixbuf (KatzeThrobber* throbber)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (KATZE_IS_THROBBER (throbber), NULL);
|
||||||
|
|
||||||
|
return throbber->pixbuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* katze_throbber_get_animated:
|
||||||
|
* @throbber: a #KatzeThrobber
|
||||||
|
*
|
||||||
|
* Retrieves the status of the animation, whcih can be animated or static.
|
||||||
|
*
|
||||||
|
* Return value: %TRUE if the throbber is animated
|
||||||
|
**/
|
||||||
|
gboolean
|
||||||
|
katze_throbber_get_animated (KatzeThrobber* throbber)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (KATZE_IS_THROBBER (throbber), FALSE);
|
||||||
|
|
||||||
|
return throbber->animated;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* katze_throbber_get_static_icon_name:
|
||||||
|
* @throbber: a #KatzeThrobber
|
||||||
|
*
|
||||||
|
* Retrieves the name of the icon providing the static image, if an icon name
|
||||||
|
* for the static image was specified.
|
||||||
|
*
|
||||||
|
* Return value: the name of the icon providing the static image, or %NULL
|
||||||
|
**/
|
||||||
|
const gchar*
|
||||||
|
katze_throbber_get_static_icon_name (KatzeThrobber* throbber)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (KATZE_IS_THROBBER (throbber), NULL);
|
||||||
|
|
||||||
|
return throbber->static_icon_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* katze_throbber_get_static pixbuf:
|
||||||
|
* @throbber: a #KatzeThrobber
|
||||||
|
*
|
||||||
|
* Retrieves the #GdkPixbuf providing the static image, if an icon name, a
|
||||||
|
* pixbuf or a stock ID for the static image was specified. The caller of this
|
||||||
|
* function does not own a reference to the returned pixbuf.
|
||||||
|
*
|
||||||
|
* Return value: the pixbuf providing the static image, or %NULL
|
||||||
|
**/
|
||||||
|
GdkPixbuf*
|
||||||
|
katze_throbber_get_static_pixbuf (KatzeThrobber* throbber)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (KATZE_IS_THROBBER (throbber), NULL);
|
||||||
|
|
||||||
|
return throbber->static_pixbuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* katze_throbber_get_static_stock_id:
|
||||||
|
* @throbber: a #KatzeThrobber
|
||||||
|
*
|
||||||
|
* Retrieves the stock ID of the icon providing the static image, if a
|
||||||
|
* stock ID for the static image was specified.
|
||||||
|
*
|
||||||
|
* Return value: the stock ID of the icon providing the static image, or %NULL
|
||||||
|
**/
|
||||||
|
const gchar*
|
||||||
|
katze_throbber_get_static_stock_id (KatzeThrobber* throbber)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (KATZE_IS_THROBBER (throbber), NULL);
|
||||||
|
|
||||||
|
return throbber->static_stock_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_throbber_realize (GtkWidget* widget)
|
||||||
|
{
|
||||||
|
(*GTK_WIDGET_CLASS (katze_throbber_parent_class)->realize) (widget);
|
||||||
|
|
||||||
|
icon_theme_changed (KATZE_THROBBER (widget));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_throbber_unrealize (GtkWidget* widget)
|
||||||
|
{
|
||||||
|
if (GTK_WIDGET_CLASS (katze_throbber_parent_class)->unrealize)
|
||||||
|
GTK_WIDGET_CLASS (katze_throbber_parent_class)->unrealize (widget);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
pixbuf_assign_icon (GdkPixbuf** pixbuf,
|
||||||
|
const gchar* icon_name,
|
||||||
|
KatzeThrobber* throbber)
|
||||||
|
{
|
||||||
|
GdkScreen* screen;
|
||||||
|
GtkIconTheme* icon_theme;
|
||||||
|
|
||||||
|
if (*pixbuf)
|
||||||
|
g_object_unref (*pixbuf);
|
||||||
|
|
||||||
|
screen = gtk_widget_get_screen (GTK_WIDGET (throbber));
|
||||||
|
icon_theme = gtk_icon_theme_get_for_screen (screen);
|
||||||
|
*pixbuf = gtk_icon_theme_load_icon (icon_theme,
|
||||||
|
icon_name,
|
||||||
|
MAX (throbber->width, throbber->height),
|
||||||
|
(GtkIconLookupFlags) 0,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
icon_theme_changed (KatzeThrobber* throbber)
|
||||||
|
{
|
||||||
|
if (throbber->icon_name)
|
||||||
|
pixbuf_assign_icon (&throbber->pixbuf,
|
||||||
|
throbber->icon_name, throbber);
|
||||||
|
|
||||||
|
if (throbber->static_icon_name)
|
||||||
|
pixbuf_assign_icon (&throbber->static_pixbuf,
|
||||||
|
throbber->static_icon_name, throbber);
|
||||||
|
else if (throbber->static_stock_id)
|
||||||
|
katze_object_assign (throbber->static_pixbuf,
|
||||||
|
gtk_widget_render_icon (GTK_WIDGET (throbber),
|
||||||
|
throbber->static_stock_id,
|
||||||
|
throbber->icon_size,
|
||||||
|
NULL));
|
||||||
|
|
||||||
|
g_object_freeze_notify (G_OBJECT (throbber));
|
||||||
|
g_object_notify (G_OBJECT (throbber), "pixbuf");
|
||||||
|
g_object_notify (G_OBJECT (throbber), "static-pixbuf");
|
||||||
|
g_object_thaw_notify (G_OBJECT (throbber));
|
||||||
|
|
||||||
|
gtk_widget_queue_draw (GTK_WIDGET (throbber));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_throbber_map (GtkWidget* widget)
|
||||||
|
{
|
||||||
|
(*GTK_WIDGET_CLASS (katze_throbber_parent_class)->map) (widget);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_throbber_unmap (GtkWidget* widget)
|
||||||
|
{
|
||||||
|
if (GTK_WIDGET_CLASS (katze_throbber_parent_class)->unmap)
|
||||||
|
GTK_WIDGET_CLASS (katze_throbber_parent_class)->unmap (widget);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
katze_throbber_timeout (KatzeThrobber* throbber)
|
||||||
|
{
|
||||||
|
throbber->index++;
|
||||||
|
gtk_widget_queue_draw (GTK_WIDGET (throbber));
|
||||||
|
|
||||||
|
return throbber->animated;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_throbber_timeout_destroy (KatzeThrobber* throbber)
|
||||||
|
{
|
||||||
|
throbber->index = 0;
|
||||||
|
throbber->timer_id = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_throbber_style_set (GtkWidget* widget,
|
||||||
|
GtkStyle* prev_style)
|
||||||
|
{
|
||||||
|
if (GTK_WIDGET_CLASS (katze_throbber_parent_class)->style_set)
|
||||||
|
GTK_WIDGET_CLASS (katze_throbber_parent_class)->style_set (widget,
|
||||||
|
prev_style);
|
||||||
|
|
||||||
|
icon_theme_changed (KATZE_THROBBER (widget));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_throbber_screen_changed (GtkWidget* widget,
|
||||||
|
GdkScreen* prev_screen)
|
||||||
|
{
|
||||||
|
if (GTK_WIDGET_CLASS (katze_throbber_parent_class)->screen_changed)
|
||||||
|
GTK_WIDGET_CLASS (katze_throbber_parent_class)->screen_changed (
|
||||||
|
widget,
|
||||||
|
prev_screen);
|
||||||
|
|
||||||
|
icon_theme_changed (KATZE_THROBBER (widget));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_throbber_size_request (GtkWidget* widget,
|
||||||
|
GtkRequisition* requisition)
|
||||||
|
{
|
||||||
|
KatzeThrobber* throbber = KATZE_THROBBER (widget);
|
||||||
|
|
||||||
|
requisition->width = throbber->width;
|
||||||
|
requisition->height = throbber->height;
|
||||||
|
|
||||||
|
GTK_WIDGET_CLASS (katze_throbber_parent_class)->size_request (widget,
|
||||||
|
requisition);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_throbber_aligned_coords (GtkWidget* widget,
|
||||||
|
gint* ax,
|
||||||
|
gint* ay)
|
||||||
|
{
|
||||||
|
gfloat xalign, yalign;
|
||||||
|
gint xpad, ypad;
|
||||||
|
|
||||||
|
gtk_misc_get_alignment (GTK_MISC (widget), &xalign, &yalign);
|
||||||
|
if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
|
||||||
|
xalign = 1.0f - xalign;
|
||||||
|
gtk_misc_get_padding (GTK_MISC (widget), &xpad, &ypad);
|
||||||
|
|
||||||
|
*ax = floor (widget->allocation.x + xpad
|
||||||
|
+ ((widget->allocation.width - widget->requisition.width) * xalign));
|
||||||
|
*ay = floor (widget->allocation.y + ypad
|
||||||
|
+ ((widget->allocation.height - widget->requisition.height) * yalign));
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
katze_throbber_expose_event (GtkWidget* widget,
|
||||||
|
GdkEventExpose* event)
|
||||||
|
{
|
||||||
|
gint ax, ay;
|
||||||
|
KatzeThrobber* throbber = KATZE_THROBBER (widget);
|
||||||
|
|
||||||
|
if (G_UNLIKELY (!throbber->width || !throbber->height))
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
if (G_UNLIKELY (!throbber->pixbuf && !throbber->static_pixbuf))
|
||||||
|
if (throbber->animated && !throbber->pixbuf && !throbber->icon_name)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
if (!throbber->animated && (throbber->static_pixbuf
|
||||||
|
|| throbber->static_icon_name || throbber->static_stock_id))
|
||||||
|
{
|
||||||
|
if (G_UNLIKELY (!throbber->static_pixbuf && throbber->static_icon_name))
|
||||||
|
{
|
||||||
|
icon_theme_changed (KATZE_THROBBER (widget));
|
||||||
|
|
||||||
|
if (!throbber->static_pixbuf)
|
||||||
|
{
|
||||||
|
g_warning (_("Named icon '%s' couldn't be loaded"),
|
||||||
|
throbber->static_icon_name);
|
||||||
|
katze_assign (throbber->static_icon_name, NULL);
|
||||||
|
g_object_notify (G_OBJECT (throbber), "static-icon-name");
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (G_UNLIKELY (!throbber->static_pixbuf && throbber->static_stock_id))
|
||||||
|
{
|
||||||
|
icon_theme_changed (KATZE_THROBBER (widget));
|
||||||
|
|
||||||
|
if (!throbber->static_pixbuf)
|
||||||
|
{
|
||||||
|
g_warning (_("Stock icon '%s' couldn't be loaded"),
|
||||||
|
throbber->static_stock_id);
|
||||||
|
katze_assign (throbber->static_stock_id, NULL);
|
||||||
|
g_object_notify (G_OBJECT (throbber), "static-stock-id");
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
katze_throbber_aligned_coords (widget, &ax, &ay);
|
||||||
|
|
||||||
|
gdk_draw_pixbuf (event->window, NULL, throbber->static_pixbuf,
|
||||||
|
0, 0, ax, ay,
|
||||||
|
throbber->width, throbber->height,
|
||||||
|
GDK_RGB_DITHER_NONE, 0, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (G_UNLIKELY (throbber->icon_name && !throbber->pixbuf))
|
||||||
|
{
|
||||||
|
icon_theme_changed (KATZE_THROBBER (widget));
|
||||||
|
|
||||||
|
if (!throbber->pixbuf)
|
||||||
|
{
|
||||||
|
/* Fallback to a stock icon */
|
||||||
|
katze_assign (throbber->icon_name, g_strdup (GTK_STOCK_EXECUTE));
|
||||||
|
g_object_notify (G_OBJECT (throbber), "icon-name");
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gint cols = gdk_pixbuf_get_width (throbber->pixbuf) / throbber->width;
|
||||||
|
gint rows = gdk_pixbuf_get_height (throbber->pixbuf) / throbber->height;
|
||||||
|
|
||||||
|
if (G_UNLIKELY (cols == 1 && cols == rows))
|
||||||
|
{
|
||||||
|
katze_throbber_aligned_coords (widget, &ax, &ay);
|
||||||
|
|
||||||
|
if (throbber->animated)
|
||||||
|
gdk_draw_pixbuf (event->window, NULL, throbber->pixbuf,
|
||||||
|
0, 0, ax, ay,
|
||||||
|
throbber->width, throbber->height,
|
||||||
|
GDK_RGB_DITHER_NONE, 0, 0);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (G_LIKELY (cols > 0 && rows > 0))
|
||||||
|
{
|
||||||
|
gint idx;
|
||||||
|
guint x, y;
|
||||||
|
|
||||||
|
katze_throbber_aligned_coords (widget, &ax, &ay);
|
||||||
|
|
||||||
|
idx = throbber->index % (cols * rows);
|
||||||
|
if (G_LIKELY (throbber->timer_id >= 0))
|
||||||
|
idx = MAX (idx, 1);
|
||||||
|
|
||||||
|
x = (idx % cols) * throbber->width;
|
||||||
|
y = (idx / cols) * throbber->height;
|
||||||
|
|
||||||
|
gdk_draw_pixbuf (event->window, NULL, throbber->pixbuf,
|
||||||
|
x, y, ax, ay,
|
||||||
|
throbber->width, throbber->height,
|
||||||
|
GDK_RGB_DITHER_NONE, 0, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_warning (_("Animation frames are broken"));
|
||||||
|
katze_assign (throbber->icon_name, NULL);
|
||||||
|
katze_object_assign (throbber->pixbuf, NULL);
|
||||||
|
|
||||||
|
g_object_freeze_notify (G_OBJECT (throbber));
|
||||||
|
g_object_notify (G_OBJECT (throbber), "icon-name");
|
||||||
|
g_object_notify (G_OBJECT (throbber), "pixbuf");
|
||||||
|
g_object_thaw_notify (G_OBJECT (throbber));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
104
katze/katze-throbber.h
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2007 Christian Dywan <christian@twotoasts.de>
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
See the file COPYING for the full license text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __KATZE_THROBBER_H__
|
||||||
|
#define __KATZE_THROBBER_H__
|
||||||
|
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define KATZE_TYPE_THROBBER \
|
||||||
|
(katze_throbber_get_type ())
|
||||||
|
#define KATZE_THROBBER(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_CAST ((obj), KATZE_TYPE_THROBBER, KatzeThrobber))
|
||||||
|
#define KATZE_THROBBER_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_CAST ((klass), KATZE_TYPE_THROBBER, KatzeThrobberClass))
|
||||||
|
#define KATZE_IS_THROBBER(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), KATZE_TYPE_THROBBER))
|
||||||
|
#define KATZE_IS_THROBBER_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_TYPE ((klass), KATZE_TYPE_THROBBER))
|
||||||
|
#define KATZE_THROBBER_GET_CLASS(obj) \
|
||||||
|
(G_TYPE_INSTANCE_GET_CLASS ((obj), KATZE_TYPE_THROBBER, KatzeThrobberClass))
|
||||||
|
|
||||||
|
typedef struct _KatzeThrobber KatzeThrobber;
|
||||||
|
typedef struct _KatzeThrobberPrivate KatzeThrobberPrivate;
|
||||||
|
typedef struct _KatzeThrobberClass KatzeThrobberClass;
|
||||||
|
|
||||||
|
struct _KatzeThrobberClass
|
||||||
|
{
|
||||||
|
GtkMiscClass parent_class;
|
||||||
|
|
||||||
|
/* Padding for future expansion */
|
||||||
|
void (*_katze_reserved1) (void);
|
||||||
|
void (*_katze_reserved2) (void);
|
||||||
|
void (*_katze_reserved3) (void);
|
||||||
|
void (*_katze_reserved4) (void);
|
||||||
|
};
|
||||||
|
|
||||||
|
GType
|
||||||
|
katze_throbber_get_type (void);
|
||||||
|
|
||||||
|
GtkWidget*
|
||||||
|
katze_throbber_new (void);
|
||||||
|
|
||||||
|
void
|
||||||
|
katze_throbber_set_icon_size (KatzeThrobber* throbber,
|
||||||
|
GtkIconSize icon_size);
|
||||||
|
|
||||||
|
void
|
||||||
|
katze_throbber_set_icon_name (KatzeThrobber* throbber,
|
||||||
|
const gchar* icon_size);
|
||||||
|
|
||||||
|
void
|
||||||
|
katze_throbber_set_pixbuf (KatzeThrobber* throbber,
|
||||||
|
GdkPixbuf* pixbuf);
|
||||||
|
|
||||||
|
void
|
||||||
|
katze_throbber_set_animated (KatzeThrobber* throbber,
|
||||||
|
gboolean animated);
|
||||||
|
|
||||||
|
void
|
||||||
|
katze_throbber_set_static_icon_name (KatzeThrobber* throbber,
|
||||||
|
const gchar* icon_name);
|
||||||
|
|
||||||
|
void
|
||||||
|
katze_throbber_set_static_pixbuf (KatzeThrobber* throbber,
|
||||||
|
GdkPixbuf* pixbuf);
|
||||||
|
|
||||||
|
void
|
||||||
|
katze_throbber_set_static_stock_id (KatzeThrobber* throbber,
|
||||||
|
const gchar* stock_id);
|
||||||
|
|
||||||
|
GtkIconSize
|
||||||
|
katze_throbber_get_icon_size (KatzeThrobber* throbber);
|
||||||
|
|
||||||
|
const gchar*
|
||||||
|
katze_throbber_get_icon_name (KatzeThrobber* throbber);
|
||||||
|
|
||||||
|
GdkPixbuf*
|
||||||
|
katze_throbber_get_pixbuf (KatzeThrobber* throbber);
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
katze_throbber_get_animated (KatzeThrobber* throbber);
|
||||||
|
|
||||||
|
const gchar*
|
||||||
|
katze_throbber_get_static_icon_name (KatzeThrobber *throbber);
|
||||||
|
|
||||||
|
GdkPixbuf*
|
||||||
|
katze_throbber_get_static_pixbuf (KatzeThrobber* throbber);
|
||||||
|
|
||||||
|
const gchar*
|
||||||
|
katze_throbber_get_static_stock_id (KatzeThrobber* throbber);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __KATZE_THROBBER_H__ */
|
768
katze/katze-utils.c
Normal file
|
@ -0,0 +1,768 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2007-2008 Christian Dywan <christian@twotoasts.de>
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
See the file COPYING for the full license text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "katze-utils.h"
|
||||||
|
|
||||||
|
#include <glib/gi18n.h>
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
static void
|
||||||
|
proxy_toggle_button_toggled_cb (GtkToggleButton* button,
|
||||||
|
GObject* object)
|
||||||
|
{
|
||||||
|
gboolean toggled = gtk_toggle_button_get_active (button);
|
||||||
|
const gchar* property = g_object_get_data (G_OBJECT (button), "property");
|
||||||
|
g_object_set (object, property, toggled, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
proxy_file_file_set_cb (GtkFileChooser* button,
|
||||||
|
GObject* object)
|
||||||
|
{
|
||||||
|
const gchar* file = gtk_file_chooser_get_filename (button);
|
||||||
|
const gchar* property = g_object_get_data (G_OBJECT (button), "property");
|
||||||
|
g_object_set (object, property, file, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
proxy_folder_file_set_cb (GtkFileChooser* button,
|
||||||
|
GObject* object)
|
||||||
|
{
|
||||||
|
const gchar* file = gtk_file_chooser_get_current_folder (button);
|
||||||
|
const gchar* property = g_object_get_data (G_OBJECT (button), "property");
|
||||||
|
g_object_set (object, property, file, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
proxy_uri_file_set_cb (GtkFileChooser* button,
|
||||||
|
GObject* object)
|
||||||
|
{
|
||||||
|
const gchar* file = gtk_file_chooser_get_uri (button);
|
||||||
|
const gchar* property = g_object_get_data (G_OBJECT (button), "property");
|
||||||
|
g_object_set (object, property, file, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
proxy_combo_box_text_changed_cb (GtkComboBox* button,
|
||||||
|
GObject* object)
|
||||||
|
{
|
||||||
|
gchar* text = gtk_combo_box_get_active_text (button);
|
||||||
|
const gchar* property = g_object_get_data (G_OBJECT (button), "property");
|
||||||
|
g_object_set (object, property, text, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
proxy_entry_activate_cb (GtkEntry* entry,
|
||||||
|
GObject* object)
|
||||||
|
{
|
||||||
|
const gchar* text = gtk_entry_get_text (entry);
|
||||||
|
const gchar* property = g_object_get_data (G_OBJECT (entry), "property");
|
||||||
|
g_object_set (object, property, text, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
proxy_entry_focus_out_event_cb (GtkEntry* entry,
|
||||||
|
GdkEventFocus* event,
|
||||||
|
GObject* object)
|
||||||
|
{
|
||||||
|
const gchar* text = gtk_entry_get_text (entry);
|
||||||
|
const gchar* property = g_object_get_data (G_OBJECT (entry), "property");
|
||||||
|
g_object_set (object, property, text, NULL);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
proxy_spin_button_changed_cb (GtkSpinButton* button,
|
||||||
|
GObject* object)
|
||||||
|
{
|
||||||
|
GObjectClass* class = G_OBJECT_GET_CLASS (object);
|
||||||
|
const gchar* property = g_object_get_data (G_OBJECT (button), "property");
|
||||||
|
GParamSpec* pspec = g_object_class_find_property (class, property);
|
||||||
|
if (G_PARAM_SPEC_TYPE (pspec) == G_TYPE_PARAM_INT)
|
||||||
|
{
|
||||||
|
gint value = gtk_spin_button_get_value_as_int (button);
|
||||||
|
g_object_set (object, property, value, NULL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gdouble value = gtk_spin_button_get_value (button);
|
||||||
|
g_object_set (object, property, value, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
proxy_combo_box_changed_cb (GtkComboBox* button,
|
||||||
|
GObject* object)
|
||||||
|
{
|
||||||
|
gint value = gtk_combo_box_get_active (button);
|
||||||
|
const gchar* property = g_object_get_data (G_OBJECT (button), "property");
|
||||||
|
g_object_set (object, property, value, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
proxy_object_notify_boolean_cb (GObject* object,
|
||||||
|
GParamSpec* pspec,
|
||||||
|
GtkWidget* proxy)
|
||||||
|
{
|
||||||
|
const gchar* property = g_object_get_data (G_OBJECT (proxy), "property");
|
||||||
|
gboolean value = katze_object_get_boolean (object, property);
|
||||||
|
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (proxy), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
proxy_object_notify_string_cb (GObject* object,
|
||||||
|
GParamSpec* pspec,
|
||||||
|
GtkWidget* proxy)
|
||||||
|
{
|
||||||
|
const gchar* property = g_object_get_data (G_OBJECT (proxy), "property");
|
||||||
|
gchar* value = katze_object_get_string (object, property);
|
||||||
|
gtk_entry_set_text (GTK_ENTRY (proxy), value);
|
||||||
|
g_free (value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* katze_property_proxy:
|
||||||
|
* @object: a #GObject
|
||||||
|
* @property: the name of a property
|
||||||
|
* @hint: a special hint
|
||||||
|
*
|
||||||
|
* Create a widget of an appropriate type to represent the specified
|
||||||
|
* object's property. If the property is writable changes of the value
|
||||||
|
* through the widget will be reflected in the value of the property.
|
||||||
|
*
|
||||||
|
* Supported values for @hint are as follows:
|
||||||
|
* "blurb": the blurb of the property will be used to provide a kind
|
||||||
|
* of label, instead of the name.
|
||||||
|
* "file": the widget created will be particularly suitable for
|
||||||
|
* choosing an existing filename.
|
||||||
|
* "folder": the widget created will be particularly suitable for
|
||||||
|
* choosing an existing folder.
|
||||||
|
* "uri": the widget created will be particularly suitable for
|
||||||
|
* choosing an existing filename, encoded as an URI.
|
||||||
|
* "font": the widget created will be particularly suitable for
|
||||||
|
* choosing a font from installed fonts.
|
||||||
|
* Since 0.1.6 the following hints are also supported:
|
||||||
|
* "toggle": the widget created will be an empty toggle button. This
|
||||||
|
* is only supported with boolean properties.
|
||||||
|
*
|
||||||
|
* Any other values for @hint are silently ignored.
|
||||||
|
*
|
||||||
|
* Since 0.1.2 strings without hints and booleans are truly synchronous
|
||||||
|
* including property changes causing the proxy to be updated.
|
||||||
|
*
|
||||||
|
* Return value: a new widget
|
||||||
|
**/
|
||||||
|
GtkWidget*
|
||||||
|
katze_property_proxy (gpointer object,
|
||||||
|
const gchar* property,
|
||||||
|
const gchar* hint)
|
||||||
|
{
|
||||||
|
GObjectClass* class;
|
||||||
|
GParamSpec* pspec;
|
||||||
|
GType type;
|
||||||
|
const gchar* nick;
|
||||||
|
const gchar* _hint;
|
||||||
|
GtkWidget* widget;
|
||||||
|
gchar* string;
|
||||||
|
|
||||||
|
g_return_val_if_fail (G_IS_OBJECT (object), NULL);
|
||||||
|
|
||||||
|
class = G_OBJECT_GET_CLASS (object);
|
||||||
|
pspec = g_object_class_find_property (class, property);
|
||||||
|
if (!pspec)
|
||||||
|
{
|
||||||
|
g_warning (_("Property '%s' is invalid for %s"),
|
||||||
|
property, G_OBJECT_CLASS_NAME (class));
|
||||||
|
return gtk_label_new (property);
|
||||||
|
}
|
||||||
|
|
||||||
|
type = G_PARAM_SPEC_TYPE (pspec);
|
||||||
|
nick = g_param_spec_get_nick (pspec);
|
||||||
|
_hint = g_intern_string (hint);
|
||||||
|
if (_hint == g_intern_string ("blurb"))
|
||||||
|
nick = g_param_spec_get_blurb (pspec);
|
||||||
|
string = NULL;
|
||||||
|
if (type == G_TYPE_PARAM_BOOLEAN)
|
||||||
|
{
|
||||||
|
gchar* notify_property;
|
||||||
|
gboolean toggled = katze_object_get_boolean (object, property);
|
||||||
|
|
||||||
|
if (_hint == g_intern_string ("toggle"))
|
||||||
|
widget = gtk_toggle_button_new ();
|
||||||
|
else
|
||||||
|
widget = gtk_check_button_new_with_label (gettext (nick));
|
||||||
|
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), toggled);
|
||||||
|
g_signal_connect (widget, "toggled",
|
||||||
|
G_CALLBACK (proxy_toggle_button_toggled_cb), object);
|
||||||
|
notify_property = g_strdup_printf ("notify::%s", property);
|
||||||
|
g_signal_connect (object, notify_property,
|
||||||
|
G_CALLBACK (proxy_object_notify_boolean_cb), widget);
|
||||||
|
g_free (notify_property);
|
||||||
|
}
|
||||||
|
else if (type == G_TYPE_PARAM_STRING && _hint == g_intern_string ("file"))
|
||||||
|
{
|
||||||
|
string = katze_object_get_string (object, property);
|
||||||
|
|
||||||
|
widget = gtk_file_chooser_button_new (_("Choose file"),
|
||||||
|
GTK_FILE_CHOOSER_ACTION_OPEN);
|
||||||
|
|
||||||
|
if (!string)
|
||||||
|
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"))
|
||||||
|
{
|
||||||
|
string = katze_object_get_string (object, property);
|
||||||
|
|
||||||
|
widget = gtk_file_chooser_button_new (_("Choose folder"),
|
||||||
|
GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER);
|
||||||
|
if (!string)
|
||||||
|
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"))
|
||||||
|
{
|
||||||
|
string = katze_object_get_string (object, property);
|
||||||
|
|
||||||
|
widget = gtk_file_chooser_button_new (_("Choose file"),
|
||||||
|
GTK_FILE_CHOOSER_ACTION_OPEN);
|
||||||
|
if (!string)
|
||||||
|
string = g_strdup (G_PARAM_SPEC_STRING (pspec)->default_value);
|
||||||
|
gtk_file_chooser_set_uri (GTK_FILE_CHOOSER (widget),
|
||||||
|
string ? string : "");
|
||||||
|
#if GTK_CHECK_VERSION (2, 12, 0)
|
||||||
|
g_signal_connect (widget, "file-set",
|
||||||
|
G_CALLBACK (proxy_uri_file_set_cb), object);
|
||||||
|
#else
|
||||||
|
if (pspec->flags & G_PARAM_WRITABLE)
|
||||||
|
g_signal_connect (widget, "selection-changed",
|
||||||
|
G_CALLBACK (proxy_uri_file_set_cb), object);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else if (type == G_TYPE_PARAM_STRING && _hint == g_intern_string ("font"))
|
||||||
|
{
|
||||||
|
int n_families, i;
|
||||||
|
PangoContext* context;
|
||||||
|
PangoFontFamily** families;
|
||||||
|
string = katze_object_get_string (object, property);
|
||||||
|
|
||||||
|
widget = gtk_combo_box_new_text ();
|
||||||
|
context = gtk_widget_get_pango_context (widget);
|
||||||
|
pango_context_list_families (context, &families, &n_families);
|
||||||
|
if (!string)
|
||||||
|
string = g_strdup (G_PARAM_SPEC_STRING (pspec)->default_value);
|
||||||
|
for (i = 0; i < n_families; i++)
|
||||||
|
{
|
||||||
|
const gchar* font = pango_font_family_get_name (families[i]);
|
||||||
|
gtk_combo_box_append_text (GTK_COMBO_BOX (widget), font);
|
||||||
|
if (string && !strcmp (font, string))
|
||||||
|
gtk_combo_box_set_active (GTK_COMBO_BOX (widget), i);
|
||||||
|
}
|
||||||
|
gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (
|
||||||
|
gtk_combo_box_get_model (GTK_COMBO_BOX (widget))),
|
||||||
|
0, GTK_SORT_ASCENDING);
|
||||||
|
g_signal_connect (widget, "changed",
|
||||||
|
G_CALLBACK (proxy_combo_box_text_changed_cb), object);
|
||||||
|
g_free (families);
|
||||||
|
}
|
||||||
|
else if (type == G_TYPE_PARAM_STRING)
|
||||||
|
{
|
||||||
|
gchar* notify_property;
|
||||||
|
|
||||||
|
widget = gtk_entry_new ();
|
||||||
|
g_object_get (object, property, &string, NULL);
|
||||||
|
if (!string)
|
||||||
|
string = g_strdup (G_PARAM_SPEC_STRING (pspec)->default_value);
|
||||||
|
gtk_entry_set_text (GTK_ENTRY (widget), string ? string : "");
|
||||||
|
g_signal_connect (widget, "activate",
|
||||||
|
G_CALLBACK (proxy_entry_activate_cb), object);
|
||||||
|
g_signal_connect (widget, "focus-out-event",
|
||||||
|
G_CALLBACK (proxy_entry_focus_out_event_cb), object);
|
||||||
|
notify_property = g_strdup_printf ("notify::%s", property);
|
||||||
|
g_signal_connect (object, notify_property,
|
||||||
|
G_CALLBACK (proxy_object_notify_string_cb), widget);
|
||||||
|
g_free (notify_property);
|
||||||
|
}
|
||||||
|
else if (type == G_TYPE_PARAM_FLOAT)
|
||||||
|
{
|
||||||
|
gfloat value = katze_object_get_float (object, property);
|
||||||
|
|
||||||
|
widget = gtk_spin_button_new_with_range (
|
||||||
|
G_PARAM_SPEC_FLOAT (pspec)->minimum,
|
||||||
|
G_PARAM_SPEC_FLOAT (pspec)->maximum, 1);
|
||||||
|
/* Keep it narrow, 5 + 2 digits are usually fine */
|
||||||
|
gtk_entry_set_width_chars (GTK_ENTRY (widget), 5 + 2);
|
||||||
|
gtk_spin_button_set_digits (GTK_SPIN_BUTTON (widget), 2);
|
||||||
|
gtk_spin_button_set_value (GTK_SPIN_BUTTON (widget), value);
|
||||||
|
g_signal_connect (widget, "value-changed",
|
||||||
|
G_CALLBACK (proxy_spin_button_changed_cb), object);
|
||||||
|
}
|
||||||
|
else if (type == G_TYPE_PARAM_INT)
|
||||||
|
{
|
||||||
|
gint value = katze_object_get_int (object, property);
|
||||||
|
|
||||||
|
widget = gtk_spin_button_new_with_range (
|
||||||
|
G_PARAM_SPEC_INT (pspec)->minimum,
|
||||||
|
G_PARAM_SPEC_INT (pspec)->maximum, 1);
|
||||||
|
/* Keep it narrow, 5 digits are usually fine */
|
||||||
|
gtk_entry_set_width_chars (GTK_ENTRY (widget), 5);
|
||||||
|
gtk_spin_button_set_value (GTK_SPIN_BUTTON (widget), value);
|
||||||
|
g_signal_connect (widget, "value-changed",
|
||||||
|
G_CALLBACK (proxy_spin_button_changed_cb), object);
|
||||||
|
}
|
||||||
|
else if (type == G_TYPE_PARAM_ENUM)
|
||||||
|
{
|
||||||
|
guint i;
|
||||||
|
GEnumClass* enum_class = G_ENUM_CLASS (
|
||||||
|
g_type_class_ref (pspec->value_type));
|
||||||
|
gint value = katze_object_get_enum (object, property);
|
||||||
|
|
||||||
|
widget = gtk_combo_box_new_text ();
|
||||||
|
for (i = 0; i < enum_class->n_values; i++)
|
||||||
|
{
|
||||||
|
const gchar* label = gettext (enum_class->values[i].value_nick);
|
||||||
|
gtk_combo_box_append_text (GTK_COMBO_BOX (widget), label);
|
||||||
|
}
|
||||||
|
gtk_combo_box_set_active (GTK_COMBO_BOX (widget), value);
|
||||||
|
g_signal_connect (widget, "changed",
|
||||||
|
G_CALLBACK (proxy_combo_box_changed_cb), object);
|
||||||
|
g_type_class_unref (enum_class);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
widget = gtk_label_new (gettext (nick));
|
||||||
|
g_free (string);
|
||||||
|
|
||||||
|
gtk_widget_set_tooltip_text (widget, g_param_spec_get_blurb (pspec));
|
||||||
|
gtk_widget_set_sensitive (widget, pspec->flags & G_PARAM_WRITABLE);
|
||||||
|
|
||||||
|
g_object_set_data_full (G_OBJECT (widget), "property",
|
||||||
|
g_strdup (property), g_free);
|
||||||
|
|
||||||
|
return widget;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* katze_property_label:
|
||||||
|
* @object: a #GObject
|
||||||
|
* @property: the name of a property
|
||||||
|
*
|
||||||
|
* Create a label widget displaying the name of the specified object's property.
|
||||||
|
*
|
||||||
|
* Return value: a new label widget
|
||||||
|
**/
|
||||||
|
GtkWidget*
|
||||||
|
katze_property_label (gpointer object,
|
||||||
|
const gchar* property)
|
||||||
|
{
|
||||||
|
GObjectClass* class;
|
||||||
|
GParamSpec* pspec;
|
||||||
|
const gchar* nick;
|
||||||
|
GtkWidget* widget;
|
||||||
|
|
||||||
|
g_return_val_if_fail (G_IS_OBJECT (object), NULL);
|
||||||
|
|
||||||
|
class = G_OBJECT_GET_CLASS (object);
|
||||||
|
pspec = g_object_class_find_property (class, property);
|
||||||
|
if (!pspec)
|
||||||
|
{
|
||||||
|
g_warning (_("Property '%s' is invalid for %s"),
|
||||||
|
property, G_OBJECT_CLASS_NAME (class));
|
||||||
|
return gtk_label_new (property);
|
||||||
|
}
|
||||||
|
nick = g_param_spec_get_nick (pspec);
|
||||||
|
widget = gtk_label_new (nick);
|
||||||
|
|
||||||
|
return widget;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
GtkWidget* widget;
|
||||||
|
KatzeMenuPos position;
|
||||||
|
} KatzePopupInfo;
|
||||||
|
|
||||||
|
static void
|
||||||
|
katze_widget_popup_position_menu (GtkMenu* menu,
|
||||||
|
gint* x,
|
||||||
|
gint* y,
|
||||||
|
gboolean* push_in,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
gint wx, wy;
|
||||||
|
gint menu_width;
|
||||||
|
GtkRequisition menu_req;
|
||||||
|
GtkRequisition widget_req;
|
||||||
|
KatzePopupInfo* info = user_data;
|
||||||
|
GtkWidget* widget = info->widget;
|
||||||
|
gint widget_height;
|
||||||
|
|
||||||
|
/* Retrieve size and position of both widget and menu */
|
||||||
|
if (GTK_WIDGET_NO_WINDOW (widget))
|
||||||
|
{
|
||||||
|
gdk_window_get_position (widget->window, &wx, &wy);
|
||||||
|
wx += widget->allocation.x;
|
||||||
|
wy += widget->allocation.y;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
gdk_window_get_origin (widget->window, &wx, &wy);
|
||||||
|
gtk_widget_size_request (GTK_WIDGET (menu), &menu_req);
|
||||||
|
gtk_widget_size_request (widget, &widget_req);
|
||||||
|
menu_width = menu_req.width;
|
||||||
|
widget_height = widget_req.height; /* Better than allocation.height */
|
||||||
|
|
||||||
|
/* Calculate menu position */
|
||||||
|
if (info->position == KATZE_MENU_POSITION_CURSOR)
|
||||||
|
; /* Do nothing? */
|
||||||
|
else if (info->position == KATZE_MENU_POSITION_RIGHT)
|
||||||
|
{
|
||||||
|
*x = wx + widget->allocation.width - menu_width;
|
||||||
|
*y = wy + widget_height;
|
||||||
|
} else if (info->position == KATZE_MENU_POSITION_LEFT)
|
||||||
|
{
|
||||||
|
*x = wx;
|
||||||
|
*y = wy + widget_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
*push_in = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* katze_widget_popup:
|
||||||
|
* @widget: a widget
|
||||||
|
* @menu: the menu to popup
|
||||||
|
* @event: a button event, or %NULL
|
||||||
|
* @pos: the preferred positioning
|
||||||
|
*
|
||||||
|
* Pops up the given menu relative to @widget. Use this
|
||||||
|
* instead of writing custom positioning functions.
|
||||||
|
*
|
||||||
|
* Return value: a new label widget
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
katze_widget_popup (GtkWidget* widget,
|
||||||
|
GtkMenu* menu,
|
||||||
|
GdkEventButton* event,
|
||||||
|
KatzeMenuPos pos)
|
||||||
|
{
|
||||||
|
int button, event_time;
|
||||||
|
if (event)
|
||||||
|
{
|
||||||
|
button = event->button;
|
||||||
|
event_time = event->time;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
button = 0;
|
||||||
|
event_time = gtk_get_current_event_time ();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!gtk_menu_get_attach_widget (menu))
|
||||||
|
gtk_menu_attach_to_widget (menu, widget, NULL);
|
||||||
|
|
||||||
|
|
||||||
|
if (widget)
|
||||||
|
{
|
||||||
|
KatzePopupInfo info = { widget, pos };
|
||||||
|
gtk_menu_popup (menu, NULL, NULL,
|
||||||
|
katze_widget_popup_position_menu, &info,
|
||||||
|
button, event_time);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
gtk_menu_popup (menu, NULL, NULL, NULL, NULL, button, event_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* katze_image_menu_item_new_ellipsized:
|
||||||
|
* @label: a label or %NULL
|
||||||
|
*
|
||||||
|
* Creates an image menu item where the label is
|
||||||
|
* reasonably ellipsized for you.
|
||||||
|
*
|
||||||
|
* Return value: a new label widget
|
||||||
|
**/
|
||||||
|
GtkWidget*
|
||||||
|
katze_image_menu_item_new_ellipsized (const gchar* label)
|
||||||
|
{
|
||||||
|
GtkWidget* menuitem;
|
||||||
|
GtkWidget* label_widget;
|
||||||
|
|
||||||
|
menuitem = gtk_image_menu_item_new ();
|
||||||
|
label_widget = gtk_label_new (label);
|
||||||
|
/* FIXME: Should text direction be respected here? */
|
||||||
|
gtk_misc_set_alignment (GTK_MISC (label_widget), 0.0, 0.0);
|
||||||
|
gtk_label_set_max_width_chars (GTK_LABEL (label_widget), 50);
|
||||||
|
gtk_label_set_ellipsize (GTK_LABEL (label_widget), PANGO_ELLIPSIZE_MIDDLE);
|
||||||
|
gtk_widget_show (label_widget);
|
||||||
|
gtk_container_add (GTK_CONTAINER (menuitem), label_widget);
|
||||||
|
|
||||||
|
return menuitem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* katze_pixbuf_new_from_buffer:
|
||||||
|
* @buffer: Buffer with image data
|
||||||
|
* @length: Length of the buffer
|
||||||
|
* @mime_type: a MIME type, or %NULL
|
||||||
|
* @error: return location for a #GError, or %NULL
|
||||||
|
*
|
||||||
|
* Creates a new #GdkPixbuf out of the specified buffer.
|
||||||
|
*
|
||||||
|
* You can specify a MIME type if looking at the buffer
|
||||||
|
* is not enough to determine the right type.
|
||||||
|
*
|
||||||
|
* Return value: A newly-allocated #GdkPixbuf
|
||||||
|
**/
|
||||||
|
GdkPixbuf*
|
||||||
|
katze_pixbuf_new_from_buffer (const guchar* buffer,
|
||||||
|
gsize length,
|
||||||
|
const gchar* mime_type,
|
||||||
|
GError** error)
|
||||||
|
{
|
||||||
|
/* Proposed for inclusion in GdkPixbuf
|
||||||
|
See http://bugzilla.gnome.org/show_bug.cgi?id=74291 */
|
||||||
|
GdkPixbufLoader* loader;
|
||||||
|
GdkPixbuf* pixbuf;
|
||||||
|
|
||||||
|
g_return_val_if_fail (buffer != NULL, NULL);
|
||||||
|
g_return_val_if_fail (length > 0, NULL);
|
||||||
|
|
||||||
|
if (mime_type)
|
||||||
|
{
|
||||||
|
loader = gdk_pixbuf_loader_new_with_mime_type (mime_type, error);
|
||||||
|
if (!loader)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
loader = gdk_pixbuf_loader_new ();
|
||||||
|
if (!gdk_pixbuf_loader_write (loader, buffer, length, error))
|
||||||
|
{
|
||||||
|
g_object_unref (loader);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (!gdk_pixbuf_loader_close (loader, error))
|
||||||
|
{
|
||||||
|
g_object_unref (loader);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
|
||||||
|
g_object_ref (pixbuf);
|
||||||
|
g_object_unref (loader);
|
||||||
|
return pixbuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* katze_tree_view_get_selected_iter:
|
||||||
|
* @treeview: a #GtkTreeView
|
||||||
|
* @model: a pointer to store the model, or %NULL
|
||||||
|
* @iter: a pointer to store the iter, or %NULL
|
||||||
|
*
|
||||||
|
* Determines whether there is a selection in @treeview
|
||||||
|
* and sets the @iter to the current selection.
|
||||||
|
*
|
||||||
|
* If there is a selection and @model is not %NULL, it is
|
||||||
|
* set to the model, mainly for convenience.
|
||||||
|
*
|
||||||
|
* Either @model or @iter or both can be %NULL in which case
|
||||||
|
* no value will be assigned in any case.
|
||||||
|
*
|
||||||
|
* Return value: %TRUE if there is a selection
|
||||||
|
*
|
||||||
|
* Since: 0.1.3
|
||||||
|
**/
|
||||||
|
gboolean
|
||||||
|
katze_tree_view_get_selected_iter (GtkTreeView* treeview,
|
||||||
|
GtkTreeModel** model,
|
||||||
|
GtkTreeIter* iter)
|
||||||
|
{
|
||||||
|
GtkTreeSelection* selection;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GTK_IS_TREE_VIEW (treeview), FALSE);
|
||||||
|
|
||||||
|
if ((selection = gtk_tree_view_get_selection (treeview)))
|
||||||
|
if (gtk_tree_selection_get_selected (selection, model, iter))
|
||||||
|
return TRUE;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* katze_object_has_property:
|
||||||
|
* @object: a #GObject
|
||||||
|
* @property: the name of the property
|
||||||
|
*
|
||||||
|
* Determine if @object has a property with the specified name.
|
||||||
|
*
|
||||||
|
* Return value: a boolean
|
||||||
|
*
|
||||||
|
* Since: 0.1.2
|
||||||
|
**/
|
||||||
|
gboolean
|
||||||
|
katze_object_has_property (gpointer object,
|
||||||
|
const gchar* property)
|
||||||
|
{
|
||||||
|
GObjectClass* class;
|
||||||
|
|
||||||
|
g_return_val_if_fail (G_IS_OBJECT (object), FALSE);
|
||||||
|
|
||||||
|
class = G_OBJECT_GET_CLASS (object);
|
||||||
|
return g_object_class_find_property (class, property) != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* katze_object_get_boolean:
|
||||||
|
* @object: a #GObject
|
||||||
|
* @property: the name of the property to get
|
||||||
|
*
|
||||||
|
* Retrieve the boolean value of the specified property.
|
||||||
|
*
|
||||||
|
* Return value: a boolean
|
||||||
|
**/
|
||||||
|
gboolean
|
||||||
|
katze_object_get_boolean (gpointer object,
|
||||||
|
const gchar* property)
|
||||||
|
{
|
||||||
|
gboolean value = FALSE;
|
||||||
|
|
||||||
|
g_return_val_if_fail (G_IS_OBJECT (object), FALSE);
|
||||||
|
/* FIXME: Check value type */
|
||||||
|
|
||||||
|
g_object_get (object, property, &value, NULL);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* katze_object_get_int:
|
||||||
|
* @object: a #GObject
|
||||||
|
* @property: the name of the property to get
|
||||||
|
*
|
||||||
|
* Retrieve the integer value of the specified property.
|
||||||
|
*
|
||||||
|
* Return value: an integer
|
||||||
|
**/
|
||||||
|
gint
|
||||||
|
katze_object_get_int (gpointer object,
|
||||||
|
const gchar* property)
|
||||||
|
{
|
||||||
|
gint value = -1;
|
||||||
|
|
||||||
|
g_return_val_if_fail (G_IS_OBJECT (object), -1);
|
||||||
|
/* FIXME: Check value type */
|
||||||
|
|
||||||
|
g_object_get (object, property, &value, NULL);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* katze_object_get_float:
|
||||||
|
* @object: a #GObject
|
||||||
|
* @property: the name of the property to get
|
||||||
|
*
|
||||||
|
* Retrieve the float value of the specified property.
|
||||||
|
*
|
||||||
|
* Return value: a float
|
||||||
|
**/
|
||||||
|
gfloat
|
||||||
|
katze_object_get_float (gpointer object,
|
||||||
|
const gchar* property)
|
||||||
|
{
|
||||||
|
gfloat value = -1.0f;
|
||||||
|
|
||||||
|
g_return_val_if_fail (G_IS_OBJECT (object), -1.0f);
|
||||||
|
/* FIXME: Check value type */
|
||||||
|
|
||||||
|
g_object_get (object, property, &value, NULL);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* katze_object_get_enum:
|
||||||
|
* @object: a #GObject
|
||||||
|
* @property: the name of the property to get
|
||||||
|
*
|
||||||
|
* Retrieve the enum value of the specified property.
|
||||||
|
*
|
||||||
|
* Return value: an enumeration
|
||||||
|
**/
|
||||||
|
gint
|
||||||
|
katze_object_get_enum (gpointer object,
|
||||||
|
const gchar* property)
|
||||||
|
{
|
||||||
|
gint value = -1;
|
||||||
|
|
||||||
|
g_return_val_if_fail (G_IS_OBJECT (object), -1);
|
||||||
|
/* FIXME: Check value type */
|
||||||
|
|
||||||
|
g_object_get (object, property, &value, NULL);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* katze_object_get_string:
|
||||||
|
* @object: a #GObject
|
||||||
|
* @property: the name of the property to get
|
||||||
|
*
|
||||||
|
* Retrieve the string value of the specified property.
|
||||||
|
*
|
||||||
|
* Return value: a newly allocated string
|
||||||
|
**/
|
||||||
|
gchar*
|
||||||
|
katze_object_get_string (gpointer object,
|
||||||
|
const gchar* property)
|
||||||
|
{
|
||||||
|
gchar* value = NULL;
|
||||||
|
|
||||||
|
g_return_val_if_fail (G_IS_OBJECT (object), NULL);
|
||||||
|
/* FIXME: Check value type */
|
||||||
|
|
||||||
|
g_object_get (object, property, &value, NULL);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* katze_object_get_object:
|
||||||
|
* @object: a #GObject
|
||||||
|
* @property: the name of the property to get
|
||||||
|
*
|
||||||
|
* Retrieve the object value of the specified property.
|
||||||
|
*
|
||||||
|
* Return value: an object
|
||||||
|
**/
|
||||||
|
gpointer
|
||||||
|
katze_object_get_object (gpointer object,
|
||||||
|
const gchar* property)
|
||||||
|
{
|
||||||
|
GObject* value = NULL;
|
||||||
|
|
||||||
|
g_return_val_if_fail (G_IS_OBJECT (object), NULL);
|
||||||
|
/* FIXME: Check value type */
|
||||||
|
|
||||||
|
g_object_get (object, property, &value, NULL);
|
||||||
|
return value;
|
||||||
|
}
|
122
katze/katze-utils.h
Normal file
|
@ -0,0 +1,122 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2007-2008 Christian Dywan <christian@twotoasts.de>
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
See the file COPYING for the full license text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __KATZE_UTILS_H__
|
||||||
|
#define __KATZE_UTILS_H__
|
||||||
|
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
/**
|
||||||
|
* KATZE_OBJECT_NAME:
|
||||||
|
* @object: an object
|
||||||
|
*
|
||||||
|
* Return the name of an object's class structure's type.
|
||||||
|
**/
|
||||||
|
#define KATZE_OBJECT_NAME(object) \
|
||||||
|
G_OBJECT_CLASS_NAME (G_OBJECT_GET_CLASS (object))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* katze_assign:
|
||||||
|
* @lvalue: a pointer
|
||||||
|
* @rvalue: the new value
|
||||||
|
*
|
||||||
|
* Frees @lvalue if needed and assigns it the value of @rvalue.
|
||||||
|
**/
|
||||||
|
#define katze_assign(lvalue, rvalue) \
|
||||||
|
if (1) \
|
||||||
|
{ \
|
||||||
|
g_free (lvalue); \
|
||||||
|
lvalue = rvalue; \
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* katze_object_assign:
|
||||||
|
* @lvalue: a gobject
|
||||||
|
* @rvalue: the new value
|
||||||
|
*
|
||||||
|
* Unrefs @lvalue if needed and assigns it the value of @rvalue.
|
||||||
|
**/
|
||||||
|
#define katze_object_assign(lvalue, rvalue) \
|
||||||
|
if (1) \
|
||||||
|
{ \
|
||||||
|
if (lvalue) \
|
||||||
|
g_object_unref (lvalue); \
|
||||||
|
lvalue = rvalue; \
|
||||||
|
}
|
||||||
|
|
||||||
|
GtkWidget*
|
||||||
|
katze_property_proxy (gpointer object,
|
||||||
|
const gchar* property,
|
||||||
|
const gchar* hint);
|
||||||
|
|
||||||
|
GtkWidget*
|
||||||
|
katze_property_label (gpointer object,
|
||||||
|
const gchar* property);
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
KATZE_MENU_POSITION_CURSOR = 0,
|
||||||
|
KATZE_MENU_POSITION_LEFT,
|
||||||
|
KATZE_MENU_POSITION_RIGHT
|
||||||
|
} KatzeMenuPos;
|
||||||
|
|
||||||
|
void
|
||||||
|
katze_widget_popup (GtkWidget* widget,
|
||||||
|
GtkMenu* menu,
|
||||||
|
GdkEventButton* event,
|
||||||
|
KatzeMenuPos pos);
|
||||||
|
|
||||||
|
GtkWidget*
|
||||||
|
katze_image_menu_item_new_ellipsized (const gchar* label);
|
||||||
|
|
||||||
|
GdkPixbuf*
|
||||||
|
katze_pixbuf_new_from_buffer (const guchar* buffer,
|
||||||
|
gsize length,
|
||||||
|
const gchar* mime_type,
|
||||||
|
GError** error);
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
katze_tree_view_get_selected_iter (GtkTreeView* treeview,
|
||||||
|
GtkTreeModel** model,
|
||||||
|
GtkTreeIter* iter);
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
katze_object_has_property (gpointer object,
|
||||||
|
const gchar* property);
|
||||||
|
|
||||||
|
gint
|
||||||
|
katze_object_get_boolean (gpointer object,
|
||||||
|
const gchar* property);
|
||||||
|
|
||||||
|
gint
|
||||||
|
katze_object_get_int (gpointer object,
|
||||||
|
const gchar* property);
|
||||||
|
|
||||||
|
gfloat
|
||||||
|
katze_object_get_float (gpointer object,
|
||||||
|
const gchar* property);
|
||||||
|
|
||||||
|
gint
|
||||||
|
katze_object_get_enum (gpointer object,
|
||||||
|
const gchar* property);
|
||||||
|
|
||||||
|
gchar*
|
||||||
|
katze_object_get_string (gpointer object,
|
||||||
|
const gchar* property);
|
||||||
|
|
||||||
|
gpointer
|
||||||
|
katze_object_get_object (gpointer object,
|
||||||
|
const gchar* property);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __KATZE_UTILS_H__ */
|
25
katze/katze.h
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2007-2009 Christian Dywan <christian@twotoasts.de>
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
See the file COPYING for the full license text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __KATZE_H__
|
||||||
|
#define __KATZE_H__
|
||||||
|
|
||||||
|
#include "katze-http-auth.h"
|
||||||
|
#include "katze-http-cookies.h"
|
||||||
|
#include "katze-throbber.h"
|
||||||
|
#include "katze-utils.h"
|
||||||
|
#include "katze-item.h"
|
||||||
|
#include "katze-array.h"
|
||||||
|
#include "katze-arrayaction.h"
|
||||||
|
#include "katze-separatoraction.h"
|
||||||
|
#include "katze-net.h"
|
||||||
|
|
||||||
|
#endif /* __KATZE_H__ */
|
1
katze/marshal.list
Normal file
|
@ -0,0 +1 @@
|
||||||
|
VOID:POINTER,INT
|
14
katze/wscript_build
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
#! /usr/bin/env python
|
||||||
|
# WAF build script for midori
|
||||||
|
# This file is licensed under the terms of the expat license, see the file EXPAT.
|
||||||
|
|
||||||
|
import platform
|
||||||
|
|
||||||
|
obj = bld.new_task_gen ('cc', 'staticlib')
|
||||||
|
obj.name = 'katze'
|
||||||
|
obj.target = 'katze'
|
||||||
|
obj.includes = '. ../.'
|
||||||
|
obj.find_sources_in_dirs ('.')
|
||||||
|
obj.add_marshal_file ('marshal.list', 'katze_cclosure_marshal')
|
||||||
|
obj.uselib = 'M GMODULE LIBSOUP GTK LIBXML WEBKIT'
|
||||||
|
obj.install_path = None
|
67
midori/compat.c
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2008-2009 Christian Dywan <christian@twotoasts.de>
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
See the file COPYING for the full license text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "compat.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#if !GTK_CHECK_VERSION (2, 14, 0)
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gtk_show_uri (GdkScreen* screen,
|
||||||
|
const gchar* uri,
|
||||||
|
guint32 timestamp,
|
||||||
|
GError** error)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (uri != NULL, FALSE);
|
||||||
|
|
||||||
|
return g_app_info_launch_default_for_uri (uri, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !GTK_CHECK_VERSION(2, 12, 0)
|
||||||
|
|
||||||
|
void
|
||||||
|
gtk_widget_set_has_tooltip (GtkWidget* widget,
|
||||||
|
gboolean has_tooltip)
|
||||||
|
{
|
||||||
|
/* Do nothing */
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gtk_widget_set_tooltip_text (GtkWidget* widget,
|
||||||
|
const gchar* text)
|
||||||
|
{
|
||||||
|
if (text && *text)
|
||||||
|
{
|
||||||
|
static GtkTooltips* tooltips = NULL;
|
||||||
|
if (G_UNLIKELY (!tooltips))
|
||||||
|
tooltips = gtk_tooltips_new ();
|
||||||
|
gtk_tooltips_set_tip (tooltips, widget, text, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gtk_tool_item_set_tooltip_text (GtkToolItem* toolitem,
|
||||||
|
const gchar* text)
|
||||||
|
{
|
||||||
|
if (text && *text)
|
||||||
|
{
|
||||||
|
static GtkTooltips* tooltips = NULL;
|
||||||
|
if (G_UNLIKELY (!tooltips))
|
||||||
|
tooltips = gtk_tooltips_new ();
|
||||||
|
|
||||||
|
gtk_tool_item_set_tooltip (toolitem, tooltips, text, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
56
midori/compat.h
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2008-2009 Christian Dywan <christian@twotoasts.de>
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
See the file COPYING for the full license text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __COMPAT_H__
|
||||||
|
#define __COMPAT_H__
|
||||||
|
|
||||||
|
#if HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <webkit/webkit.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#if !GLIB_CHECK_VERSION (2, 14, 0)
|
||||||
|
#define G_PARAM_STATIC_STRINGS \
|
||||||
|
(G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !GTK_CHECK_VERSION (2, 14, 0)
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gtk_show_uri (GdkScreen* screen,
|
||||||
|
const gchar* uri,
|
||||||
|
guint32 timestamp,
|
||||||
|
GError** error);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !GTK_CHECK_VERSION(2, 12, 0)
|
||||||
|
|
||||||
|
void
|
||||||
|
gtk_widget_set_has_tooltip (GtkWidget* widget,
|
||||||
|
gboolean has_tooltip);
|
||||||
|
|
||||||
|
void
|
||||||
|
gtk_widget_set_tooltip_text (GtkWidget* widget,
|
||||||
|
const gchar* text);
|
||||||
|
|
||||||
|
void
|
||||||
|
gtk_tool_item_set_tooltip_text (GtkToolItem* toolitem,
|
||||||
|
const gchar* text);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __COMPAT_H__ */
|
1608
midori/gtkiconentry.c
Normal file
135
midori/gtkiconentry.h
Normal file
|
@ -0,0 +1,135 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2004-2006 Christian Hammond.
|
||||||
|
* Copyright (C) 2008 Cody Russell <bratsche@gnome.org>
|
||||||
|
*
|
||||||
|
* 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 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GTK_ICON_ENTRY_H__
|
||||||
|
#define __GTK_ICON_ENTRY_H__
|
||||||
|
|
||||||
|
#if HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <gio/gio.h>
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#if GTK_CHECK_VERSION (2, 16, 0)
|
||||||
|
#define GtkIconEntry GtkEntry
|
||||||
|
#define GtkIconEntryPosition GtkEntryIconPosition
|
||||||
|
#define GTK_ICON_ENTRY_PRIMARY GTK_ENTRY_ICON_PRIMARY
|
||||||
|
#define GTK_ICON_ENTRY_SECONDARY GTK_ENTRY_ICON_SECONDARY
|
||||||
|
#define GTK_ICON_ENTRY GTK_ENTRY
|
||||||
|
#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,
|
||||||
|
GdkPixbuf* pixbuf);
|
||||||
|
#define gtk_icon_entry_set_icon_highlight gtk_entry_set_icon_activatable
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define GTK_TYPE_ICON_ENTRY (gtk_icon_entry_get_type())
|
||||||
|
#define GTK_ICON_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_ICON_ENTRY, GtkIconEntry))
|
||||||
|
#define GTK_ICON_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GTK_TYPE_ICON_ENTRY, GtkIconEntryClass))
|
||||||
|
#define GTK_IS_ICON_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTK_TYPE_ICON_ENTRY))
|
||||||
|
#define GTK_IS_ICON_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GTK_TYPE_ICON_ENTRY))
|
||||||
|
#define GTK_ICON_ENTRY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_ICON_ENTRY, GtkIconEntryClass))
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
GTK_ICON_ENTRY_PRIMARY,
|
||||||
|
GTK_ICON_ENTRY_SECONDARY
|
||||||
|
} GtkIconEntryPosition;
|
||||||
|
|
||||||
|
typedef struct _GtkIconEntry GtkIconEntry;
|
||||||
|
typedef struct _GtkIconEntryClass GtkIconEntryClass;
|
||||||
|
|
||||||
|
struct _GtkIconEntry
|
||||||
|
{
|
||||||
|
GtkEntry parent_object;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GtkIconEntryClass
|
||||||
|
{
|
||||||
|
GtkEntryClass parent_class;
|
||||||
|
|
||||||
|
/* Signals */
|
||||||
|
void (*icon_pressed) (GtkIconEntry *entry,
|
||||||
|
GtkIconEntryPosition icon_pos,
|
||||||
|
int button);
|
||||||
|
void (*icon_released) (GtkIconEntry *entry,
|
||||||
|
GtkIconEntryPosition icon_pos,
|
||||||
|
int button);
|
||||||
|
|
||||||
|
void (*gtk_reserved1) (void);
|
||||||
|
void (*gtk_reserved2) (void);
|
||||||
|
void (*gtk_reserved3) (void);
|
||||||
|
void (*gtk_reserved4) (void);
|
||||||
|
};
|
||||||
|
|
||||||
|
GType gtk_icon_entry_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
GtkWidget* gtk_icon_entry_new (void);
|
||||||
|
|
||||||
|
void gtk_icon_entry_set_icon_from_pixbuf (GtkIconEntry *entry,
|
||||||
|
GtkIconEntryPosition icon_pos,
|
||||||
|
GdkPixbuf *pixbuf);
|
||||||
|
void gtk_icon_entry_set_icon_from_stock (GtkIconEntry *entry,
|
||||||
|
GtkIconEntryPosition icon_pos,
|
||||||
|
const gchar *stock_id);
|
||||||
|
void gtk_icon_entry_set_icon_from_icon_name (GtkIconEntry *entry,
|
||||||
|
GtkIconEntryPosition icon_pos,
|
||||||
|
const gchar *icon_name);
|
||||||
|
|
||||||
|
void gtk_icon_entry_set_icon_from_gicon (const GtkIconEntry *entry,
|
||||||
|
GtkIconEntryPosition icon_pos,
|
||||||
|
GIcon *icon);
|
||||||
|
|
||||||
|
GdkPixbuf* gtk_icon_entry_get_pixbuf (const GtkIconEntry *entry,
|
||||||
|
GtkIconEntryPosition icon_pos);
|
||||||
|
|
||||||
|
GIcon* gtk_icon_entry_get_gicon (const GtkIconEntry *entry,
|
||||||
|
GtkIconEntryPosition icon_pos);
|
||||||
|
|
||||||
|
void gtk_icon_entry_set_icon_highlight (const GtkIconEntry *entry,
|
||||||
|
GtkIconEntryPosition icon_pos,
|
||||||
|
gboolean highlight);
|
||||||
|
|
||||||
|
gboolean gtk_icon_entry_get_icon_highlight (const GtkIconEntry *entry,
|
||||||
|
GtkIconEntryPosition icon_pos);
|
||||||
|
|
||||||
|
void gtk_icon_entry_set_cursor (const GtkIconEntry *icon_entry,
|
||||||
|
GtkIconEntryPosition icon_pos,
|
||||||
|
GdkCursorType cursor_type);
|
||||||
|
|
||||||
|
void gtk_icon_entry_set_tooltip (const GtkIconEntry *icon_entry,
|
||||||
|
GtkIconEntryPosition icon_pos,
|
||||||
|
const gchar *text);
|
||||||
|
|
||||||
|
void gtk_icon_entry_set_icon_sensitive (const GtkIconEntry *icon_entry,
|
||||||
|
GtkIconEntryPosition icon_pos,
|
||||||
|
gboolean sensitive);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __GTK_ICON_ENTRY_H__ */
|
1768
midori/main.c
Normal file
6
midori/marshal.list
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
BOOLEAN:OBJECT
|
||||||
|
BOOLEAN:VOID
|
||||||
|
VOID:BOOLEAN,STRING
|
||||||
|
VOID:OBJECT,ENUM
|
||||||
|
VOID:STRING,BOOLEAN
|
||||||
|
VOID:STRING,INT,STRING
|
785
midori/midori-app.c
Normal file
|
@ -0,0 +1,785 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2008 Christian Dywan <christian@twotoasts.de>
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
See the file COPYING for the full license text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "midori-app.h"
|
||||||
|
#include "sokoke.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
#include <glib/gi18n.h>
|
||||||
|
|
||||||
|
#if HAVE_UNIQUE
|
||||||
|
#include <unique/unique.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct _MidoriApp
|
||||||
|
{
|
||||||
|
GObject parent_instance;
|
||||||
|
|
||||||
|
MidoriBrowser* browser;
|
||||||
|
GtkAccelGroup* accel_group;
|
||||||
|
|
||||||
|
gchar* name;
|
||||||
|
MidoriWebSettings* settings;
|
||||||
|
KatzeArray* bookmarks;
|
||||||
|
KatzeArray* trash;
|
||||||
|
KatzeArray* search_engines;
|
||||||
|
KatzeArray* history;
|
||||||
|
KatzeArray* extensions;
|
||||||
|
KatzeArray* browsers;
|
||||||
|
|
||||||
|
gpointer instance;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _MidoriAppClass
|
||||||
|
{
|
||||||
|
GObjectClass parent_class;
|
||||||
|
|
||||||
|
/* Signals */
|
||||||
|
void
|
||||||
|
(*add_browser) (MidoriApp* app,
|
||||||
|
MidoriBrowser* browser);
|
||||||
|
void
|
||||||
|
(*quit) (MidoriApp* app);
|
||||||
|
};
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (MidoriApp, midori_app, G_TYPE_OBJECT)
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
PROP_0,
|
||||||
|
|
||||||
|
PROP_NAME,
|
||||||
|
PROP_SETTINGS,
|
||||||
|
PROP_BOOKMARKS,
|
||||||
|
PROP_TRASH,
|
||||||
|
PROP_SEARCH_ENGINES,
|
||||||
|
PROP_HISTORY,
|
||||||
|
PROP_EXTENSIONS,
|
||||||
|
PROP_BROWSERS,
|
||||||
|
PROP_BROWSER,
|
||||||
|
PROP_BROWSER_COUNT
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
ADD_BROWSER,
|
||||||
|
QUIT,
|
||||||
|
|
||||||
|
LAST_SIGNAL
|
||||||
|
};
|
||||||
|
|
||||||
|
static guint signals[LAST_SIGNAL];
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_app_finalize (GObject* object);
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_app_set_property (GObject* object,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue* value,
|
||||||
|
GParamSpec* pspec);
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_app_get_property (GObject* object,
|
||||||
|
guint prop_id,
|
||||||
|
GValue* value,
|
||||||
|
GParamSpec* pspec);
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
midori_browser_focus_in_event_cb (MidoriBrowser* browser,
|
||||||
|
GdkEventFocus* event,
|
||||||
|
MidoriApp* app)
|
||||||
|
{
|
||||||
|
app->browser = browser;
|
||||||
|
g_object_notify (G_OBJECT (app), "browser");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_browser_new_window_cb (MidoriBrowser* browser,
|
||||||
|
const gchar* uri,
|
||||||
|
MidoriApp* app)
|
||||||
|
{
|
||||||
|
MidoriBrowser* new_browser = midori_app_create_browser (app);
|
||||||
|
midori_app_add_browser (app, new_browser);
|
||||||
|
|
||||||
|
midori_browser_add_uri (new_browser, uri);
|
||||||
|
gtk_widget_show (GTK_WIDGET (new_browser));
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
midori_browser_delete_event_cb (MidoriBrowser* browser,
|
||||||
|
GdkEvent* event,
|
||||||
|
MidoriApp* app)
|
||||||
|
{
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
midori_browser_destroy_cb (MidoriBrowser* browser,
|
||||||
|
MidoriApp* app)
|
||||||
|
{
|
||||||
|
katze_array_remove_item (app->browsers, browser);
|
||||||
|
if (!katze_array_is_empty (app->browsers))
|
||||||
|
return FALSE;
|
||||||
|
midori_app_quit (app);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_browser_quit_cb (MidoriBrowser* browser,
|
||||||
|
MidoriApp* app)
|
||||||
|
{
|
||||||
|
midori_app_quit (app);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_midori_app_add_browser (MidoriApp* app,
|
||||||
|
MidoriBrowser* browser)
|
||||||
|
{
|
||||||
|
g_return_if_fail (MIDORI_IS_APP (app));
|
||||||
|
g_return_if_fail (MIDORI_IS_BROWSER (browser));
|
||||||
|
|
||||||
|
gtk_window_add_accel_group (GTK_WINDOW (browser), app->accel_group);
|
||||||
|
g_object_connect (browser,
|
||||||
|
"signal::focus-in-event", midori_browser_focus_in_event_cb, app,
|
||||||
|
"signal::new-window", midori_browser_new_window_cb, app,
|
||||||
|
"signal::delete-event", midori_browser_delete_event_cb, app,
|
||||||
|
"signal::destroy", midori_browser_destroy_cb, app,
|
||||||
|
"signal::quit", midori_browser_quit_cb, app,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
katze_array_add_item (app->browsers, browser);
|
||||||
|
|
||||||
|
#if HAVE_UNIQUE
|
||||||
|
if (app->instance)
|
||||||
|
unique_app_watch_window (app->instance, GTK_WINDOW (browser));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_midori_app_quit (MidoriApp* app)
|
||||||
|
{
|
||||||
|
gtk_main_quit ();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_app_class_init (MidoriAppClass* class)
|
||||||
|
{
|
||||||
|
GObjectClass* gobject_class;
|
||||||
|
|
||||||
|
signals[ADD_BROWSER] = g_signal_new (
|
||||||
|
"add-browser",
|
||||||
|
G_TYPE_FROM_CLASS (class),
|
||||||
|
(GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
|
||||||
|
G_STRUCT_OFFSET (MidoriAppClass, add_browser),
|
||||||
|
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),
|
||||||
|
(GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
|
||||||
|
G_STRUCT_OFFSET (MidoriAppClass, quit),
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
g_cclosure_marshal_VOID__VOID,
|
||||||
|
G_TYPE_NONE, 0);
|
||||||
|
|
||||||
|
gobject_class = G_OBJECT_CLASS (class);
|
||||||
|
gobject_class->finalize = midori_app_finalize;
|
||||||
|
gobject_class->set_property = midori_app_set_property;
|
||||||
|
gobject_class->get_property = midori_app_get_property;
|
||||||
|
|
||||||
|
class->add_browser = _midori_app_add_browser;
|
||||||
|
class->quit = _midori_app_quit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MidoriApp:name:
|
||||||
|
*
|
||||||
|
* The name of the instance.
|
||||||
|
*
|
||||||
|
* Since: 0.1.6
|
||||||
|
*/
|
||||||
|
g_object_class_install_property (gobject_class,
|
||||||
|
PROP_NAME,
|
||||||
|
g_param_spec_string (
|
||||||
|
"name",
|
||||||
|
"Name",
|
||||||
|
"The name of the instance",
|
||||||
|
"midori",
|
||||||
|
G_PARAM_CONSTRUCT_ONLY |
|
||||||
|
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
|
g_object_class_install_property (gobject_class,
|
||||||
|
PROP_SETTINGS,
|
||||||
|
g_param_spec_object (
|
||||||
|
"settings",
|
||||||
|
"Settings",
|
||||||
|
"The associated settings",
|
||||||
|
MIDORI_TYPE_WEB_SETTINGS,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
|
g_object_class_install_property (gobject_class,
|
||||||
|
PROP_BOOKMARKS,
|
||||||
|
g_param_spec_object (
|
||||||
|
"bookmarks",
|
||||||
|
"Bookmarks",
|
||||||
|
"The bookmarks folder, containing all bookmarks",
|
||||||
|
KATZE_TYPE_ARRAY,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
|
g_object_class_install_property (gobject_class,
|
||||||
|
PROP_TRASH,
|
||||||
|
g_param_spec_object (
|
||||||
|
"trash",
|
||||||
|
"Trash",
|
||||||
|
"The trash, collecting recently closed tabs and windows",
|
||||||
|
KATZE_TYPE_ARRAY,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
|
g_object_class_install_property (gobject_class,
|
||||||
|
PROP_SEARCH_ENGINES,
|
||||||
|
g_param_spec_object (
|
||||||
|
"search-engines",
|
||||||
|
"Search Engines",
|
||||||
|
"The list of search engines",
|
||||||
|
KATZE_TYPE_ARRAY,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
|
g_object_class_install_property (gobject_class,
|
||||||
|
PROP_HISTORY,
|
||||||
|
g_param_spec_object (
|
||||||
|
"history",
|
||||||
|
"History",
|
||||||
|
"The list of history items",
|
||||||
|
KATZE_TYPE_ARRAY,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
|
g_object_class_install_property (gobject_class,
|
||||||
|
PROP_EXTENSIONS,
|
||||||
|
g_param_spec_object (
|
||||||
|
"extensions",
|
||||||
|
"Extensions",
|
||||||
|
"The list of extensions",
|
||||||
|
KATZE_TYPE_ARRAY,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MidoriApp:browsers:
|
||||||
|
*
|
||||||
|
* The list of browsers.
|
||||||
|
*
|
||||||
|
* Since: 0.1.3
|
||||||
|
*/
|
||||||
|
g_object_class_install_property (gobject_class,
|
||||||
|
PROP_BROWSERS,
|
||||||
|
g_param_spec_object (
|
||||||
|
"browsers",
|
||||||
|
"Browsers",
|
||||||
|
"The list of browsers",
|
||||||
|
KATZE_TYPE_ARRAY,
|
||||||
|
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MidoriApp:browser:
|
||||||
|
*
|
||||||
|
* The current browser, that is the one that was last used.
|
||||||
|
*
|
||||||
|
* Since: 0.1.3
|
||||||
|
*/
|
||||||
|
g_object_class_install_property (gobject_class,
|
||||||
|
PROP_BROWSER,
|
||||||
|
g_param_spec_object (
|
||||||
|
"browser",
|
||||||
|
"Browser",
|
||||||
|
"The current browser",
|
||||||
|
MIDORI_TYPE_BROWSER,
|
||||||
|
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MidoriApp:browser-count:
|
||||||
|
*
|
||||||
|
* The number of browsers.
|
||||||
|
*
|
||||||
|
* Deprecated: 0.1.3 Use MidoriApp:browsers instead.
|
||||||
|
*/
|
||||||
|
g_object_class_install_property (gobject_class,
|
||||||
|
PROP_BROWSER_COUNT,
|
||||||
|
g_param_spec_uint (
|
||||||
|
"browser-count",
|
||||||
|
"Browser Count",
|
||||||
|
"The current number of browsers",
|
||||||
|
0, G_MAXUINT, 0,
|
||||||
|
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
|
||||||
|
}
|
||||||
|
|
||||||
|
#if HAVE_UNIQUE
|
||||||
|
static UniqueResponse
|
||||||
|
midori_browser_message_received_cb (UniqueApp* instance,
|
||||||
|
UniqueCommand command,
|
||||||
|
UniqueMessageData* message,
|
||||||
|
guint timestamp,
|
||||||
|
MidoriApp* app)
|
||||||
|
{
|
||||||
|
UniqueResponse response;
|
||||||
|
MidoriBrowser* browser;
|
||||||
|
gchar** uris;
|
||||||
|
MidoriNewPage open_external_pages_in;
|
||||||
|
gboolean first;
|
||||||
|
|
||||||
|
switch (command)
|
||||||
|
{
|
||||||
|
case UNIQUE_ACTIVATE:
|
||||||
|
gtk_window_set_screen (GTK_WINDOW (app->browser),
|
||||||
|
unique_message_data_get_screen (message));
|
||||||
|
gtk_window_present (GTK_WINDOW (app->browser));
|
||||||
|
response = UNIQUE_RESPONSE_OK;
|
||||||
|
break;
|
||||||
|
case UNIQUE_NEW:
|
||||||
|
browser = midori_app_create_browser (app);
|
||||||
|
midori_app_add_browser (app, browser);
|
||||||
|
/* FIXME: Should open the homepage according to settings */
|
||||||
|
midori_browser_add_uri (browser, "");
|
||||||
|
midori_browser_activate_action (browser, "Location");
|
||||||
|
gtk_window_set_screen (GTK_WINDOW (app->browser),
|
||||||
|
unique_message_data_get_screen (message));
|
||||||
|
gtk_widget_show (GTK_WIDGET (browser));
|
||||||
|
response = UNIQUE_RESPONSE_OK;
|
||||||
|
break;
|
||||||
|
case UNIQUE_OPEN:
|
||||||
|
gtk_window_set_screen (GTK_WINDOW (app->browser),
|
||||||
|
unique_message_data_get_screen (message));
|
||||||
|
gtk_window_present (GTK_WINDOW (app->browser));
|
||||||
|
uris = unique_message_data_get_uris (message);
|
||||||
|
if (!uris)
|
||||||
|
response = UNIQUE_RESPONSE_FAIL;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_object_get (app->settings, "open-external-pages-in",
|
||||||
|
&open_external_pages_in, NULL);
|
||||||
|
if (open_external_pages_in == MIDORI_NEW_PAGE_WINDOW)
|
||||||
|
{
|
||||||
|
browser = midori_app_create_browser (app);
|
||||||
|
midori_app_add_browser (app, browser);
|
||||||
|
gtk_window_set_screen (GTK_WINDOW (app->browser),
|
||||||
|
unique_message_data_get_screen (message));
|
||||||
|
gtk_widget_show (GTK_WIDGET (browser));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
browser = app->browser;
|
||||||
|
first = (open_external_pages_in == MIDORI_NEW_PAGE_CURRENT);
|
||||||
|
while (*uris)
|
||||||
|
{
|
||||||
|
gchar* fixed_uri = sokoke_magic_uri (*uris, NULL);
|
||||||
|
if (first)
|
||||||
|
{
|
||||||
|
midori_browser_set_current_uri (browser, fixed_uri);
|
||||||
|
first = FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
midori_browser_set_current_page (browser,
|
||||||
|
midori_browser_add_uri (browser, fixed_uri));
|
||||||
|
g_free (fixed_uri);
|
||||||
|
uris++;
|
||||||
|
}
|
||||||
|
/* g_strfreev (uris); */
|
||||||
|
response = UNIQUE_RESPONSE_OK;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
response = UNIQUE_RESPONSE_FAIL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static gpointer
|
||||||
|
midori_app_create_instance (MidoriApp* app,
|
||||||
|
const gchar* name)
|
||||||
|
{
|
||||||
|
#if HAVE_UNIQUE
|
||||||
|
gpointer instance;
|
||||||
|
GdkDisplay* display;
|
||||||
|
gchar* display_name;
|
||||||
|
gchar* instance_name;
|
||||||
|
guint i, n;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!name)
|
||||||
|
name = "midori";
|
||||||
|
|
||||||
|
#if HAVE_UNIQUE
|
||||||
|
if (!(display = gdk_display_get_default ()))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
display_name = g_strdup (gdk_display_get_name (display));
|
||||||
|
n = strlen (display_name);
|
||||||
|
for (i = 0; i < n; i++)
|
||||||
|
if (display_name[i] == ':' || display_name[i] == '.')
|
||||||
|
display_name[i] = '_';
|
||||||
|
instance_name = g_strdup_printf ("de.twotoasts.%s_%s", name, display_name);
|
||||||
|
instance = unique_app_new (instance_name, NULL);
|
||||||
|
g_free (instance_name);
|
||||||
|
g_free (display_name);
|
||||||
|
g_signal_connect (instance, "message-received",
|
||||||
|
G_CALLBACK (midori_browser_message_received_cb), app);
|
||||||
|
return instance;
|
||||||
|
#else
|
||||||
|
return NULL;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_app_init (MidoriApp* app)
|
||||||
|
{
|
||||||
|
app->accel_group = gtk_accel_group_new ();
|
||||||
|
|
||||||
|
app->settings = NULL;
|
||||||
|
app->bookmarks = NULL;
|
||||||
|
app->trash = NULL;
|
||||||
|
app->search_engines = NULL;
|
||||||
|
app->history = NULL;
|
||||||
|
app->extensions = NULL;
|
||||||
|
app->browsers = katze_array_new (MIDORI_TYPE_BROWSER);
|
||||||
|
|
||||||
|
app->instance = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_app_finalize (GObject* object)
|
||||||
|
{
|
||||||
|
MidoriApp* app = MIDORI_APP (object);
|
||||||
|
|
||||||
|
g_object_unref (app->accel_group);
|
||||||
|
|
||||||
|
katze_assign (app->name, NULL);
|
||||||
|
katze_object_assign (app->settings, NULL);
|
||||||
|
katze_object_assign (app->bookmarks, NULL);
|
||||||
|
katze_object_assign (app->trash, NULL);
|
||||||
|
katze_object_assign (app->search_engines, NULL);
|
||||||
|
katze_object_assign (app->history, NULL);
|
||||||
|
katze_object_assign (app->extensions, NULL);
|
||||||
|
katze_object_assign (app->browsers, NULL);
|
||||||
|
|
||||||
|
katze_object_assign (app->instance, NULL);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (midori_app_parent_class)->finalize (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_app_set_property (GObject* object,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue* value,
|
||||||
|
GParamSpec* pspec)
|
||||||
|
{
|
||||||
|
MidoriApp* app = MIDORI_APP (object);
|
||||||
|
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_NAME:
|
||||||
|
katze_assign (app->name, g_value_dup_string (value));
|
||||||
|
break;
|
||||||
|
case PROP_SETTINGS:
|
||||||
|
katze_object_assign (app->settings, g_value_dup_object (value));
|
||||||
|
/* FIXME: Propagate settings to all browsers */
|
||||||
|
break;
|
||||||
|
case PROP_BOOKMARKS:
|
||||||
|
katze_object_assign (app->bookmarks, g_value_dup_object (value));
|
||||||
|
/* FIXME: Propagate bookmarks to all browsers */
|
||||||
|
break;
|
||||||
|
case PROP_TRASH:
|
||||||
|
katze_object_assign (app->trash, g_value_dup_object (value));
|
||||||
|
/* FIXME: Propagate trash to all browsers */
|
||||||
|
break;
|
||||||
|
case PROP_SEARCH_ENGINES:
|
||||||
|
katze_object_assign (app->search_engines, g_value_dup_object (value));
|
||||||
|
/* FIXME: Propagate search engines to all browsers */
|
||||||
|
break;
|
||||||
|
case PROP_HISTORY:
|
||||||
|
katze_object_assign (app->history, g_value_dup_object (value));
|
||||||
|
/* FIXME: Propagate history to all browsers */
|
||||||
|
break;
|
||||||
|
case PROP_EXTENSIONS:
|
||||||
|
katze_object_assign (app->extensions, g_value_dup_object (value));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_app_get_property (GObject* object,
|
||||||
|
guint prop_id,
|
||||||
|
GValue* value,
|
||||||
|
GParamSpec* pspec)
|
||||||
|
{
|
||||||
|
MidoriApp* app = MIDORI_APP (object);
|
||||||
|
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_NAME:
|
||||||
|
g_value_set_string (value, app->name);
|
||||||
|
break;
|
||||||
|
case PROP_SETTINGS:
|
||||||
|
g_value_set_object (value, app->settings);
|
||||||
|
break;
|
||||||
|
case PROP_BOOKMARKS:
|
||||||
|
g_value_set_object (value, app->bookmarks);
|
||||||
|
break;
|
||||||
|
case PROP_TRASH:
|
||||||
|
g_value_set_object (value, app->trash);
|
||||||
|
break;
|
||||||
|
case PROP_SEARCH_ENGINES:
|
||||||
|
g_value_set_object (value, app->search_engines);
|
||||||
|
break;
|
||||||
|
case PROP_HISTORY:
|
||||||
|
g_value_set_object (value, app->history);
|
||||||
|
break;
|
||||||
|
case PROP_EXTENSIONS:
|
||||||
|
g_value_set_object (value, app->extensions);
|
||||||
|
break;
|
||||||
|
case PROP_BROWSERS:
|
||||||
|
g_value_set_object (value, app->browsers);
|
||||||
|
break;
|
||||||
|
case PROP_BROWSER:
|
||||||
|
g_value_set_object (value, app->browser);
|
||||||
|
break;
|
||||||
|
case PROP_BROWSER_COUNT:
|
||||||
|
g_value_set_uint (value, katze_array_get_length (app->browsers));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* midori_app_new:
|
||||||
|
*
|
||||||
|
* Instantiates a new #MidoriApp singleton.
|
||||||
|
*
|
||||||
|
* Subsequent calls will ref the initial instance.
|
||||||
|
*
|
||||||
|
* Return value: a new #MidoriApp
|
||||||
|
**/
|
||||||
|
MidoriApp*
|
||||||
|
midori_app_new (void)
|
||||||
|
{
|
||||||
|
MidoriApp* app = g_object_new (MIDORI_TYPE_APP,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
return app;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* midori_app_instance_is_running:
|
||||||
|
* @app: a #MidoriApp
|
||||||
|
*
|
||||||
|
* Determines whether an instance of Midori is
|
||||||
|
* already running on the default display.
|
||||||
|
*
|
||||||
|
* Use the "name" property if you want to run more
|
||||||
|
* than one instance.
|
||||||
|
*
|
||||||
|
* If Midori was built without single instance support
|
||||||
|
* this function will always return %FALSE.
|
||||||
|
*
|
||||||
|
* Return value: %TRUE if an instance is already running
|
||||||
|
**/
|
||||||
|
gboolean
|
||||||
|
midori_app_instance_is_running (MidoriApp* app)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (MIDORI_IS_APP (app), FALSE);
|
||||||
|
|
||||||
|
#if HAVE_UNIQUE
|
||||||
|
if (!app->instance)
|
||||||
|
app->instance = midori_app_create_instance (app, app->name);
|
||||||
|
if (app->instance)
|
||||||
|
return unique_app_is_running (app->instance);
|
||||||
|
#endif
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* midori_app_instance_send_activate:
|
||||||
|
* @app: a #MidoriApp
|
||||||
|
*
|
||||||
|
* Sends a message to an instance of Midori already
|
||||||
|
* running on the default display, asking to activate it.
|
||||||
|
*
|
||||||
|
* Practically the current browser will be focussed.
|
||||||
|
*
|
||||||
|
* Return value: %TRUE if the message was sent successfully
|
||||||
|
**/
|
||||||
|
gboolean
|
||||||
|
midori_app_instance_send_activate (MidoriApp* app)
|
||||||
|
{
|
||||||
|
#if HAVE_UNIQUE
|
||||||
|
UniqueResponse response;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* g_return_val_if_fail (MIDORI_IS_APP (app), FALSE); */
|
||||||
|
g_return_val_if_fail (midori_app_instance_is_running (app), FALSE);
|
||||||
|
|
||||||
|
#if HAVE_UNIQUE
|
||||||
|
if (app->instance)
|
||||||
|
{
|
||||||
|
response = unique_app_send_message (app->instance, UNIQUE_ACTIVATE, NULL);
|
||||||
|
if (response == UNIQUE_RESPONSE_OK)
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* midori_app_instance_send_new_browser:
|
||||||
|
* @app: a #MidoriApp
|
||||||
|
*
|
||||||
|
* Sends a message to an instance of Midori already
|
||||||
|
* running on the default display, asking to open a new browser.
|
||||||
|
*
|
||||||
|
* Return value: %TRUE if the message was sent successfully
|
||||||
|
**/
|
||||||
|
gboolean
|
||||||
|
midori_app_instance_send_new_browser (MidoriApp* app)
|
||||||
|
{
|
||||||
|
#if HAVE_UNIQUE
|
||||||
|
UniqueResponse response;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* g_return_val_if_fail (MIDORI_IS_APP (app), FALSE); */
|
||||||
|
g_return_val_if_fail (midori_app_instance_is_running (app), FALSE);
|
||||||
|
|
||||||
|
#if HAVE_UNIQUE
|
||||||
|
if (app->instance)
|
||||||
|
{
|
||||||
|
response = unique_app_send_message (app->instance, UNIQUE_NEW, NULL);
|
||||||
|
if (response == UNIQUE_RESPONSE_OK)
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* midori_app_instance_send_uris:
|
||||||
|
* @app: a #MidoriApp
|
||||||
|
* @uris: a string vector of URIs
|
||||||
|
*
|
||||||
|
* Sends a message to an instance of Midori already
|
||||||
|
* running on the default display, asking to open @uris.
|
||||||
|
*
|
||||||
|
* The strings in @uris will each be opened in a new tab.
|
||||||
|
*
|
||||||
|
* Return value: %TRUE if the message was sent successfully
|
||||||
|
**/
|
||||||
|
gboolean
|
||||||
|
midori_app_instance_send_uris (MidoriApp* app,
|
||||||
|
gchar** uris)
|
||||||
|
{
|
||||||
|
#if HAVE_UNIQUE
|
||||||
|
UniqueMessageData* message;
|
||||||
|
UniqueResponse response;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* g_return_val_if_fail (MIDORI_IS_APP (app), FALSE); */
|
||||||
|
g_return_val_if_fail (midori_app_instance_is_running (app), FALSE);
|
||||||
|
g_return_val_if_fail (uris != NULL, FALSE);
|
||||||
|
|
||||||
|
#if HAVE_UNIQUE
|
||||||
|
if (app->instance)
|
||||||
|
{
|
||||||
|
message = unique_message_data_new ();
|
||||||
|
unique_message_data_set_uris (message, uris);
|
||||||
|
response = unique_app_send_message (app->instance, UNIQUE_OPEN, message);
|
||||||
|
unique_message_data_free (message);
|
||||||
|
if (response == UNIQUE_RESPONSE_OK)
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* midori_app_add_browser:
|
||||||
|
* @app: a #MidoriApp
|
||||||
|
* @browser: a #MidoriBrowser
|
||||||
|
*
|
||||||
|
* Adds a #MidoriBrowser to the #MidoriApp.
|
||||||
|
*
|
||||||
|
* The app will take care of the browser's new-window and quit signals, as well
|
||||||
|
* as watch window closing so that the last closed window quits the app.
|
||||||
|
* Also the app watches focus changes to indicate the 'current' browser.
|
||||||
|
*
|
||||||
|
* Return value: a new #MidoriApp
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
midori_app_add_browser (MidoriApp* app,
|
||||||
|
MidoriBrowser* browser)
|
||||||
|
{
|
||||||
|
g_return_if_fail (MIDORI_IS_APP (app));
|
||||||
|
g_return_if_fail (MIDORI_IS_BROWSER (browser));
|
||||||
|
|
||||||
|
g_signal_emit (app, signals[ADD_BROWSER], 0, browser);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* midori_app_create_browser:
|
||||||
|
* @app: a #MidoriApp
|
||||||
|
*
|
||||||
|
* Creates a #MidoriBrowser which inherits its settings,
|
||||||
|
* bookmarks, trash, search engines and history from @app.
|
||||||
|
*
|
||||||
|
* Return value: a new #MidoriBrowser
|
||||||
|
*
|
||||||
|
* Since: 1.0.2
|
||||||
|
**/
|
||||||
|
MidoriBrowser*
|
||||||
|
midori_app_create_browser (MidoriApp* app)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (MIDORI_IS_APP (app), NULL);
|
||||||
|
|
||||||
|
return g_object_new (MIDORI_TYPE_BROWSER,
|
||||||
|
"settings", app->settings,
|
||||||
|
"bookmarks", app->bookmarks,
|
||||||
|
"trash", app->trash,
|
||||||
|
"search-engines", app->search_engines,
|
||||||
|
"history", app->history,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* midori_app_quit:
|
||||||
|
* @app: a #MidoriApp
|
||||||
|
*
|
||||||
|
* Quits the #MidoriApp singleton.
|
||||||
|
*
|
||||||
|
* Since 0.1.2 the "quit" signal is always emitted before quitting.
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
midori_app_quit (MidoriApp* app)
|
||||||
|
{
|
||||||
|
g_return_if_fail (MIDORI_IS_APP (app));
|
||||||
|
|
||||||
|
g_signal_emit (app, signals[QUIT], 0);
|
||||||
|
}
|
69
midori/midori-app.h
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2008 Christian Dywan <christian@twotoasts.de>
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
See the file COPYING for the full license text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __MIDORI_APP_H__
|
||||||
|
#define __MIDORI_APP_H__
|
||||||
|
|
||||||
|
#include <katze/katze.h>
|
||||||
|
|
||||||
|
#include "midori-browser.h"
|
||||||
|
#include "midori-websettings.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define MIDORI_TYPE_APP \
|
||||||
|
(midori_app_get_type ())
|
||||||
|
#define MIDORI_APP(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_CAST ((obj), MIDORI_TYPE_APP, MidoriApp))
|
||||||
|
#define MIDORI_APP_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_CAST ((klass), MIDORI_TYPE_APP, MidoriAppClass))
|
||||||
|
#define MIDORI_IS_APP(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), MIDORI_TYPE_APP))
|
||||||
|
#define MIDORI_IS_APP_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_TYPE ((klass), MIDORI_TYPE_APP))
|
||||||
|
#define MIDORI_APP_GET_CLASS(obj) \
|
||||||
|
(G_TYPE_INSTANCE_GET_CLASS ((obj), MIDORI_TYPE_APP, MidoriAppClass))
|
||||||
|
|
||||||
|
typedef struct _MidoriApp MidoriApp;
|
||||||
|
typedef struct _MidoriAppClass MidoriAppClass;
|
||||||
|
|
||||||
|
GType
|
||||||
|
midori_app_get_type (void);
|
||||||
|
|
||||||
|
MidoriApp*
|
||||||
|
midori_app_new (void);
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
midori_app_instance_is_running (MidoriApp* app);
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
midori_app_instance_send_activate (MidoriApp* app);
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
midori_app_instance_send_new_browser (MidoriApp* app);
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
midori_app_instance_send_uris (MidoriApp* app,
|
||||||
|
gchar** uris);
|
||||||
|
|
||||||
|
void
|
||||||
|
midori_app_add_browser (MidoriApp* app,
|
||||||
|
MidoriBrowser* browser);
|
||||||
|
|
||||||
|
MidoriBrowser*
|
||||||
|
midori_app_create_browser (MidoriApp* app);
|
||||||
|
|
||||||
|
void
|
||||||
|
midori_app_quit (MidoriApp* app);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __MIDORI_APP_H__ */
|
374
midori/midori-array.c
Normal file
|
@ -0,0 +1,374 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2007-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 <katze/katze.h>
|
||||||
|
|
||||||
|
#if HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <glib/gi18n.h>
|
||||||
|
|
||||||
|
#if HAVE_LIBXML
|
||||||
|
#include <libxml/parser.h>
|
||||||
|
#include <libxml/tree.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if HAVE_LIBXML
|
||||||
|
static KatzeItem*
|
||||||
|
katze_item_from_xmlNodePtr (xmlNodePtr cur)
|
||||||
|
{
|
||||||
|
KatzeItem* item;
|
||||||
|
xmlChar* key;
|
||||||
|
|
||||||
|
item = katze_item_new ();
|
||||||
|
key = xmlGetProp (cur, (xmlChar*)"href");
|
||||||
|
katze_item_set_uri (item, (gchar*)key);
|
||||||
|
g_free (key);
|
||||||
|
|
||||||
|
cur = cur->xmlChildrenNode;
|
||||||
|
while (cur)
|
||||||
|
{
|
||||||
|
if (!xmlStrcmp (cur->name, (const xmlChar*)"title"))
|
||||||
|
{
|
||||||
|
key = xmlNodeGetContent (cur);
|
||||||
|
katze_item_set_name (item, g_strstrip ((gchar*)key));
|
||||||
|
g_free (key);
|
||||||
|
}
|
||||||
|
else if (!xmlStrcmp (cur->name, (const xmlChar*)"desc"))
|
||||||
|
{
|
||||||
|
key = xmlNodeGetContent (cur);
|
||||||
|
katze_item_set_text (item, g_strstrip ((gchar*)key));
|
||||||
|
g_free (key);
|
||||||
|
}
|
||||||
|
cur = cur->next;
|
||||||
|
}
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create an array from an xmlNodePtr */
|
||||||
|
static KatzeArray*
|
||||||
|
katze_array_from_xmlNodePtr (xmlNodePtr cur)
|
||||||
|
{
|
||||||
|
KatzeArray* array;
|
||||||
|
xmlChar* key;
|
||||||
|
KatzeItem* item;
|
||||||
|
|
||||||
|
array = katze_array_new (KATZE_TYPE_ARRAY);
|
||||||
|
|
||||||
|
key = xmlGetProp (cur, (xmlChar*)"folded");
|
||||||
|
if (key)
|
||||||
|
{
|
||||||
|
/* if (!g_ascii_strncasecmp ((gchar*)key, "yes", 3))
|
||||||
|
folder->folded = TRUE;
|
||||||
|
else if (!g_ascii_strncasecmp ((gchar*)key, "no", 2))
|
||||||
|
folder->folded = FALSE;
|
||||||
|
else
|
||||||
|
g_warning ("XBEL: Unknown value for folded."); */
|
||||||
|
xmlFree (key);
|
||||||
|
}
|
||||||
|
|
||||||
|
cur = cur->xmlChildrenNode;
|
||||||
|
while (cur)
|
||||||
|
{
|
||||||
|
if (!xmlStrcmp (cur->name, (const xmlChar*)"title"))
|
||||||
|
{
|
||||||
|
key = xmlNodeGetContent (cur);
|
||||||
|
katze_item_set_name (KATZE_ITEM (array), g_strstrip ((gchar*)key));
|
||||||
|
}
|
||||||
|
else if (!xmlStrcmp (cur->name, (const xmlChar*)"desc"))
|
||||||
|
{
|
||||||
|
key = xmlNodeGetContent (cur);
|
||||||
|
katze_item_set_text (KATZE_ITEM (array), g_strstrip ((gchar*)key));
|
||||||
|
}
|
||||||
|
else if (!xmlStrcmp (cur->name, (const xmlChar*)"folder"))
|
||||||
|
{
|
||||||
|
item = (KatzeItem*)katze_array_from_xmlNodePtr (cur);
|
||||||
|
katze_array_add_item (array, item);
|
||||||
|
}
|
||||||
|
else if (!xmlStrcmp (cur->name, (const xmlChar*)"bookmark"))
|
||||||
|
{
|
||||||
|
item = katze_item_from_xmlNodePtr (cur);
|
||||||
|
katze_array_add_item (array, item);
|
||||||
|
}
|
||||||
|
else if (!xmlStrcmp (cur->name, (const xmlChar*)"separator"))
|
||||||
|
{
|
||||||
|
item = katze_item_new ();
|
||||||
|
katze_array_add_item (array, item);
|
||||||
|
}
|
||||||
|
cur = cur->next;
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Loads the contents from an xmlNodePtr into an array. */
|
||||||
|
static gboolean
|
||||||
|
katze_array_from_xmlDocPtr (KatzeArray* array,
|
||||||
|
xmlDocPtr doc)
|
||||||
|
{
|
||||||
|
xmlNodePtr cur;
|
||||||
|
xmlChar* version;
|
||||||
|
gchar* value;
|
||||||
|
KatzeItem* item;
|
||||||
|
|
||||||
|
cur = xmlDocGetRootElement (doc);
|
||||||
|
version = xmlGetProp (cur, (xmlChar*)"version");
|
||||||
|
if (xmlStrcmp (version, (xmlChar*)"1.0"))
|
||||||
|
g_warning ("XBEL version is not 1.0.");
|
||||||
|
xmlFree (version);
|
||||||
|
|
||||||
|
value = (gchar*)xmlGetProp (cur, (xmlChar*)"title");
|
||||||
|
katze_item_set_name (KATZE_ITEM (array), value);
|
||||||
|
g_free (value);
|
||||||
|
|
||||||
|
value = (gchar*)xmlGetProp (cur, (xmlChar*)"desc");
|
||||||
|
katze_item_set_text (KATZE_ITEM (array), value);
|
||||||
|
g_free (value);
|
||||||
|
|
||||||
|
if ((cur = xmlDocGetRootElement (doc)) == NULL)
|
||||||
|
{
|
||||||
|
/* Empty document */
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (xmlStrcmp (cur->name, (const xmlChar*)"xbel"))
|
||||||
|
{
|
||||||
|
/* Wrong document kind */
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
cur = cur->xmlChildrenNode;
|
||||||
|
while (cur)
|
||||||
|
{
|
||||||
|
item = NULL;
|
||||||
|
if (!xmlStrcmp (cur->name, (const xmlChar*)"folder"))
|
||||||
|
item = (KatzeItem*)katze_array_from_xmlNodePtr (cur);
|
||||||
|
else if (!xmlStrcmp (cur->name, (const xmlChar*)"bookmark"))
|
||||||
|
item = katze_item_from_xmlNodePtr (cur);
|
||||||
|
else if (!xmlStrcmp (cur->name, (const xmlChar*)"separator"))
|
||||||
|
item = katze_item_new ();
|
||||||
|
/*else if (!xmlStrcmp (cur->name, (const xmlChar*)"info"))
|
||||||
|
item = katze_xbel_parse_info (xbel, cur);*/
|
||||||
|
if (item)
|
||||||
|
katze_array_add_item (array, item);
|
||||||
|
cur = cur->next;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* midori_array_from_file:
|
||||||
|
* @array: a #KatzeArray
|
||||||
|
* @filename: a filename to load from
|
||||||
|
* @format: the desired format
|
||||||
|
* @error: a #GError or %NULL
|
||||||
|
*
|
||||||
|
* Loads the contents of a file in the specified format.
|
||||||
|
*
|
||||||
|
* Return value: %TRUE on success, %FALSE otherwise
|
||||||
|
*
|
||||||
|
* Since: 0.1.6
|
||||||
|
**/
|
||||||
|
gboolean
|
||||||
|
midori_array_from_file (KatzeArray* array,
|
||||||
|
const gchar* filename,
|
||||||
|
const gchar* format,
|
||||||
|
GError** error)
|
||||||
|
{
|
||||||
|
xmlDocPtr doc;
|
||||||
|
|
||||||
|
g_return_val_if_fail (katze_array_is_a (array, KATZE_TYPE_ITEM), FALSE);
|
||||||
|
g_return_val_if_fail (filename != NULL, FALSE);
|
||||||
|
g_return_val_if_fail (!g_strcmp0 (format, "xbel"), FALSE);
|
||||||
|
g_return_val_if_fail (!error || !*error, FALSE);
|
||||||
|
|
||||||
|
if (!g_file_test (filename, G_FILE_TEST_EXISTS))
|
||||||
|
{
|
||||||
|
/* File doesn't exist */
|
||||||
|
*error = g_error_new_literal (G_FILE_ERROR, G_FILE_ERROR_NOENT,
|
||||||
|
_("File not found."));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((doc = xmlParseFile (filename)) == NULL)
|
||||||
|
{
|
||||||
|
/* No valid xml or broken encoding */
|
||||||
|
*error = g_error_new_literal (G_FILE_ERROR, G_FILE_ERROR_FAILED,
|
||||||
|
_("Malformed document."));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!katze_array_from_xmlDocPtr (array, doc))
|
||||||
|
{
|
||||||
|
/* Parsing failed */
|
||||||
|
xmlFreeDoc (doc);
|
||||||
|
*error = g_error_new_literal (G_FILE_ERROR, G_FILE_ERROR_FAILED,
|
||||||
|
_("Malformed document."));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
xmlFreeDoc (doc);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static gchar*
|
||||||
|
_simple_xml_element (const gchar* name,
|
||||||
|
const gchar* value)
|
||||||
|
{
|
||||||
|
gchar* value_escaped;
|
||||||
|
gchar* markup;
|
||||||
|
|
||||||
|
if (!value)
|
||||||
|
return g_strdup ("");
|
||||||
|
value_escaped = g_markup_escape_text (value, -1);
|
||||||
|
markup = g_strdup_printf ("<%s>%s</%s>\n", name, value_escaped, name);
|
||||||
|
g_free (value_escaped);
|
||||||
|
return markup;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gchar*
|
||||||
|
katze_item_to_data (KatzeItem* item)
|
||||||
|
{
|
||||||
|
gchar* markup;
|
||||||
|
|
||||||
|
g_return_val_if_fail (KATZE_IS_ITEM (item), NULL);
|
||||||
|
|
||||||
|
markup = NULL;
|
||||||
|
if (KATZE_IS_ARRAY (item))
|
||||||
|
{
|
||||||
|
GString* _markup = g_string_new (NULL);
|
||||||
|
guint i = 0;
|
||||||
|
KatzeItem* _item;
|
||||||
|
while ((_item = katze_array_get_nth_item (KATZE_ARRAY (item), i++)))
|
||||||
|
{
|
||||||
|
gchar* item_markup = katze_item_to_data (_item);
|
||||||
|
g_string_append (_markup, item_markup);
|
||||||
|
g_free (item_markup);
|
||||||
|
}
|
||||||
|
/* gchar* folded = item->folded ? NULL : g_strdup_printf (" folded=\"no\""); */
|
||||||
|
gchar* title = _simple_xml_element ("title", katze_item_get_name (item));
|
||||||
|
gchar* desc = _simple_xml_element ("desc", katze_item_get_text (item));
|
||||||
|
markup = g_strdup_printf ("<folder%s>\n%s%s%s</folder>\n",
|
||||||
|
"" /* folded ? folded : "" */,
|
||||||
|
title, desc,
|
||||||
|
_markup->str);
|
||||||
|
g_string_free (_markup, TRUE);
|
||||||
|
/* g_free (folded); */
|
||||||
|
g_free (title);
|
||||||
|
g_free (desc);
|
||||||
|
}
|
||||||
|
else if (katze_item_get_uri (item))
|
||||||
|
{
|
||||||
|
gchar* href_escaped = g_markup_escape_text (katze_item_get_uri (item), -1);
|
||||||
|
gchar* href = g_strdup_printf (" href=\"%s\"", href_escaped);
|
||||||
|
g_free (href_escaped);
|
||||||
|
gchar* title = _simple_xml_element ("title", katze_item_get_name (item));
|
||||||
|
gchar* desc = _simple_xml_element ("desc", katze_item_get_text (item));
|
||||||
|
markup = g_strdup_printf ("<bookmark%s>\n%s%s%s</bookmark>\n",
|
||||||
|
href,
|
||||||
|
title, desc,
|
||||||
|
"");
|
||||||
|
g_free (href);
|
||||||
|
g_free (title);
|
||||||
|
g_free (desc);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
markup = g_strdup ("<separator/>\n");
|
||||||
|
return markup;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gchar*
|
||||||
|
katze_array_to_xbel (KatzeArray* array,
|
||||||
|
GError** error)
|
||||||
|
{
|
||||||
|
GString* inner_markup;
|
||||||
|
guint i;
|
||||||
|
KatzeItem* item;
|
||||||
|
gchar* item_xml;
|
||||||
|
gchar* title;
|
||||||
|
gchar* desc;
|
||||||
|
gchar* outer_markup;
|
||||||
|
|
||||||
|
inner_markup = g_string_new (NULL);
|
||||||
|
i = 0;
|
||||||
|
while ((item = katze_array_get_nth_item (array, i++)))
|
||||||
|
{
|
||||||
|
item_xml = katze_item_to_data (item);
|
||||||
|
g_string_append (inner_markup, item_xml);
|
||||||
|
g_free (item_xml);
|
||||||
|
}
|
||||||
|
|
||||||
|
title = _simple_xml_element ("title", katze_item_get_name (KATZE_ITEM (array)));
|
||||||
|
desc = _simple_xml_element ("desc", katze_item_get_text (KATZE_ITEM (array)));
|
||||||
|
outer_markup = g_strdup_printf (
|
||||||
|
"%s%s<xbel version=\"1.0\">\n%s%s%s</xbel>\n",
|
||||||
|
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n",
|
||||||
|
"<!DOCTYPE xbel PUBLIC \"+//IDN python.org//DTD "
|
||||||
|
"XML Bookmark Exchange Language 1.0//EN//XML\" "
|
||||||
|
"\"http://www.python.org/topics/xml/dtds/xbel-1.0.dtd\">\n",
|
||||||
|
title,
|
||||||
|
desc,
|
||||||
|
inner_markup->str);
|
||||||
|
g_string_free (inner_markup, TRUE);
|
||||||
|
g_free (title);
|
||||||
|
g_free (desc);
|
||||||
|
|
||||||
|
return outer_markup;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
midori_array_to_file_xbel (KatzeArray* array,
|
||||||
|
const gchar* filename,
|
||||||
|
GError** error)
|
||||||
|
{
|
||||||
|
gchar* data;
|
||||||
|
FILE* fp;
|
||||||
|
|
||||||
|
if (!(data = katze_array_to_xbel (array, error)))
|
||||||
|
return FALSE;
|
||||||
|
if (!(fp = fopen (filename, "w")))
|
||||||
|
{
|
||||||
|
*error = g_error_new_literal (G_FILE_ERROR, G_FILE_ERROR_ACCES,
|
||||||
|
_("Writing failed."));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
fputs (data, fp);
|
||||||
|
fclose (fp);
|
||||||
|
g_free (data);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* midori_array_to_file:
|
||||||
|
* @array: a #KatzeArray
|
||||||
|
* @filename: a filename to load from
|
||||||
|
* @format: the desired format
|
||||||
|
* @error: a #GError or %NULL
|
||||||
|
*
|
||||||
|
* Saves the contents to a file in the specified format.
|
||||||
|
*
|
||||||
|
* Return value: %TRUE on success, %FALSE otherwise
|
||||||
|
*
|
||||||
|
* Since: 0.1.6
|
||||||
|
**/
|
||||||
|
gboolean
|
||||||
|
midori_array_to_file (KatzeArray* array,
|
||||||
|
const gchar* filename,
|
||||||
|
const gchar* format,
|
||||||
|
GError** error)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (katze_array_is_a (array, KATZE_TYPE_ITEM), FALSE);
|
||||||
|
g_return_val_if_fail (filename, FALSE);
|
||||||
|
g_return_val_if_fail (!error || !*error, FALSE);
|
||||||
|
|
||||||
|
if (!g_strcmp0 (format, "xbel"))
|
||||||
|
return midori_array_to_file_xbel (array, filename, error);
|
||||||
|
g_critical ("Cannot write KatzeArray to unknown format '%s'.", format);
|
||||||
|
return FALSE;
|
||||||
|
}
|
29
midori/midori-array.h
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2007-2009 Christian Dywan <christian@twotoasts.de>
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
See the file COPYING for the full license text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __MIDORI_ARRAY_H__
|
||||||
|
#define __MIDORI_ARRAY_H__ 1
|
||||||
|
|
||||||
|
#include <katze/katze.h>
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
midori_array_from_file (KatzeArray* array,
|
||||||
|
const gchar* filename,
|
||||||
|
const gchar* format,
|
||||||
|
GError** error);
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
midori_array_to_file (KatzeArray* array,
|
||||||
|
const gchar* filename,
|
||||||
|
const gchar* format,
|
||||||
|
GError** error);
|
||||||
|
|
||||||
|
#endif /* !__MIDORI_ARRAY_H__ */
|
5234
midori/midori-browser.c
Normal file
135
midori/midori-browser.h
Normal file
|
@ -0,0 +1,135 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2008 Christian Dywan <christian@twotoasts.de>
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
See the file COPYING for the full license text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __MIDORI_BROWSER_H__
|
||||||
|
#define __MIDORI_BROWSER_H__
|
||||||
|
|
||||||
|
#include <webkit/webkit.h>
|
||||||
|
#if defined(HAVE_HILDON) && HAVE_HILDON
|
||||||
|
#include <hildon/hildon.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <katze/katze.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define MIDORI_TYPE_BROWSER \
|
||||||
|
(midori_browser_get_type ())
|
||||||
|
#define MIDORI_BROWSER(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_CAST ((obj), MIDORI_TYPE_BROWSER, MidoriBrowser))
|
||||||
|
#define MIDORI_BROWSER_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_CAST ((klass), MIDORI_TYPE_BROWSER, MidoriBrowserClass))
|
||||||
|
#define MIDORI_IS_BROWSER(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), MIDORI_TYPE_BROWSER))
|
||||||
|
#define MIDORI_IS_BROWSER_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_TYPE ((klass), MIDORI_TYPE_BROWSER))
|
||||||
|
#define MIDORI_BROWSER_GET_CLASS(obj) \
|
||||||
|
(G_TYPE_INSTANCE_GET_CLASS ((obj), MIDORI_TYPE_BROWSER, MidoriBrowserClass))
|
||||||
|
|
||||||
|
typedef struct _MidoriBrowser MidoriBrowser;
|
||||||
|
typedef struct _MidoriBrowserClass MidoriBrowserClass;
|
||||||
|
|
||||||
|
struct _MidoriBrowserClass
|
||||||
|
{
|
||||||
|
#if defined(HAVE_HILDON) && HAVE_HILDON
|
||||||
|
HildonWindowClass parent_class;
|
||||||
|
#else
|
||||||
|
GtkWindowClass parent_class;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Signals */
|
||||||
|
void
|
||||||
|
(*window_object_cleared) (MidoriBrowser* browser,
|
||||||
|
WebKitWebFrame* web_frame,
|
||||||
|
JSContextRef* context,
|
||||||
|
JSObjectRef* window_object);
|
||||||
|
void
|
||||||
|
(*statusbar_text_changed) (MidoriBrowser* browser,
|
||||||
|
const gchar* text);
|
||||||
|
void
|
||||||
|
(*element_motion) (MidoriBrowser* browser,
|
||||||
|
const gchar* link_uri);
|
||||||
|
void
|
||||||
|
(*new_window) (MidoriBrowser* browser,
|
||||||
|
const gchar* uri);
|
||||||
|
|
||||||
|
void
|
||||||
|
(*add_tab) (MidoriBrowser* browser,
|
||||||
|
GtkWidget* view);
|
||||||
|
void
|
||||||
|
(*remove_tab) (MidoriBrowser* browser,
|
||||||
|
GtkWidget* view);
|
||||||
|
void
|
||||||
|
(*activate_action) (MidoriBrowser* browser,
|
||||||
|
const gchar* name);
|
||||||
|
void
|
||||||
|
(*quit) (MidoriBrowser* browser);
|
||||||
|
};
|
||||||
|
|
||||||
|
GType
|
||||||
|
midori_browser_get_type (void);
|
||||||
|
|
||||||
|
MidoriBrowser*
|
||||||
|
midori_browser_new (void);
|
||||||
|
|
||||||
|
gint
|
||||||
|
midori_browser_add_tab (MidoriBrowser* browser,
|
||||||
|
GtkWidget* widget);
|
||||||
|
|
||||||
|
void
|
||||||
|
midori_browser_remove_tab (MidoriBrowser* browser,
|
||||||
|
GtkWidget* widget);
|
||||||
|
|
||||||
|
gint
|
||||||
|
midori_browser_add_item (MidoriBrowser* browser,
|
||||||
|
KatzeItem* item);
|
||||||
|
|
||||||
|
gint
|
||||||
|
midori_browser_add_uri (MidoriBrowser* browser,
|
||||||
|
const gchar* uri);
|
||||||
|
|
||||||
|
void
|
||||||
|
midori_browser_activate_action (MidoriBrowser* browser,
|
||||||
|
const gchar* name);
|
||||||
|
|
||||||
|
GtkActionGroup*
|
||||||
|
midori_browser_get_action_group (MidoriBrowser* browser);
|
||||||
|
|
||||||
|
void
|
||||||
|
midori_browser_set_current_uri (MidoriBrowser* browser,
|
||||||
|
const gchar* uri);
|
||||||
|
|
||||||
|
const gchar*
|
||||||
|
midori_browser_get_current_uri (MidoriBrowser* browser);
|
||||||
|
|
||||||
|
void
|
||||||
|
midori_browser_set_current_page (MidoriBrowser* browser,
|
||||||
|
gint n);
|
||||||
|
|
||||||
|
gint
|
||||||
|
midori_browser_get_current_page (MidoriBrowser* browser);
|
||||||
|
|
||||||
|
void
|
||||||
|
midori_browser_set_current_tab (MidoriBrowser* browser,
|
||||||
|
GtkWidget* widget);
|
||||||
|
|
||||||
|
GtkWidget*
|
||||||
|
midori_browser_get_current_tab (MidoriBrowser* browser);
|
||||||
|
|
||||||
|
KatzeArray*
|
||||||
|
midori_browser_get_proxy_array (MidoriBrowser* browser);
|
||||||
|
|
||||||
|
void
|
||||||
|
midori_browser_quit (MidoriBrowser* browser);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __MIDORI_BROWSER_H__ */
|
772
midori/midori-extension.c
Normal file
|
@ -0,0 +1,772 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2008-2009 Christian Dywan <christian@twotoasts.de>
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
See the file COPYING for the full license text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "midori-extension.h"
|
||||||
|
|
||||||
|
#if HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <katze/katze.h>
|
||||||
|
#include "sokoke.h"
|
||||||
|
#include <glib/gi18n.h>
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (MidoriExtension, midori_extension, G_TYPE_OBJECT);
|
||||||
|
|
||||||
|
struct _MidoriExtensionPrivate
|
||||||
|
{
|
||||||
|
gchar* name;
|
||||||
|
gchar* description;
|
||||||
|
gchar* version;
|
||||||
|
gchar* authors;
|
||||||
|
|
||||||
|
MidoriApp* app;
|
||||||
|
gboolean active;
|
||||||
|
gchar* config_dir;
|
||||||
|
GList* lsettings;
|
||||||
|
GHashTable* settings;
|
||||||
|
GKeyFile* key_file;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
gchar* name;
|
||||||
|
GType type;
|
||||||
|
gboolean default_value;
|
||||||
|
gboolean value;
|
||||||
|
} MESettingBoolean;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
gchar* name;
|
||||||
|
GType type;
|
||||||
|
gint default_value;
|
||||||
|
gint value;
|
||||||
|
} MESettingInteger;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
gchar* name;
|
||||||
|
GType type;
|
||||||
|
gchar* default_value;
|
||||||
|
gchar* value;
|
||||||
|
} MESettingString;
|
||||||
|
|
||||||
|
void me_setting_free (gpointer setting)
|
||||||
|
{
|
||||||
|
MESettingString* string_setting = (MESettingString*)setting;
|
||||||
|
|
||||||
|
g_free (string_setting->name);
|
||||||
|
if (string_setting->type == G_TYPE_STRING)
|
||||||
|
{
|
||||||
|
g_free (string_setting->default_value);
|
||||||
|
g_free (string_setting->value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define midori_extension_can_install_setting(extension, name) \
|
||||||
|
if (extension->priv->active) \
|
||||||
|
{ \
|
||||||
|
g_critical ("%s: Settings have to be installed before " \
|
||||||
|
"the extension is activated.", G_STRFUNC); \
|
||||||
|
return; \
|
||||||
|
} \
|
||||||
|
if (g_hash_table_lookup (extension->priv->settings, name)) \
|
||||||
|
{ \
|
||||||
|
g_critical ("%s: A setting with the name '%s' is already installed.", \
|
||||||
|
G_STRFUNC, name); \
|
||||||
|
return; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define me_setting_install(stype, _name, gtype, _default_value, _value) \
|
||||||
|
setting = g_new (stype, 1); \
|
||||||
|
setting->name = _name; \
|
||||||
|
setting->type = gtype; \
|
||||||
|
setting->default_value = _default_value; \
|
||||||
|
setting->value = _value; \
|
||||||
|
g_hash_table_insert (extension->priv->settings, setting->name, setting); \
|
||||||
|
extension->priv->lsettings = g_list_prepend \
|
||||||
|
(extension->priv->lsettings, setting);
|
||||||
|
|
||||||
|
#define me_setting_type(setting, gtype, rreturn) \
|
||||||
|
if (!setting) { \
|
||||||
|
g_critical ("%s: There is no setting with the name '%s' installed.", G_STRFUNC, name); \
|
||||||
|
rreturn; } \
|
||||||
|
if (setting->type != gtype) { \
|
||||||
|
g_critical ("%s: The setting '%s' is not a string.", G_STRFUNC, name); \
|
||||||
|
rreturn; }
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
PROP_0,
|
||||||
|
|
||||||
|
PROP_NAME,
|
||||||
|
PROP_DESCRIPTION,
|
||||||
|
PROP_VERSION,
|
||||||
|
PROP_AUTHORS
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
ACTIVATE,
|
||||||
|
DEACTIVATE,
|
||||||
|
|
||||||
|
LAST_SIGNAL
|
||||||
|
};
|
||||||
|
|
||||||
|
static guint signals[LAST_SIGNAL];
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_extension_finalize (GObject* object);
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_extension_set_property (GObject* object,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue* value,
|
||||||
|
GParamSpec* pspec);
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_extension_get_property (GObject* object,
|
||||||
|
guint prop_id,
|
||||||
|
GValue* value,
|
||||||
|
GParamSpec* pspec);
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_extension_class_init (MidoriExtensionClass* class)
|
||||||
|
{
|
||||||
|
GObjectClass* gobject_class;
|
||||||
|
GParamFlags flags;
|
||||||
|
|
||||||
|
signals[ACTIVATE] = g_signal_new (
|
||||||
|
"activate",
|
||||||
|
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_APP);
|
||||||
|
|
||||||
|
signals[DEACTIVATE] = g_signal_new (
|
||||||
|
"deactivate",
|
||||||
|
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,
|
||||||
|
G_TYPE_NONE);
|
||||||
|
|
||||||
|
gobject_class = G_OBJECT_CLASS (class);
|
||||||
|
gobject_class->finalize = midori_extension_finalize;
|
||||||
|
gobject_class->set_property = midori_extension_set_property;
|
||||||
|
gobject_class->get_property = midori_extension_get_property;
|
||||||
|
|
||||||
|
flags = G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS;
|
||||||
|
|
||||||
|
g_object_class_install_property (gobject_class,
|
||||||
|
PROP_NAME,
|
||||||
|
g_param_spec_string (
|
||||||
|
"name",
|
||||||
|
"Name",
|
||||||
|
"The name of the extension",
|
||||||
|
NULL,
|
||||||
|
flags));
|
||||||
|
|
||||||
|
g_object_class_install_property (gobject_class,
|
||||||
|
PROP_DESCRIPTION,
|
||||||
|
g_param_spec_string (
|
||||||
|
"description",
|
||||||
|
"Description",
|
||||||
|
"The description of the extension",
|
||||||
|
NULL,
|
||||||
|
flags));
|
||||||
|
|
||||||
|
g_object_class_install_property (gobject_class,
|
||||||
|
PROP_VERSION,
|
||||||
|
g_param_spec_string (
|
||||||
|
"version",
|
||||||
|
"Version",
|
||||||
|
"The version of the extension",
|
||||||
|
NULL,
|
||||||
|
flags));
|
||||||
|
|
||||||
|
g_object_class_install_property (gobject_class,
|
||||||
|
PROP_AUTHORS,
|
||||||
|
g_param_spec_string (
|
||||||
|
"authors",
|
||||||
|
"Authors",
|
||||||
|
"The authors of the extension",
|
||||||
|
NULL,
|
||||||
|
flags));
|
||||||
|
|
||||||
|
g_type_class_add_private (class, sizeof (MidoriExtensionPrivate));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_extension_activate_cb (MidoriExtension* extension,
|
||||||
|
MidoriApp* app)
|
||||||
|
{
|
||||||
|
GList* lsettings;
|
||||||
|
|
||||||
|
g_return_if_fail (MIDORI_IS_APP (app));
|
||||||
|
|
||||||
|
lsettings = g_list_first (extension->priv->lsettings);
|
||||||
|
|
||||||
|
/* If a configuration directory was requested before activation we
|
||||||
|
assume we should load and save settings. This is a detail that
|
||||||
|
extension writers shouldn't worry about. */
|
||||||
|
extension->priv->key_file = lsettings && extension->priv->config_dir
|
||||||
|
? g_key_file_new () : NULL;
|
||||||
|
if (extension->priv->key_file)
|
||||||
|
{
|
||||||
|
gchar* config_file;
|
||||||
|
GError* error = NULL;
|
||||||
|
|
||||||
|
config_file = g_build_filename (extension->priv->config_dir, "config", NULL);
|
||||||
|
if (!g_key_file_load_from_file (extension->priv->key_file, config_file,
|
||||||
|
G_KEY_FILE_KEEP_COMMENTS, &error))
|
||||||
|
{
|
||||||
|
if (error->code != G_FILE_ERROR_NOENT)
|
||||||
|
printf (_("The configuration of the extension '%s' couldn't be loaded: %s\n"),
|
||||||
|
extension->priv->name, error->message);
|
||||||
|
g_error_free (error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (lsettings)
|
||||||
|
{
|
||||||
|
MESettingString* setting = (MESettingString*)lsettings->data;
|
||||||
|
|
||||||
|
if (setting->type == G_TYPE_BOOLEAN)
|
||||||
|
{
|
||||||
|
MESettingBoolean* setting_ = (MESettingBoolean*)setting;
|
||||||
|
if (extension->priv->key_file)
|
||||||
|
setting_->value = sokoke_key_file_get_boolean_default (
|
||||||
|
extension->priv->key_file,
|
||||||
|
"settings", setting->name, setting_->default_value, NULL);
|
||||||
|
else
|
||||||
|
setting_->value = setting_->default_value;
|
||||||
|
}
|
||||||
|
else if (setting->type == G_TYPE_INT)
|
||||||
|
{
|
||||||
|
MESettingInteger* setting_ = (MESettingInteger*)setting;
|
||||||
|
if (extension->priv->key_file)
|
||||||
|
setting_->value = sokoke_key_file_get_integer_default (
|
||||||
|
extension->priv->key_file,
|
||||||
|
"settings", setting->name, setting_->default_value, NULL);
|
||||||
|
else
|
||||||
|
setting_->value = setting_->default_value;
|
||||||
|
}
|
||||||
|
else if (setting->type == G_TYPE_STRING)
|
||||||
|
{
|
||||||
|
if (extension->priv->key_file)
|
||||||
|
setting->value = sokoke_key_file_get_string_default (
|
||||||
|
extension->priv->key_file,
|
||||||
|
"settings", setting->name, setting->default_value, NULL);
|
||||||
|
else
|
||||||
|
setting->value = g_strdup (setting->default_value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
g_assert_not_reached ();
|
||||||
|
|
||||||
|
lsettings = g_list_next (lsettings);
|
||||||
|
}
|
||||||
|
|
||||||
|
extension->priv->app = g_object_ref (app);
|
||||||
|
extension->priv->active = TRUE;
|
||||||
|
/* FIXME: Disconnect all signal handlers */
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_extension_init (MidoriExtension* extension)
|
||||||
|
{
|
||||||
|
extension->priv = G_TYPE_INSTANCE_GET_PRIVATE (extension,
|
||||||
|
MIDORI_TYPE_EXTENSION, MidoriExtensionPrivate);
|
||||||
|
|
||||||
|
extension->priv->app = NULL;
|
||||||
|
extension->priv->active = FALSE;
|
||||||
|
extension->priv->config_dir = NULL;
|
||||||
|
extension->priv->lsettings = NULL;
|
||||||
|
extension->priv->settings = g_hash_table_new_full (g_str_hash, g_str_equal,
|
||||||
|
g_free, me_setting_free);
|
||||||
|
extension->priv->key_file = NULL;
|
||||||
|
|
||||||
|
g_signal_connect (extension, "activate",
|
||||||
|
G_CALLBACK (midori_extension_activate_cb), NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_extension_finalize (GObject* object)
|
||||||
|
{
|
||||||
|
MidoriExtension* extension = MIDORI_EXTENSION (object);
|
||||||
|
|
||||||
|
katze_object_assign (extension->priv->app, NULL);
|
||||||
|
katze_assign (extension->priv->name, NULL);
|
||||||
|
katze_assign (extension->priv->description, NULL);
|
||||||
|
katze_assign (extension->priv->version, NULL);
|
||||||
|
katze_assign (extension->priv->authors, NULL);
|
||||||
|
|
||||||
|
katze_assign (extension->priv->config_dir, NULL);
|
||||||
|
g_list_free (extension->priv->lsettings);
|
||||||
|
g_hash_table_destroy (extension->priv->settings);
|
||||||
|
if (extension->priv->key_file)
|
||||||
|
g_key_file_free (extension->priv->key_file);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_extension_set_property (GObject* object,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue* value,
|
||||||
|
GParamSpec* pspec)
|
||||||
|
{
|
||||||
|
MidoriExtension* extension = MIDORI_EXTENSION (object);
|
||||||
|
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_NAME:
|
||||||
|
katze_assign (extension->priv->name, g_value_dup_string (value));
|
||||||
|
break;
|
||||||
|
case PROP_DESCRIPTION:
|
||||||
|
katze_assign (extension->priv->description, g_value_dup_string (value));
|
||||||
|
break;
|
||||||
|
case PROP_VERSION:
|
||||||
|
katze_assign (extension->priv->version, g_value_dup_string (value));
|
||||||
|
break;
|
||||||
|
case PROP_AUTHORS:
|
||||||
|
katze_assign (extension->priv->authors, g_value_dup_string (value));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_extension_get_property (GObject* object,
|
||||||
|
guint prop_id,
|
||||||
|
GValue* value,
|
||||||
|
GParamSpec* pspec)
|
||||||
|
{
|
||||||
|
MidoriExtension* extension = MIDORI_EXTENSION (object);
|
||||||
|
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_NAME:
|
||||||
|
g_value_set_string (value, extension->priv->name);
|
||||||
|
break;
|
||||||
|
case PROP_DESCRIPTION:
|
||||||
|
g_value_set_string (value, extension->priv->description);
|
||||||
|
break;
|
||||||
|
case PROP_VERSION:
|
||||||
|
g_value_set_string (value, extension->priv->version);
|
||||||
|
break;
|
||||||
|
case PROP_AUTHORS:
|
||||||
|
g_value_set_string (value, extension->priv->authors);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* midori_extension_is_prepared:
|
||||||
|
* @extension: a #MidoriExtension
|
||||||
|
*
|
||||||
|
* Determines if @extension is prepared for use, for instance
|
||||||
|
* by ensuring that all required values are set and that it
|
||||||
|
* is actually activatable.
|
||||||
|
*
|
||||||
|
* Return value: %TRUE if @extension is ready for use
|
||||||
|
**/
|
||||||
|
gboolean
|
||||||
|
midori_extension_is_prepared (MidoriExtension* extension)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (MIDORI_IS_EXTENSION (extension), FALSE);
|
||||||
|
|
||||||
|
if (extension->priv->name && extension->priv->description
|
||||||
|
&& extension->priv->version && extension->priv->authors
|
||||||
|
&& g_signal_has_handler_pending (extension, signals[ACTIVATE], 0, FALSE))
|
||||||
|
return TRUE;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* midori_extension_is_active:
|
||||||
|
* @extension: a #MidoriExtension
|
||||||
|
*
|
||||||
|
* Determines if @extension is active.
|
||||||
|
*
|
||||||
|
* Return value: %TRUE if @extension is active
|
||||||
|
*
|
||||||
|
* Since: 0.1.2
|
||||||
|
**/
|
||||||
|
gboolean
|
||||||
|
midori_extension_is_active (MidoriExtension* extension)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (MIDORI_IS_EXTENSION (extension), FALSE);
|
||||||
|
|
||||||
|
return extension->priv->active;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* midori_extension_deactivate:
|
||||||
|
* @extension: a #MidoriExtension
|
||||||
|
*
|
||||||
|
* Attempts to deactivate @extension.
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
midori_extension_deactivate (MidoriExtension* extension)
|
||||||
|
{
|
||||||
|
g_return_if_fail (midori_extension_is_active (extension));
|
||||||
|
|
||||||
|
g_signal_emit (extension, signals[DEACTIVATE], 0);
|
||||||
|
extension->priv->active = FALSE;
|
||||||
|
katze_object_assign (extension->priv->app, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* midori_extension_get_app:
|
||||||
|
* @extension: a #MidoriExtension
|
||||||
|
*
|
||||||
|
* Retrieves the #MidoriApp the extension belongs to. The
|
||||||
|
* extension has to be active.
|
||||||
|
*
|
||||||
|
* Return value: the #MidoriApp instance
|
||||||
|
*
|
||||||
|
* Since 0.1.6
|
||||||
|
**/
|
||||||
|
MidoriApp*
|
||||||
|
midori_extension_get_app (MidoriExtension* extension)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (midori_extension_is_active (extension), NULL);
|
||||||
|
|
||||||
|
return extension->priv->app;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* midori_extension_get_config_dir:
|
||||||
|
* @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.
|
||||||
|
*
|
||||||
|
* If settings are installed on the extension, they will be
|
||||||
|
* loaded from and saved to a file "config" in this path.
|
||||||
|
*
|
||||||
|
* Return value: a path, such as ~/.config/midori/extensions/name
|
||||||
|
**/
|
||||||
|
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)
|
||||||
|
extension->priv->config_dir = g_build_filename (
|
||||||
|
sokoke_set_config_dir (NULL), "extensions",
|
||||||
|
extension->priv->name, NULL);
|
||||||
|
|
||||||
|
return extension->priv->config_dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* midori_extension_install_boolean:
|
||||||
|
* @extension: a #MidoriExtension
|
||||||
|
* @name: the name of the setting
|
||||||
|
* @default_value: the default value
|
||||||
|
*
|
||||||
|
* Installs a boolean 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.3
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
midori_extension_install_boolean (MidoriExtension* extension,
|
||||||
|
const gchar* name,
|
||||||
|
gboolean default_value)
|
||||||
|
{
|
||||||
|
MESettingBoolean* setting;
|
||||||
|
|
||||||
|
g_return_if_fail (midori_extension_is_prepared (extension));
|
||||||
|
midori_extension_can_install_setting (extension, name);
|
||||||
|
|
||||||
|
me_setting_install (MESettingBoolean, g_strdup (name), G_TYPE_BOOLEAN,
|
||||||
|
default_value, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* midori_extension_get_boolean:
|
||||||
|
* @extension: a #MidoriExtension
|
||||||
|
* @name: the name of the setting
|
||||||
|
*
|
||||||
|
* Retrieves the value of the specified setting.
|
||||||
|
*
|
||||||
|
* Since: 0.1.3
|
||||||
|
**/
|
||||||
|
gboolean
|
||||||
|
midori_extension_get_boolean (MidoriExtension* extension,
|
||||||
|
const gchar* name)
|
||||||
|
{
|
||||||
|
MESettingBoolean* setting;
|
||||||
|
|
||||||
|
g_return_val_if_fail (midori_extension_is_prepared (extension), FALSE);
|
||||||
|
g_return_val_if_fail (name != NULL, FALSE);
|
||||||
|
|
||||||
|
setting = g_hash_table_lookup (extension->priv->settings, name);
|
||||||
|
|
||||||
|
me_setting_type (setting, G_TYPE_BOOLEAN, return FALSE);
|
||||||
|
|
||||||
|
return setting->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* midori_extension_set_boolean:
|
||||||
|
* @extension: a #MidoriExtension
|
||||||
|
* @name: the name of the setting
|
||||||
|
* @value: the new value
|
||||||
|
*
|
||||||
|
* Assigns a new value to the specified setting.
|
||||||
|
*
|
||||||
|
* Since: 0.1.3
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
midori_extension_set_boolean (MidoriExtension* extension,
|
||||||
|
const gchar* name,
|
||||||
|
gboolean value)
|
||||||
|
{
|
||||||
|
MESettingBoolean* 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_BOOLEAN, return);
|
||||||
|
|
||||||
|
setting->value = value;
|
||||||
|
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_boolean (extension->priv->key_file,
|
||||||
|
"settings", name, value);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* midori_extension_install_integer:
|
||||||
|
* @extension: a #MidoriExtension
|
||||||
|
* @name: the name of the setting
|
||||||
|
* @default_value: the default value
|
||||||
|
*
|
||||||
|
* Installs an integer 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.3
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
midori_extension_install_integer (MidoriExtension* extension,
|
||||||
|
const gchar* name,
|
||||||
|
gint default_value)
|
||||||
|
{
|
||||||
|
MESettingInteger* setting;
|
||||||
|
|
||||||
|
g_return_if_fail (midori_extension_is_prepared (extension));
|
||||||
|
midori_extension_can_install_setting (extension, name);
|
||||||
|
|
||||||
|
me_setting_install (MESettingInteger, g_strdup (name), G_TYPE_INT,
|
||||||
|
default_value, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* midori_extension_get_integer:
|
||||||
|
* @extension: a #MidoriExtension
|
||||||
|
* @name: the name of the setting
|
||||||
|
*
|
||||||
|
* Retrieves the value of the specified setting.
|
||||||
|
*
|
||||||
|
* Since: 0.1.3
|
||||||
|
**/
|
||||||
|
gint
|
||||||
|
midori_extension_get_integer (MidoriExtension* extension,
|
||||||
|
const gchar* name)
|
||||||
|
{
|
||||||
|
MESettingInteger* setting;
|
||||||
|
|
||||||
|
g_return_val_if_fail (midori_extension_is_prepared (extension), 0);
|
||||||
|
g_return_val_if_fail (name != NULL, 0);
|
||||||
|
|
||||||
|
setting = g_hash_table_lookup (extension->priv->settings, name);
|
||||||
|
|
||||||
|
me_setting_type (setting, G_TYPE_INT, return 0);
|
||||||
|
|
||||||
|
return setting->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* midori_extension_set_integer:
|
||||||
|
* @extension: a #MidoriExtension
|
||||||
|
* @name: the name of the setting
|
||||||
|
* @value: the new value
|
||||||
|
*
|
||||||
|
* Assigns a new value to the specified setting.
|
||||||
|
*
|
||||||
|
* Since: 0.1.3
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
midori_extension_set_integer (MidoriExtension* extension,
|
||||||
|
const gchar* name,
|
||||||
|
gint value)
|
||||||
|
{
|
||||||
|
MESettingInteger* 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_INT, return);
|
||||||
|
|
||||||
|
setting->value = value;
|
||||||
|
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_integer (extension->priv->key_file,
|
||||||
|
"settings", name, value);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* midori_extension_install_string:
|
||||||
|
* @extension: a #MidoriExtension
|
||||||
|
* @name: the name of the setting
|
||||||
|
* @default_value: the default value
|
||||||
|
*
|
||||||
|
* Installs a string 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.3
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
midori_extension_install_string (MidoriExtension* extension,
|
||||||
|
const gchar* name,
|
||||||
|
const gchar* default_value)
|
||||||
|
{
|
||||||
|
MESettingString* setting;
|
||||||
|
|
||||||
|
g_return_if_fail (midori_extension_is_prepared (extension));
|
||||||
|
midori_extension_can_install_setting (extension, name);
|
||||||
|
|
||||||
|
me_setting_install (MESettingString, g_strdup (name), G_TYPE_STRING,
|
||||||
|
g_strdup (default_value), NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* midori_extension_get_string:
|
||||||
|
* @extension: a #MidoriExtension
|
||||||
|
* @name: the name of the setting
|
||||||
|
*
|
||||||
|
* Retrieves the value of the specified setting.
|
||||||
|
*
|
||||||
|
* Since: 0.1.3
|
||||||
|
**/
|
||||||
|
const gchar*
|
||||||
|
midori_extension_get_string (MidoriExtension* extension,
|
||||||
|
const gchar* name)
|
||||||
|
{
|
||||||
|
MESettingString* 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_STRING, return NULL);
|
||||||
|
|
||||||
|
return setting->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* midori_extension_set_string:
|
||||||
|
* @extension: a #MidoriExtension
|
||||||
|
* @name: the name of the setting
|
||||||
|
* @value: the new value
|
||||||
|
*
|
||||||
|
* Assigns a new value to the specified setting.
|
||||||
|
*
|
||||||
|
* Since: 0.1.3
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
midori_extension_set_string (MidoriExtension* extension,
|
||||||
|
const gchar* name,
|
||||||
|
const gchar* value)
|
||||||
|
{
|
||||||
|
MESettingString* 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_STRING, return);
|
||||||
|
|
||||||
|
katze_assign (setting->value, g_strdup (value));
|
||||||
|
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 (extension->priv->key_file,
|
||||||
|
"settings", name, value);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
110
midori/midori-extension.h
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2008 Christian Dywan <christian@twotoasts.de>
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
See the file COPYING for the full license text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __MIDORI_EXTENSION_H__
|
||||||
|
#define __MIDORI_EXTENSION_H__
|
||||||
|
|
||||||
|
#include "midori-app.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define MIDORI_TYPE_EXTENSION \
|
||||||
|
(midori_extension_get_type ())
|
||||||
|
#define MIDORI_EXTENSION(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_CAST ((obj), MIDORI_TYPE_EXTENSION, MidoriExtension))
|
||||||
|
#define MIDORI_EXTENSION_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_CAST ((klass), MIDORI_TYPE_EXTENSION, MidoriExtensionClass))
|
||||||
|
#define MIDORI_IS_EXTENSION(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), MIDORI_TYPE_EXTENSION))
|
||||||
|
#define MIDORI_IS_EXTENSION_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_TYPE ((klass), MIDORI_TYPE_EXTENSION))
|
||||||
|
#define MIDORI_EXTENSION_GET_CLASS(obj) \
|
||||||
|
(G_TYPE_INSTANCE_GET_CLASS ((obj), MIDORI_TYPE_EXTENSION, MidoriExtensionClass))
|
||||||
|
|
||||||
|
typedef struct _MidoriExtension MidoriExtension;
|
||||||
|
typedef struct _MidoriExtensionClass MidoriExtensionClass;
|
||||||
|
typedef struct _MidoriExtensionPrivate MidoriExtensionPrivate;
|
||||||
|
|
||||||
|
struct _MidoriExtension
|
||||||
|
{
|
||||||
|
GObject parent_instance;
|
||||||
|
|
||||||
|
MidoriExtensionPrivate* priv;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _MidoriExtensionClass
|
||||||
|
{
|
||||||
|
GObjectClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
GType
|
||||||
|
midori_extension_get_type (void);
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
midori_extension_is_prepared (MidoriExtension* extension);
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
midori_extension_is_active (MidoriExtension* extension);
|
||||||
|
|
||||||
|
void
|
||||||
|
midori_extension_deactivate (MidoriExtension* extension);
|
||||||
|
|
||||||
|
MidoriApp*
|
||||||
|
midori_extension_get_app (MidoriExtension* extension);
|
||||||
|
|
||||||
|
const gchar*
|
||||||
|
midori_extension_get_config_dir (MidoriExtension* extension);
|
||||||
|
|
||||||
|
void
|
||||||
|
midori_extension_install_boolean (MidoriExtension* extension,
|
||||||
|
const gchar* name,
|
||||||
|
gboolean default_value);
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
midori_extension_get_boolean (MidoriExtension* extension,
|
||||||
|
const gchar* name);
|
||||||
|
|
||||||
|
void
|
||||||
|
midori_extension_set_boolean (MidoriExtension* extension,
|
||||||
|
const gchar* name,
|
||||||
|
gboolean value);
|
||||||
|
|
||||||
|
void
|
||||||
|
midori_extension_install_integer (MidoriExtension* extension,
|
||||||
|
const gchar* name,
|
||||||
|
gint default_value);
|
||||||
|
|
||||||
|
gint
|
||||||
|
midori_extension_get_integer (MidoriExtension* extension,
|
||||||
|
const gchar* name);
|
||||||
|
|
||||||
|
void
|
||||||
|
midori_extension_set_integer (MidoriExtension* extension,
|
||||||
|
const gchar* name,
|
||||||
|
gint value);
|
||||||
|
|
||||||
|
void
|
||||||
|
midori_extension_install_string (MidoriExtension* extension,
|
||||||
|
const gchar* name,
|
||||||
|
const gchar* default_value);
|
||||||
|
|
||||||
|
const gchar*
|
||||||
|
midori_extension_get_string (MidoriExtension* extension,
|
||||||
|
const gchar* name);
|
||||||
|
|
||||||
|
void
|
||||||
|
midori_extension_set_string (MidoriExtension* extension,
|
||||||
|
const gchar* name,
|
||||||
|
const gchar* value);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __MIDORI_EXTENSION_H__ */
|
1363
midori/midori-locationaction.c
Normal file
108
midori/midori-locationaction.h
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2008 Christian Dywan <christian@twotoasts.de>
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
See the file COPYING for the full license text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __MIDORI_LOCATION_ACTION_H__
|
||||||
|
#define __MIDORI_LOCATION_ACTION_H__
|
||||||
|
|
||||||
|
#include "midori-locationentry.h"
|
||||||
|
|
||||||
|
#include <katze/katze.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define MIDORI_TYPE_LOCATION_ACTION \
|
||||||
|
(midori_location_action_get_type ())
|
||||||
|
#define MIDORI_LOCATION_ACTION(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_CAST ((obj), MIDORI_TYPE_LOCATION_ACTION, MidoriLocationAction))
|
||||||
|
#define MIDORI_LOCATION_ACTION_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_CAST ((klass), MIDORI_TYPE_LOCATION_ACTION, MidoriLocationActionClass))
|
||||||
|
#define MIDORI_IS_LOCATION_ACTION(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), MIDORI_TYPE_LOCATION_ACTION))
|
||||||
|
#define MIDORI_IS_LOCATION_ACTION_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_TYPE ((klass), MIDORI_TYPE_LOCATION_ACTION))
|
||||||
|
#define MIDORI_LOCATION_ACTION_GET_CLASS(obj) \
|
||||||
|
(G_TYPE_INSTANCE_GET_CLASS ((obj), MIDORI_TYPE_LOCATION_ACTION, MidoriLocationActionClass))
|
||||||
|
|
||||||
|
typedef struct _MidoriLocationAction MidoriLocationAction;
|
||||||
|
typedef struct _MidoriLocationActionClass MidoriLocationActionClass;
|
||||||
|
|
||||||
|
struct _MidoriLocationEntryItem
|
||||||
|
{
|
||||||
|
GdkPixbuf* favicon;
|
||||||
|
const gchar* uri;
|
||||||
|
const gchar* title;
|
||||||
|
};
|
||||||
|
|
||||||
|
GType
|
||||||
|
midori_location_action_get_type (void);
|
||||||
|
|
||||||
|
void
|
||||||
|
midori_location_action_freeze (MidoriLocationAction* location_action);
|
||||||
|
|
||||||
|
void
|
||||||
|
midori_location_action_thaw (MidoriLocationAction* location_action);
|
||||||
|
|
||||||
|
const gchar*
|
||||||
|
midori_location_action_get_uri (MidoriLocationAction* location_action);
|
||||||
|
|
||||||
|
void
|
||||||
|
midori_location_action_set_uri (MidoriLocationAction* location_action,
|
||||||
|
const gchar* uri);
|
||||||
|
|
||||||
|
void
|
||||||
|
midori_location_action_set_icon (MidoriLocationAction* location_action,
|
||||||
|
GdkPixbuf* icon);
|
||||||
|
|
||||||
|
void
|
||||||
|
midori_location_action_add_uri (MidoriLocationAction* location_action,
|
||||||
|
const gchar* uri);
|
||||||
|
|
||||||
|
void
|
||||||
|
midori_location_action_add_item (MidoriLocationAction* location_action,
|
||||||
|
const gchar* uri,
|
||||||
|
GdkPixbuf* icon,
|
||||||
|
const gchar* title);
|
||||||
|
|
||||||
|
void
|
||||||
|
midori_location_action_set_icon_for_uri (MidoriLocationAction* location_action,
|
||||||
|
GdkPixbuf* icon,
|
||||||
|
const gchar* text);
|
||||||
|
|
||||||
|
void
|
||||||
|
midori_location_action_set_title_for_uri (MidoriLocationAction* location_action,
|
||||||
|
const gchar* title,
|
||||||
|
const gchar* text);
|
||||||
|
|
||||||
|
void
|
||||||
|
midori_location_action_set_search_engines (MidoriLocationAction* location_action,
|
||||||
|
KatzeArray* search_engines);
|
||||||
|
|
||||||
|
gdouble
|
||||||
|
midori_location_action_get_progress (MidoriLocationAction* location_action);
|
||||||
|
|
||||||
|
void
|
||||||
|
midori_location_action_set_progress (MidoriLocationAction* location_action,
|
||||||
|
gdouble progress);
|
||||||
|
|
||||||
|
void
|
||||||
|
midori_location_action_set_secondary_icon (MidoriLocationAction* location_action,
|
||||||
|
const gchar* stock_id);
|
||||||
|
|
||||||
|
void
|
||||||
|
midori_location_action_delete_item_from_uri (MidoriLocationAction* location_action,
|
||||||
|
const gchar* uri);
|
||||||
|
|
||||||
|
void
|
||||||
|
midori_location_action_clear (MidoriLocationAction* location_action);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __MIDORI_LOCATION_ACTION_H__ */
|
436
midori/midori-locationentry.c
Normal file
|
@ -0,0 +1,436 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2008 Dale Whittaker <dayul@users.sf.net>
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
See the file COPYING for the full license text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "midori-locationentry.h"
|
||||||
|
|
||||||
|
#include "gtkiconentry.h"
|
||||||
|
#include "sokoke.h"
|
||||||
|
#include <gdk/gdkkeysyms.h>
|
||||||
|
|
||||||
|
struct _MidoriLocationEntry
|
||||||
|
{
|
||||||
|
GtkComboBoxEntry parent_instance;
|
||||||
|
|
||||||
|
gdouble progress;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _MidoriLocationEntryClass
|
||||||
|
{
|
||||||
|
GtkComboBoxEntryClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (MidoriLocationEntry,
|
||||||
|
midori_location_entry, GTK_TYPE_COMBO_BOX_ENTRY)
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
FAVICON_COL,
|
||||||
|
URI_COL,
|
||||||
|
TITLE_COL,
|
||||||
|
VISITS_COL,
|
||||||
|
VISIBLE_COL,
|
||||||
|
N_COLS
|
||||||
|
};
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
entry_key_press_event (GtkWidget* widget,
|
||||||
|
GdkEventKey* event,
|
||||||
|
MidoriLocationEntry* location_entry);
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_location_entry_class_init (MidoriLocationEntryClass* class)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !GTK_CHECK_VERSION (2, 16, 0)
|
||||||
|
|
||||||
|
/* GTK+/ GtkEntry internal helper function
|
||||||
|
Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||||
|
Modified by the GTK+ Team and others 1997-2000
|
||||||
|
Copied from Gtk+ 2.13, whitespace adjusted */
|
||||||
|
static void
|
||||||
|
gtk_entry_get_pixel_ranges (GtkEntry *entry,
|
||||||
|
gint **ranges,
|
||||||
|
gint *n_ranges)
|
||||||
|
{
|
||||||
|
gint start_char, end_char;
|
||||||
|
|
||||||
|
if (gtk_editable_get_selection_bounds (GTK_EDITABLE (entry),
|
||||||
|
&start_char, &end_char))
|
||||||
|
{
|
||||||
|
PangoLayout *layout = gtk_entry_get_layout (entry);
|
||||||
|
PangoLayoutLine *line = pango_layout_get_lines (layout)->data;
|
||||||
|
const char *text = pango_layout_get_text (layout);
|
||||||
|
gsize start_index = g_utf8_offset_to_pointer (text, start_char) - text;
|
||||||
|
gsize end_index = g_utf8_offset_to_pointer (text, end_char) - text;
|
||||||
|
gint real_n_ranges, i;
|
||||||
|
|
||||||
|
pango_layout_line_get_x_ranges (line,
|
||||||
|
start_index, end_index, ranges, &real_n_ranges);
|
||||||
|
|
||||||
|
if (ranges)
|
||||||
|
{
|
||||||
|
gint *r = *ranges;
|
||||||
|
|
||||||
|
for (i = 0; i < real_n_ranges; ++i)
|
||||||
|
{
|
||||||
|
r[2 * i + 1] = (r[2 * i + 1] - r[2 * i]) / PANGO_SCALE;
|
||||||
|
r[2 * i] = r[2 * i] / PANGO_SCALE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n_ranges)
|
||||||
|
*n_ranges = real_n_ranges;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (n_ranges)
|
||||||
|
*n_ranges = 0;
|
||||||
|
if (ranges)
|
||||||
|
*ranges = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* GTK+/ GtkEntry internal helper function
|
||||||
|
Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||||
|
Modified by the GTK+ Team and others 1997-2000
|
||||||
|
Copied from Gtk+ 2.13, whitespace adjusted
|
||||||
|
Code adjusted to not rely on internal qdata */
|
||||||
|
static void
|
||||||
|
_gtk_entry_effective_inner_border (GtkEntry *entry,
|
||||||
|
GtkBorder *border)
|
||||||
|
{
|
||||||
|
static const GtkBorder default_inner_border = { 2, 2, 2, 2 };
|
||||||
|
GtkBorder *tmp_border;
|
||||||
|
|
||||||
|
tmp_border = (GtkBorder*) gtk_entry_get_inner_border (entry);
|
||||||
|
|
||||||
|
if (tmp_border)
|
||||||
|
{
|
||||||
|
*border = *tmp_border;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
gtk_widget_style_get (GTK_WIDGET (entry), "inner-border", &tmp_border, NULL);
|
||||||
|
|
||||||
|
if (tmp_border)
|
||||||
|
{
|
||||||
|
*border = *tmp_border;
|
||||||
|
gtk_border_free (tmp_border);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
*border = default_inner_border;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_entry_borders (GtkEntry* entry,
|
||||||
|
gint* xborder,
|
||||||
|
gint* yborder,
|
||||||
|
gboolean* interior_focus,
|
||||||
|
gint* focus_width)
|
||||||
|
{
|
||||||
|
GtkWidget *widget = GTK_WIDGET (entry);
|
||||||
|
|
||||||
|
if (entry->has_frame)
|
||||||
|
{
|
||||||
|
*xborder = widget->style->xthickness;
|
||||||
|
*yborder = widget->style->ythickness;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*xborder = 0;
|
||||||
|
*yborder = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
gtk_widget_style_get (widget, "interior-focus", interior_focus,
|
||||||
|
"focus-line-width", focus_width, NULL);
|
||||||
|
|
||||||
|
if (interior_focus)
|
||||||
|
{
|
||||||
|
*xborder += *focus_width;
|
||||||
|
*yborder += *focus_width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* GTK+/ GtkEntry internal helper function
|
||||||
|
Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||||
|
Modified by the GTK+ Team and others 1997-2000
|
||||||
|
Copied from Gtk+ 2.13, whitespace adjusted */
|
||||||
|
static void
|
||||||
|
gtk_entry_get_text_area_size (GtkEntry *entry,
|
||||||
|
gint *x,
|
||||||
|
gint *y,
|
||||||
|
gint *width,
|
||||||
|
gint *height)
|
||||||
|
{
|
||||||
|
gint frame_height;
|
||||||
|
gint xborder, yborder;
|
||||||
|
gboolean interior_focus;
|
||||||
|
gint focus_width;
|
||||||
|
GtkRequisition requisition;
|
||||||
|
GtkWidget *widget = GTK_WIDGET (entry);
|
||||||
|
|
||||||
|
gtk_widget_get_child_requisition (widget, &requisition);
|
||||||
|
gtk_entry_borders (entry, &xborder, &yborder, &interior_focus, &focus_width);
|
||||||
|
|
||||||
|
if (GTK_WIDGET_REALIZED (widget))
|
||||||
|
gdk_drawable_get_size (widget->window, NULL, &frame_height);
|
||||||
|
else
|
||||||
|
frame_height = requisition.height;
|
||||||
|
|
||||||
|
if (GTK_WIDGET_HAS_FOCUS (widget) && interior_focus)
|
||||||
|
frame_height -= 2 * focus_width;
|
||||||
|
|
||||||
|
if (x)
|
||||||
|
*x = xborder;
|
||||||
|
|
||||||
|
if (y)
|
||||||
|
*y = frame_height / 2 - (requisition.height - yborder * 2) / 2;
|
||||||
|
|
||||||
|
if (width)
|
||||||
|
*width = GTK_WIDGET (entry)->allocation.width - xborder * 2;
|
||||||
|
|
||||||
|
if (height)
|
||||||
|
*height = requisition.height - yborder * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* GTK+/ GtkEntry internal helper function
|
||||||
|
Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||||
|
Modified by the GTK+ Team and others 1997-2000
|
||||||
|
Copied from Gtk+ 2.13, whitespace adjusted */
|
||||||
|
static void
|
||||||
|
get_layout_position (GtkEntry *entry,
|
||||||
|
gint *x,
|
||||||
|
gint *y)
|
||||||
|
{
|
||||||
|
PangoLayout *layout;
|
||||||
|
PangoRectangle logical_rect;
|
||||||
|
gint area_width, area_height;
|
||||||
|
GtkBorder inner_border;
|
||||||
|
gint y_pos;
|
||||||
|
PangoLayoutLine *line;
|
||||||
|
|
||||||
|
layout = gtk_entry_get_layout (entry);
|
||||||
|
|
||||||
|
gtk_entry_get_text_area_size (entry, NULL, NULL, &area_width, &area_height);
|
||||||
|
_gtk_entry_effective_inner_border (entry, &inner_border);
|
||||||
|
|
||||||
|
area_height = PANGO_SCALE *
|
||||||
|
(area_height - inner_border.top - inner_border.bottom);
|
||||||
|
|
||||||
|
line = pango_layout_get_lines (layout)->data;
|
||||||
|
pango_layout_line_get_extents (line, NULL, &logical_rect);
|
||||||
|
|
||||||
|
/* Align primarily for locale's ascent/descent */
|
||||||
|
y_pos = ((area_height - entry->ascent - entry->descent) / 2 +
|
||||||
|
entry->ascent + logical_rect.y);
|
||||||
|
|
||||||
|
/* Now see if we need to adjust to fit in actual drawn string */
|
||||||
|
if (logical_rect.height > area_height)
|
||||||
|
y_pos = (area_height - logical_rect.height) / 2;
|
||||||
|
else if (y_pos < 0)
|
||||||
|
y_pos = 0;
|
||||||
|
else if (y_pos + logical_rect.height > area_height)
|
||||||
|
y_pos = area_height - logical_rect.height;
|
||||||
|
|
||||||
|
y_pos = inner_border.top + y_pos / PANGO_SCALE;
|
||||||
|
|
||||||
|
if (x)
|
||||||
|
*x = inner_border.left - entry->scroll_offset;
|
||||||
|
|
||||||
|
if (y)
|
||||||
|
*y = y_pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* GTK+/ GtkEntry internal helper function
|
||||||
|
Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||||
|
Modified by the GTK+ Team and others 1997-2000
|
||||||
|
Copied from Gtk+ 2.13, whitespace adjusted
|
||||||
|
Code adjusted to not rely on internal _gtk_entry_ensure_layout */
|
||||||
|
static void
|
||||||
|
gtk_entry_draw_text (GtkEntry *entry)
|
||||||
|
{
|
||||||
|
GtkWidget *widget;
|
||||||
|
|
||||||
|
if (!entry->visible && entry->invisible_char == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (GTK_WIDGET_DRAWABLE (entry))
|
||||||
|
{
|
||||||
|
PangoLayout *layout = gtk_entry_get_layout (entry);
|
||||||
|
cairo_t *cr;
|
||||||
|
gint x, y;
|
||||||
|
gint start_pos, end_pos;
|
||||||
|
|
||||||
|
widget = GTK_WIDGET (entry);
|
||||||
|
|
||||||
|
get_layout_position (entry, &x, &y);
|
||||||
|
|
||||||
|
cr = gdk_cairo_create (entry->text_area);
|
||||||
|
|
||||||
|
cairo_move_to (cr, x, y);
|
||||||
|
gdk_cairo_set_source_color (cr, &widget->style->text [widget->state]);
|
||||||
|
pango_cairo_show_layout (cr, layout);
|
||||||
|
|
||||||
|
if (gtk_editable_get_selection_bounds (GTK_EDITABLE (entry),
|
||||||
|
&start_pos, &end_pos))
|
||||||
|
{
|
||||||
|
gint *ranges;
|
||||||
|
gint n_ranges, i;
|
||||||
|
PangoRectangle logical_rect;
|
||||||
|
GdkColor *selection_color, *text_color;
|
||||||
|
GtkBorder inner_border;
|
||||||
|
|
||||||
|
pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
|
||||||
|
gtk_entry_get_pixel_ranges (entry, &ranges, &n_ranges);
|
||||||
|
|
||||||
|
if (GTK_WIDGET_HAS_FOCUS (entry))
|
||||||
|
{
|
||||||
|
selection_color = &widget->style->base [GTK_STATE_SELECTED];
|
||||||
|
text_color = &widget->style->text [GTK_STATE_SELECTED];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
selection_color = &widget->style->base [GTK_STATE_ACTIVE];
|
||||||
|
text_color = &widget->style->text [GTK_STATE_ACTIVE];
|
||||||
|
}
|
||||||
|
|
||||||
|
_gtk_entry_effective_inner_border (entry, &inner_border);
|
||||||
|
|
||||||
|
for (i = 0; i < n_ranges; ++i)
|
||||||
|
cairo_rectangle (cr,
|
||||||
|
inner_border.left -
|
||||||
|
entry->scroll_offset + ranges[2 * i],
|
||||||
|
y,
|
||||||
|
ranges[2 * i + 1],
|
||||||
|
logical_rect.height);
|
||||||
|
|
||||||
|
cairo_clip (cr);
|
||||||
|
|
||||||
|
gdk_cairo_set_source_color (cr, selection_color);
|
||||||
|
cairo_paint (cr);
|
||||||
|
|
||||||
|
cairo_move_to (cr, x, y);
|
||||||
|
gdk_cairo_set_source_color (cr, text_color);
|
||||||
|
pango_cairo_show_layout (cr, layout);
|
||||||
|
|
||||||
|
g_free (ranges);
|
||||||
|
}
|
||||||
|
|
||||||
|
cairo_destroy (cr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
entry_expose_event (GtkWidget* entry,
|
||||||
|
GdkEventExpose* event,
|
||||||
|
MidoriLocationEntry* location_entry)
|
||||||
|
{
|
||||||
|
GdkWindow* text_area;
|
||||||
|
gint width, height;
|
||||||
|
|
||||||
|
text_area = GTK_ENTRY (entry)->text_area;
|
||||||
|
|
||||||
|
gdk_drawable_get_size (text_area, &width, &height);
|
||||||
|
|
||||||
|
if (location_entry->progress > 0.0)
|
||||||
|
{
|
||||||
|
gtk_paint_box (entry->style, text_area,
|
||||||
|
GTK_STATE_SELECTED, GTK_SHADOW_OUT,
|
||||||
|
&event->area, entry, "bar",
|
||||||
|
0, 0, location_entry->progress * width, height);
|
||||||
|
gtk_entry_draw_text (GTK_ENTRY (entry));
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void
|
||||||
|
midori_location_entry_set_progress (MidoriLocationEntry* location_entry,
|
||||||
|
gdouble progress)
|
||||||
|
{
|
||||||
|
GtkWidget* child;
|
||||||
|
|
||||||
|
g_return_if_fail (MIDORI_IS_LOCATION_ENTRY (location_entry));
|
||||||
|
|
||||||
|
location_entry->progress = CLAMP (progress, 0.0, 1.0);
|
||||||
|
|
||||||
|
child = gtk_bin_get_child (GTK_BIN (location_entry));
|
||||||
|
#if !GTK_CHECK_VERSION (2, 16, 0)
|
||||||
|
if (GTK_ENTRY (child)->text_area)
|
||||||
|
gdk_window_invalidate_rect (GTK_ENTRY (child)->text_area, NULL, FALSE);
|
||||||
|
#else
|
||||||
|
gtk_entry_set_progress_fraction (GTK_ENTRY (child), progress);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_location_entry_init (MidoriLocationEntry* location_entry)
|
||||||
|
{
|
||||||
|
GtkWidget* entry;
|
||||||
|
|
||||||
|
/* We want the widget to have appears-as-list applied */
|
||||||
|
gtk_rc_parse_string ("style \"midori-location-entry-style\" {\n"
|
||||||
|
" GtkComboBox::appears-as-list = 1\n }\n"
|
||||||
|
"widget_class \"*MidoriLocationEntry\" "
|
||||||
|
"style \"midori-location-entry-style\"\n");
|
||||||
|
|
||||||
|
location_entry->progress = 0.0;
|
||||||
|
|
||||||
|
entry = gtk_icon_entry_new ();
|
||||||
|
gtk_icon_entry_set_icon_from_stock (GTK_ICON_ENTRY (entry),
|
||||||
|
GTK_ICON_ENTRY_PRIMARY, GTK_STOCK_FILE);
|
||||||
|
gtk_icon_entry_set_icon_highlight (GTK_ICON_ENTRY (entry),
|
||||||
|
GTK_ICON_ENTRY_SECONDARY, TRUE);
|
||||||
|
g_signal_connect_after (entry, "key-press-event",
|
||||||
|
G_CALLBACK (entry_key_press_event), location_entry);
|
||||||
|
#if !GTK_CHECK_VERSION (2, 16, 0)
|
||||||
|
g_signal_connect_after (entry, "expose-event",
|
||||||
|
G_CALLBACK (entry_expose_event), location_entry);
|
||||||
|
#endif
|
||||||
|
gtk_widget_show (entry);
|
||||||
|
gtk_container_add (GTK_CONTAINER (location_entry), entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
entry_key_press_event (GtkWidget* widget,
|
||||||
|
GdkEventKey* event,
|
||||||
|
MidoriLocationEntry* location_entry)
|
||||||
|
{
|
||||||
|
switch (event->keyval)
|
||||||
|
{
|
||||||
|
case GDK_Down:
|
||||||
|
case GDK_Up:
|
||||||
|
{
|
||||||
|
if (!katze_object_get_boolean (location_entry, "popup-shown"))
|
||||||
|
gtk_combo_box_popup (GTK_COMBO_BOX (location_entry));
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* midori_location_entry_new:
|
||||||
|
*
|
||||||
|
* Creates a new #MidoriLocationEntry.
|
||||||
|
*
|
||||||
|
* Return value: a new #MidoriLocationEntry
|
||||||
|
**/
|
||||||
|
GtkWidget*
|
||||||
|
midori_location_entry_new (void)
|
||||||
|
{
|
||||||
|
return g_object_new (MIDORI_TYPE_LOCATION_ENTRY, NULL);
|
||||||
|
}
|
42
midori/midori-locationentry.h
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2008 Dale Whittaker <dayul@users.sf.net>
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
See the file COPYING for the full license text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __MIDORI_LOCATION_ENTRY_H__
|
||||||
|
#define __MIDORI_LOCATION_ENTRY_H__
|
||||||
|
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define MIDORI_TYPE_LOCATION_ENTRY (midori_location_entry_get_type ())
|
||||||
|
#define MIDORI_LOCATION_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), MIDORI_TYPE_LOCATION_ENTRY, MidoriLocationEntry))
|
||||||
|
#define MIDORI_LOCATION_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), MIDORI_TYPE_LOCATION_ENTRY, MidoriLocationEntryClass))
|
||||||
|
#define MIDORI_IS_LOCATION_ENTRY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), MIDORI_TYPE_LOCATION_ENTRY))
|
||||||
|
#define MIDORI_IS_LOCATION_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), MIDORI_TYPE_LOCATION_ENTRY))
|
||||||
|
#define MIDORI_LOCATION_ENTRY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), MIDORI_TYPE_LOCATION_ENTRY, MidoriLocationEntryClass))
|
||||||
|
|
||||||
|
typedef struct _MidoriLocationEntry MidoriLocationEntry;
|
||||||
|
typedef struct _MidoriLocationEntryClass MidoriLocationEntryClass;
|
||||||
|
typedef struct _MidoriLocationEntryItem MidoriLocationEntryItem;
|
||||||
|
|
||||||
|
GType
|
||||||
|
midori_location_entry_get_type (void);
|
||||||
|
|
||||||
|
GtkWidget*
|
||||||
|
midori_location_entry_new (void);
|
||||||
|
|
||||||
|
void
|
||||||
|
midori_location_entry_set_progress (MidoriLocationEntry* location_entry,
|
||||||
|
gdouble progress);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __MIDORI_LOCATION_ENTRY_H__ */
|
943
midori/midori-panel.c
Normal file
|
@ -0,0 +1,943 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2007-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-panel.h"
|
||||||
|
|
||||||
|
#include "midori-view.h"
|
||||||
|
|
||||||
|
#include "compat.h"
|
||||||
|
#include "marshal.h"
|
||||||
|
#include "sokoke.h"
|
||||||
|
|
||||||
|
#include <glib/gi18n.h>
|
||||||
|
|
||||||
|
struct _MidoriPanel
|
||||||
|
{
|
||||||
|
GtkHBox parent_instance;
|
||||||
|
|
||||||
|
GtkWidget* toolbar;
|
||||||
|
GtkToolItem* button_align;
|
||||||
|
GtkWidget* toolbar_label;
|
||||||
|
GtkWidget* frame;
|
||||||
|
GtkWidget* toolbook;
|
||||||
|
GtkWidget* notebook;
|
||||||
|
GtkMenu* menu;
|
||||||
|
|
||||||
|
gboolean right_aligned;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _MidoriPanelClass
|
||||||
|
{
|
||||||
|
GtkHBoxClass parent_class;
|
||||||
|
|
||||||
|
/* Signals */
|
||||||
|
gboolean
|
||||||
|
(*close) (MidoriPanel* panel);
|
||||||
|
};
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (MidoriPanel, midori_panel, GTK_TYPE_HBOX)
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
PROP_0,
|
||||||
|
|
||||||
|
PROP_SHADOW_TYPE,
|
||||||
|
PROP_MENU,
|
||||||
|
PROP_PAGE,
|
||||||
|
PROP_RIGHT_ALIGNED,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
CLOSE,
|
||||||
|
SWITCH_PAGE,
|
||||||
|
|
||||||
|
LAST_SIGNAL
|
||||||
|
};
|
||||||
|
|
||||||
|
static guint signals[LAST_SIGNAL];
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_panel_finalize (GObject* object);
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_panel_set_property (GObject* object,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue* value,
|
||||||
|
GParamSpec* pspec);
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_panel_get_property (GObject* object,
|
||||||
|
guint prop_id,
|
||||||
|
GValue* value,
|
||||||
|
GParamSpec* pspec);
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
midori_panel_close (MidoriPanel* panel)
|
||||||
|
{
|
||||||
|
gtk_widget_hide (GTK_WIDGET (panel));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_panel_class_init (MidoriPanelClass* class)
|
||||||
|
{
|
||||||
|
GObjectClass* gobject_class;
|
||||||
|
GParamFlags flags;
|
||||||
|
|
||||||
|
signals[CLOSE] = g_signal_new (
|
||||||
|
"close",
|
||||||
|
G_TYPE_FROM_CLASS (class),
|
||||||
|
(GSignalFlags)(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
|
||||||
|
G_STRUCT_OFFSET (MidoriPanelClass, close),
|
||||||
|
g_signal_accumulator_true_handled,
|
||||||
|
NULL,
|
||||||
|
midori_cclosure_marshal_BOOLEAN__VOID,
|
||||||
|
G_TYPE_BOOLEAN, 0);
|
||||||
|
|
||||||
|
signals[SWITCH_PAGE] = g_signal_new (
|
||||||
|
"switch-page",
|
||||||
|
G_TYPE_FROM_CLASS (class),
|
||||||
|
(GSignalFlags)(G_SIGNAL_RUN_LAST),
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
g_cclosure_marshal_VOID__INT,
|
||||||
|
G_TYPE_NONE, 1,
|
||||||
|
G_TYPE_INT);
|
||||||
|
|
||||||
|
gobject_class = G_OBJECT_CLASS (class);
|
||||||
|
gobject_class->finalize = midori_panel_finalize;
|
||||||
|
gobject_class->set_property = midori_panel_set_property;
|
||||||
|
gobject_class->get_property = midori_panel_get_property;
|
||||||
|
|
||||||
|
class->close = midori_panel_close;
|
||||||
|
|
||||||
|
flags = G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS;
|
||||||
|
|
||||||
|
g_object_class_install_property (gobject_class,
|
||||||
|
PROP_SHADOW_TYPE,
|
||||||
|
g_param_spec_enum (
|
||||||
|
"shadow-type",
|
||||||
|
"Shadow Type",
|
||||||
|
"Appearance of the shadow around each panel",
|
||||||
|
GTK_TYPE_SHADOW_TYPE,
|
||||||
|
GTK_SHADOW_NONE,
|
||||||
|
flags));
|
||||||
|
|
||||||
|
g_object_class_install_property (gobject_class,
|
||||||
|
PROP_MENU,
|
||||||
|
g_param_spec_object (
|
||||||
|
"menu",
|
||||||
|
"Menu",
|
||||||
|
"Menu to hold panel items",
|
||||||
|
GTK_TYPE_MENU,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
|
g_object_class_install_property (gobject_class,
|
||||||
|
PROP_PAGE,
|
||||||
|
g_param_spec_int (
|
||||||
|
"page",
|
||||||
|
"Page",
|
||||||
|
"The index of the current page",
|
||||||
|
-1, G_MAXINT, -1,
|
||||||
|
flags));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MidoriWebSettings:right-aligned:
|
||||||
|
*
|
||||||
|
* Whether to align the panel on the right.
|
||||||
|
*
|
||||||
|
* Since: 0.1.3
|
||||||
|
*/
|
||||||
|
g_object_class_install_property (gobject_class,
|
||||||
|
PROP_RIGHT_ALIGNED,
|
||||||
|
g_param_spec_boolean (
|
||||||
|
"right-aligned",
|
||||||
|
"Right aligned",
|
||||||
|
"Whether the panel is aligned to the right",
|
||||||
|
FALSE,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_panel_button_close_clicked_cb (GtkWidget* toolitem,
|
||||||
|
MidoriPanel* panel)
|
||||||
|
{
|
||||||
|
gboolean return_value;
|
||||||
|
g_signal_emit (panel, signals[CLOSE], 0, &return_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GtkToolItem*
|
||||||
|
midori_panel_construct_tool_item (MidoriPanel* panel,
|
||||||
|
MidoriViewable* viewable);
|
||||||
|
|
||||||
|
static GtkWidget*
|
||||||
|
_midori_panel_child_for_scrolled (MidoriPanel* panel,
|
||||||
|
GtkWidget* scrolled);
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
midori_panel_detached_window_delete_event_cb (GtkWidget* window,
|
||||||
|
GdkEvent* event,
|
||||||
|
MidoriPanel* panel)
|
||||||
|
{
|
||||||
|
/* FIXME: The panel will not end up at its original position */
|
||||||
|
/* FIXME: The menuitem may be mispositioned */
|
||||||
|
GtkWidget* vbox = gtk_bin_get_child (GTK_BIN (window));
|
||||||
|
GtkWidget* scrolled = g_object_get_data (G_OBJECT (window), "scrolled");
|
||||||
|
GtkWidget* toolbar = g_object_get_data (G_OBJECT (scrolled), "panel-toolbar");
|
||||||
|
GtkWidget* menuitem = g_object_get_data (G_OBJECT (scrolled), "panel-menuitem");
|
||||||
|
GtkToolItem* toolitem;
|
||||||
|
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);
|
||||||
|
g_object_unref (scrolled);
|
||||||
|
toolitem = midori_panel_construct_tool_item (panel,
|
||||||
|
MIDORI_VIEWABLE (_midori_panel_child_for_scrolled (panel, scrolled)));
|
||||||
|
if (menuitem)
|
||||||
|
{
|
||||||
|
gtk_widget_show (menuitem);
|
||||||
|
g_object_set_data (G_OBJECT (menuitem), "toolitem", toolitem);
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_panel_button_detach_clicked_cb (GtkWidget* toolbutton,
|
||||||
|
MidoriPanel* panel)
|
||||||
|
{
|
||||||
|
/* FIXME: Use stock icon for window */
|
||||||
|
/* FIXME: What happens when the browser is destroyed? */
|
||||||
|
/* FIXME: What about multiple browsers? */
|
||||||
|
/* FIXME: Should we remember if the child was detached? */
|
||||||
|
/* 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);
|
||||||
|
const gchar* title = gtk_tool_button_get_label (GTK_TOOL_BUTTON (toolitem));
|
||||||
|
GtkWidget* toolbar = gtk_notebook_get_nth_page (
|
||||||
|
GTK_NOTEBOOK (panel->toolbook), n);
|
||||||
|
GtkWidget* scrolled = gtk_notebook_get_nth_page (
|
||||||
|
GTK_NOTEBOOK (panel->notebook), n);
|
||||||
|
GtkWidget* menuitem = g_object_get_data (G_OBJECT (scrolled), "panel-menuitem");
|
||||||
|
GtkWidget* window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||||
|
GtkWidget* vbox = gtk_vbox_new (FALSE, 0);
|
||||||
|
g_object_set_data (G_OBJECT (window), "scrolled", scrolled);
|
||||||
|
gtk_window_set_title (GTK_WINDOW (window), title);
|
||||||
|
gtk_window_set_default_size (GTK_WINDOW (window), 250, 400);
|
||||||
|
gtk_window_set_transient_for (GTK_WINDOW (window),
|
||||||
|
GTK_WINDOW (gtk_widget_get_toplevel (panel->notebook)));
|
||||||
|
gtk_widget_show (vbox);
|
||||||
|
gtk_container_add (GTK_CONTAINER (window), vbox);
|
||||||
|
if (menuitem)
|
||||||
|
gtk_widget_hide (menuitem);
|
||||||
|
gtk_container_remove (GTK_CONTAINER (panel->toolbar), GTK_WIDGET (toolitem));
|
||||||
|
g_object_ref (toolbar);
|
||||||
|
gtk_container_remove (GTK_CONTAINER (panel->toolbook), toolbar);
|
||||||
|
gtk_box_pack_start (GTK_BOX (vbox), toolbar, FALSE, FALSE, 0);
|
||||||
|
g_object_unref (toolbar);
|
||||||
|
g_object_set_data (G_OBJECT (scrolled), "panel-toolbar", toolbar);
|
||||||
|
g_object_ref (scrolled);
|
||||||
|
gtk_container_remove (GTK_CONTAINER (panel->notebook), scrolled);
|
||||||
|
gtk_box_pack_start (GTK_BOX (vbox), scrolled, TRUE, TRUE, 0);
|
||||||
|
g_object_unref (scrolled);
|
||||||
|
g_signal_connect (window, "delete-event",
|
||||||
|
G_CALLBACK (midori_panel_detached_window_delete_event_cb), panel);
|
||||||
|
gtk_widget_show (window);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_panel_button_align_clicked_cb (GtkWidget* toolitem,
|
||||||
|
MidoriPanel* panel)
|
||||||
|
{
|
||||||
|
midori_panel_set_right_aligned (panel, !panel->right_aligned);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_panel_destroy_cb (MidoriPanel* panel)
|
||||||
|
{
|
||||||
|
/* Destroy pages first, so they don't need special care */
|
||||||
|
gtk_container_foreach (GTK_CONTAINER (panel->notebook),
|
||||||
|
(GtkCallback) gtk_widget_destroy, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_panel_init (MidoriPanel* panel)
|
||||||
|
{
|
||||||
|
GtkWidget* vbox;
|
||||||
|
GtkWidget* labelbar;
|
||||||
|
GtkToolItem* toolitem;
|
||||||
|
|
||||||
|
panel->right_aligned = FALSE;
|
||||||
|
|
||||||
|
/* Create the sidebar */
|
||||||
|
panel->toolbar = gtk_toolbar_new ();
|
||||||
|
gtk_toolbar_set_style (GTK_TOOLBAR (panel->toolbar), GTK_TOOLBAR_BOTH);
|
||||||
|
gtk_toolbar_set_icon_size (GTK_TOOLBAR (panel->toolbar),
|
||||||
|
GTK_ICON_SIZE_BUTTON);
|
||||||
|
gtk_toolbar_set_orientation (GTK_TOOLBAR (panel->toolbar),
|
||||||
|
GTK_ORIENTATION_VERTICAL);
|
||||||
|
gtk_box_pack_start (GTK_BOX (panel), panel->toolbar, FALSE, FALSE, 0);
|
||||||
|
gtk_widget_show_all (panel->toolbar);
|
||||||
|
vbox = gtk_vbox_new (FALSE, 0);
|
||||||
|
gtk_box_pack_start (GTK_BOX (panel), vbox, TRUE, TRUE, 0);
|
||||||
|
|
||||||
|
/* Create the titlebar */
|
||||||
|
labelbar = gtk_toolbar_new ();
|
||||||
|
gtk_toolbar_set_icon_size (GTK_TOOLBAR (labelbar), GTK_ICON_SIZE_MENU);
|
||||||
|
gtk_toolbar_set_style (GTK_TOOLBAR (labelbar), GTK_TOOLBAR_ICONS);
|
||||||
|
toolitem = gtk_tool_item_new ();
|
||||||
|
gtk_tool_item_set_expand (toolitem, TRUE);
|
||||||
|
panel->toolbar_label = gtk_label_new (NULL);
|
||||||
|
gtk_misc_set_alignment (GTK_MISC (panel->toolbar_label), 0, 0.5);
|
||||||
|
gtk_container_add (GTK_CONTAINER (toolitem), panel->toolbar_label);
|
||||||
|
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_tool_button_set_label (GTK_TOOL_BUTTON (toolitem),
|
||||||
|
_("Detach chosen panel from the window"));
|
||||||
|
gtk_tool_item_set_tooltip_text (GTK_TOOL_ITEM (toolitem),
|
||||||
|
_("Whether to detach the chosen panel from the window"));
|
||||||
|
g_signal_connect (toolitem, "clicked",
|
||||||
|
G_CALLBACK (midori_panel_button_detach_clicked_cb), panel);
|
||||||
|
#if HAVE_OSX
|
||||||
|
gtk_toolbar_insert (GTK_TOOLBAR (labelbar), toolitem, 0);
|
||||||
|
#else
|
||||||
|
gtk_toolbar_insert (GTK_TOOLBAR (labelbar), toolitem, -1);
|
||||||
|
#endif
|
||||||
|
toolitem = gtk_tool_button_new_from_stock (GTK_STOCK_GO_FORWARD);
|
||||||
|
gtk_tool_button_set_label (GTK_TOOL_BUTTON (toolitem),
|
||||||
|
_("Align sidepanel on the right"));
|
||||||
|
gtk_tool_item_set_tooltip_text (GTK_TOOL_ITEM (toolitem),
|
||||||
|
_("Whether to align the sidepanel on the right"));
|
||||||
|
g_signal_connect (toolitem, "clicked",
|
||||||
|
G_CALLBACK (midori_panel_button_align_clicked_cb), panel);
|
||||||
|
#if HAVE_OSX
|
||||||
|
gtk_toolbar_insert (GTK_TOOLBAR (labelbar), toolitem, 0);
|
||||||
|
#else
|
||||||
|
gtk_toolbar_insert (GTK_TOOLBAR (labelbar), toolitem, -1);
|
||||||
|
#endif
|
||||||
|
panel->button_align = toolitem;
|
||||||
|
toolitem = gtk_tool_button_new_from_stock (GTK_STOCK_CLOSE);
|
||||||
|
gtk_tool_button_set_label (GTK_TOOL_BUTTON (toolitem), _("Close panel"));
|
||||||
|
gtk_tool_item_set_tooltip_text (GTK_TOOL_ITEM (toolitem), _("Close panel"));
|
||||||
|
g_signal_connect (toolitem, "clicked",
|
||||||
|
G_CALLBACK (midori_panel_button_close_clicked_cb), panel);
|
||||||
|
#if HAVE_OSX
|
||||||
|
gtk_toolbar_insert (GTK_TOOLBAR (labelbar), toolitem, 0);
|
||||||
|
#else
|
||||||
|
gtk_toolbar_insert (GTK_TOOLBAR (labelbar), toolitem, -1);
|
||||||
|
#endif
|
||||||
|
gtk_box_pack_start (GTK_BOX (vbox), labelbar, FALSE, FALSE, 0);
|
||||||
|
gtk_widget_show_all (vbox);
|
||||||
|
|
||||||
|
/* Create the toolbook */
|
||||||
|
panel->toolbook = gtk_notebook_new ();
|
||||||
|
gtk_notebook_set_show_border (GTK_NOTEBOOK (panel->toolbook), FALSE);
|
||||||
|
gtk_notebook_set_show_tabs (GTK_NOTEBOOK (panel->toolbook), FALSE);
|
||||||
|
gtk_box_pack_start (GTK_BOX (vbox), panel->toolbook, FALSE, FALSE, 0);
|
||||||
|
gtk_widget_show (panel->toolbook);
|
||||||
|
|
||||||
|
/* Create the notebook */
|
||||||
|
panel->notebook = gtk_notebook_new ();
|
||||||
|
gtk_notebook_set_show_border (GTK_NOTEBOOK (panel->notebook), FALSE);
|
||||||
|
gtk_notebook_set_show_tabs (GTK_NOTEBOOK (panel->notebook), FALSE);
|
||||||
|
panel->frame = gtk_frame_new (NULL);
|
||||||
|
gtk_container_add (GTK_CONTAINER (panel->frame), panel->notebook);
|
||||||
|
gtk_box_pack_start (GTK_BOX (vbox), panel->frame, TRUE, TRUE, 0);
|
||||||
|
gtk_widget_show_all (panel->frame);
|
||||||
|
|
||||||
|
g_signal_connect (panel, "destroy",
|
||||||
|
G_CALLBACK (midori_panel_destroy_cb), NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_panel_finalize (GObject* object)
|
||||||
|
{
|
||||||
|
G_OBJECT_CLASS (midori_panel_parent_class)->finalize (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_panel_set_property (GObject* object,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue* value,
|
||||||
|
GParamSpec* pspec)
|
||||||
|
{
|
||||||
|
MidoriPanel* panel = MIDORI_PANEL (object);
|
||||||
|
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_SHADOW_TYPE:
|
||||||
|
gtk_frame_set_shadow_type (GTK_FRAME (panel->frame),
|
||||||
|
g_value_get_enum (value));
|
||||||
|
break;
|
||||||
|
case PROP_MENU:
|
||||||
|
katze_object_assign (panel->menu, g_value_dup_object (value));
|
||||||
|
/* FIXME: Move existing items to the new menu */
|
||||||
|
break;
|
||||||
|
case PROP_PAGE:
|
||||||
|
midori_panel_set_current_page (panel, g_value_get_int (value));
|
||||||
|
break;
|
||||||
|
case PROP_RIGHT_ALIGNED:
|
||||||
|
midori_panel_set_right_aligned (panel, g_value_get_boolean (value));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_panel_get_property (GObject* object,
|
||||||
|
guint prop_id,
|
||||||
|
GValue* value,
|
||||||
|
GParamSpec* pspec)
|
||||||
|
{
|
||||||
|
MidoriPanel* panel = MIDORI_PANEL (object);
|
||||||
|
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_SHADOW_TYPE:
|
||||||
|
g_value_set_enum (value,
|
||||||
|
gtk_frame_get_shadow_type (GTK_FRAME (panel->frame)));
|
||||||
|
break;
|
||||||
|
case PROP_MENU:
|
||||||
|
g_value_set_object (value, panel->menu);
|
||||||
|
break;
|
||||||
|
case PROP_PAGE:
|
||||||
|
g_value_set_int (value, midori_panel_get_current_page (panel));
|
||||||
|
break;
|
||||||
|
case PROP_RIGHT_ALIGNED:
|
||||||
|
g_value_set_boolean (value, panel->right_aligned);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* midori_panel_new:
|
||||||
|
*
|
||||||
|
* Creates a new empty panel.
|
||||||
|
*
|
||||||
|
* Return value: a new #MidoriPanel
|
||||||
|
**/
|
||||||
|
GtkWidget*
|
||||||
|
midori_panel_new (void)
|
||||||
|
{
|
||||||
|
MidoriPanel* panel = g_object_new (MIDORI_TYPE_PANEL,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
return GTK_WIDGET (panel);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* midori_panel_set_compact:
|
||||||
|
* @compact: %TRUE if the panel should be compact
|
||||||
|
*
|
||||||
|
* Determines if the panel should be compact.
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
midori_panel_set_compact (MidoriPanel* panel,
|
||||||
|
gboolean compact)
|
||||||
|
{
|
||||||
|
g_return_if_fail (MIDORI_IS_PANEL (panel));
|
||||||
|
|
||||||
|
#if HAVE_HILDON
|
||||||
|
compact = TRUE;
|
||||||
|
#endif
|
||||||
|
gtk_toolbar_set_style (GTK_TOOLBAR (panel->toolbar),
|
||||||
|
compact ? GTK_TOOLBAR_ICONS : GTK_TOOLBAR_BOTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* midori_panel_set_right_aligned:
|
||||||
|
* @compact: %TRUE if the panel should be aligned to the right
|
||||||
|
*
|
||||||
|
* Determines if the panel should be right aligned.
|
||||||
|
*
|
||||||
|
* Since: 0.1.3
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
midori_panel_set_right_aligned (MidoriPanel* panel,
|
||||||
|
gboolean right_aligned)
|
||||||
|
{
|
||||||
|
GtkWidget* box;
|
||||||
|
|
||||||
|
g_return_if_fail (MIDORI_IS_PANEL (panel));
|
||||||
|
|
||||||
|
box = gtk_widget_get_parent (panel->toolbar);
|
||||||
|
gtk_box_reorder_child (GTK_BOX (box), panel->toolbar,
|
||||||
|
right_aligned ? -1 : 0);
|
||||||
|
gtk_tool_button_set_stock_id (GTK_TOOL_BUTTON (panel->button_align),
|
||||||
|
right_aligned ? GTK_STOCK_GO_BACK : GTK_STOCK_GO_FORWARD);
|
||||||
|
panel->right_aligned = right_aligned;
|
||||||
|
g_object_notify (G_OBJECT (panel), "right-aligned");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_panel_menu_item_activate_cb (GtkWidget* widget,
|
||||||
|
MidoriPanel* panel)
|
||||||
|
{
|
||||||
|
GtkWidget* child;
|
||||||
|
GtkToggleToolButton* toolitem;
|
||||||
|
guint n;
|
||||||
|
|
||||||
|
child = g_object_get_data (G_OBJECT (widget), "page");
|
||||||
|
toolitem = g_object_get_data (G_OBJECT (widget), "toolitem");
|
||||||
|
|
||||||
|
if (toolitem)
|
||||||
|
{
|
||||||
|
/* Unsetting the button before setting it ensures that
|
||||||
|
it will emit signals even if it was active before */
|
||||||
|
gtk_toggle_tool_button_set_active (toolitem, FALSE);
|
||||||
|
gtk_toggle_tool_button_set_active (toolitem, TRUE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
n = midori_panel_page_num (panel, child);
|
||||||
|
midori_panel_set_current_page (panel, n);
|
||||||
|
g_signal_emit (panel, signals[SWITCH_PAGE], 0, n);
|
||||||
|
gtk_widget_show (GTK_WIDGET (panel));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_panel_viewable_destroy_cb (GtkWidget* viewable,
|
||||||
|
MidoriPanel* panel)
|
||||||
|
{
|
||||||
|
gint i = gtk_notebook_page_num (GTK_NOTEBOOK (panel->notebook), viewable);
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
const gchar* label = midori_viewable_get_label (viewable);
|
||||||
|
const gchar* stock_id = midori_viewable_get_stock_id (viewable);
|
||||||
|
GtkToolItem* toolitem;
|
||||||
|
GtkWidget* image;
|
||||||
|
|
||||||
|
toolitem = gtk_radio_tool_button_new_from_stock (NULL, stock_id);
|
||||||
|
g_object_set (toolitem, "group",
|
||||||
|
gtk_toolbar_get_nth_item (GTK_TOOLBAR (panel->toolbar), 0), NULL);
|
||||||
|
image = gtk_image_new_from_stock (stock_id, GTK_ICON_SIZE_BUTTON);
|
||||||
|
gtk_tool_button_set_icon_widget (GTK_TOOL_BUTTON (toolitem), image);
|
||||||
|
if (label)
|
||||||
|
{
|
||||||
|
gtk_tool_button_set_label (GTK_TOOL_BUTTON (toolitem), label);
|
||||||
|
gtk_widget_set_tooltip_text (GTK_WIDGET (toolitem), label);
|
||||||
|
}
|
||||||
|
g_object_set_data (G_OBJECT (toolitem), "page", viewable);
|
||||||
|
g_signal_connect (toolitem, "clicked",
|
||||||
|
G_CALLBACK (midori_panel_menu_item_activate_cb), panel);
|
||||||
|
gtk_widget_show_all (GTK_WIDGET (toolitem));
|
||||||
|
gtk_toolbar_insert (GTK_TOOLBAR (panel->toolbar), toolitem, -1);
|
||||||
|
g_signal_connect (viewable, "destroy",
|
||||||
|
G_CALLBACK (midori_panel_widget_destroy_cb), toolitem);
|
||||||
|
return toolitem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* midori_panel_append_page:
|
||||||
|
* @panel: a #MidoriPanel
|
||||||
|
* @viewable: a viewable widget
|
||||||
|
* @toolbar: a toolbar widget, or %NULL
|
||||||
|
* @stock_id: a stock ID
|
||||||
|
* @label: a string to use as the label
|
||||||
|
*
|
||||||
|
* Appends a new page to the panel. If @toolbar is specified it will
|
||||||
|
* be packed above @viewable.
|
||||||
|
*
|
||||||
|
* Since 0.1.3 destroying the @viewable implicitly removes
|
||||||
|
* the page including the menu and eventual toolbar.
|
||||||
|
*
|
||||||
|
* In the case of an error, -1 is returned.
|
||||||
|
*
|
||||||
|
* Return value: the index of the new page, or -1
|
||||||
|
**/
|
||||||
|
gint
|
||||||
|
midori_panel_append_page (MidoriPanel* panel,
|
||||||
|
MidoriViewable* viewable)
|
||||||
|
{
|
||||||
|
GtkWidget* scrolled;
|
||||||
|
GObjectClass* gobject_class;
|
||||||
|
GtkWidget* widget;
|
||||||
|
GtkWidget* toolbar;
|
||||||
|
const gchar* label;
|
||||||
|
const gchar* stock_id;
|
||||||
|
GtkToolItem* toolitem;
|
||||||
|
GtkWidget* menuitem;
|
||||||
|
guint n;
|
||||||
|
|
||||||
|
g_return_val_if_fail (MIDORI_IS_PANEL (panel), -1);
|
||||||
|
g_return_val_if_fail (MIDORI_IS_VIEWABLE (viewable), -1);
|
||||||
|
|
||||||
|
if (GTK_IS_SCROLLED_WINDOW (viewable))
|
||||||
|
scrolled = (GtkWidget*)viewable;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
scrolled = gtk_scrolled_window_new (NULL, NULL);
|
||||||
|
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled),
|
||||||
|
GTK_POLICY_AUTOMATIC,
|
||||||
|
GTK_POLICY_AUTOMATIC);
|
||||||
|
GTK_WIDGET_SET_FLAGS (scrolled, GTK_CAN_FOCUS);
|
||||||
|
gtk_widget_show (scrolled);
|
||||||
|
gobject_class = G_OBJECT_GET_CLASS (viewable);
|
||||||
|
if (GTK_WIDGET_CLASS (gobject_class)->set_scroll_adjustments_signal)
|
||||||
|
widget = (GtkWidget*)viewable;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
widget = gtk_viewport_new (NULL, NULL);
|
||||||
|
gtk_widget_show (widget);
|
||||||
|
gtk_container_add (GTK_CONTAINER (widget), GTK_WIDGET (viewable));
|
||||||
|
}
|
||||||
|
gtk_container_add (GTK_CONTAINER (scrolled), widget);
|
||||||
|
}
|
||||||
|
gtk_container_add (GTK_CONTAINER (panel->notebook), scrolled);
|
||||||
|
|
||||||
|
toolbar = midori_viewable_get_toolbar (viewable);
|
||||||
|
gtk_widget_show (toolbar);
|
||||||
|
gtk_container_add (GTK_CONTAINER (panel->toolbook), toolbar);
|
||||||
|
g_signal_connect (viewable, "destroy",
|
||||||
|
G_CALLBACK (midori_panel_widget_destroy_cb), toolbar);
|
||||||
|
|
||||||
|
n = midori_panel_page_num (panel, scrolled);
|
||||||
|
label = midori_viewable_get_label (viewable);
|
||||||
|
stock_id = midori_viewable_get_stock_id (viewable);
|
||||||
|
|
||||||
|
toolitem = midori_panel_construct_tool_item (panel, viewable);
|
||||||
|
|
||||||
|
if (panel->menu)
|
||||||
|
{
|
||||||
|
menuitem = gtk_image_menu_item_new_from_stock (stock_id, NULL);
|
||||||
|
gtk_widget_show (menuitem);
|
||||||
|
g_object_set_data (G_OBJECT (menuitem), "page", viewable);
|
||||||
|
g_object_set_data (G_OBJECT (menuitem), "toolitem", toolitem);
|
||||||
|
g_signal_connect (menuitem, "activate",
|
||||||
|
G_CALLBACK (midori_panel_menu_item_activate_cb),
|
||||||
|
panel);
|
||||||
|
gtk_menu_shell_append (GTK_MENU_SHELL (panel->menu), menuitem);
|
||||||
|
g_object_set_data (G_OBJECT (scrolled), "panel-menuitem", menuitem);
|
||||||
|
g_signal_connect (viewable, "destroy",
|
||||||
|
G_CALLBACK (midori_panel_widget_destroy_cb), menuitem);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_signal_connect (viewable, "destroy",
|
||||||
|
G_CALLBACK (midori_panel_viewable_destroy_cb), panel);
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* midori_panel_get_current_page:
|
||||||
|
* @panel: a #MidoriPanel
|
||||||
|
*
|
||||||
|
* Retrieves the index of the currently selected page.
|
||||||
|
*
|
||||||
|
* If @panel has no children, -1 is returned.
|
||||||
|
*
|
||||||
|
* Return value: the index of the current page, or -1
|
||||||
|
**/
|
||||||
|
gint
|
||||||
|
midori_panel_get_current_page (MidoriPanel* panel)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (MIDORI_IS_PANEL (panel), -1);
|
||||||
|
|
||||||
|
return gtk_notebook_get_current_page (GTK_NOTEBOOK (panel->notebook));
|
||||||
|
}
|
||||||
|
|
||||||
|
static GtkWidget*
|
||||||
|
_midori_panel_child_for_scrolled (MidoriPanel* panel,
|
||||||
|
GtkWidget* scrolled)
|
||||||
|
{
|
||||||
|
GtkWidget* child;
|
||||||
|
|
||||||
|
/* This is a lazy hack, we should have a way of determining
|
||||||
|
whether the scrolled is the actual child. */
|
||||||
|
if (MIDORI_IS_VIEW (scrolled))
|
||||||
|
return scrolled;
|
||||||
|
child = gtk_bin_get_child (GTK_BIN (scrolled));
|
||||||
|
if (GTK_IS_VIEWPORT (child))
|
||||||
|
child = gtk_bin_get_child (GTK_BIN (child));
|
||||||
|
return child;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* midori_panel_get_nth_page:
|
||||||
|
* @panel: a #MidoriPanel
|
||||||
|
*
|
||||||
|
* Retrieves the child widget of the nth page.
|
||||||
|
*
|
||||||
|
* If @panel has no children, %NULL is returned.
|
||||||
|
*
|
||||||
|
* Return value: the child widget of the new page, or %NULL
|
||||||
|
**/
|
||||||
|
GtkWidget*
|
||||||
|
midori_panel_get_nth_page (MidoriPanel* panel,
|
||||||
|
guint page_num)
|
||||||
|
{
|
||||||
|
GtkWidget* scrolled;
|
||||||
|
|
||||||
|
g_return_val_if_fail (MIDORI_IS_PANEL (panel), NULL);
|
||||||
|
|
||||||
|
scrolled = gtk_notebook_get_nth_page (
|
||||||
|
GTK_NOTEBOOK (panel->notebook), page_num);
|
||||||
|
if (scrolled)
|
||||||
|
return _midori_panel_child_for_scrolled (panel, scrolled);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* midori_panel_get_n_pages:
|
||||||
|
* @panel: a #MidoriPanel
|
||||||
|
*
|
||||||
|
* Retrieves the number of pages contained in the panel.
|
||||||
|
*
|
||||||
|
* Return value: the number of pages
|
||||||
|
**/
|
||||||
|
guint
|
||||||
|
midori_panel_get_n_pages (MidoriPanel* panel)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (MIDORI_IS_PANEL (panel), 0);
|
||||||
|
|
||||||
|
return gtk_notebook_get_n_pages (GTK_NOTEBOOK (panel->notebook));
|
||||||
|
}
|
||||||
|
|
||||||
|
static GtkWidget*
|
||||||
|
_midori_panel_scrolled_for_child (MidoriPanel* panel,
|
||||||
|
GtkWidget* child)
|
||||||
|
{
|
||||||
|
GtkWidget* scrolled;
|
||||||
|
|
||||||
|
/* This is a lazy hack, we should have a way of determining
|
||||||
|
whether the scrolled is the actual child. */
|
||||||
|
if (MIDORI_IS_VIEW (child))
|
||||||
|
return child;
|
||||||
|
scrolled = gtk_widget_get_parent (GTK_WIDGET (child));
|
||||||
|
if (GTK_IS_VIEWPORT (scrolled))
|
||||||
|
scrolled = gtk_widget_get_parent (scrolled);
|
||||||
|
return scrolled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* midori_panel_page_num:
|
||||||
|
* @panel: a #MidoriPanel
|
||||||
|
*
|
||||||
|
* Retrieves the index of the page associated to @widget.
|
||||||
|
*
|
||||||
|
* If @panel has no children, -1 is returned.
|
||||||
|
*
|
||||||
|
* Return value: the index of page associated to @widget, or -1
|
||||||
|
**/
|
||||||
|
gint
|
||||||
|
midori_panel_page_num (MidoriPanel* panel,
|
||||||
|
GtkWidget* child)
|
||||||
|
{
|
||||||
|
GtkWidget* scrolled;
|
||||||
|
|
||||||
|
g_return_val_if_fail (MIDORI_IS_PANEL (panel), -1);
|
||||||
|
g_return_val_if_fail (GTK_IS_WIDGET (child), -1);
|
||||||
|
|
||||||
|
scrolled = _midori_panel_scrolled_for_child (panel, child);
|
||||||
|
return gtk_notebook_page_num (GTK_NOTEBOOK (panel->notebook), scrolled);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* midori_panel_set_current_page:
|
||||||
|
* @panel: a #MidoriPanel
|
||||||
|
* @n: index of the page to switch to, or -1 to mean the last page
|
||||||
|
*
|
||||||
|
* Switches to the page with the given index.
|
||||||
|
*
|
||||||
|
* The child must be visible, otherwise the underlying GtkNotebook will
|
||||||
|
* silently ignore the attempt to switch the page.
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
midori_panel_set_current_page (MidoriPanel* panel,
|
||||||
|
gint n)
|
||||||
|
{
|
||||||
|
GtkWidget* viewable;
|
||||||
|
|
||||||
|
g_return_if_fail (MIDORI_IS_PANEL (panel));
|
||||||
|
|
||||||
|
gtk_notebook_set_current_page (GTK_NOTEBOOK (panel->toolbook), n);
|
||||||
|
gtk_notebook_set_current_page (GTK_NOTEBOOK (panel->notebook), n);
|
||||||
|
|
||||||
|
if ((viewable = midori_panel_get_nth_page (panel, n)))
|
||||||
|
{
|
||||||
|
const gchar* label;
|
||||||
|
|
||||||
|
label = midori_viewable_get_label (MIDORI_VIEWABLE (viewable));
|
||||||
|
g_object_set (panel->toolbar_label, "label", label, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
GtkAlignment parent_instance;
|
||||||
|
|
||||||
|
gchar* label;
|
||||||
|
gchar* stock_id;
|
||||||
|
GtkWidget* toolbar;
|
||||||
|
} MidoriDummyViewable;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
GtkAlignmentClass parent_class;
|
||||||
|
} MidoriDummyViewableClass;
|
||||||
|
|
||||||
|
GType midori_dummy_viewable_get_type (void) G_GNUC_CONST;
|
||||||
|
#define MIDORI_TYPE_DUMMY_VIEWABLE (midori_dummy_viewable_get_type ())
|
||||||
|
#define MIDORI_DUMMY_VIEWABLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), \
|
||||||
|
MIDORI_TYPE_DUMMY_VIEWABLE, MidoriDummyViewable))
|
||||||
|
#define MIDORI_IS_DUMMY_VIEWABLE(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), MIDORI_TYPE_DUMMY_VIEWABLE))
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_dummy_viewable_iface_init (MidoriViewableIface* iface);
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_dummy_viewable_finalize (GObject* object);
|
||||||
|
|
||||||
|
G_DEFINE_TYPE_WITH_CODE (MidoriDummyViewable, midori_dummy_viewable,
|
||||||
|
GTK_TYPE_ALIGNMENT,
|
||||||
|
G_IMPLEMENT_INTERFACE (MIDORI_TYPE_VIEWABLE,
|
||||||
|
midori_dummy_viewable_iface_init));
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_dummy_viewable_class_init (MidoriDummyViewableClass* class)
|
||||||
|
{
|
||||||
|
GObjectClass* gobject_class;
|
||||||
|
|
||||||
|
gobject_class = G_OBJECT_CLASS (class);
|
||||||
|
gobject_class->finalize = midori_dummy_viewable_finalize;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const gchar*
|
||||||
|
midori_dummy_viewable_get_label (MidoriViewable* viewable)
|
||||||
|
{
|
||||||
|
return MIDORI_DUMMY_VIEWABLE (viewable)->label;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const gchar*
|
||||||
|
midori_dummy_viewable_get_stock_id (MidoriViewable* viewable)
|
||||||
|
{
|
||||||
|
return MIDORI_DUMMY_VIEWABLE (viewable)->stock_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GtkWidget*
|
||||||
|
midori_dummy_viewable_get_toolbar (MidoriViewable* viewable)
|
||||||
|
{
|
||||||
|
return MIDORI_DUMMY_VIEWABLE (viewable)->toolbar;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_dummy_viewable_iface_init (MidoriViewableIface* iface)
|
||||||
|
{
|
||||||
|
iface->get_stock_id = midori_dummy_viewable_get_stock_id;
|
||||||
|
iface->get_label = midori_dummy_viewable_get_label;
|
||||||
|
iface->get_toolbar = midori_dummy_viewable_get_toolbar;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_dummy_viewable_init (MidoriDummyViewable* viewable)
|
||||||
|
{
|
||||||
|
viewable->stock_id = NULL;
|
||||||
|
viewable->label = NULL;
|
||||||
|
viewable->toolbar = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_dummy_viewable_finalize (GObject* object)
|
||||||
|
{
|
||||||
|
MidoriDummyViewable* viewable = MIDORI_DUMMY_VIEWABLE (object);
|
||||||
|
|
||||||
|
katze_assign (viewable->stock_id, NULL);
|
||||||
|
katze_assign (viewable->label, NULL);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (midori_dummy_viewable_parent_class)->finalize (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */ GtkWidget*
|
||||||
|
midori_dummy_viewable_new (const gchar* stock_id,
|
||||||
|
const gchar* label,
|
||||||
|
GtkWidget* toolbar)
|
||||||
|
{
|
||||||
|
GtkWidget* viewable = g_object_new (MIDORI_TYPE_DUMMY_VIEWABLE, NULL);
|
||||||
|
|
||||||
|
MIDORI_DUMMY_VIEWABLE (viewable)->stock_id = g_strdup (stock_id);
|
||||||
|
MIDORI_DUMMY_VIEWABLE (viewable)->label = g_strdup (label);
|
||||||
|
MIDORI_DUMMY_VIEWABLE (viewable)->toolbar = toolbar;
|
||||||
|
|
||||||
|
return viewable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* midori_panel_append_widget:
|
||||||
|
* @panel: a #MidoriPanel
|
||||||
|
* @widget: the child widget
|
||||||
|
* @stock_id: a stock ID
|
||||||
|
* @label: a string to use as the label, or %NULL
|
||||||
|
* @toolbar: a toolbar widget, or %NULL
|
||||||
|
*
|
||||||
|
* Appends an arbitrary widget to the panel by wrapping it
|
||||||
|
* in a #MidoriViewable created on the fly.
|
||||||
|
*
|
||||||
|
* Actually implementing #MidoriViewable instead of using
|
||||||
|
* this convenience is recommended.
|
||||||
|
*
|
||||||
|
* Since 0.1.3 destroying the @widget implicitly removes
|
||||||
|
* the page including the menu and eventual toolbar.
|
||||||
|
*
|
||||||
|
* In the case of an error, -1 is returned.
|
||||||
|
*
|
||||||
|
* Return value: the index of the new page, or -1
|
||||||
|
**/
|
||||||
|
gint
|
||||||
|
midori_panel_append_widget (MidoriPanel* panel,
|
||||||
|
GtkWidget* widget,
|
||||||
|
const gchar* stock_id,
|
||||||
|
const gchar* label,
|
||||||
|
GtkWidget* toolbar)
|
||||||
|
{
|
||||||
|
GtkWidget* viewable;
|
||||||
|
|
||||||
|
g_return_val_if_fail (MIDORI_IS_PANEL (panel), -1);
|
||||||
|
g_return_val_if_fail (GTK_IS_WIDGET (widget), -1);
|
||||||
|
|
||||||
|
g_return_val_if_fail (stock_id != NULL, -1);
|
||||||
|
g_return_val_if_fail (!toolbar || GTK_IS_WIDGET (toolbar), -1);
|
||||||
|
|
||||||
|
viewable = midori_dummy_viewable_new (stock_id, label, toolbar);
|
||||||
|
gtk_widget_show (viewable);
|
||||||
|
gtk_container_add (GTK_CONTAINER (viewable), widget);
|
||||||
|
g_signal_connect (widget, "destroy",
|
||||||
|
G_CALLBACK (midori_panel_widget_destroy_cb), viewable);
|
||||||
|
return midori_panel_append_page (panel, MIDORI_VIEWABLE (viewable));
|
||||||
|
}
|
84
midori/midori-panel.h
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2008 Christian Dywan <christian@twotoasts.de>
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
See the file COPYING for the full license text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __MIDORI_PANEL_H__
|
||||||
|
#define __MIDORI_PANEL_H__
|
||||||
|
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
#include <katze/katze.h>
|
||||||
|
|
||||||
|
#include "midori-viewable.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define MIDORI_TYPE_PANEL \
|
||||||
|
(midori_panel_get_type ())
|
||||||
|
#define MIDORI_PANEL(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_CAST ((obj), MIDORI_TYPE_PANEL, MidoriPanel))
|
||||||
|
#define MIDORI_PANEL_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_CAST ((klass), MIDORI_TYPE_PANEL, MidoriPanelClass))
|
||||||
|
#define MIDORI_IS_PANEL(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), MIDORI_TYPE_PANEL))
|
||||||
|
#define MIDORI_IS_PANEL_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_TYPE ((klass), MIDORI_TYPE_PANEL))
|
||||||
|
#define MIDORI_PANEL_GET_CLASS(obj) \
|
||||||
|
(G_TYPE_INSTANCE_GET_CLASS ((obj), MIDORI_TYPE_PANEL, MidoriPanelClass))
|
||||||
|
|
||||||
|
typedef struct _MidoriPanel MidoriPanel;
|
||||||
|
typedef struct _MidoriPanelClass MidoriPanelClass;
|
||||||
|
|
||||||
|
GType
|
||||||
|
midori_panel_get_type (void);
|
||||||
|
|
||||||
|
GtkWidget*
|
||||||
|
midori_panel_new (void);
|
||||||
|
|
||||||
|
void
|
||||||
|
midori_panel_set_compact (MidoriPanel* panel,
|
||||||
|
gboolean compact);
|
||||||
|
|
||||||
|
void
|
||||||
|
midori_panel_set_right_aligned (MidoriPanel* panel,
|
||||||
|
gboolean right_aligned);
|
||||||
|
|
||||||
|
gint
|
||||||
|
midori_panel_append_page (MidoriPanel* panel,
|
||||||
|
MidoriViewable* viewable);
|
||||||
|
|
||||||
|
gint
|
||||||
|
midori_panel_get_current_page (MidoriPanel* panel);
|
||||||
|
|
||||||
|
GtkWidget*
|
||||||
|
midori_panel_get_nth_page (MidoriPanel* panel,
|
||||||
|
guint page_num);
|
||||||
|
|
||||||
|
guint
|
||||||
|
midori_panel_get_n_pages (MidoriPanel* panel);
|
||||||
|
|
||||||
|
gint
|
||||||
|
midori_panel_page_num (MidoriPanel* panel,
|
||||||
|
GtkWidget* child);
|
||||||
|
|
||||||
|
void
|
||||||
|
midori_panel_set_current_page (MidoriPanel* panel,
|
||||||
|
gint n);
|
||||||
|
|
||||||
|
gint
|
||||||
|
midori_panel_append_widget (MidoriPanel* panel,
|
||||||
|
GtkWidget* widget,
|
||||||
|
const gchar* stock_id,
|
||||||
|
const gchar* label,
|
||||||
|
GtkWidget* toolbar);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __MIDORI_PANEL_H__ */
|
672
midori/midori-preferences.c
Normal file
|
@ -0,0 +1,672 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2007-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-preferences.h"
|
||||||
|
|
||||||
|
#if HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "sokoke.h"
|
||||||
|
#include "compat.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <glib/gi18n.h>
|
||||||
|
#include <libsoup/soup.h>
|
||||||
|
|
||||||
|
struct _MidoriPreferences
|
||||||
|
{
|
||||||
|
GtkDialog parent_instance;
|
||||||
|
|
||||||
|
MidoriWebSettings* settings;
|
||||||
|
GtkWidget* notebook;
|
||||||
|
};
|
||||||
|
|
||||||
|
G_DEFINE_TYPE (MidoriPreferences, midori_preferences, GTK_TYPE_DIALOG)
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
PROP_0,
|
||||||
|
|
||||||
|
PROP_SETTINGS
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_preferences_finalize (GObject* object);
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_preferences_set_property (GObject* object,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue* value,
|
||||||
|
GParamSpec* pspec);
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_preferences_get_property (GObject* object,
|
||||||
|
guint prop_id,
|
||||||
|
GValue* value,
|
||||||
|
GParamSpec* pspec);
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_preferences_class_init (MidoriPreferencesClass* class)
|
||||||
|
{
|
||||||
|
GObjectClass* gobject_class = G_OBJECT_CLASS (class);
|
||||||
|
gobject_class->finalize = midori_preferences_finalize;
|
||||||
|
gobject_class->set_property = midori_preferences_set_property;
|
||||||
|
gobject_class->get_property = midori_preferences_get_property;
|
||||||
|
|
||||||
|
g_object_class_install_property (gobject_class,
|
||||||
|
PROP_SETTINGS,
|
||||||
|
g_param_spec_object (
|
||||||
|
"settings",
|
||||||
|
"Settings",
|
||||||
|
"Settings instance to provide properties",
|
||||||
|
MIDORI_TYPE_WEB_SETTINGS,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_preferences_response_cb (MidoriPreferences* preferences,
|
||||||
|
gint response)
|
||||||
|
{
|
||||||
|
if (response == GTK_RESPONSE_CLOSE)
|
||||||
|
gtk_widget_destroy (GTK_WIDGET (preferences));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_preferences_init (MidoriPreferences* preferences)
|
||||||
|
{
|
||||||
|
gchar* dialog_title;
|
||||||
|
|
||||||
|
preferences->settings = NULL;
|
||||||
|
preferences->notebook = NULL;
|
||||||
|
|
||||||
|
dialog_title = g_strdup_printf (_("Preferences for %s"),
|
||||||
|
g_get_application_name ());
|
||||||
|
g_object_set (preferences,
|
||||||
|
"icon-name", GTK_STOCK_PREFERENCES,
|
||||||
|
"title", dialog_title,
|
||||||
|
"has-separator", FALSE,
|
||||||
|
NULL);
|
||||||
|
g_free (dialog_title);
|
||||||
|
#if !HAVE_OSX
|
||||||
|
gtk_dialog_add_buttons (GTK_DIALOG (preferences),
|
||||||
|
GTK_STOCK_HELP, GTK_RESPONSE_HELP,
|
||||||
|
GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
|
||||||
|
NULL);
|
||||||
|
#endif
|
||||||
|
g_signal_connect (preferences, "response",
|
||||||
|
G_CALLBACK (midori_preferences_response_cb), NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_preferences_finalize (GObject* object)
|
||||||
|
{
|
||||||
|
G_OBJECT_CLASS (midori_preferences_parent_class)->finalize (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_preferences_set_property (GObject* object,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue* value,
|
||||||
|
GParamSpec* pspec)
|
||||||
|
{
|
||||||
|
MidoriPreferences* preferences = MIDORI_PREFERENCES (object);
|
||||||
|
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_SETTINGS:
|
||||||
|
midori_preferences_set_settings (preferences,
|
||||||
|
g_value_get_object (value));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_preferences_get_property (GObject* object,
|
||||||
|
guint prop_id,
|
||||||
|
GValue* value,
|
||||||
|
GParamSpec* pspec)
|
||||||
|
{
|
||||||
|
MidoriPreferences* preferences = MIDORI_PREFERENCES (object);
|
||||||
|
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_SETTINGS:
|
||||||
|
g_value_set_object (value, preferences->settings);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* midori_preferences_new:
|
||||||
|
* @parent: the parent window
|
||||||
|
* @settings: the settings
|
||||||
|
*
|
||||||
|
* Creates a new preferences dialog.
|
||||||
|
*
|
||||||
|
* Since 0.1.2 @parent may be %NULL.
|
||||||
|
*
|
||||||
|
* Return value: a new #MidoriPreferences
|
||||||
|
**/
|
||||||
|
GtkWidget*
|
||||||
|
midori_preferences_new (GtkWindow* parent,
|
||||||
|
MidoriWebSettings* settings)
|
||||||
|
{
|
||||||
|
MidoriPreferences* preferences;
|
||||||
|
|
||||||
|
g_return_val_if_fail (!parent || GTK_IS_WINDOW (parent), NULL);
|
||||||
|
g_return_val_if_fail (MIDORI_IS_WEB_SETTINGS (settings), NULL);
|
||||||
|
|
||||||
|
preferences = g_object_new (MIDORI_TYPE_PREFERENCES,
|
||||||
|
"transient-for", parent,
|
||||||
|
"settings", settings,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
return GTK_WIDGET (preferences);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_preferences_homepage_current_clicked_cb (GtkWidget* button,
|
||||||
|
MidoriWebSettings* settings)
|
||||||
|
{
|
||||||
|
GtkWidget* preferences = gtk_widget_get_toplevel (button);
|
||||||
|
GtkWidget* browser = katze_object_get_object (preferences, "transient-for");
|
||||||
|
|
||||||
|
if (GTK_IS_WINDOW (browser))
|
||||||
|
{
|
||||||
|
gchar* uri = katze_object_get_string (browser, "uri");
|
||||||
|
g_object_set (settings, "homepage", uri, NULL);
|
||||||
|
g_free (uri);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
proxy_download_manager_icon_cb (GtkWidget* entry,
|
||||||
|
GdkEventFocus* event,
|
||||||
|
GtkImage* icon)
|
||||||
|
{
|
||||||
|
const gchar* command;
|
||||||
|
gchar* first_space;
|
||||||
|
gchar* first_part;
|
||||||
|
gchar* path;
|
||||||
|
|
||||||
|
command = gtk_entry_get_text (GTK_ENTRY (entry));
|
||||||
|
if ((first_space = strstr (command, " ")))
|
||||||
|
first_part = g_strndup (command, first_space - command);
|
||||||
|
else
|
||||||
|
first_part = g_strdup (command);
|
||||||
|
path = g_find_program_in_path (first_part);
|
||||||
|
|
||||||
|
if (path)
|
||||||
|
{
|
||||||
|
if (gtk_icon_theme_has_icon (gtk_icon_theme_get_for_screen (
|
||||||
|
gtk_widget_get_screen (entry)), first_part))
|
||||||
|
gtk_image_set_from_icon_name (icon, first_part, GTK_ICON_SIZE_MENU);
|
||||||
|
else
|
||||||
|
gtk_image_set_from_stock (icon, GTK_STOCK_EXECUTE, GTK_ICON_SIZE_MENU);
|
||||||
|
g_free (path);
|
||||||
|
}
|
||||||
|
else if (first_part && *first_part)
|
||||||
|
gtk_image_set_from_stock (icon, GTK_STOCK_STOP, GTK_ICON_SIZE_MENU);
|
||||||
|
else
|
||||||
|
gtk_image_clear (icon);
|
||||||
|
|
||||||
|
g_free (first_part);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_preferences_notify_preferred_encoding_cb (MidoriWebSettings* settings,
|
||||||
|
GParamSpec* pspec,
|
||||||
|
GtkWidget* entry)
|
||||||
|
{
|
||||||
|
MidoriPreferredEncoding preferred_encoding;
|
||||||
|
|
||||||
|
preferred_encoding = katze_object_get_enum (settings, "preferred-encoding");
|
||||||
|
gtk_widget_set_sensitive (entry, preferred_encoding == MIDORI_ENCODING_CUSTOM);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_preferences_notify_auto_detect_proxy_cb (MidoriWebSettings* settings,
|
||||||
|
GParamSpec* pspec,
|
||||||
|
GtkWidget* entry)
|
||||||
|
{
|
||||||
|
MidoriIdentity auto_detect_proxy = katze_object_get_enum (settings,
|
||||||
|
"auto-detect-proxy");
|
||||||
|
|
||||||
|
gtk_widget_set_sensitive (entry, !auto_detect_proxy);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_preferences_notify_identify_as_cb (MidoriWebSettings* settings,
|
||||||
|
GParamSpec* pspec,
|
||||||
|
GtkWidget* entry)
|
||||||
|
{
|
||||||
|
MidoriIdentity identify_as = katze_object_get_enum (settings, "identify-as");
|
||||||
|
|
||||||
|
gtk_widget_set_sensitive (entry, identify_as == MIDORI_IDENT_CUSTOM);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if HAVE_OSX
|
||||||
|
static void
|
||||||
|
midori_preferences_help_clicked_cb (GtkWidget* button,
|
||||||
|
GtkDialog* dialog)
|
||||||
|
{
|
||||||
|
gtk_dialog_response (dialog, GTK_RESPONSE_HELP);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_preferences_toolbutton_clicked_cb (GtkWidget* toolbutton,
|
||||||
|
GtkWidget* page)
|
||||||
|
{
|
||||||
|
gpointer notebook = g_object_get_data (G_OBJECT (toolbutton), "notebook");
|
||||||
|
guint n = gtk_notebook_page_num (notebook, page);
|
||||||
|
gtk_notebook_set_current_page (notebook, n);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
midori_preferences_add_toolbutton (GtkWidget* toolbar,
|
||||||
|
GtkWidget** toolbutton,
|
||||||
|
const gchar* icon,
|
||||||
|
const gchar* label,
|
||||||
|
GtkWidget* page)
|
||||||
|
{
|
||||||
|
#if HAVE_OSX
|
||||||
|
*toolbutton = GTK_WIDGET (*toolbutton ? gtk_radio_tool_button_new_from_widget (
|
||||||
|
GTK_RADIO_TOOL_BUTTON (*toolbutton)) : gtk_radio_tool_button_new (NULL));
|
||||||
|
gtk_tool_button_set_label (GTK_TOOL_BUTTON (*toolbutton), label);
|
||||||
|
gtk_tool_button_set_stock_id (GTK_TOOL_BUTTON (*toolbutton), icon);
|
||||||
|
gtk_toolbar_insert (GTK_TOOLBAR (toolbar), GTK_TOOL_ITEM (*toolbutton), -1);
|
||||||
|
g_signal_connect (*toolbutton, "clicked",
|
||||||
|
G_CALLBACK (midori_preferences_toolbutton_clicked_cb), page);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* midori_preferences_set_settings:
|
||||||
|
* @settings: the settings
|
||||||
|
*
|
||||||
|
* Assigns a settings instance to a preferences dialog.
|
||||||
|
*
|
||||||
|
* Note: This must not be called more than once.
|
||||||
|
*
|
||||||
|
* Since 0.1.2 this is equal to setting #MidoriPreferences:settings:.
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
midori_preferences_set_settings (MidoriPreferences* preferences,
|
||||||
|
MidoriWebSettings* settings)
|
||||||
|
{
|
||||||
|
GtkWidget* header;
|
||||||
|
GtkWindow* parent;
|
||||||
|
const gchar* icon_name;
|
||||||
|
GtkSizeGroup* sizegroup;
|
||||||
|
GtkWidget* toolbar;
|
||||||
|
GtkWidget* toolbutton;
|
||||||
|
GtkWidget* page;
|
||||||
|
GtkWidget* frame;
|
||||||
|
GtkWidget* table;
|
||||||
|
GtkWidget* align;
|
||||||
|
GtkWidget* label;
|
||||||
|
GtkWidget* button;
|
||||||
|
GtkWidget* entry;
|
||||||
|
GtkWidget* hbox;
|
||||||
|
gint icon_width, icon_height;
|
||||||
|
|
||||||
|
g_return_if_fail (MIDORI_IS_PREFERENCES (preferences));
|
||||||
|
g_return_if_fail (MIDORI_IS_WEB_SETTINGS (settings));
|
||||||
|
|
||||||
|
g_return_if_fail (!preferences->notebook);
|
||||||
|
|
||||||
|
katze_assign (preferences->settings, g_object_ref (settings));
|
||||||
|
|
||||||
|
g_object_get (preferences, "transient-for", &parent, NULL);
|
||||||
|
icon_name = parent ? gtk_window_get_icon_name (parent) : NULL;
|
||||||
|
if ((header = sokoke_xfce_header_new (icon_name,
|
||||||
|
gtk_window_get_title (GTK_WINDOW (preferences)))))
|
||||||
|
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (preferences)->vbox),
|
||||||
|
header, FALSE, FALSE, 0);
|
||||||
|
|
||||||
|
preferences->notebook = gtk_notebook_new ();
|
||||||
|
gtk_container_set_border_width (GTK_CONTAINER (preferences->notebook), 6);
|
||||||
|
|
||||||
|
#if HAVE_OSX
|
||||||
|
gtk_notebook_set_show_tabs (GTK_NOTEBOOK (preferences->notebook), FALSE);
|
||||||
|
gtk_notebook_set_show_border (GTK_NOTEBOOK (preferences->notebook), FALSE);
|
||||||
|
toolbar = gtk_toolbar_new ();
|
||||||
|
gtk_toolbar_set_style (GTK_TOOLBAR (toolbar), GTK_TOOLBAR_BOTH);
|
||||||
|
gtk_toolbar_set_show_arrow (GTK_TOOLBAR (toolbar), FALSE);
|
||||||
|
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (preferences)->vbox),
|
||||||
|
toolbar, FALSE, FALSE, 0);
|
||||||
|
#else
|
||||||
|
toolbar = NULL;
|
||||||
|
#endif
|
||||||
|
toolbutton = NULL;
|
||||||
|
|
||||||
|
sizegroup = NULL;
|
||||||
|
#define PAGE_NEW(__icon, __label) \
|
||||||
|
page = gtk_vbox_new (FALSE, 0); \
|
||||||
|
midori_preferences_add_toolbutton (toolbar, &toolbutton, \
|
||||||
|
__icon, __label, page); \
|
||||||
|
if (toolbutton) g_object_set_data (G_OBJECT (toolbutton), \
|
||||||
|
"notebook", preferences->notebook); \
|
||||||
|
if (sizegroup) g_object_unref (sizegroup); \
|
||||||
|
sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL); \
|
||||||
|
gtk_container_set_border_width (GTK_CONTAINER (page), 4); \
|
||||||
|
gtk_notebook_append_page (GTK_NOTEBOOK (preferences->notebook), page, \
|
||||||
|
gtk_label_new (__label))
|
||||||
|
#define FRAME_NEW(__label) frame = sokoke_hig_frame_new (__label); \
|
||||||
|
gtk_container_set_border_width (GTK_CONTAINER (frame), 4); \
|
||||||
|
gtk_box_pack_start (GTK_BOX (page), frame, FALSE, FALSE, 0);
|
||||||
|
#define TABLE_NEW(__rows, __cols) table = gtk_table_new ( \
|
||||||
|
__rows, __cols, FALSE); \
|
||||||
|
gtk_container_set_border_width (GTK_CONTAINER (table), 4); \
|
||||||
|
gtk_container_add (GTK_CONTAINER (frame), table);
|
||||||
|
#define WIDGET_ADD(__widget, __left, __right, __top, __bottom) \
|
||||||
|
gtk_table_attach (GTK_TABLE (table), __widget \
|
||||||
|
, __left, __right, __top, __bottom \
|
||||||
|
, GTK_FILL, GTK_FILL, 8, 2)
|
||||||
|
#define FILLED_ADD(__widget, __left, __right, __top, __bottom) \
|
||||||
|
gtk_table_attach (GTK_TABLE (table), __widget \
|
||||||
|
, __left, __right, __top, __bottom\
|
||||||
|
, GTK_EXPAND | GTK_FILL, GTK_FILL, 8, 2)
|
||||||
|
#define INDENTED_ADD(__widget, __left, __right, __top, __bottom) \
|
||||||
|
align = gtk_alignment_new (0, 0.5, 0, 0); \
|
||||||
|
gtk_container_add (GTK_CONTAINER (align), __widget); \
|
||||||
|
gtk_size_group_add_widget (sizegroup, align); \
|
||||||
|
WIDGET_ADD (align, __left, __right, __top, __bottom)
|
||||||
|
#define SPANNED_ADD(__widget, __left, __right, __top, __bottom) \
|
||||||
|
align = gtk_alignment_new (0, 0.5, 0, 0); \
|
||||||
|
gtk_container_add (GTK_CONTAINER (align), __widget); \
|
||||||
|
FILLED_ADD (align, __left, __right, __top, __bottom)
|
||||||
|
/* Page "General" */
|
||||||
|
PAGE_NEW (GTK_STOCK_HOME, _("General"));
|
||||||
|
FRAME_NEW (_("Startup"));
|
||||||
|
TABLE_NEW (3, 2);
|
||||||
|
label = katze_property_label (settings, "load-on-startup");
|
||||||
|
INDENTED_ADD (label, 0, 1, 0, 1);
|
||||||
|
button = katze_property_proxy (settings, "load-on-startup", NULL);
|
||||||
|
FILLED_ADD (button, 1, 2, 0, 1);
|
||||||
|
label = katze_property_label (settings, "homepage");
|
||||||
|
INDENTED_ADD (label, 0, 1, 1, 2);
|
||||||
|
hbox = gtk_hbox_new (FALSE, 4);
|
||||||
|
entry = katze_property_proxy (settings, "homepage", NULL);
|
||||||
|
gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0);
|
||||||
|
if (parent && katze_object_has_property (parent, "uri"))
|
||||||
|
{
|
||||||
|
button = gtk_button_new ();
|
||||||
|
label = gtk_image_new_from_stock (GTK_STOCK_JUMP_TO, GTK_ICON_SIZE_BUTTON);
|
||||||
|
gtk_button_set_image (GTK_BUTTON (button), label);
|
||||||
|
gtk_widget_set_tooltip_text (button, _("Use current page as homepage"));
|
||||||
|
g_signal_connect (button, "clicked",
|
||||||
|
G_CALLBACK (midori_preferences_homepage_current_clicked_cb), settings);
|
||||||
|
gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
|
||||||
|
}
|
||||||
|
FILLED_ADD (hbox, 1, 2, 1, 2);
|
||||||
|
button = katze_property_proxy (settings, "show-crash-dialog", NULL);
|
||||||
|
SPANNED_ADD (button, 0, 2, 2, 3);
|
||||||
|
FRAME_NEW (_("Transfers"));
|
||||||
|
TABLE_NEW (4, 2);
|
||||||
|
#if WEBKIT_CHECK_VERSION (1, 1, 3)
|
||||||
|
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");
|
||||||
|
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);
|
||||||
|
|
||||||
|
/* Page "Appearance" */
|
||||||
|
PAGE_NEW (GTK_STOCK_SELECT_FONT, _("Appearance"));
|
||||||
|
FRAME_NEW (_("Font settings"));
|
||||||
|
TABLE_NEW (6, 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_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"));
|
||||||
|
INDENTED_ADD (label, 0, 1, 1, 2);
|
||||||
|
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);
|
||||||
|
label = katze_property_label (settings, "preferred-encoding");
|
||||||
|
INDENTED_ADD (label, 0, 1, 2, 3);
|
||||||
|
button = katze_property_proxy (settings, "preferred-encoding", NULL);
|
||||||
|
FILLED_ADD (button, 1, 2, 2, 3);
|
||||||
|
label = katze_property_label (settings, "default-encoding");
|
||||||
|
gtk_label_set_label (GTK_LABEL (label), _("Encoding"));
|
||||||
|
INDENTED_ADD (label, 0, 1, 3, 4);
|
||||||
|
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);
|
||||||
|
|
||||||
|
/* Page "Behavior" */
|
||||||
|
PAGE_NEW (GTK_STOCK_SELECT_COLOR, _("Behavior"));
|
||||||
|
FRAME_NEW (_("Features"));
|
||||||
|
TABLE_NEW (6, 2);
|
||||||
|
button = katze_property_proxy (settings, "auto-load-images", NULL);
|
||||||
|
gtk_button_set_label (GTK_BUTTON (button), _("Load images automatically"));
|
||||||
|
gtk_widget_set_tooltip_text (button, _("Load and display images automatically"));
|
||||||
|
INDENTED_ADD (button, 0, 1, 0, 1);
|
||||||
|
button = katze_property_proxy (settings, "auto-shrink-images", NULL);
|
||||||
|
gtk_button_set_label (GTK_BUTTON (button), _("Shrink images automatically"));
|
||||||
|
gtk_widget_set_tooltip_text (button, _("Automatically shrink standalone images to fit"));
|
||||||
|
SPANNED_ADD (button, 1, 2, 0, 1);
|
||||||
|
button = katze_property_proxy (settings, "print-backgrounds", NULL);
|
||||||
|
gtk_button_set_label (GTK_BUTTON (button), _("Print background images"));
|
||||||
|
gtk_widget_set_tooltip_text (button, _("Whether background images should be printed"));
|
||||||
|
INDENTED_ADD (button, 0, 1, 1, 2);
|
||||||
|
button = katze_property_proxy (settings, "resizable-text-areas", NULL);
|
||||||
|
gtk_button_set_label (GTK_BUTTON (button), _("Resizable text areas"));
|
||||||
|
gtk_widget_set_tooltip_text (button, _("Whether text areas are resizable"));
|
||||||
|
SPANNED_ADD (button, 1, 2, 1, 2);
|
||||||
|
button = katze_property_proxy (settings, "enable-scripts", NULL);
|
||||||
|
gtk_button_set_label (GTK_BUTTON (button), _("Enable scripts"));
|
||||||
|
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"));
|
||||||
|
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"));
|
||||||
|
gtk_widget_set_tooltip_text (button, _("Enforce a video dot density of 96 DPI"));
|
||||||
|
SPANNED_ADD (button, 0, 1, 3, 4);
|
||||||
|
button = katze_property_proxy (settings, "enable-developer-extras", NULL);
|
||||||
|
gtk_button_set_label (GTK_BUTTON (button), _("Enable developer tools"));
|
||||||
|
gtk_widget_set_tooltip_text (button, _("Enable special extensions for developers"));
|
||||||
|
SPANNED_ADD (button, 1, 2, 3, 4);
|
||||||
|
button = katze_property_proxy (settings, "zoom-text-and-images", NULL);
|
||||||
|
SPANNED_ADD (button, 0, 1, 4, 5);
|
||||||
|
button = katze_property_proxy (settings, "find-while-typing", NULL);
|
||||||
|
SPANNED_ADD (button, 1, 2, 4, 5);
|
||||||
|
|
||||||
|
/* Page "Interface" */
|
||||||
|
PAGE_NEW (GTK_STOCK_CONVERT, _("Interface"));
|
||||||
|
FRAME_NEW (_("Navigationbar"));
|
||||||
|
TABLE_NEW (2, 2);
|
||||||
|
#if !HAVE_HILDON
|
||||||
|
INDENTED_ADD (katze_property_label (settings, "toolbar-style"), 0, 1, 0, 1);
|
||||||
|
button = katze_property_proxy (settings, "toolbar-style", NULL);
|
||||||
|
FILLED_ADD (button, 1, 2, 0, 1);
|
||||||
|
#endif
|
||||||
|
button = katze_property_proxy (settings, "progress-in-location", NULL);
|
||||||
|
FILLED_ADD (button, 0, 1, 1, 2);
|
||||||
|
button = katze_property_proxy (settings, "search-engines-in-completion", NULL);
|
||||||
|
FILLED_ADD (button, 1, 2, 1, 2);
|
||||||
|
FRAME_NEW (_("Browsing"));
|
||||||
|
TABLE_NEW (5, 2);
|
||||||
|
label = katze_property_label (settings, "open-new-pages-in");
|
||||||
|
INDENTED_ADD (label, 0, 1, 0, 1);
|
||||||
|
button = katze_property_proxy (settings, "open-new-pages-in", NULL);
|
||||||
|
FILLED_ADD (button, 1, 2, 0, 1);
|
||||||
|
#if HAVE_UNIQUE
|
||||||
|
label = katze_property_label (settings, "open-external-pages-in");
|
||||||
|
INDENTED_ADD (label, 0, 1, 1, 2);
|
||||||
|
button = katze_property_proxy (settings, "open-external-pages-in", NULL);
|
||||||
|
FILLED_ADD (button, 1, 2, 1, 2);
|
||||||
|
#endif
|
||||||
|
button = katze_property_proxy (settings, "always-show-tabbar", NULL);
|
||||||
|
INDENTED_ADD (button, 0, 1, 2, 3);
|
||||||
|
button = katze_property_proxy (settings, "open-tabs-in-the-background", NULL);
|
||||||
|
INDENTED_ADD (button, 1, 2, 2, 3);
|
||||||
|
#if !HAVE_HILDON
|
||||||
|
button = katze_property_proxy (settings, "middle-click-opens-selection", NULL);
|
||||||
|
INDENTED_ADD (button, 0, 1, 3, 4);
|
||||||
|
button = katze_property_proxy (settings, "compact-sidepanel", NULL);
|
||||||
|
WIDGET_ADD (button, 1, 2, 3, 4);
|
||||||
|
#endif
|
||||||
|
/* button = katze_property_proxy (settings, "open-popups-in-tabs", NULL);
|
||||||
|
SPANNED_ADD (button, 0, 1, 4, 5);*/
|
||||||
|
button = katze_property_proxy (settings, "open-tabs-next-to-current", NULL);
|
||||||
|
WIDGET_ADD (button, 0, 1, 5, 6);
|
||||||
|
button = katze_property_proxy (settings, "close-buttons-on-tabs", NULL);
|
||||||
|
WIDGET_ADD (button, 1, 2, 5, 6);
|
||||||
|
|
||||||
|
/* Page "Network" */
|
||||||
|
PAGE_NEW (GTK_STOCK_NETWORK, _("Network"));
|
||||||
|
FRAME_NEW (_("Network"));
|
||||||
|
TABLE_NEW (5, 2);
|
||||||
|
label = katze_property_label (settings, "http-proxy");
|
||||||
|
INDENTED_ADD (label, 0, 1, 0, 1);
|
||||||
|
entry = katze_property_proxy (settings, "http-proxy", NULL);
|
||||||
|
FILLED_ADD (entry, 1, 2, 0, 1);
|
||||||
|
button = katze_property_proxy (settings, "auto-detect-proxy", NULL);
|
||||||
|
FILLED_ADD (button, 1, 2, 1, 2);
|
||||||
|
g_signal_connect (settings, "notify::auto-detect-proxy",
|
||||||
|
G_CALLBACK (midori_preferences_notify_auto_detect_proxy_cb), entry);
|
||||||
|
midori_preferences_notify_auto_detect_proxy_cb (settings, NULL, entry);
|
||||||
|
label = katze_property_label (settings, "identify-as");
|
||||||
|
INDENTED_ADD (label, 0, 1, 2, 3);
|
||||||
|
button = katze_property_proxy (settings, "identify-as", NULL);
|
||||||
|
FILLED_ADD (button, 1, 2, 2, 3);
|
||||||
|
label = katze_property_label (settings, "ident-string");
|
||||||
|
INDENTED_ADD (label, 0, 1, 3, 4);
|
||||||
|
entry = katze_property_proxy (settings, "ident-string", NULL);
|
||||||
|
g_signal_connect (settings, "notify::identify-as",
|
||||||
|
G_CALLBACK (midori_preferences_notify_identify_as_cb), entry);
|
||||||
|
midori_preferences_notify_identify_as_cb (settings, NULL, entry);
|
||||||
|
FILLED_ADD (entry, 1, 2, 3, 4);
|
||||||
|
label = katze_property_label (settings, "cache-size");
|
||||||
|
INDENTED_ADD (label, 0, 1, 4, 5);
|
||||||
|
hbox = gtk_hbox_new (FALSE, 4);
|
||||||
|
entry = katze_property_proxy (settings, "cache-size", NULL);
|
||||||
|
gtk_box_pack_start (GTK_BOX (hbox), entry, FALSE, FALSE, 0);
|
||||||
|
gtk_box_pack_start (GTK_BOX (hbox), gtk_label_new (_("MB")),
|
||||||
|
FALSE, FALSE, 0);
|
||||||
|
FILLED_ADD (hbox, 1, 2, 4, 5);
|
||||||
|
|
||||||
|
/* Page "Privacy" */
|
||||||
|
PAGE_NEW (GTK_STOCK_INDEX, _("Privacy"));
|
||||||
|
FRAME_NEW (_("Web Cookies"));
|
||||||
|
TABLE_NEW (3, 2);
|
||||||
|
label = katze_property_label (settings, "accept-cookies");
|
||||||
|
INDENTED_ADD (label, 0, 1, 0, 1);
|
||||||
|
button = katze_property_proxy (settings, "accept-cookies", NULL);
|
||||||
|
FILLED_ADD (button, 1, 2, 0, 1);
|
||||||
|
button = katze_property_proxy (settings, "original-cookies-only", NULL);
|
||||||
|
SPANNED_ADD (button, 0, 2, 1, 2);
|
||||||
|
label = katze_property_label (settings, "maximum-cookie-age");
|
||||||
|
INDENTED_ADD (label, 0, 1, 2, 3);
|
||||||
|
hbox = gtk_hbox_new (FALSE, 4);
|
||||||
|
entry = katze_property_proxy (settings, "maximum-cookie-age", NULL);
|
||||||
|
gtk_box_pack_start (GTK_BOX (hbox), entry, FALSE, FALSE, 0);
|
||||||
|
gtk_box_pack_start (GTK_BOX (hbox), gtk_label_new (_("days")),
|
||||||
|
FALSE, FALSE, 0);
|
||||||
|
FILLED_ADD (hbox, 1, 2, 2, 3);
|
||||||
|
FRAME_NEW (_("History"));
|
||||||
|
TABLE_NEW (3, 2);
|
||||||
|
button = katze_property_proxy (settings, "remember-last-visited-pages", NULL);
|
||||||
|
SPANNED_ADD (button, 0, 1, 0, 1);
|
||||||
|
hbox = gtk_hbox_new (FALSE, 4);
|
||||||
|
button = katze_property_proxy (settings, "maximum-history-age", NULL);
|
||||||
|
gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, FALSE, 0);
|
||||||
|
gtk_box_pack_start (GTK_BOX (hbox), gtk_label_new (_("days")),
|
||||||
|
FALSE, FALSE, 0);
|
||||||
|
SPANNED_ADD (hbox, 1, 2, 0, 1);
|
||||||
|
button = katze_property_proxy (settings, "remember-last-form-inputs", NULL);
|
||||||
|
SPANNED_ADD (button, 0, 2, 1, 2);
|
||||||
|
button = katze_property_proxy (settings, "remember-last-downloaded-files", NULL);
|
||||||
|
SPANNED_ADD (button, 0, 2, 2, 3);
|
||||||
|
|
||||||
|
g_object_unref (sizegroup);
|
||||||
|
gtk_box_pack_start (GTK_BOX (GTK_DIALOG (preferences)->vbox),
|
||||||
|
preferences->notebook, FALSE, FALSE, 4);
|
||||||
|
#if HAVE_OSX
|
||||||
|
GtkWidget* icon;
|
||||||
|
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);
|
||||||
|
g_signal_connect (button, "clicked",
|
||||||
|
G_CALLBACK (midori_preferences_help_clicked_cb), preferences);
|
||||||
|
gtk_box_pack_end (GTK_BOX (hbox),
|
||||||
|
button, FALSE, FALSE, 4);
|
||||||
|
gtk_box_pack_end (GTK_BOX (GTK_DIALOG (preferences)->vbox),
|
||||||
|
hbox, FALSE, FALSE, 0);
|
||||||
|
#endif
|
||||||
|
gtk_widget_show_all (GTK_DIALOG (preferences)->vbox);
|
||||||
|
}
|
57
midori/midori-preferences.h
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2008 Christian Dywan <christian@twotoasts.de>
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
See the file COPYING for the full license text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __MIDORI_PREFERENCES_H__
|
||||||
|
#define __MIDORI_PREFERENCES_H__
|
||||||
|
|
||||||
|
#include "midori-websettings.h"
|
||||||
|
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
#include <katze/katze.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define MIDORI_TYPE_PREFERENCES \
|
||||||
|
(midori_preferences_get_type ())
|
||||||
|
#define MIDORI_PREFERENCES(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_CAST ((obj), MIDORI_TYPE_PREFERENCES, MidoriPreferences))
|
||||||
|
#define MIDORI_PREFERENCES_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_CAST ((klass), MIDORI_TYPE_PREFERENCES, MidoriPreferencesClass))
|
||||||
|
#define MIDORI_IS_PREFERENCES(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), MIDORI_TYPE_PREFERENCES))
|
||||||
|
#define MIDORI_IS_PREFERENCES_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_TYPE ((klass), MIDORI_TYPE_PREFERENCES))
|
||||||
|
#define MIDORI_PREFERENCES_GET_CLASS(obj) \
|
||||||
|
(G_TYPE_INSTANCE_GET_CLASS ((obj), MIDORI_TYPE_PREFERENCES, MidoriPreferencesClass))
|
||||||
|
|
||||||
|
typedef struct _MidoriPreferences MidoriPreferences;
|
||||||
|
typedef struct _MidoriPreferencesClass MidoriPreferencesClass;
|
||||||
|
|
||||||
|
struct _MidoriPreferencesClass
|
||||||
|
{
|
||||||
|
GtkDialogClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
GType
|
||||||
|
midori_preferences_get_type (void);
|
||||||
|
|
||||||
|
GtkWidget*
|
||||||
|
midori_preferences_new (GtkWindow* parent,
|
||||||
|
MidoriWebSettings* settings);
|
||||||
|
|
||||||
|
void
|
||||||
|
midori_preferences_set_settings (MidoriPreferences* preferences,
|
||||||
|
MidoriWebSettings* settings);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __MIDORI_PREFERENCES_H__ */
|
1337
midori/midori-searchaction.c
Normal file
71
midori/midori-searchaction.h
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2008 Christian Dywan <christian@twotoasts.de>
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
See the file COPYING for the full license text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __MIDORI_SEARCH_ACTION_H__
|
||||||
|
#define __MIDORI_SEARCH_ACTION_H__
|
||||||
|
|
||||||
|
#include <katze/katze.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define MIDORI_TYPE_SEARCH_ACTION \
|
||||||
|
(midori_search_action_get_type ())
|
||||||
|
#define MIDORI_SEARCH_ACTION(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_CAST ((obj), MIDORI_TYPE_SEARCH_ACTION, MidoriSearchAction))
|
||||||
|
#define MIDORI_SEARCH_ACTION_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_CAST ((klass), MIDORI_TYPE_SEARCH_ACTION, MidoriSearchActionClass))
|
||||||
|
#define MIDORI_IS_SEARCH_ACTION(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), MIDORI_TYPE_SEARCH_ACTION))
|
||||||
|
#define MIDORI_IS_SEARCH_ACTION_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_TYPE ((klass), MIDORI_TYPE_SEARCH_ACTION))
|
||||||
|
#define MIDORI_SEARCH_ACTION_GET_CLASS(obj) \
|
||||||
|
(G_TYPE_INSTANCE_GET_CLASS ((obj), MIDORI_TYPE_SEARCH_ACTION, MidoriSearchActionClass))
|
||||||
|
|
||||||
|
typedef struct _MidoriSearchAction MidoriSearchAction;
|
||||||
|
typedef struct _MidoriSearchActionClass MidoriSearchActionClass;
|
||||||
|
|
||||||
|
GType
|
||||||
|
midori_search_action_get_type (void);
|
||||||
|
|
||||||
|
const gchar*
|
||||||
|
midori_search_action_get_text (MidoriSearchAction* action);
|
||||||
|
|
||||||
|
void
|
||||||
|
midori_search_action_set_text (MidoriSearchAction* search_action,
|
||||||
|
const gchar* text);
|
||||||
|
|
||||||
|
KatzeArray*
|
||||||
|
midori_search_action_get_search_engines (MidoriSearchAction* search_action);
|
||||||
|
|
||||||
|
void
|
||||||
|
midori_search_action_set_search_engines (MidoriSearchAction* search_action,
|
||||||
|
KatzeArray* search_engines);
|
||||||
|
|
||||||
|
KatzeItem*
|
||||||
|
midori_search_action_get_current_item (MidoriSearchAction* search_action);
|
||||||
|
|
||||||
|
void
|
||||||
|
midori_search_action_set_current_item (MidoriSearchAction* search_action,
|
||||||
|
KatzeItem* item);
|
||||||
|
|
||||||
|
KatzeItem*
|
||||||
|
midori_search_action_get_default_item (MidoriSearchAction* search_action);
|
||||||
|
|
||||||
|
void
|
||||||
|
midori_search_action_set_default_item (MidoriSearchAction* search_action,
|
||||||
|
KatzeItem* item);
|
||||||
|
|
||||||
|
GtkWidget*
|
||||||
|
midori_search_action_get_dialog (MidoriSearchAction* search_action);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __MIDORI_SEARCH_ACTION_H__ */
|
46
midori/midori-stock.h
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2007-2008 Christian Dywan <christian@twotoasts.de>
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
See the file COPYING for the full license text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __MIDORI_STOCK_H__
|
||||||
|
#define __MIDORI_STOCK_H__ 1
|
||||||
|
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
/* Custom stock items
|
||||||
|
|
||||||
|
We should distribute these
|
||||||
|
Names should match with epiphany and/ or xdg spec */
|
||||||
|
|
||||||
|
#define STOCK_BOOKMARK "stock_bookmark"
|
||||||
|
#define STOCK_BOOKMARKS "vcard"
|
||||||
|
#define STOCK_CONSOLE "terminal"
|
||||||
|
#define STOCK_EXTENSION "extension"
|
||||||
|
#define STOCK_EXTENSIONS "extension"
|
||||||
|
#define STOCK_HISTORY "document-open-recent"
|
||||||
|
#define STOCK_NEWS_FEED "news-feed"
|
||||||
|
#define STOCK_STYLE "gnome-settings-theme"
|
||||||
|
#define STOCK_STYLES "gnome-settings-theme"
|
||||||
|
#define STOCK_TRANSFER "package"
|
||||||
|
#define STOCK_TRANSFERS "package"
|
||||||
|
#define STOCK_PLUGINS GTK_STOCK_CONVERT
|
||||||
|
|
||||||
|
#define STOCK_BOOKMARK_ADD "stock_add-bookmark"
|
||||||
|
#define STOCK_HOMEPAGE GTK_STOCK_HOME
|
||||||
|
#define STOCK_IMAGE "gnome-mime-image"
|
||||||
|
#define STOCK_NETWORK_OFFLINE "network-offline"
|
||||||
|
#define STOCK_SCRIPT "stock_script"
|
||||||
|
#define STOCK_SCRIPTS "stock_script"
|
||||||
|
#define STOCK_SEND "stock_mail-send"
|
||||||
|
#define STOCK_TAB_NEW "stock_new-tab"
|
||||||
|
#define STOCK_USER_TRASH "gnome-stock-trash"
|
||||||
|
#define STOCK_WINDOW_NEW "stock_new-window"
|
||||||
|
|
||||||
|
#endif /* !__MIDORI_STOCK_H__ */
|
2681
midori/midori-view.c
Normal file
194
midori/midori-view.h
Normal file
|
@ -0,0 +1,194 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2008 Christian Dywan <christian@twotoasts.de>
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
See the file COPYING for the full license text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __MIDORI_VIEW_H__
|
||||||
|
#define __MIDORI_VIEW_H__
|
||||||
|
|
||||||
|
#include "midori-websettings.h"
|
||||||
|
|
||||||
|
#include <katze/katze.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
MIDORI_LOAD_PROVISIONAL,
|
||||||
|
MIDORI_LOAD_COMMITTED,
|
||||||
|
MIDORI_LOAD_FINISHED
|
||||||
|
} MidoriLoadStatus;
|
||||||
|
|
||||||
|
GType
|
||||||
|
midori_load_status_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
#define MIDORI_TYPE_LOAD_STATUS \
|
||||||
|
(midori_load_status_get_type ())
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
MIDORI_NEW_VIEW_TAB,
|
||||||
|
MIDORI_NEW_VIEW_BACKGROUND,
|
||||||
|
MIDORI_NEW_VIEW_WINDOW
|
||||||
|
} MidoriNewView;
|
||||||
|
|
||||||
|
GType
|
||||||
|
midori_new_view_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
#define MIDORI_TYPE_NEW_VIEW \
|
||||||
|
(midori_new_view_get_type ())
|
||||||
|
|
||||||
|
#define MIDORI_TYPE_VIEW \
|
||||||
|
(midori_view_get_type ())
|
||||||
|
#define MIDORI_VIEW(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_CAST ((obj), MIDORI_TYPE_VIEW, MidoriView))
|
||||||
|
#define MIDORI_VIEW_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_CAST ((klass), MIDORI_TYPE_VIEW, MidoriViewClass))
|
||||||
|
#define MIDORI_IS_VIEW(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), MIDORI_TYPE_VIEW))
|
||||||
|
#define MIDORI_IS_VIEW_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_TYPE ((klass), MIDORI_TYPE_VIEW))
|
||||||
|
#define MIDORI_VIEW_GET_CLASS(obj) \
|
||||||
|
(G_TYPE_INSTANCE_GET_CLASS ((obj), MIDORI_TYPE_VIEW, MidoriViewClass))
|
||||||
|
|
||||||
|
typedef struct _MidoriView MidoriView;
|
||||||
|
typedef struct _MidoriViewClass MidoriViewClass;
|
||||||
|
|
||||||
|
GType
|
||||||
|
midori_view_get_type (void);
|
||||||
|
|
||||||
|
GtkWidget*
|
||||||
|
midori_view_new (KatzeNet* net);
|
||||||
|
|
||||||
|
void
|
||||||
|
midori_view_set_settings (MidoriView* view,
|
||||||
|
MidoriWebSettings* settings);
|
||||||
|
|
||||||
|
gdouble
|
||||||
|
midori_view_get_progress (MidoriView* view);
|
||||||
|
|
||||||
|
MidoriLoadStatus
|
||||||
|
midori_view_get_load_status (MidoriView* view);
|
||||||
|
|
||||||
|
void
|
||||||
|
midori_view_set_uri (MidoriView* view,
|
||||||
|
const gchar* uri);
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
midori_view_is_blank (MidoriView* view);
|
||||||
|
|
||||||
|
const gchar*
|
||||||
|
midori_view_get_display_uri (MidoriView* view);
|
||||||
|
|
||||||
|
const gchar*
|
||||||
|
midori_view_get_display_title (MidoriView* view);
|
||||||
|
|
||||||
|
GdkPixbuf*
|
||||||
|
midori_view_get_icon (MidoriView* view);
|
||||||
|
|
||||||
|
const gchar*
|
||||||
|
midori_view_get_link_uri (MidoriView* view);
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
midori_view_has_selection (MidoriView* view);
|
||||||
|
|
||||||
|
const gchar*
|
||||||
|
midori_view_get_selected_text (MidoriView* view);
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
midori_view_can_cut_clipboard (MidoriView* view);
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
midori_view_can_copy_clipboard (MidoriView* view);
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
midori_view_can_paste_clipboard (MidoriView* view);
|
||||||
|
|
||||||
|
GtkWidget*
|
||||||
|
midori_view_get_proxy_menu_item (MidoriView* view);
|
||||||
|
|
||||||
|
GtkWidget*
|
||||||
|
midori_view_get_proxy_tab_label (MidoriView* view);
|
||||||
|
|
||||||
|
KatzeItem*
|
||||||
|
midori_view_get_proxy_item (MidoriView* view);
|
||||||
|
|
||||||
|
gfloat
|
||||||
|
midori_view_get_zoom_level (MidoriView* view);
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
midori_view_can_zoom_in (MidoriView* view);
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
midori_view_can_zoom_out (MidoriView* view);
|
||||||
|
|
||||||
|
void
|
||||||
|
midori_view_set_zoom_level (MidoriView* view,
|
||||||
|
gfloat zoom_level);
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
midori_view_can_reload (MidoriView* view);
|
||||||
|
|
||||||
|
void
|
||||||
|
midori_view_reload (MidoriView* view,
|
||||||
|
gboolean from_cache);
|
||||||
|
|
||||||
|
void
|
||||||
|
midori_view_stop_loading (MidoriView* view);
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
midori_view_can_go_back (MidoriView* view);
|
||||||
|
|
||||||
|
void
|
||||||
|
midori_view_go_back (MidoriView* view);
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
midori_view_can_go_forward (MidoriView* view);
|
||||||
|
|
||||||
|
void
|
||||||
|
midori_view_go_forward (MidoriView* view);
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
midori_view_can_print (MidoriView* view);
|
||||||
|
|
||||||
|
void
|
||||||
|
midori_view_print (MidoriView* view);
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
midori_view_can_view_source (MidoriView* view);
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
midori_view_can_find (MidoriView* view);
|
||||||
|
|
||||||
|
void
|
||||||
|
midori_view_unmark_text_matches (MidoriView* view);
|
||||||
|
|
||||||
|
void
|
||||||
|
midori_view_search_text (MidoriView* view,
|
||||||
|
const gchar* text,
|
||||||
|
gboolean case_sensitive,
|
||||||
|
gboolean forward);
|
||||||
|
|
||||||
|
void
|
||||||
|
midori_view_mark_text_matches (MidoriView* view,
|
||||||
|
const gchar* text,
|
||||||
|
gboolean case_sensitive);
|
||||||
|
|
||||||
|
void
|
||||||
|
midori_view_set_highlight_text_matches (MidoriView* view,
|
||||||
|
gboolean highlight);
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
midori_view_execute_script (MidoriView* view,
|
||||||
|
const gchar* script,
|
||||||
|
gchar** exception);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __MIDORI_VIEW_H__ */
|
263
midori/midori-viewable.c
Normal file
|
@ -0,0 +1,263 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2008 Christian Dywan <christian@twotoasts.de>
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
See the file COPYING for the full license text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "midori-viewable.h"
|
||||||
|
|
||||||
|
#include <glib/gi18n.h>
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_viewable_base_init (MidoriViewableIface* iface);
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_viewable_base_finalize (MidoriViewableIface* iface);
|
||||||
|
|
||||||
|
GType
|
||||||
|
midori_viewable_get_type (void)
|
||||||
|
{
|
||||||
|
static GType viewable_type = 0;
|
||||||
|
|
||||||
|
if (!viewable_type)
|
||||||
|
{
|
||||||
|
const GTypeInfo viewable_info =
|
||||||
|
{
|
||||||
|
sizeof (MidoriViewableIface),
|
||||||
|
(GBaseInitFunc) midori_viewable_base_init,
|
||||||
|
(GBaseFinalizeFunc) midori_viewable_base_finalize,
|
||||||
|
};
|
||||||
|
|
||||||
|
viewable_type = g_type_register_static (G_TYPE_INTERFACE,
|
||||||
|
"MidoriViewable",
|
||||||
|
&viewable_info, 0);
|
||||||
|
g_type_interface_add_prerequisite (viewable_type, GTK_TYPE_WIDGET);
|
||||||
|
}
|
||||||
|
|
||||||
|
return viewable_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const gchar*
|
||||||
|
midori_viewable_default_get_stock_id (MidoriViewable* viewable)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const gchar*
|
||||||
|
midori_viewable_default_get_label (MidoriViewable* viewable)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GtkWidget*
|
||||||
|
midori_viewable_default_get_toolbar (MidoriViewable* viewable)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_viewable_base_init (MidoriViewableIface* iface)
|
||||||
|
{
|
||||||
|
static gboolean initialized = FALSE;
|
||||||
|
|
||||||
|
if (initialized)
|
||||||
|
return;
|
||||||
|
|
||||||
|
iface->p = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
|
||||||
|
|
||||||
|
iface->get_stock_id = midori_viewable_default_get_stock_id;
|
||||||
|
iface->get_label = midori_viewable_default_get_label;
|
||||||
|
iface->get_toolbar = midori_viewable_default_get_toolbar;
|
||||||
|
|
||||||
|
initialized = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_viewable_base_finalize (MidoriViewableIface* iface)
|
||||||
|
{
|
||||||
|
g_hash_table_destroy (iface->p);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* midori_viewable_new_from_uri:
|
||||||
|
* @uri: an URI
|
||||||
|
*
|
||||||
|
* Attempts to create a new #MidoriViewable from the specified URI.
|
||||||
|
*
|
||||||
|
* The protocol of @uri must previously have been registered by
|
||||||
|
* the #MidoriViewable via midori_viewable_register_protocol().
|
||||||
|
*
|
||||||
|
* Return value: a new #MidoriViewable, or %NULL
|
||||||
|
**/
|
||||||
|
GtkWidget*
|
||||||
|
midori_viewable_new_from_uri (const gchar* uri)
|
||||||
|
{
|
||||||
|
MidoriViewableIface* iface;
|
||||||
|
gchar** parts;
|
||||||
|
gchar* type_name;
|
||||||
|
GType type;
|
||||||
|
|
||||||
|
if (!(iface = g_type_default_interface_peek (MIDORI_TYPE_VIEWABLE)))
|
||||||
|
{
|
||||||
|
g_warning ("No viewable interface available");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_return_val_if_fail (uri != NULL, NULL);
|
||||||
|
|
||||||
|
if (!g_hash_table_size (iface->p))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if ((parts = g_strsplit (uri, "://", 2)))
|
||||||
|
{
|
||||||
|
if (!(type_name = g_hash_table_lookup (iface->p, parts[0])))
|
||||||
|
{
|
||||||
|
/* FIXME: Support midori://dummy/foo */
|
||||||
|
|
||||||
|
type_name = g_hash_table_lookup (iface->p, uri);
|
||||||
|
}
|
||||||
|
g_strfreev (parts);
|
||||||
|
if (type_name)
|
||||||
|
{
|
||||||
|
type = g_type_from_name (type_name);
|
||||||
|
g_free (type_name);
|
||||||
|
if (type)
|
||||||
|
return g_object_new (type, "uri", uri, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ((parts = g_strsplit_set (uri, ":", 2)))
|
||||||
|
{
|
||||||
|
type_name = g_hash_table_lookup (iface->p, parts[0]);
|
||||||
|
g_strfreev (parts);
|
||||||
|
if (type_name)
|
||||||
|
{
|
||||||
|
type = g_type_from_name (type_name);
|
||||||
|
g_free (type_name);
|
||||||
|
if (type)
|
||||||
|
return g_object_new (type, "uri", uri, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
viewable_type_implements (GType type,
|
||||||
|
GType interface)
|
||||||
|
{
|
||||||
|
GType *interfaces;
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
if (!(interfaces = g_type_interfaces (type, NULL)))
|
||||||
|
return FALSE;
|
||||||
|
for (i = 0; interfaces[i]; i++)
|
||||||
|
{
|
||||||
|
if (interfaces[i] == interface)
|
||||||
|
{
|
||||||
|
g_free (interfaces);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g_free (interfaces);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* midori_viewable_register_protocol:
|
||||||
|
* @type: a type that implements #MidoriViewable
|
||||||
|
* @protocol: a protocol
|
||||||
|
*
|
||||||
|
* Registers the specified protocol as supported by @type.
|
||||||
|
*
|
||||||
|
* The following kinds of protocols are supported:
|
||||||
|
*
|
||||||
|
* "dummy": support URIs like "dummy://foo/bar"
|
||||||
|
* "about:dummy": support URIs like "about:dummy"
|
||||||
|
* FIXME: The following is not yet fully supported
|
||||||
|
* "midori://dummy": support URIs like "midori://dummy/foo"
|
||||||
|
*
|
||||||
|
* Return value: a new #MidoriViewable, or %NULL
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
midori_viewable_register_protocol (GType type,
|
||||||
|
const gchar* protocol)
|
||||||
|
{
|
||||||
|
MidoriViewableIface* iface;
|
||||||
|
GObjectClass* class;
|
||||||
|
|
||||||
|
if (!(iface = g_type_default_interface_peek (MIDORI_TYPE_VIEWABLE)))
|
||||||
|
{
|
||||||
|
g_warning ("No viewable interface available");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_return_if_fail (viewable_type_implements (type, MIDORI_TYPE_VIEWABLE));
|
||||||
|
|
||||||
|
if (!(class = g_type_class_peek (type)))
|
||||||
|
{
|
||||||
|
g_warning ("No class for %s available", g_type_name (type));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
g_return_if_fail (g_object_class_find_property (class, "uri"));
|
||||||
|
/* FIXME: Verify the syntax of protocol */
|
||||||
|
|
||||||
|
g_hash_table_insert (iface->p, g_strdup (protocol),
|
||||||
|
g_strdup (g_type_name (type)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* midori_viewable_get_stock_id:
|
||||||
|
* @viewable: a #MidoriViewable
|
||||||
|
*
|
||||||
|
* Retrieves the stock ID of the viewable.
|
||||||
|
*
|
||||||
|
* Return value: a stock ID
|
||||||
|
**/
|
||||||
|
const gchar*
|
||||||
|
midori_viewable_get_stock_id (MidoriViewable* viewable)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (MIDORI_IS_VIEWABLE (viewable), NULL);
|
||||||
|
|
||||||
|
return MIDORI_VIEWABLE_GET_IFACE (viewable)->get_stock_id (viewable);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* midori_viewable_get_label:
|
||||||
|
* @viewable: a #MidoriViewable
|
||||||
|
*
|
||||||
|
* Retrieves the label of the viewable.
|
||||||
|
*
|
||||||
|
* Return value: a label string
|
||||||
|
**/
|
||||||
|
const gchar*
|
||||||
|
midori_viewable_get_label (MidoriViewable* viewable)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (MIDORI_IS_VIEWABLE (viewable), NULL);
|
||||||
|
|
||||||
|
return MIDORI_VIEWABLE_GET_IFACE (viewable)->get_label (viewable);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* midori_viewable_get_toolbar:
|
||||||
|
* @viewable: a #MidoriViewable
|
||||||
|
*
|
||||||
|
* Retrieves the toolbar of the viewable.
|
||||||
|
*
|
||||||
|
* Return value: a toolbar
|
||||||
|
**/
|
||||||
|
GtkWidget*
|
||||||
|
midori_viewable_get_toolbar (MidoriViewable* viewable)
|
||||||
|
{
|
||||||
|
GtkWidget* toolbar;
|
||||||
|
|
||||||
|
g_return_val_if_fail (MIDORI_IS_VIEWABLE (viewable), NULL);
|
||||||
|
|
||||||
|
toolbar = MIDORI_VIEWABLE_GET_IFACE (viewable)->get_toolbar (viewable);
|
||||||
|
if (!toolbar)
|
||||||
|
toolbar = gtk_event_box_new ();
|
||||||
|
return toolbar;
|
||||||
|
}
|
73
midori/midori-viewable.h
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2008 Christian Dywan <christian@twotoasts.de>
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
See the file COPYING for the full license text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __MIDORI_VIEWABLE_H__
|
||||||
|
#define __MIDORI_VIEWABLE_H__
|
||||||
|
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
#include <katze/katze.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define MIDORI_TYPE_VIEWABLE \
|
||||||
|
(midori_viewable_get_type ())
|
||||||
|
#define MIDORI_VIEWABLE(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_CAST ((obj), MIDORI_TYPE_VIEWABLE, MidoriViewable))
|
||||||
|
#define MIDORI_IS_VIEWABLE(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), MIDORI_TYPE_VIEWABLE))
|
||||||
|
#define MIDORI_VIEWABLE_GET_IFACE(inst) \
|
||||||
|
(G_TYPE_INSTANCE_GET_INTERFACE ((inst), MIDORI_TYPE_VIEWABLE, \
|
||||||
|
MidoriViewableIface))
|
||||||
|
|
||||||
|
typedef struct _MidoriViewable MidoriViewable;
|
||||||
|
typedef struct _MidoriViewableIface MidoriViewableIface;
|
||||||
|
|
||||||
|
struct _MidoriViewableIface
|
||||||
|
{
|
||||||
|
GTypeInterface base_iface;
|
||||||
|
|
||||||
|
/* Virtual functions */
|
||||||
|
const gchar*
|
||||||
|
(*get_stock_id) (MidoriViewable* viewable);
|
||||||
|
|
||||||
|
const gchar*
|
||||||
|
(*get_label) (MidoriViewable* viewable);
|
||||||
|
|
||||||
|
GtkWidget*
|
||||||
|
(*get_toolbar) (MidoriViewable* viewable);
|
||||||
|
|
||||||
|
/* Private data */
|
||||||
|
gpointer p;
|
||||||
|
};
|
||||||
|
|
||||||
|
GType
|
||||||
|
midori_viewable_get_type (void);
|
||||||
|
|
||||||
|
GtkWidget*
|
||||||
|
midori_viewable_new_from_uri (const gchar* uri);
|
||||||
|
|
||||||
|
void
|
||||||
|
midori_viewable_register_protocol (GType type,
|
||||||
|
const gchar* protocol);
|
||||||
|
|
||||||
|
const gchar*
|
||||||
|
midori_viewable_get_stock_id (MidoriViewable* viewable);
|
||||||
|
|
||||||
|
const gchar*
|
||||||
|
midori_viewable_get_label (MidoriViewable* viewable);
|
||||||
|
|
||||||
|
GtkWidget*
|
||||||
|
midori_viewable_get_toolbar (MidoriViewable* viewable);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __MIDORI_VIEWABLE_H__ */
|
1399
midori/midori-websettings.c
Normal file
144
midori/midori-websettings.h
Normal file
|
@ -0,0 +1,144 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2008 Christian Dywan <christian@twotoasts.de>
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
See the file COPYING for the full license text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __MIDORI_WEB_SETTINGS_H__
|
||||||
|
#define __MIDORI_WEB_SETTINGS_H__
|
||||||
|
|
||||||
|
#include <webkit/webkit.h>
|
||||||
|
|
||||||
|
#include <katze/katze.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define MIDORI_TYPE_WEB_SETTINGS \
|
||||||
|
(midori_web_settings_get_type ())
|
||||||
|
#define MIDORI_WEB_SETTINGS(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_CAST ((obj), MIDORI_TYPE_WEB_SETTINGS, MidoriWebSettings))
|
||||||
|
#define MIDORI_WEB_SETTINGS_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_CAST ((klass), MIDORI_TYPE_WEB_SETTINGS, MidoriWebSettingsClass))
|
||||||
|
#define MIDORI_IS_WEB_SETTINGS(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), MIDORI_TYPE_WEB_SETTINGS))
|
||||||
|
#define MIDORI_IS_WEB_SETTINGS_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_TYPE ((klass), MIDORI_TYPE_WEB_SETTINGS))
|
||||||
|
#define MIDORI_WEB_SETTINGS_GET_CLASS(obj) \
|
||||||
|
(G_TYPE_INSTANCE_GET_CLASS ((obj), MIDORI_TYPE_WEB_SETTINGS, MidoriWebSettingsClass))
|
||||||
|
|
||||||
|
typedef struct _MidoriWebSettings MidoriWebSettings;
|
||||||
|
typedef struct _MidoriWebSettingsClass MidoriWebSettingsClass;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
MIDORI_WINDOW_NORMAL,
|
||||||
|
MIDORI_WINDOW_MINIMIZED,
|
||||||
|
MIDORI_WINDOW_MAXIMIZED,
|
||||||
|
MIDORI_WINDOW_FULLSCREEN,
|
||||||
|
} MidoriWindowState;
|
||||||
|
|
||||||
|
GType
|
||||||
|
midori_window_state_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
#define MIDORI_TYPE_WINDOW_STATE \
|
||||||
|
(midori_window_state_get_type ())
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
MIDORI_STARTUP_BLANK_PAGE,
|
||||||
|
MIDORI_STARTUP_HOMEPAGE,
|
||||||
|
MIDORI_STARTUP_LAST_OPEN_PAGES
|
||||||
|
} MidoriStartup;
|
||||||
|
|
||||||
|
GType
|
||||||
|
midori_startup_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
#define MIDORI_TYPE_STARTUP \
|
||||||
|
(midori_startup_get_type ())
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
MIDORI_ENCODING_CHINESE,
|
||||||
|
MIDORI_ENCODING_JAPANESE,
|
||||||
|
MIDORI_ENCODING_RUSSIAN,
|
||||||
|
MIDORI_ENCODING_UNICODE,
|
||||||
|
MIDORI_ENCODING_WESTERN,
|
||||||
|
MIDORI_ENCODING_CUSTOM
|
||||||
|
} MidoriPreferredEncoding;
|
||||||
|
|
||||||
|
GType
|
||||||
|
midori_preferred_encoding_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
#define MIDORI_TYPE_PREFERRED_ENCODING \
|
||||||
|
(midori_preferred_encoding_get_type ())
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
MIDORI_NEW_PAGE_TAB,
|
||||||
|
MIDORI_NEW_PAGE_WINDOW,
|
||||||
|
MIDORI_NEW_PAGE_CURRENT
|
||||||
|
} MidoriNewPage;
|
||||||
|
|
||||||
|
GType
|
||||||
|
midori_new_page_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
#define MIDORI_TYPE_NEW_PAGE \
|
||||||
|
(midori_new_page_get_type ())
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
MIDORI_TOOLBAR_DEFAULT,
|
||||||
|
MIDORI_TOOLBAR_ICONS,
|
||||||
|
MIDORI_TOOLBAR_TEXT,
|
||||||
|
MIDORI_TOOLBAR_BOTH,
|
||||||
|
MIDORI_TOOLBAR_BOTH_HORIZ
|
||||||
|
} MidoriToolbarStyle;
|
||||||
|
|
||||||
|
GType
|
||||||
|
midori_toolbar_style_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
#define MIDORI_TYPE_TOOLBAR_STYLE \
|
||||||
|
(midori_toolbar_style_get_type ())
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
MIDORI_ACCEPT_COOKIES_ALL,
|
||||||
|
MIDORI_ACCEPT_COOKIES_SESSION,
|
||||||
|
MIDORI_ACCEPT_COOKIES_NONE
|
||||||
|
} MidoriAcceptCookies;
|
||||||
|
|
||||||
|
GType
|
||||||
|
midori_accept_cookies_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
#define MIDORI_TYPE_ACCEPT_COOKIES \
|
||||||
|
(midori_accept_cookies_get_type ())
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
MIDORI_IDENT_MIDORI,
|
||||||
|
MIDORI_IDENT_SAFARI,
|
||||||
|
MIDORI_IDENT_FIREFOX,
|
||||||
|
MIDORI_IDENT_EXPLORER,
|
||||||
|
MIDORI_IDENT_CUSTOM
|
||||||
|
} MidoriIdentity;
|
||||||
|
|
||||||
|
GType
|
||||||
|
midori_identity_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
#define MIDORI_TYPE_IDENTITY \
|
||||||
|
(midori_identity_get_type ())
|
||||||
|
|
||||||
|
GType
|
||||||
|
midori_web_settings_get_type (void);
|
||||||
|
|
||||||
|
MidoriWebSettings*
|
||||||
|
midori_web_settings_new (void);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __MIDORI_WEB_SETTINGS_H__ */
|
38
midori/midori.h
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2008-2009 Christian Dywan <christian@twotoasts.de>
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
See the file COPYING for the full license text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __MIDORI_H__
|
||||||
|
#define __MIDORI_H__
|
||||||
|
|
||||||
|
#include "midori-app.h"
|
||||||
|
#include "midori-array.h"
|
||||||
|
#include "midori-browser.h"
|
||||||
|
#include "midori-extension.h"
|
||||||
|
#include "midori-locationaction.h"
|
||||||
|
#include "midori-locationentry.h"
|
||||||
|
#include "midori-panel.h"
|
||||||
|
#include "midori-preferences.h"
|
||||||
|
#include "midori-searchaction.h"
|
||||||
|
#include "midori-stock.h"
|
||||||
|
#include "midori-view.h"
|
||||||
|
#include "midori-viewable.h"
|
||||||
|
#include "midori-websettings.h"
|
||||||
|
|
||||||
|
/* For convenience, include localization header */
|
||||||
|
#include <glib/gi18n.h>
|
||||||
|
|
||||||
|
#define MIDORI_CHECK_VERSION(major, minor, micro) \
|
||||||
|
(MIDORI_MAJOR_VERSION > (major) || \
|
||||||
|
(MIDORI_MAJOR_VERSION == (major) && MIDORI_MINOR_VERSION > (minor)) || \
|
||||||
|
(MIDORI_MAJOR_VERSION == (major) && MIDORI_MINOR_VERSION == (minor) && \
|
||||||
|
MIDORI_MICRO_VERSION >= (micro)))
|
||||||
|
|
||||||
|
#endif /* __MIDORI_H__ */
|
882
midori/sokoke.c
Normal file
|
@ -0,0 +1,882 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2007-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 "sokoke.h"
|
||||||
|
#include "midori-stock.h"
|
||||||
|
|
||||||
|
#if HAVE_CONFIG_H
|
||||||
|
#include <config.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if HAVE_UNISTD_H
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <gdk/gdkkeysyms.h>
|
||||||
|
#include <glib/gi18n.h>
|
||||||
|
#include <glib/gprintf.h>
|
||||||
|
#include <glib/gstdio.h>
|
||||||
|
|
||||||
|
#if HAVE_LIBIDN
|
||||||
|
#include <stringprep.h>
|
||||||
|
#include <punycode.h>
|
||||||
|
#include <idna.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static gchar*
|
||||||
|
sokoke_js_string_utf8 (JSStringRef js_string)
|
||||||
|
{
|
||||||
|
size_t size_utf8;
|
||||||
|
gchar* string_utf8;
|
||||||
|
|
||||||
|
g_return_val_if_fail (js_string, NULL);
|
||||||
|
|
||||||
|
size_utf8 = JSStringGetMaximumUTF8CStringSize (js_string);
|
||||||
|
string_utf8 = g_new (gchar, size_utf8);
|
||||||
|
JSStringGetUTF8CString (js_string, string_utf8, size_utf8);
|
||||||
|
return string_utf8;
|
||||||
|
}
|
||||||
|
|
||||||
|
gchar*
|
||||||
|
sokoke_js_script_eval (JSContextRef js_context,
|
||||||
|
const gchar* script,
|
||||||
|
gchar** exception)
|
||||||
|
{
|
||||||
|
gchar* value;
|
||||||
|
JSStringRef js_value_string;
|
||||||
|
|
||||||
|
g_return_val_if_fail (js_context, FALSE);
|
||||||
|
g_return_val_if_fail (script, FALSE);
|
||||||
|
|
||||||
|
JSStringRef js_script = JSStringCreateWithUTF8CString (script);
|
||||||
|
JSValueRef js_exception = NULL;
|
||||||
|
JSValueRef js_value = JSEvaluateScript (js_context, js_script,
|
||||||
|
JSContextGetGlobalObject (js_context), NULL, 0, &js_exception);
|
||||||
|
if (!js_value && exception)
|
||||||
|
{
|
||||||
|
JSStringRef js_message = JSValueToStringCopy (js_context,
|
||||||
|
js_exception, NULL);
|
||||||
|
*exception = sokoke_js_string_utf8 (js_message);
|
||||||
|
JSStringRelease (js_message);
|
||||||
|
js_value = JSValueMakeNull (js_context);
|
||||||
|
}
|
||||||
|
JSStringRelease (js_script);
|
||||||
|
|
||||||
|
js_value_string = JSValueToStringCopy (js_context, js_value, NULL);
|
||||||
|
value = sokoke_js_string_utf8 (js_value_string);
|
||||||
|
JSStringRelease (js_value_string);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
error_dialog (const gchar* short_message,
|
||||||
|
const gchar* detailed_message)
|
||||||
|
{
|
||||||
|
GtkWidget* dialog = gtk_message_dialog_new (
|
||||||
|
NULL, 0, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK, "%s", short_message);
|
||||||
|
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
|
||||||
|
"%s", detailed_message);
|
||||||
|
gtk_widget_show (dialog);
|
||||||
|
g_signal_connect_swapped (dialog, "response",
|
||||||
|
G_CALLBACK (gtk_widget_destroy), dialog);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
sokoke_spawn_program (const gchar* command,
|
||||||
|
const gchar* argument)
|
||||||
|
{
|
||||||
|
gchar* argument_escaped;
|
||||||
|
gchar* command_ready;
|
||||||
|
gchar** argv;
|
||||||
|
GError* error;
|
||||||
|
|
||||||
|
g_return_val_if_fail (command != NULL, FALSE);
|
||||||
|
g_return_val_if_fail (argument != NULL, FALSE);
|
||||||
|
|
||||||
|
argument_escaped = g_shell_quote (argument);
|
||||||
|
if (strstr (command, "%s"))
|
||||||
|
command_ready = g_strdup_printf (command, argument_escaped);
|
||||||
|
else
|
||||||
|
command_ready = g_strconcat (command, " ", argument_escaped, NULL);
|
||||||
|
|
||||||
|
error = NULL;
|
||||||
|
if (!g_shell_parse_argv (command_ready, NULL, &argv, &error))
|
||||||
|
{
|
||||||
|
error_dialog (_("Could not run external program."), error->message);
|
||||||
|
g_error_free (error);
|
||||||
|
g_free (command_ready);
|
||||||
|
g_free (argument_escaped);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
error = NULL;
|
||||||
|
if (!g_spawn_async (NULL, argv, NULL,
|
||||||
|
(GSpawnFlags)G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
|
||||||
|
NULL, NULL, NULL, &error))
|
||||||
|
{
|
||||||
|
error_dialog (_("Could not run external program."), error->message);
|
||||||
|
g_error_free (error);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_strfreev (argv);
|
||||||
|
g_free (command_ready);
|
||||||
|
g_free (argument_escaped);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gchar*
|
||||||
|
sokoke_idn_to_punycode (gchar* uri)
|
||||||
|
{
|
||||||
|
#if HAVE_LIBIDN
|
||||||
|
gchar* proto;
|
||||||
|
gchar* hostname;
|
||||||
|
gchar* path;
|
||||||
|
char *s;
|
||||||
|
uint32_t *q;
|
||||||
|
int rc;
|
||||||
|
gchar *result;
|
||||||
|
|
||||||
|
if ((proto = g_utf8_strchr (uri, -1, ':')))
|
||||||
|
{
|
||||||
|
gulong offset;
|
||||||
|
gchar* buffer;
|
||||||
|
|
||||||
|
/* 'file' URIs don't have a hostname */
|
||||||
|
if (!strcmp (proto, "file"))
|
||||||
|
return uri;
|
||||||
|
|
||||||
|
offset = g_utf8_pointer_to_offset (uri, proto);
|
||||||
|
buffer = g_malloc0 (offset + 1);
|
||||||
|
g_utf8_strncpy (buffer, uri, offset);
|
||||||
|
proto = buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
path = NULL;
|
||||||
|
if ((hostname = g_utf8_strchr (uri, -1, '/')))
|
||||||
|
{
|
||||||
|
if (hostname[1] == '/')
|
||||||
|
hostname += 2;
|
||||||
|
if ((path = g_utf8_strchr (hostname, -1, '/')))
|
||||||
|
{
|
||||||
|
gulong offset = g_utf8_pointer_to_offset (hostname, path);
|
||||||
|
gchar* buffer = g_malloc0 (offset + 1);
|
||||||
|
g_utf8_strncpy (buffer, hostname, offset);
|
||||||
|
hostname = buffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
hostname = g_strdup (uri);
|
||||||
|
|
||||||
|
if (!(q = stringprep_utf8_to_ucs4 (hostname, -1, NULL)))
|
||||||
|
{
|
||||||
|
g_free (proto);
|
||||||
|
g_free (hostname);
|
||||||
|
return uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = idna_to_ascii_4z (q, &s, IDNA_ALLOW_UNASSIGNED);
|
||||||
|
free (q);
|
||||||
|
if (rc != IDNA_SUCCESS)
|
||||||
|
{
|
||||||
|
g_free (proto);
|
||||||
|
g_free (hostname);
|
||||||
|
return uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (proto)
|
||||||
|
{
|
||||||
|
result = g_strconcat (proto, "://", s, path ? path : "", NULL);
|
||||||
|
g_free (proto);
|
||||||
|
if (path)
|
||||||
|
g_free (hostname);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
result = g_strdup (s);
|
||||||
|
g_free (uri);
|
||||||
|
free (s);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
#else
|
||||||
|
return uri;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
gchar*
|
||||||
|
sokoke_magic_uri (const gchar* uri,
|
||||||
|
KatzeArray* search_engines)
|
||||||
|
{
|
||||||
|
gchar* current_dir;
|
||||||
|
gchar* result;
|
||||||
|
gchar** parts;
|
||||||
|
gchar* search;
|
||||||
|
const gchar* search_uri;
|
||||||
|
KatzeItem* item;
|
||||||
|
|
||||||
|
g_return_val_if_fail (uri, NULL);
|
||||||
|
g_return_val_if_fail (!search_engines ||
|
||||||
|
katze_array_is_a (search_engines, KATZE_TYPE_ITEM), NULL);
|
||||||
|
|
||||||
|
/* Just return if it's a javascript: or mailto: uri */
|
||||||
|
if (g_str_has_prefix (uri, "javascript:")
|
||||||
|
|| g_str_has_prefix (uri, "mailto:")
|
||||||
|
|| g_str_has_prefix (uri, "data:"))
|
||||||
|
return g_strdup (uri);
|
||||||
|
/* Add file:// if we have a local path */
|
||||||
|
if (g_path_is_absolute (uri))
|
||||||
|
return g_strconcat ("file://", uri, NULL);
|
||||||
|
/* Construct an absolute path if the file is relative */
|
||||||
|
if (g_file_test (uri, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))
|
||||||
|
{
|
||||||
|
current_dir = g_get_current_dir ();
|
||||||
|
result = g_strconcat ("file://", current_dir,
|
||||||
|
G_DIR_SEPARATOR_S, uri, NULL);
|
||||||
|
g_free (current_dir);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
/* Do we have a protocol? */
|
||||||
|
if (g_strstr_len (uri, 8, "://"))
|
||||||
|
return sokoke_idn_to_punycode (g_strdup (uri));
|
||||||
|
|
||||||
|
/* Do we have a domain, ip address or localhost? */
|
||||||
|
search = NULL;
|
||||||
|
if (!strchr (uri, ' ') &&
|
||||||
|
((search = strchr (uri, ':')) || (search = strchr (uri, '@'))) &&
|
||||||
|
search[0] && !g_ascii_isalpha (search[1]))
|
||||||
|
return sokoke_idn_to_punycode (g_strconcat ("http://", uri, NULL));
|
||||||
|
if (!strcmp (uri, "localhost") || g_str_has_prefix (uri, "localhost/"))
|
||||||
|
return g_strconcat ("http://", uri, NULL);
|
||||||
|
parts = g_strsplit (uri, ".", 0);
|
||||||
|
if (!search && parts[0] && parts[1])
|
||||||
|
{
|
||||||
|
if (!(parts[1][1] == '\0' && !g_ascii_isalpha (parts[1][0])))
|
||||||
|
if (!strchr (parts[0], ' ') && !strchr (parts[1], ' '))
|
||||||
|
if ((search = g_strconcat ("http://", uri, NULL)))
|
||||||
|
{
|
||||||
|
g_strfreev (parts);
|
||||||
|
return sokoke_idn_to_punycode (search);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g_strfreev (parts);
|
||||||
|
/* We don't want to search? So return early. */
|
||||||
|
if (!search_engines)
|
||||||
|
return g_strdup (uri);
|
||||||
|
search = NULL;
|
||||||
|
search_uri = NULL;
|
||||||
|
/* Do we have a keyword and a string? */
|
||||||
|
parts = g_strsplit (uri, " ", 2);
|
||||||
|
if (parts[0] && 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_);
|
||||||
|
}
|
||||||
|
g_strfreev (parts);
|
||||||
|
return search;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
sokoke_combo_box_add_strings (GtkComboBox* combobox,
|
||||||
|
const gchar* label_first, ...)
|
||||||
|
{
|
||||||
|
const gchar* label;
|
||||||
|
|
||||||
|
/* Add a number of strings to a combobox, terminated with NULL
|
||||||
|
This works only for text comboboxes */
|
||||||
|
va_list args;
|
||||||
|
va_start (args, label_first);
|
||||||
|
|
||||||
|
for (label = label_first; label; label = va_arg (args, const gchar*))
|
||||||
|
gtk_combo_box_append_text (combobox, label);
|
||||||
|
|
||||||
|
va_end (args);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sokoke_widget_set_visible (GtkWidget* widget, gboolean visible)
|
||||||
|
{
|
||||||
|
/* Show or hide the widget */
|
||||||
|
if (visible)
|
||||||
|
gtk_widget_show (widget);
|
||||||
|
else
|
||||||
|
gtk_widget_hide (widget);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
sokoke_container_show_children (GtkContainer* container)
|
||||||
|
{
|
||||||
|
/* Show every child but not the container itself */
|
||||||
|
gtk_container_foreach (container, (GtkCallback)(gtk_widget_show_all), NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
sokoke_widget_popup (GtkWidget* widget,
|
||||||
|
GtkMenu* menu,
|
||||||
|
GdkEventButton* event,
|
||||||
|
SokokeMenuPos pos)
|
||||||
|
{
|
||||||
|
katze_widget_popup (widget, menu, event, (KatzeMenuPos)pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
SOKOKE_DESKTOP_UNTESTED,
|
||||||
|
SOKOKE_DESKTOP_XFCE,
|
||||||
|
SOKOKE_DESKTOP_OSX,
|
||||||
|
SOKOKE_DESKTOP_UNKNOWN
|
||||||
|
} SokokeDesktop;
|
||||||
|
|
||||||
|
static SokokeDesktop
|
||||||
|
sokoke_get_desktop (void)
|
||||||
|
{
|
||||||
|
#if HAVE_OSX
|
||||||
|
return SOKOKE_DESKTOP_OSX;
|
||||||
|
#else
|
||||||
|
static SokokeDesktop desktop = SOKOKE_DESKTOP_UNTESTED;
|
||||||
|
if (G_UNLIKELY (desktop == SOKOKE_DESKTOP_UNTESTED))
|
||||||
|
{
|
||||||
|
/* Are we running in Xfce? */
|
||||||
|
gint result;
|
||||||
|
gchar *out = NULL;
|
||||||
|
gboolean success = g_spawn_command_line_sync ("xprop -root _DT_SAVE_MODE",
|
||||||
|
&out, NULL, &result, NULL);
|
||||||
|
if (success && ! result && out != NULL && strstr (out, "xfce4") != NULL)
|
||||||
|
desktop = SOKOKE_DESKTOP_XFCE;
|
||||||
|
else
|
||||||
|
desktop = SOKOKE_DESKTOP_UNKNOWN;
|
||||||
|
g_free (out);
|
||||||
|
}
|
||||||
|
|
||||||
|
return desktop;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sokoke_xfce_header_new:
|
||||||
|
* @icon: an icon name
|
||||||
|
* @title: the title of the header
|
||||||
|
*
|
||||||
|
* Creates an Xfce style header *if* Xfce is running.
|
||||||
|
*
|
||||||
|
* Return value: A #GtkWidget or %NULL
|
||||||
|
*
|
||||||
|
* Since 0.1.2 @icon may be NULL, and a default is used.
|
||||||
|
**/
|
||||||
|
GtkWidget*
|
||||||
|
sokoke_xfce_header_new (const gchar* icon,
|
||||||
|
const gchar* title)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (title, NULL);
|
||||||
|
|
||||||
|
/* Create an xfce header with icon and title
|
||||||
|
This returns NULL if the desktop is not Xfce */
|
||||||
|
if (sokoke_get_desktop () == SOKOKE_DESKTOP_XFCE)
|
||||||
|
{
|
||||||
|
GtkWidget* entry;
|
||||||
|
gchar* markup;
|
||||||
|
GtkWidget* xfce_heading;
|
||||||
|
GtkWidget* hbox;
|
||||||
|
GtkWidget* image;
|
||||||
|
GtkWidget* label;
|
||||||
|
GtkWidget* vbox;
|
||||||
|
GtkWidget* separator;
|
||||||
|
|
||||||
|
xfce_heading = gtk_event_box_new ();
|
||||||
|
entry = gtk_entry_new ();
|
||||||
|
gtk_widget_modify_bg (xfce_heading, GTK_STATE_NORMAL,
|
||||||
|
&entry->style->base[GTK_STATE_NORMAL]);
|
||||||
|
hbox = gtk_hbox_new (FALSE, 12);
|
||||||
|
gtk_container_set_border_width (GTK_CONTAINER (hbox), 6);
|
||||||
|
if (icon)
|
||||||
|
image = gtk_image_new_from_icon_name (icon, GTK_ICON_SIZE_DIALOG);
|
||||||
|
else
|
||||||
|
image = gtk_image_new_from_stock (GTK_STOCK_PREFERENCES,
|
||||||
|
GTK_ICON_SIZE_DIALOG);
|
||||||
|
gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0);
|
||||||
|
label = gtk_label_new (NULL);
|
||||||
|
gtk_widget_modify_fg (label, GTK_STATE_NORMAL
|
||||||
|
, &entry->style->text[GTK_STATE_NORMAL]);
|
||||||
|
markup = g_strdup_printf ("<span size='large' weight='bold'>%s</span>",
|
||||||
|
title);
|
||||||
|
gtk_label_set_markup (GTK_LABEL (label), markup);
|
||||||
|
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
|
||||||
|
gtk_container_add (GTK_CONTAINER (xfce_heading), hbox);
|
||||||
|
g_free (markup);
|
||||||
|
gtk_widget_destroy (entry);
|
||||||
|
|
||||||
|
vbox = gtk_vbox_new (FALSE, 0);
|
||||||
|
gtk_box_pack_start (GTK_BOX (vbox), xfce_heading, FALSE, FALSE, 0);
|
||||||
|
|
||||||
|
separator = gtk_hseparator_new ();
|
||||||
|
gtk_box_pack_start (GTK_BOX (vbox), separator, FALSE, FALSE, 0);
|
||||||
|
|
||||||
|
return vbox;
|
||||||
|
}
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
/* Create a frame with no actual frame but a bold label and indentation */
|
||||||
|
GtkWidget* frame = gtk_frame_new (NULL);
|
||||||
|
gchar* title_bold = g_strdup_printf ("<b>%s</b>", title);
|
||||||
|
GtkWidget* label = gtk_label_new (NULL);
|
||||||
|
gtk_label_set_markup (GTK_LABEL (label), title_bold);
|
||||||
|
g_free (title_bold);
|
||||||
|
gtk_frame_set_label_widget (GTK_FRAME (frame), label);
|
||||||
|
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE);
|
||||||
|
return frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
sokoke_widget_set_pango_font_style (GtkWidget* widget,
|
||||||
|
PangoStyle style)
|
||||||
|
{
|
||||||
|
/* Conveniently change the pango font style
|
||||||
|
For some reason we need to reset if we actually want the normal style */
|
||||||
|
if (style == PANGO_STYLE_NORMAL)
|
||||||
|
gtk_widget_modify_font (widget, NULL);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PangoFontDescription* font_description = pango_font_description_new ();
|
||||||
|
pango_font_description_set_style (font_description, PANGO_STYLE_ITALIC);
|
||||||
|
gtk_widget_modify_font (widget, font_description);
|
||||||
|
pango_font_description_free (font_description);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
sokoke_on_entry_focus_in_event (GtkEntry* entry,
|
||||||
|
GdkEventFocus* event,
|
||||||
|
gpointer userdata)
|
||||||
|
{
|
||||||
|
gint has_default = GPOINTER_TO_INT (
|
||||||
|
g_object_get_data (G_OBJECT (entry), "sokoke_has_default"));
|
||||||
|
if (has_default)
|
||||||
|
{
|
||||||
|
gtk_entry_set_text (entry, "");
|
||||||
|
g_object_set_data (G_OBJECT (entry), "sokoke_has_default",
|
||||||
|
GINT_TO_POINTER (0));
|
||||||
|
sokoke_widget_set_pango_font_style (GTK_WIDGET (entry),
|
||||||
|
PANGO_STYLE_NORMAL);
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
sokoke_on_entry_focus_out_event (GtkEntry* entry,
|
||||||
|
GdkEventFocus* event,
|
||||||
|
gpointer userdata)
|
||||||
|
{
|
||||||
|
const gchar* text = gtk_entry_get_text (entry);
|
||||||
|
if (text && !*text)
|
||||||
|
{
|
||||||
|
const gchar* default_text = (const gchar*)g_object_get_data (
|
||||||
|
G_OBJECT (entry), "sokoke_default_text");
|
||||||
|
gtk_entry_set_text (entry, default_text);
|
||||||
|
g_object_set_data (G_OBJECT (entry),
|
||||||
|
"sokoke_has_default", GINT_TO_POINTER (1));
|
||||||
|
sokoke_widget_set_pango_font_style (GTK_WIDGET (entry),
|
||||||
|
PANGO_STYLE_ITALIC);
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
sokoke_entry_set_default_text (GtkEntry* entry,
|
||||||
|
const gchar* default_text)
|
||||||
|
{
|
||||||
|
/* Note: The default text initially overwrites any previous text */
|
||||||
|
gchar* old_value = g_object_get_data (G_OBJECT (entry),
|
||||||
|
"sokoke_default_text");
|
||||||
|
if (!old_value)
|
||||||
|
{
|
||||||
|
g_object_set_data (G_OBJECT (entry), "sokoke_has_default",
|
||||||
|
GINT_TO_POINTER (1));
|
||||||
|
sokoke_widget_set_pango_font_style (GTK_WIDGET (entry),
|
||||||
|
PANGO_STYLE_ITALIC);
|
||||||
|
gtk_entry_set_text (entry, default_text);
|
||||||
|
}
|
||||||
|
else if (!GTK_WIDGET_HAS_FOCUS (GTK_WIDGET (entry)))
|
||||||
|
{
|
||||||
|
gint has_default = GPOINTER_TO_INT (
|
||||||
|
g_object_get_data (G_OBJECT (entry), "sokoke_has_default"));
|
||||||
|
if (has_default)
|
||||||
|
{
|
||||||
|
gtk_entry_set_text (entry, default_text);
|
||||||
|
sokoke_widget_set_pango_font_style (GTK_WIDGET (entry),
|
||||||
|
PANGO_STYLE_ITALIC);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g_object_set_data (G_OBJECT (entry), "sokoke_default_text",
|
||||||
|
(gpointer)default_text);
|
||||||
|
g_signal_connect (entry, "focus-in-event",
|
||||||
|
G_CALLBACK (sokoke_on_entry_focus_in_event), NULL);
|
||||||
|
g_signal_connect (entry, "focus-out-event",
|
||||||
|
G_CALLBACK (sokoke_on_entry_focus_out_event), NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
gchar*
|
||||||
|
sokoke_key_file_get_string_default (GKeyFile* key_file,
|
||||||
|
const gchar* group,
|
||||||
|
const gchar* key,
|
||||||
|
const gchar* default_value,
|
||||||
|
GError** error)
|
||||||
|
{
|
||||||
|
gchar* value = g_key_file_get_string (key_file, group, key, error);
|
||||||
|
return value == NULL ? g_strdup (default_value) : value;
|
||||||
|
}
|
||||||
|
|
||||||
|
gint
|
||||||
|
sokoke_key_file_get_integer_default (GKeyFile* key_file,
|
||||||
|
const gchar* group,
|
||||||
|
const gchar* key,
|
||||||
|
const gint default_value,
|
||||||
|
GError** error)
|
||||||
|
{
|
||||||
|
if (!g_key_file_has_key (key_file, group, key, NULL))
|
||||||
|
return default_value;
|
||||||
|
return g_key_file_get_integer (key_file, group, key, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
gdouble
|
||||||
|
sokoke_key_file_get_double_default (GKeyFile* key_file,
|
||||||
|
const gchar* group,
|
||||||
|
const gchar* key,
|
||||||
|
const gdouble default_value,
|
||||||
|
GError** error)
|
||||||
|
{
|
||||||
|
if (!g_key_file_has_key (key_file, group, key, NULL))
|
||||||
|
return default_value;
|
||||||
|
return g_key_file_get_double (key_file, group, key, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
sokoke_key_file_get_boolean_default (GKeyFile* key_file,
|
||||||
|
const gchar* group,
|
||||||
|
const gchar* key,
|
||||||
|
const gboolean default_value,
|
||||||
|
GError** error)
|
||||||
|
{
|
||||||
|
if (!g_key_file_has_key (key_file, group, key, NULL))
|
||||||
|
return default_value;
|
||||||
|
return g_key_file_get_boolean (key_file, group, key, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
sokoke_key_file_save_to_file (GKeyFile* key_file,
|
||||||
|
const gchar* filename,
|
||||||
|
GError** error)
|
||||||
|
{
|
||||||
|
gchar* data;
|
||||||
|
FILE* fp;
|
||||||
|
|
||||||
|
data = g_key_file_to_data (key_file, NULL, error);
|
||||||
|
if (!data)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (!(fp = fopen (filename, "w")))
|
||||||
|
{
|
||||||
|
*error = g_error_new (G_FILE_ERROR, G_FILE_ERROR_ACCES,
|
||||||
|
_("Writing failed."));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
fputs (data, fp);
|
||||||
|
fclose (fp);
|
||||||
|
g_free (data);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
sokoke_widget_get_text_size (GtkWidget* widget,
|
||||||
|
const gchar* text,
|
||||||
|
gint* width,
|
||||||
|
gint* height)
|
||||||
|
{
|
||||||
|
PangoLayout* layout = gtk_widget_create_pango_layout (widget, text);
|
||||||
|
pango_layout_get_pixel_size (layout, width, height);
|
||||||
|
g_object_unref (layout);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sokoke_action_create_popup_menu_item:
|
||||||
|
* @action: a #GtkAction
|
||||||
|
*
|
||||||
|
* Creates a menu item from an action, just like
|
||||||
|
* gtk_action_create_menu_item(), but it won't
|
||||||
|
* display an accelerator.
|
||||||
|
*
|
||||||
|
* Note: This menu item is not a proxy and will
|
||||||
|
* not reflect any changes to the action.
|
||||||
|
*
|
||||||
|
* Return value: a new #GtkMenuItem
|
||||||
|
**/
|
||||||
|
GtkWidget*
|
||||||
|
sokoke_action_create_popup_menu_item (GtkAction* action)
|
||||||
|
{
|
||||||
|
GtkWidget* menuitem;
|
||||||
|
GtkWidget* icon;
|
||||||
|
gchar* label;
|
||||||
|
gchar* stock_id;
|
||||||
|
gchar* icon_name;
|
||||||
|
gboolean sensitive;
|
||||||
|
gboolean visible;
|
||||||
|
|
||||||
|
g_return_val_if_fail (GTK_IS_ACTION (action), NULL);
|
||||||
|
|
||||||
|
g_object_get (action,
|
||||||
|
"label", &label,
|
||||||
|
"stock-id", &stock_id,
|
||||||
|
"icon-name", &icon_name,
|
||||||
|
"sensitive", &sensitive,
|
||||||
|
"visible", &visible,
|
||||||
|
NULL);
|
||||||
|
if (GTK_IS_TOGGLE_ACTION (action))
|
||||||
|
{
|
||||||
|
menuitem = gtk_check_menu_item_new_with_mnemonic (label);
|
||||||
|
gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (menuitem),
|
||||||
|
gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)));
|
||||||
|
}
|
||||||
|
else if (stock_id)
|
||||||
|
{
|
||||||
|
if (label)
|
||||||
|
{
|
||||||
|
menuitem = gtk_image_menu_item_new_with_mnemonic (label);
|
||||||
|
icon = gtk_image_new_from_stock (stock_id, GTK_ICON_SIZE_MENU);
|
||||||
|
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), icon);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
menuitem = gtk_image_menu_item_new_from_stock (stock_id, NULL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
menuitem = gtk_image_menu_item_new_with_mnemonic (label);
|
||||||
|
if (icon_name)
|
||||||
|
{
|
||||||
|
icon = gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_MENU);
|
||||||
|
gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (menuitem), icon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gtk_widget_set_sensitive (menuitem, sensitive);
|
||||||
|
sokoke_widget_set_visible (menuitem, visible);
|
||||||
|
g_signal_connect_swapped (menuitem, "activate",
|
||||||
|
G_CALLBACK (gtk_action_activate), action);
|
||||||
|
|
||||||
|
return menuitem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sokoke_image_menu_item_new_ellipsized:
|
||||||
|
* @label: the text of the menu item
|
||||||
|
*
|
||||||
|
* Creates a new #GtkImageMenuItem containing an ellipsized label.
|
||||||
|
*
|
||||||
|
* Return value: a new #GtkImageMenuItem
|
||||||
|
**/
|
||||||
|
GtkWidget*
|
||||||
|
sokoke_image_menu_item_new_ellipsized (const gchar* label)
|
||||||
|
{
|
||||||
|
return katze_image_menu_item_new_ellipsized (label);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sokoke_time_t_to_julian:
|
||||||
|
* @timestamp: a time_t timestamp value
|
||||||
|
*
|
||||||
|
* Calculates a unix timestamp to a julian day value.
|
||||||
|
*
|
||||||
|
* Return value: an integer.
|
||||||
|
**/
|
||||||
|
gint64
|
||||||
|
sokoke_time_t_to_julian (const time_t* timestamp)
|
||||||
|
{
|
||||||
|
GDate* date;
|
||||||
|
gint64 julian;
|
||||||
|
|
||||||
|
date = g_date_new ();
|
||||||
|
|
||||||
|
g_date_set_time_t (date, *timestamp);
|
||||||
|
julian = (gint64)g_date_get_julian (date);
|
||||||
|
|
||||||
|
g_date_free (date);
|
||||||
|
|
||||||
|
return julian;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sokoke_register_stock_items:
|
||||||
|
*
|
||||||
|
* Registers several custom stock items used throughout Midori.
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
sokoke_register_stock_items (void)
|
||||||
|
{
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
const gchar* stock_id;
|
||||||
|
const gchar* label;
|
||||||
|
GdkModifierType modifier;
|
||||||
|
guint keyval;
|
||||||
|
const gchar* fallback;
|
||||||
|
} FatStockItem;
|
||||||
|
GtkIconSource* icon_source;
|
||||||
|
GtkIconSet* icon_set;
|
||||||
|
GtkIconFactory* factory = gtk_icon_factory_new ();
|
||||||
|
gsize i;
|
||||||
|
|
||||||
|
static FatStockItem items[] =
|
||||||
|
{
|
||||||
|
{ STOCK_EXTENSION, NULL, 0, 0, GTK_STOCK_CONVERT },
|
||||||
|
{ STOCK_IMAGE, NULL, 0, 0, GTK_STOCK_ORIENTATION_PORTRAIT },
|
||||||
|
{ STOCK_NEWS_FEED, NULL, 0, 0, GTK_STOCK_INDEX },
|
||||||
|
{ STOCK_SCRIPT, NULL, 0, 0, GTK_STOCK_EXECUTE },
|
||||||
|
{ STOCK_STYLE, NULL, 0, 0, GTK_STOCK_SELECT_COLOR },
|
||||||
|
{ STOCK_TRANSFER, NULL, 0, 0, GTK_STOCK_SAVE },
|
||||||
|
|
||||||
|
{ STOCK_BOOKMARK, N_("_Bookmark"), 0, 0, GTK_STOCK_FILE },
|
||||||
|
{ STOCK_BOOKMARKS, N_("_Bookmarks"), 0, 0, GTK_STOCK_DIRECTORY },
|
||||||
|
{ STOCK_BOOKMARK_ADD, N_("_Add Bookmark"), 0, 0, GTK_STOCK_ADD },
|
||||||
|
{ STOCK_CONSOLE, N_("_Console"), 0, 0, GTK_STOCK_DIALOG_WARNING },
|
||||||
|
{ STOCK_EXTENSIONS, N_("_Extensions"), 0, 0, GTK_STOCK_CONVERT },
|
||||||
|
{ STOCK_HISTORY, N_("_History"), 0, 0, GTK_STOCK_SORT_ASCENDING },
|
||||||
|
{ STOCK_HOMEPAGE, N_("_Homepage"), 0, 0, GTK_STOCK_HOME },
|
||||||
|
{ STOCK_SCRIPTS, N_("_Userscripts"), 0, 0, GTK_STOCK_EXECUTE },
|
||||||
|
{ 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_USER_TRASH, N_("_Closed Tabs and Windows"), 0, 0, "gtk-undo-ltr" },
|
||||||
|
{ STOCK_WINDOW_NEW, N_("New _Window"), 0, 0, GTK_STOCK_ADD },
|
||||||
|
};
|
||||||
|
|
||||||
|
for (i = 0; i < G_N_ELEMENTS (items); i++)
|
||||||
|
{
|
||||||
|
icon_set = gtk_icon_set_new ();
|
||||||
|
icon_source = gtk_icon_source_new ();
|
||||||
|
if (items[i].fallback)
|
||||||
|
{
|
||||||
|
gtk_icon_source_set_icon_name (icon_source, items[i].fallback);
|
||||||
|
items[i].fallback = NULL;
|
||||||
|
gtk_icon_set_add_source (icon_set, icon_source);
|
||||||
|
}
|
||||||
|
gtk_icon_source_set_icon_name (icon_source, items[i].stock_id);
|
||||||
|
gtk_icon_set_add_source (icon_set, icon_source);
|
||||||
|
gtk_icon_source_free (icon_source);
|
||||||
|
gtk_icon_factory_add (factory, items[i].stock_id, icon_set);
|
||||||
|
gtk_icon_set_unref (icon_set);
|
||||||
|
}
|
||||||
|
gtk_stock_add ((GtkStockItem*)items, G_N_ELEMENTS (items));
|
||||||
|
gtk_icon_factory_add_default (factory);
|
||||||
|
g_object_unref (factory);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sokoke_set_config_dir:
|
||||||
|
* @new_config_dir: an absolute path, or %NULL
|
||||||
|
*
|
||||||
|
* Retrieves and/ or sets the base configuration folder.
|
||||||
|
*
|
||||||
|
* Return value: the configuration folder, or %NULL
|
||||||
|
**/
|
||||||
|
const gchar*
|
||||||
|
sokoke_set_config_dir (const gchar* new_config_dir)
|
||||||
|
{
|
||||||
|
static gchar* config_dir = NULL;
|
||||||
|
|
||||||
|
if (config_dir)
|
||||||
|
return config_dir;
|
||||||
|
|
||||||
|
if (!new_config_dir)
|
||||||
|
config_dir = g_build_filename (g_get_user_config_dir (),
|
||||||
|
PACKAGE_NAME, NULL);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (g_path_is_absolute (new_config_dir), NULL);
|
||||||
|
katze_assign (config_dir, g_strdup (new_config_dir));
|
||||||
|
}
|
||||||
|
|
||||||
|
return config_dir;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sokoke_remove_path:
|
||||||
|
* @path: an absolute path
|
||||||
|
* @ignore_errors: keep removing even if an error occurred
|
||||||
|
*
|
||||||
|
* Removes the file at @path or the folder including any
|
||||||
|
* child folders and files if @path is a folder.
|
||||||
|
*
|
||||||
|
* If @ignore_errors is %TRUE and @path is a folder with
|
||||||
|
* children, one of which can't be removed, remaining
|
||||||
|
* children will be deleted nevertheless
|
||||||
|
* If @ignore_errors is %FALSE and @path is a folder, the
|
||||||
|
* removal process will cancel immediately.
|
||||||
|
*
|
||||||
|
* Return value: %TRUE on success, %FALSE if an error occurred
|
||||||
|
**/
|
||||||
|
gboolean
|
||||||
|
sokoke_remove_path (const gchar* path,
|
||||||
|
gboolean ignore_errors)
|
||||||
|
{
|
||||||
|
GDir* dir = g_dir_open (path, 0, NULL);
|
||||||
|
const gchar* name;
|
||||||
|
|
||||||
|
if (!dir)
|
||||||
|
return g_remove (path) == 0;
|
||||||
|
|
||||||
|
while ((name = g_dir_read_name (dir)))
|
||||||
|
{
|
||||||
|
gchar* sub_path = g_build_filename (path, name, NULL);
|
||||||
|
if (!sokoke_remove_path (sub_path, ignore_errors) && !ignore_errors)
|
||||||
|
return FALSE;
|
||||||
|
g_free (sub_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_dir_close (dir);
|
||||||
|
g_rmdir (path);
|
||||||
|
return TRUE;
|
||||||
|
}
|
137
midori/sokoke.h
Normal file
|
@ -0,0 +1,137 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2007-2008 Christian Dywan <christian@twotoasts.de>
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
See the file COPYING for the full license text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __SOKOKE_H__
|
||||||
|
#define __SOKOKE_H__ 1
|
||||||
|
|
||||||
|
#include <katze/katze.h>
|
||||||
|
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
#include <JavaScriptCore/JavaScript.h>
|
||||||
|
|
||||||
|
gchar*
|
||||||
|
sokoke_js_script_eval (JSContextRef js_context,
|
||||||
|
const gchar* script,
|
||||||
|
gchar** exception);
|
||||||
|
|
||||||
|
/* Many themes need this hack for small toolbars to work */
|
||||||
|
#define GTK_ICON_SIZE_SMALL_TOOLBAR GTK_ICON_SIZE_BUTTON
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
sokoke_spawn_program (const gchar* command,
|
||||||
|
const gchar* argument);
|
||||||
|
|
||||||
|
gchar*
|
||||||
|
sokoke_magic_uri (const gchar* uri,
|
||||||
|
KatzeArray* search_engines);
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
SOKOKE_MENU_POSITION_CURSOR = 0,
|
||||||
|
SOKOKE_MENU_POSITION_LEFT,
|
||||||
|
SOKOKE_MENU_POSITION_RIGHT
|
||||||
|
} SokokeMenuPos;
|
||||||
|
|
||||||
|
void
|
||||||
|
sokoke_combo_box_add_strings (GtkComboBox* combobox,
|
||||||
|
const gchar* label_first,
|
||||||
|
...);
|
||||||
|
|
||||||
|
void
|
||||||
|
sokoke_widget_set_visible (GtkWidget* widget,
|
||||||
|
gboolean visible);
|
||||||
|
|
||||||
|
void
|
||||||
|
sokoke_container_show_children (GtkContainer* container);
|
||||||
|
|
||||||
|
void
|
||||||
|
sokoke_widget_popup (GtkWidget* widget,
|
||||||
|
GtkMenu* menu,
|
||||||
|
GdkEventButton* event,
|
||||||
|
SokokeMenuPos pos);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
void
|
||||||
|
sokoke_widget_set_pango_font_style (GtkWidget* widget,
|
||||||
|
PangoStyle style);
|
||||||
|
|
||||||
|
void
|
||||||
|
sokoke_entry_set_default_text (GtkEntry* entry,
|
||||||
|
const gchar* default_text);
|
||||||
|
|
||||||
|
gchar*
|
||||||
|
sokoke_key_file_get_string_default (GKeyFile* key_file,
|
||||||
|
const gchar* group,
|
||||||
|
const gchar* key,
|
||||||
|
const gchar* default_value,
|
||||||
|
GError** error);
|
||||||
|
|
||||||
|
gint
|
||||||
|
sokoke_key_file_get_integer_default (GKeyFile* key_file,
|
||||||
|
const gchar* group,
|
||||||
|
const gchar* key,
|
||||||
|
const gint default_value,
|
||||||
|
GError** error);
|
||||||
|
|
||||||
|
gdouble
|
||||||
|
sokoke_key_file_get_double_default (GKeyFile* key_file,
|
||||||
|
const gchar* group,
|
||||||
|
const gchar* key,
|
||||||
|
gdouble default_value,
|
||||||
|
GError** error);
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
sokoke_key_file_get_boolean_default (GKeyFile* key_file,
|
||||||
|
const gchar* group,
|
||||||
|
const gchar* key,
|
||||||
|
gboolean default_value,
|
||||||
|
GError** error);
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
sokoke_key_file_save_to_file (GKeyFile* key_file,
|
||||||
|
const gchar* filename,
|
||||||
|
GError** error);
|
||||||
|
|
||||||
|
void
|
||||||
|
sokoke_widget_get_text_size (GtkWidget* widget,
|
||||||
|
const gchar* text,
|
||||||
|
gint* width,
|
||||||
|
gint* height);
|
||||||
|
|
||||||
|
GtkWidget*
|
||||||
|
sokoke_action_create_popup_menu_item (GtkAction* action);
|
||||||
|
|
||||||
|
GtkWidget*
|
||||||
|
sokoke_image_menu_item_new_ellipsized (const gchar* label);
|
||||||
|
|
||||||
|
gint64
|
||||||
|
sokoke_time_t_to_julian (const time_t* timestamp);
|
||||||
|
|
||||||
|
void
|
||||||
|
sokoke_register_stock_items (void);
|
||||||
|
|
||||||
|
const gchar*
|
||||||
|
sokoke_set_config_dir (const gchar* new_config_dir);
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
sokoke_remove_path (const gchar* path,
|
||||||
|
gboolean ignore_errors);
|
||||||
|
|
||||||
|
#endif /* !__SOKOKE_H__ */
|
31
midori/wscript_build
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
#! /usr/bin/env python
|
||||||
|
# WAF build script for midori
|
||||||
|
# This file is licensed under the terms of the expat license, see the file EXPAT.
|
||||||
|
|
||||||
|
import platform
|
||||||
|
|
||||||
|
obj = bld.new_task_gen ('cc', 'staticlib')
|
||||||
|
obj.name = 'midori'
|
||||||
|
obj.target = 'midori'
|
||||||
|
obj.includes = '. ..'
|
||||||
|
obj.find_sources_in_dirs ('.', excludes=['main.c'])
|
||||||
|
obj.add_marshal_file ('marshal.list', 'midori_cclosure_marshal')
|
||||||
|
obj.uselib = 'UNIQUE LIBSOUP LIBIDN GIO GTK SQLITE WEBKIT LIBXML HILDON'
|
||||||
|
obj.uselib_local = 'katze'
|
||||||
|
obj.install_path = None
|
||||||
|
|
||||||
|
obj = bld.new_task_gen ('cc', 'staticlib')
|
||||||
|
obj.name = 'panels'
|
||||||
|
obj.target = 'panels'
|
||||||
|
obj.includes = '. ..'
|
||||||
|
obj.find_sources_in_dirs ('../panels')
|
||||||
|
obj.uselib = 'UNIQUE LIBSOUP GMODULE GTHREAD GIO GTK SQLITE WEBKIT LIBXML'
|
||||||
|
obj.uselib_local = 'midori'
|
||||||
|
obj.install_path = None
|
||||||
|
|
||||||
|
obj = bld.new_task_gen ('cc', 'program')
|
||||||
|
obj.target = 'midori'
|
||||||
|
obj.includes = '. .. ../panels'
|
||||||
|
obj.source = 'main.c'
|
||||||
|
obj.uselib = 'UNIQUE LIBSOUP GMODULE GTHREAD GIO GTK SQLITE WEBKIT LIBXML'
|
||||||
|
obj.uselib_local = 'panels'
|
1081
panels/midori-addons.c
Normal file
67
panels/midori-addons.h
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2008 Christian Dywan <christian@twotoasts.de>
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
See the file COPYING for the full license text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __MIDORI_ADDONS_H__
|
||||||
|
#define __MIDORI_ADDONS_H__
|
||||||
|
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
#include <katze/katze.h>
|
||||||
|
|
||||||
|
#include "midori-viewable.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define MIDORI_TYPE_ADDONS \
|
||||||
|
(midori_addons_get_type ())
|
||||||
|
#define MIDORI_ADDONS(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_CAST ((obj), MIDORI_TYPE_ADDONS, MidoriAddons))
|
||||||
|
#define MIDORI_ADDONS_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_CAST ((klass), MIDORI_TYPE_ADDONS, MidoriAddonsClass))
|
||||||
|
#define MIDORI_IS_ADDONS(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), MIDORI_TYPE_ADDONS))
|
||||||
|
#define MIDORI_IS_ADDONS_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_TYPE ((klass), MIDORI_TYPE_ADDONS))
|
||||||
|
#define MIDORI_ADDONS_GET_CLASS(obj) \
|
||||||
|
(G_TYPE_INSTANCE_GET_CLASS ((obj), MIDORI_TYPE_ADDONS, MidoriAddonsClass))
|
||||||
|
|
||||||
|
typedef struct _MidoriAddons MidoriAddons;
|
||||||
|
typedef struct _MidoriAddonsClass MidoriAddonsClass;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
MIDORI_ADDON_NONE,
|
||||||
|
MIDORI_ADDON_USER_SCRIPTS,
|
||||||
|
MIDORI_ADDON_USER_STYLES
|
||||||
|
} MidoriAddonKind;
|
||||||
|
|
||||||
|
GType
|
||||||
|
midori_addon_kind_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
#define MIDORI_TYPE_ADDON_KIND \
|
||||||
|
(midori_addon_kind_get_type ())
|
||||||
|
|
||||||
|
GType
|
||||||
|
midori_addons_get_type (void);
|
||||||
|
|
||||||
|
GtkWidget*
|
||||||
|
midori_addons_new (MidoriAddonKind kind,
|
||||||
|
GtkWidget* web_widget);
|
||||||
|
|
||||||
|
GtkWidget*
|
||||||
|
midori_addons_get_toolbar (MidoriViewable* addons);
|
||||||
|
|
||||||
|
void
|
||||||
|
midori_addons_update_elements (MidoriAddons* addons);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __MIDORI_ADDONS_H__ */
|
959
panels/midori-bookmarks.c
Normal file
|
@ -0,0 +1,959 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2008-2009 Christian Dywan <christian@twotoasts.de>
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
See the file COPYING for the full license text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "midori-bookmarks.h"
|
||||||
|
|
||||||
|
#include "midori-app.h"
|
||||||
|
#include "midori-browser.h"
|
||||||
|
#include "midori-stock.h"
|
||||||
|
#include "midori-view.h"
|
||||||
|
#include "midori-viewable.h"
|
||||||
|
|
||||||
|
#include "sokoke.h"
|
||||||
|
|
||||||
|
#include <glib/gi18n.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <katze/katze.h>
|
||||||
|
#include <gdk/gdkkeysyms.h>
|
||||||
|
|
||||||
|
void
|
||||||
|
midori_browser_edit_bookmark_dialog_new (MidoriBrowser* browser,
|
||||||
|
KatzeItem* bookmark,
|
||||||
|
gboolean new_bookmark,
|
||||||
|
gboolean is_folder);
|
||||||
|
|
||||||
|
struct _MidoriBookmarks
|
||||||
|
{
|
||||||
|
GtkVBox parent_instance;
|
||||||
|
|
||||||
|
GtkWidget* toolbar;
|
||||||
|
GtkWidget* edit;
|
||||||
|
GtkWidget* delete;
|
||||||
|
GtkWidget* treeview;
|
||||||
|
MidoriApp* app;
|
||||||
|
KatzeArray* array;
|
||||||
|
KatzeNet* net;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _MidoriBookmarksClass
|
||||||
|
{
|
||||||
|
GtkVBoxClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_bookmarks_viewable_iface_init (MidoriViewableIface* iface);
|
||||||
|
|
||||||
|
G_DEFINE_TYPE_WITH_CODE (MidoriBookmarks, midori_bookmarks, GTK_TYPE_VBOX,
|
||||||
|
G_IMPLEMENT_INTERFACE (MIDORI_TYPE_VIEWABLE,
|
||||||
|
midori_bookmarks_viewable_iface_init));
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
PROP_0,
|
||||||
|
|
||||||
|
PROP_APP
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_bookmarks_finalize (GObject* object);
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_bookmarks_set_property (GObject* object,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue* value,
|
||||||
|
GParamSpec* pspec);
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_bookmarks_get_property (GObject* object,
|
||||||
|
guint prop_id,
|
||||||
|
GValue* value,
|
||||||
|
GParamSpec* pspec);
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_bookmarks_class_init (MidoriBookmarksClass* class)
|
||||||
|
{
|
||||||
|
GObjectClass* gobject_class;
|
||||||
|
GParamFlags flags;
|
||||||
|
|
||||||
|
gobject_class = G_OBJECT_CLASS (class);
|
||||||
|
gobject_class->finalize = midori_bookmarks_finalize;
|
||||||
|
gobject_class->set_property = midori_bookmarks_set_property;
|
||||||
|
gobject_class->get_property = midori_bookmarks_get_property;
|
||||||
|
|
||||||
|
flags = G_PARAM_READWRITE | G_PARAM_CONSTRUCT;
|
||||||
|
|
||||||
|
g_object_class_install_property (gobject_class,
|
||||||
|
PROP_APP,
|
||||||
|
g_param_spec_object (
|
||||||
|
"app",
|
||||||
|
"App",
|
||||||
|
"The app",
|
||||||
|
MIDORI_TYPE_APP,
|
||||||
|
flags));
|
||||||
|
}
|
||||||
|
|
||||||
|
static const gchar*
|
||||||
|
midori_bookmarks_get_label (MidoriViewable* viewable)
|
||||||
|
{
|
||||||
|
return _("Bookmarks");
|
||||||
|
}
|
||||||
|
|
||||||
|
static const gchar*
|
||||||
|
midori_bookmarks_get_stock_id (MidoriViewable* viewable)
|
||||||
|
{
|
||||||
|
return STOCK_BOOKMARKS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_bookmarks_add_clicked_cb (GtkWidget* toolitem)
|
||||||
|
{
|
||||||
|
GtkWidget* browser = gtk_widget_get_toplevel (toolitem);
|
||||||
|
/* FIXME: Take selected folder into account */
|
||||||
|
midori_browser_edit_bookmark_dialog_new (MIDORI_BROWSER (browser),
|
||||||
|
NULL, TRUE, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_bookmarks_edit_clicked_cb (GtkWidget* toolitem,
|
||||||
|
MidoriBookmarks* bookmarks)
|
||||||
|
{
|
||||||
|
GtkTreeModel* model;
|
||||||
|
GtkTreeIter iter;
|
||||||
|
|
||||||
|
if (katze_tree_view_get_selected_iter (GTK_TREE_VIEW (bookmarks->treeview),
|
||||||
|
&model, &iter))
|
||||||
|
{
|
||||||
|
KatzeItem* item;
|
||||||
|
gboolean is_separator;
|
||||||
|
|
||||||
|
gtk_tree_model_get (model, &iter, 0, &item, -1);
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_object_unref (item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_bookmarks_delete_clicked_cb (GtkWidget* toolitem,
|
||||||
|
MidoriBookmarks* bookmarks)
|
||||||
|
{
|
||||||
|
GtkTreeModel* model;
|
||||||
|
GtkTreeIter iter;
|
||||||
|
|
||||||
|
if (katze_tree_view_get_selected_iter (GTK_TREE_VIEW (bookmarks->treeview),
|
||||||
|
&model, &iter))
|
||||||
|
{
|
||||||
|
KatzeItem* item;
|
||||||
|
KatzeArray* parent;
|
||||||
|
|
||||||
|
gtk_tree_model_get (model, &iter, 0, &item, -1);
|
||||||
|
|
||||||
|
/* FIXME: Even toplevel items should technically have a parent */
|
||||||
|
g_return_if_fail (katze_item_get_parent (item));
|
||||||
|
|
||||||
|
parent = katze_item_get_parent (item);
|
||||||
|
katze_array_remove_item (parent, item);
|
||||||
|
|
||||||
|
g_object_unref (item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_bookmarks_folder_clicked_cb (GtkWidget* toolitem)
|
||||||
|
{
|
||||||
|
GtkWidget* browser = gtk_widget_get_toplevel (toolitem);
|
||||||
|
/* FIXME: Take selected folder into account */
|
||||||
|
midori_browser_edit_bookmark_dialog_new (MIDORI_BROWSER (browser),
|
||||||
|
NULL, TRUE, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_bookmarks_cursor_or_row_changed_cb (GtkTreeView* treeview,
|
||||||
|
MidoriBookmarks* bookmarks)
|
||||||
|
{
|
||||||
|
GtkTreeModel* model;
|
||||||
|
GtkTreeIter iter;
|
||||||
|
KatzeItem* item;
|
||||||
|
|
||||||
|
if (!bookmarks->edit)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (katze_tree_view_get_selected_iter (treeview, &model, &iter))
|
||||||
|
{
|
||||||
|
gboolean is_separator;
|
||||||
|
|
||||||
|
gtk_tree_model_get (model, &iter, 0, &item, -1);
|
||||||
|
|
||||||
|
is_separator = !KATZE_IS_ARRAY (item) && !katze_item_get_uri (item);
|
||||||
|
gtk_widget_set_sensitive (bookmarks->edit, !is_separator);
|
||||||
|
gtk_widget_set_sensitive (bookmarks->delete, TRUE);
|
||||||
|
|
||||||
|
g_object_unref (item);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gtk_widget_set_sensitive (bookmarks->edit, FALSE);
|
||||||
|
gtk_widget_set_sensitive (bookmarks->delete, FALSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static GtkWidget*
|
||||||
|
midori_bookmarks_get_toolbar (MidoriViewable* viewable)
|
||||||
|
{
|
||||||
|
MidoriBookmarks* bookmarks = MIDORI_BOOKMARKS (viewable);
|
||||||
|
|
||||||
|
if (!bookmarks->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);
|
||||||
|
bookmarks->toolbar = toolbar;
|
||||||
|
toolitem = gtk_tool_button_new_from_stock (GTK_STOCK_ADD);
|
||||||
|
gtk_widget_set_tooltip_text (GTK_WIDGET (toolitem),
|
||||||
|
_("Add a new bookmark"));
|
||||||
|
gtk_tool_item_set_is_important (toolitem, TRUE);
|
||||||
|
g_signal_connect (toolitem, "clicked",
|
||||||
|
G_CALLBACK (midori_bookmarks_add_clicked_cb), bookmarks);
|
||||||
|
gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1);
|
||||||
|
gtk_widget_show (GTK_WIDGET (toolitem));
|
||||||
|
toolitem = gtk_tool_button_new_from_stock (GTK_STOCK_EDIT);
|
||||||
|
gtk_widget_set_tooltip_text (GTK_WIDGET (toolitem),
|
||||||
|
_("Edit the selected bookmark"));
|
||||||
|
g_signal_connect (toolitem, "clicked",
|
||||||
|
G_CALLBACK (midori_bookmarks_edit_clicked_cb), bookmarks);
|
||||||
|
gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1);
|
||||||
|
gtk_widget_show (GTK_WIDGET (toolitem));
|
||||||
|
bookmarks->edit = GTK_WIDGET (toolitem);
|
||||||
|
toolitem = gtk_tool_button_new_from_stock (GTK_STOCK_DELETE);
|
||||||
|
gtk_widget_set_tooltip_text (GTK_WIDGET (toolitem),
|
||||||
|
_("Delete the selected bookmark"));
|
||||||
|
g_signal_connect (toolitem, "clicked",
|
||||||
|
G_CALLBACK (midori_bookmarks_delete_clicked_cb), bookmarks);
|
||||||
|
gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1);
|
||||||
|
gtk_widget_show (GTK_WIDGET (toolitem));
|
||||||
|
bookmarks->delete = GTK_WIDGET (toolitem);
|
||||||
|
toolitem = gtk_separator_tool_item_new ();
|
||||||
|
gtk_separator_tool_item_set_draw (GTK_SEPARATOR_TOOL_ITEM (toolitem), FALSE);
|
||||||
|
gtk_tool_item_set_expand (toolitem, TRUE);
|
||||||
|
gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1);
|
||||||
|
gtk_widget_show (GTK_WIDGET (toolitem));
|
||||||
|
toolitem = gtk_tool_button_new_from_stock (GTK_STOCK_DIRECTORY);
|
||||||
|
gtk_widget_set_tooltip_text (GTK_WIDGET (toolitem),
|
||||||
|
_("Add a new folder"));
|
||||||
|
g_signal_connect (toolitem, "clicked",
|
||||||
|
G_CALLBACK (midori_bookmarks_folder_clicked_cb), bookmarks);
|
||||||
|
gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1);
|
||||||
|
gtk_widget_show (GTK_WIDGET (toolitem));
|
||||||
|
|
||||||
|
midori_bookmarks_cursor_or_row_changed_cb (
|
||||||
|
GTK_TREE_VIEW (bookmarks->treeview), bookmarks);
|
||||||
|
g_signal_connect (bookmarks->edit, "destroy",
|
||||||
|
G_CALLBACK (gtk_widget_destroyed), &bookmarks->edit);
|
||||||
|
g_signal_connect (bookmarks->delete, "destroy",
|
||||||
|
G_CALLBACK (gtk_widget_destroyed), &bookmarks->delete);
|
||||||
|
}
|
||||||
|
|
||||||
|
return bookmarks->toolbar;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_bookmarks_viewable_iface_init (MidoriViewableIface* iface)
|
||||||
|
{
|
||||||
|
iface->get_stock_id = midori_bookmarks_get_stock_id;
|
||||||
|
iface->get_label = midori_bookmarks_get_label;
|
||||||
|
iface->get_toolbar = midori_bookmarks_get_toolbar;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_bookmarks_add_item_cb (KatzeArray* array,
|
||||||
|
KatzeItem* added_item,
|
||||||
|
MidoriBookmarks* bookmarks);
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_bookmarks_remove_item_cb (KatzeArray* array,
|
||||||
|
KatzeItem* removed_item,
|
||||||
|
MidoriBookmarks* bookmarks);
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_bookmarks_clear_cb (KatzeArray* array,
|
||||||
|
MidoriBookmarks* bookmarks);
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_bookmarks_disconnect_folder (MidoriBookmarks* bookmarks,
|
||||||
|
KatzeArray* array)
|
||||||
|
{
|
||||||
|
KatzeItem* item;
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
g_return_if_fail (KATZE_IS_ARRAY (array));
|
||||||
|
|
||||||
|
g_signal_handlers_disconnect_by_func (array,
|
||||||
|
midori_bookmarks_add_item_cb, bookmarks);
|
||||||
|
g_signal_handlers_disconnect_by_func (array,
|
||||||
|
midori_bookmarks_remove_item_cb, bookmarks);
|
||||||
|
g_signal_handlers_disconnect_by_func (array,
|
||||||
|
midori_bookmarks_clear_cb, bookmarks);
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
while ((item = katze_array_get_nth_item (array, i++)))
|
||||||
|
{
|
||||||
|
if (KATZE_IS_ARRAY (item))
|
||||||
|
midori_bookmarks_disconnect_folder (bookmarks, KATZE_ARRAY (item));
|
||||||
|
g_object_unref (item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_bookmarks_add_item_cb (KatzeArray* array,
|
||||||
|
KatzeItem* added_item,
|
||||||
|
MidoriBookmarks* bookmarks)
|
||||||
|
{
|
||||||
|
GtkTreeModel* model;
|
||||||
|
GtkTreeIter iter;
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
g_return_if_fail (KATZE_IS_ARRAY (array));
|
||||||
|
g_return_if_fail (KATZE_IS_ITEM (added_item));
|
||||||
|
|
||||||
|
if (KATZE_IS_ARRAY (added_item))
|
||||||
|
{
|
||||||
|
g_signal_connect (added_item, "add-item",
|
||||||
|
G_CALLBACK (midori_bookmarks_add_item_cb), bookmarks);
|
||||||
|
g_signal_connect (added_item, "remove-item",
|
||||||
|
G_CALLBACK (midori_bookmarks_remove_item_cb), bookmarks);
|
||||||
|
g_signal_connect (added_item, "clear",
|
||||||
|
G_CALLBACK (midori_bookmarks_clear_cb), bookmarks);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_object_ref (added_item);
|
||||||
|
model = gtk_tree_view_get_model (GTK_TREE_VIEW (bookmarks->treeview));
|
||||||
|
|
||||||
|
if (array == bookmarks->array)
|
||||||
|
{
|
||||||
|
gtk_tree_store_insert_with_values (GTK_TREE_STORE (model),
|
||||||
|
&iter, NULL, G_MAXINT, 0, added_item, -1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
/* FIXME: Recurse over children of folders, too */
|
||||||
|
while (gtk_tree_model_iter_nth_child (model, &iter, NULL, i))
|
||||||
|
{
|
||||||
|
KatzeItem* item;
|
||||||
|
|
||||||
|
gtk_tree_model_get (model, &iter, 0, &item, -1);
|
||||||
|
if (item == (KatzeItem*)array)
|
||||||
|
{
|
||||||
|
GtkTreeIter child_iter;
|
||||||
|
|
||||||
|
gtk_tree_store_insert_with_values (GTK_TREE_STORE (model),
|
||||||
|
&child_iter, &iter, G_MAXINT, 0, added_item, -1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
g_object_unref (item);
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_bookmarks_remove_iter (GtkTreeModel* model,
|
||||||
|
GtkTreeIter* parent,
|
||||||
|
KatzeItem* removed_item)
|
||||||
|
{
|
||||||
|
guint i;
|
||||||
|
GtkTreeIter iter;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
while (gtk_tree_model_iter_nth_child (model, &iter, parent, i))
|
||||||
|
{
|
||||||
|
KatzeItem* item;
|
||||||
|
|
||||||
|
gtk_tree_model_get (model, &iter, 0, &item, -1);
|
||||||
|
|
||||||
|
if (item == removed_item)
|
||||||
|
{
|
||||||
|
gtk_tree_store_remove (GTK_TREE_STORE (model), &iter);
|
||||||
|
g_object_unref (item);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (KATZE_IS_ARRAY (item))
|
||||||
|
midori_bookmarks_remove_iter (model, &iter, removed_item);
|
||||||
|
|
||||||
|
g_object_unref (item);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_bookmarks_remove_item_cb (KatzeArray* array,
|
||||||
|
KatzeItem* removed_item,
|
||||||
|
MidoriBookmarks* bookmarks)
|
||||||
|
{
|
||||||
|
GtkTreeModel* model;
|
||||||
|
|
||||||
|
g_return_if_fail (KATZE_IS_ARRAY (array));
|
||||||
|
g_return_if_fail (KATZE_IS_ITEM (removed_item));
|
||||||
|
|
||||||
|
if (KATZE_IS_ARRAY (removed_item))
|
||||||
|
midori_bookmarks_disconnect_folder (bookmarks, KATZE_ARRAY (removed_item));
|
||||||
|
|
||||||
|
model = gtk_tree_view_get_model (GTK_TREE_VIEW (bookmarks->treeview));
|
||||||
|
midori_bookmarks_remove_iter (model, NULL, removed_item);
|
||||||
|
g_object_unref (removed_item);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_bookmarks_clear_cb (KatzeArray* array,
|
||||||
|
MidoriBookmarks* bookmarks)
|
||||||
|
{
|
||||||
|
GtkTreeView* treeview;
|
||||||
|
GtkTreeStore* store;
|
||||||
|
|
||||||
|
g_return_if_fail (KATZE_IS_ARRAY (array));
|
||||||
|
|
||||||
|
if (array == bookmarks->array)
|
||||||
|
{
|
||||||
|
treeview = GTK_TREE_VIEW (bookmarks->treeview);
|
||||||
|
store = GTK_TREE_STORE (gtk_tree_view_get_model (treeview));
|
||||||
|
gtk_tree_store_clear (store);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
KatzeItem* item;
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
while ((item = katze_array_get_nth_item (array, i++)))
|
||||||
|
midori_bookmarks_remove_item_cb (array, item, bookmarks);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_bookmarks_insert_folder (MidoriBookmarks* bookmarks,
|
||||||
|
GtkTreeStore* treestore,
|
||||||
|
GtkTreeIter* parent,
|
||||||
|
KatzeArray* array)
|
||||||
|
{
|
||||||
|
KatzeItem* item;
|
||||||
|
guint i;
|
||||||
|
GtkTreeIter iter;
|
||||||
|
|
||||||
|
g_return_if_fail (KATZE_IS_ARRAY (array));
|
||||||
|
|
||||||
|
g_signal_connect (array, "add-item",
|
||||||
|
G_CALLBACK (midori_bookmarks_add_item_cb), bookmarks);
|
||||||
|
g_signal_connect (array, "remove-item",
|
||||||
|
G_CALLBACK (midori_bookmarks_remove_item_cb), bookmarks);
|
||||||
|
g_signal_connect (array, "clear",
|
||||||
|
G_CALLBACK (midori_bookmarks_clear_cb), bookmarks);
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
while ((item = katze_array_get_nth_item (array, i++)))
|
||||||
|
{
|
||||||
|
g_object_ref (item);
|
||||||
|
gtk_tree_store_insert_with_values (treestore, &iter, parent, i,
|
||||||
|
0, item, -1);
|
||||||
|
if (KATZE_IS_ARRAY (item))
|
||||||
|
midori_bookmarks_insert_folder (bookmarks, treestore,
|
||||||
|
&iter, KATZE_ARRAY (item));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_bookmarks_set_app (MidoriBookmarks* bookmarks,
|
||||||
|
MidoriApp* app)
|
||||||
|
{
|
||||||
|
GtkTreeModel* model;
|
||||||
|
|
||||||
|
if (bookmarks->array)
|
||||||
|
{
|
||||||
|
midori_bookmarks_disconnect_folder (bookmarks, bookmarks->array);
|
||||||
|
g_object_unref (bookmarks->array);
|
||||||
|
model = gtk_tree_view_get_model (GTK_TREE_VIEW (bookmarks->treeview));
|
||||||
|
gtk_tree_store_clear (GTK_TREE_STORE (model));
|
||||||
|
}
|
||||||
|
katze_assign (bookmarks->app, app);
|
||||||
|
if (!app)
|
||||||
|
return;
|
||||||
|
|
||||||
|
g_object_ref (app);
|
||||||
|
bookmarks->array = katze_object_get_object (app, "bookmarks");
|
||||||
|
if (bookmarks->array)
|
||||||
|
{
|
||||||
|
/* FIXME: Dereference the app on finalization */
|
||||||
|
model = gtk_tree_view_get_model (GTK_TREE_VIEW (bookmarks->treeview));
|
||||||
|
midori_bookmarks_insert_folder (bookmarks, GTK_TREE_STORE (model),
|
||||||
|
NULL, g_object_ref (bookmarks->array));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_bookmarks_set_property (GObject* object,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue* value,
|
||||||
|
GParamSpec* pspec)
|
||||||
|
{
|
||||||
|
MidoriBookmarks* bookmarks = MIDORI_BOOKMARKS (object);
|
||||||
|
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_APP:
|
||||||
|
midori_bookmarks_set_app (bookmarks, g_value_get_object (value));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_bookmarks_get_property (GObject* object,
|
||||||
|
guint prop_id,
|
||||||
|
GValue* value,
|
||||||
|
GParamSpec* pspec)
|
||||||
|
{
|
||||||
|
MidoriBookmarks* bookmarks = MIDORI_BOOKMARKS (object);
|
||||||
|
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_APP:
|
||||||
|
g_value_set_object (value, bookmarks->app);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_bookmarks_treeview_render_icon_cb (GtkTreeViewColumn* column,
|
||||||
|
GtkCellRenderer* renderer,
|
||||||
|
GtkTreeModel* model,
|
||||||
|
GtkTreeIter* iter,
|
||||||
|
GtkWidget* treeview)
|
||||||
|
{
|
||||||
|
KatzeItem* item;
|
||||||
|
GdkPixbuf* pixbuf;
|
||||||
|
|
||||||
|
gtk_tree_model_get (model, iter, 0, &item, -1);
|
||||||
|
|
||||||
|
/* TODO: Would it be better to not do this on every redraw? */
|
||||||
|
pixbuf = NULL;
|
||||||
|
if (KATZE_IS_ARRAY (item))
|
||||||
|
pixbuf = gtk_widget_render_icon (treeview, GTK_STOCK_DIRECTORY,
|
||||||
|
GTK_ICON_SIZE_MENU, NULL);
|
||||||
|
else if (katze_item_get_uri (item))
|
||||||
|
pixbuf = katze_net_load_icon (
|
||||||
|
MIDORI_BOOKMARKS (gtk_widget_get_parent (treeview))->net,
|
||||||
|
katze_item_get_uri (item), NULL, treeview, NULL);
|
||||||
|
g_object_set (renderer, "pixbuf", pixbuf, NULL);
|
||||||
|
|
||||||
|
if (pixbuf)
|
||||||
|
g_object_unref (pixbuf);
|
||||||
|
|
||||||
|
g_object_unref (item);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_bookmarks_treeview_render_text_cb (GtkTreeViewColumn* column,
|
||||||
|
GtkCellRenderer* renderer,
|
||||||
|
GtkTreeModel* model,
|
||||||
|
GtkTreeIter* iter,
|
||||||
|
GtkWidget* treeview)
|
||||||
|
{
|
||||||
|
KatzeItem* item;
|
||||||
|
|
||||||
|
gtk_tree_model_get (model, iter, 0, &item, -1);
|
||||||
|
|
||||||
|
if (KATZE_IS_ARRAY (item) || katze_item_get_uri (item))
|
||||||
|
g_object_set (renderer, "markup", NULL,
|
||||||
|
"text", katze_item_get_name (item), NULL);
|
||||||
|
else
|
||||||
|
g_object_set (renderer, "markup", _("<i>Separator</i>"), NULL);
|
||||||
|
|
||||||
|
g_object_unref (item);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_bookmarks_row_activated_cb (GtkTreeView* treeview,
|
||||||
|
GtkTreePath* path,
|
||||||
|
GtkTreeViewColumn* column,
|
||||||
|
MidoriBookmarks* bookmarks)
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
GtkWidget* browser;
|
||||||
|
|
||||||
|
browser = gtk_widget_get_toplevel (GTK_WIDGET (bookmarks));
|
||||||
|
midori_browser_set_current_uri (MIDORI_BROWSER (browser), uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_object_unref (item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_bookmarks_popup_item (GtkWidget* menu,
|
||||||
|
const gchar* stock_id,
|
||||||
|
const gchar* label,
|
||||||
|
KatzeItem* item,
|
||||||
|
gpointer callback,
|
||||||
|
MidoriBookmarks* bookmarks)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
if (!strcmp (stock_id, GTK_STOCK_EDIT))
|
||||||
|
gtk_widget_set_sensitive (menuitem,
|
||||||
|
KATZE_IS_ARRAY (item) || uri != NULL);
|
||||||
|
else if (!KATZE_IS_ARRAY (item) && strcmp (stock_id, GTK_STOCK_DELETE))
|
||||||
|
gtk_widget_set_sensitive (menuitem, uri != NULL);
|
||||||
|
g_object_set_data (G_OBJECT (menuitem), "KatzeItem", item);
|
||||||
|
g_signal_connect (menuitem, "activate", G_CALLBACK (callback), bookmarks);
|
||||||
|
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
|
||||||
|
gtk_widget_show (menuitem);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_bookmarks_open_activate_cb (GtkWidget* menuitem,
|
||||||
|
MidoriBookmarks* bookmarks)
|
||||||
|
{
|
||||||
|
KatzeItem* item;
|
||||||
|
const gchar* uri;
|
||||||
|
|
||||||
|
item = (KatzeItem*)g_object_get_data (G_OBJECT (menuitem), "KatzeItem");
|
||||||
|
uri = katze_item_get_uri (item);
|
||||||
|
|
||||||
|
if (uri && *uri)
|
||||||
|
{
|
||||||
|
GtkWidget* browser = gtk_widget_get_toplevel (GTK_WIDGET (bookmarks));
|
||||||
|
midori_browser_set_current_uri (MIDORI_BROWSER (browser), uri);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_bookmarks_open_in_tab_activate_cb (GtkWidget* menuitem,
|
||||||
|
MidoriBookmarks* bookmarks)
|
||||||
|
{
|
||||||
|
KatzeItem* item;
|
||||||
|
const gchar* uri;
|
||||||
|
guint n;
|
||||||
|
|
||||||
|
item = (KatzeItem*)g_object_get_data (G_OBJECT (menuitem), "KatzeItem");
|
||||||
|
if (KATZE_IS_ARRAY (item))
|
||||||
|
{
|
||||||
|
KatzeItem* child;
|
||||||
|
guint i = 0;
|
||||||
|
|
||||||
|
while ((child = katze_array_get_nth_item (KATZE_ARRAY (item), i)))
|
||||||
|
{
|
||||||
|
if ((uri = katze_item_get_uri (child)) && *uri)
|
||||||
|
{
|
||||||
|
GtkWidget* browser;
|
||||||
|
MidoriWebSettings* settings;
|
||||||
|
|
||||||
|
browser = gtk_widget_get_toplevel (GTK_WIDGET (bookmarks));
|
||||||
|
n = midori_browser_add_item (MIDORI_BROWSER (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);
|
||||||
|
g_object_unref (settings);
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((uri = katze_item_get_uri (item)) && *uri)
|
||||||
|
{
|
||||||
|
GtkWidget* browser;
|
||||||
|
MidoriWebSettings* settings;
|
||||||
|
|
||||||
|
browser = gtk_widget_get_toplevel (GTK_WIDGET (bookmarks));
|
||||||
|
n = midori_browser_add_item (MIDORI_BROWSER (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);
|
||||||
|
g_object_unref (settings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_bookmarks_open_in_window_activate_cb (GtkWidget* menuitem,
|
||||||
|
MidoriBookmarks* bookmarks)
|
||||||
|
{
|
||||||
|
KatzeItem* item;
|
||||||
|
const gchar* uri;
|
||||||
|
|
||||||
|
item = (KatzeItem*)g_object_get_data (G_OBJECT (menuitem), "KatzeItem");
|
||||||
|
uri = katze_item_get_uri (item);
|
||||||
|
|
||||||
|
if (uri && *uri)
|
||||||
|
{
|
||||||
|
GtkWidget* browser = gtk_widget_get_toplevel (GTK_WIDGET (bookmarks));
|
||||||
|
g_signal_emit_by_name (browser, "new-window", uri);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_bookmarks_edit_activate_cb (GtkWidget* menuitem,
|
||||||
|
MidoriBookmarks* bookmarks)
|
||||||
|
{
|
||||||
|
KatzeItem* item;
|
||||||
|
gboolean is_separator;
|
||||||
|
|
||||||
|
item = (KatzeItem*)g_object_get_data (G_OBJECT (menuitem), "KatzeItem");
|
||||||
|
is_separator = !KATZE_IS_ARRAY (item) && !katze_item_get_uri (item);
|
||||||
|
|
||||||
|
if (!is_separator)
|
||||||
|
{
|
||||||
|
GtkWidget* browser = gtk_widget_get_toplevel (GTK_WIDGET (bookmarks));
|
||||||
|
midori_browser_edit_bookmark_dialog_new (MIDORI_BROWSER (browser), item, FALSE, FALSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_bookmarks_delete_activate_cb (GtkWidget* menuitem,
|
||||||
|
MidoriBookmarks* bookmarks)
|
||||||
|
{
|
||||||
|
KatzeItem* item;
|
||||||
|
KatzeArray* parent;
|
||||||
|
|
||||||
|
item = (KatzeItem*)g_object_get_data (G_OBJECT (menuitem), "KatzeItem");
|
||||||
|
|
||||||
|
/* FIXME: Even toplevel items should technically have a parent */
|
||||||
|
g_return_if_fail (katze_item_get_parent (item));
|
||||||
|
|
||||||
|
parent = katze_item_get_parent (item);
|
||||||
|
katze_array_remove_item (parent, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_bookmarks_popup (GtkWidget* widget,
|
||||||
|
GdkEventButton* event,
|
||||||
|
KatzeItem* item,
|
||||||
|
MidoriBookmarks* bookmarks)
|
||||||
|
{
|
||||||
|
GtkWidget* menu;
|
||||||
|
GtkWidget* menuitem;
|
||||||
|
|
||||||
|
menu = gtk_menu_new ();
|
||||||
|
if (KATZE_IS_ARRAY (item))
|
||||||
|
midori_bookmarks_popup_item (menu,
|
||||||
|
STOCK_TAB_NEW, _("Open all in _Tabs"),
|
||||||
|
item, midori_bookmarks_open_in_tab_activate_cb, bookmarks);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
midori_bookmarks_popup_item (menu, GTK_STOCK_OPEN, NULL,
|
||||||
|
item, midori_bookmarks_open_activate_cb, bookmarks);
|
||||||
|
midori_bookmarks_popup_item (menu, STOCK_TAB_NEW, _("Open in New _Tab"),
|
||||||
|
item, midori_bookmarks_open_in_tab_activate_cb, bookmarks);
|
||||||
|
midori_bookmarks_popup_item (menu, STOCK_WINDOW_NEW, _("Open in New _Window"),
|
||||||
|
item, midori_bookmarks_open_in_window_activate_cb, bookmarks);
|
||||||
|
}
|
||||||
|
menuitem = gtk_separator_menu_item_new ();
|
||||||
|
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
|
||||||
|
gtk_widget_show (menuitem);
|
||||||
|
midori_bookmarks_popup_item (menu, GTK_STOCK_EDIT, NULL,
|
||||||
|
item, midori_bookmarks_edit_activate_cb, bookmarks);
|
||||||
|
midori_bookmarks_popup_item (menu, GTK_STOCK_DELETE, NULL,
|
||||||
|
item, midori_bookmarks_delete_activate_cb, bookmarks);
|
||||||
|
|
||||||
|
sokoke_widget_popup (widget, GTK_MENU (menu),
|
||||||
|
event, SOKOKE_MENU_POSITION_CURSOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
midori_bookmarks_button_release_event_cb (GtkWidget* widget,
|
||||||
|
GdkEventButton* event,
|
||||||
|
MidoriBookmarks* bookmarks)
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
GtkWidget* 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
midori_bookmarks_popup (widget, event, item, bookmarks);
|
||||||
|
|
||||||
|
g_object_unref (item);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
midori_bookmarks_key_release_event_cb (GtkWidget* widget,
|
||||||
|
GdkEventKey* event,
|
||||||
|
MidoriBookmarks* bookmarks)
|
||||||
|
{
|
||||||
|
GtkTreeModel* model;
|
||||||
|
GtkTreeIter iter;
|
||||||
|
|
||||||
|
if (event->keyval != GDK_Delete)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (katze_tree_view_get_selected_iter (GTK_TREE_VIEW (widget), &model, &iter))
|
||||||
|
{
|
||||||
|
KatzeItem* item;
|
||||||
|
KatzeArray* parent;
|
||||||
|
|
||||||
|
gtk_tree_model_get (model, &iter, 0, &item, -1);
|
||||||
|
parent = katze_item_get_parent (item);
|
||||||
|
katze_array_remove_item (parent, item);
|
||||||
|
|
||||||
|
g_object_unref (item);
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_bookmarks_popup_menu_cb (GtkWidget* widget,
|
||||||
|
MidoriBookmarks* bookmarks)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
midori_bookmarks_popup (widget, NULL, item, bookmarks);
|
||||||
|
g_object_unref (item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_bookmarks_init (MidoriBookmarks* bookmarks)
|
||||||
|
{
|
||||||
|
GtkTreeStore* model;
|
||||||
|
GtkWidget* treeview;
|
||||||
|
GtkTreeViewColumn* column;
|
||||||
|
GtkCellRenderer* renderer_pixbuf;
|
||||||
|
GtkCellRenderer* renderer_text;
|
||||||
|
|
||||||
|
bookmarks->net = katze_net_new ();
|
||||||
|
|
||||||
|
/* Create the treeview */
|
||||||
|
model = gtk_tree_store_new (1, KATZE_TYPE_ITEM);
|
||||||
|
treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (model));
|
||||||
|
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE);
|
||||||
|
column = gtk_tree_view_column_new ();
|
||||||
|
renderer_pixbuf = gtk_cell_renderer_pixbuf_new ();
|
||||||
|
gtk_tree_view_column_pack_start (column, renderer_pixbuf, FALSE);
|
||||||
|
gtk_tree_view_column_set_cell_data_func (column, renderer_pixbuf,
|
||||||
|
(GtkTreeCellDataFunc)midori_bookmarks_treeview_render_icon_cb,
|
||||||
|
treeview, NULL);
|
||||||
|
renderer_text = gtk_cell_renderer_text_new ();
|
||||||
|
gtk_tree_view_column_pack_start (column, renderer_text, FALSE);
|
||||||
|
gtk_tree_view_column_set_cell_data_func (column, renderer_text,
|
||||||
|
(GtkTreeCellDataFunc)midori_bookmarks_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",
|
||||||
|
midori_bookmarks_row_activated_cb, bookmarks,
|
||||||
|
"signal::cursor-changed",
|
||||||
|
midori_bookmarks_cursor_or_row_changed_cb, bookmarks,
|
||||||
|
"signal::columns-changed",
|
||||||
|
midori_bookmarks_cursor_or_row_changed_cb, bookmarks,
|
||||||
|
"signal::button-release-event",
|
||||||
|
midori_bookmarks_button_release_event_cb, bookmarks,
|
||||||
|
"signal::key-release-event",
|
||||||
|
midori_bookmarks_key_release_event_cb, bookmarks,
|
||||||
|
"signal::popup-menu",
|
||||||
|
midori_bookmarks_popup_menu_cb, bookmarks,
|
||||||
|
NULL);
|
||||||
|
gtk_widget_show (treeview);
|
||||||
|
gtk_box_pack_start (GTK_BOX (bookmarks), treeview, TRUE, TRUE, 0);
|
||||||
|
bookmarks->treeview = treeview;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_bookmarks_finalize (GObject* object)
|
||||||
|
{
|
||||||
|
MidoriBookmarks* bookmarks = MIDORI_BOOKMARKS (object);
|
||||||
|
|
||||||
|
if (bookmarks->app)
|
||||||
|
g_object_unref (bookmarks->app);
|
||||||
|
g_object_unref (bookmarks->net);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* midori_bookmarks_new:
|
||||||
|
*
|
||||||
|
* Creates a new empty bookmarks.
|
||||||
|
*
|
||||||
|
* Return value: a new #MidoriBookmarks
|
||||||
|
*
|
||||||
|
* Since: 0.1.3
|
||||||
|
**/
|
||||||
|
GtkWidget*
|
||||||
|
midori_bookmarks_new (void)
|
||||||
|
{
|
||||||
|
MidoriBookmarks* bookmarks = g_object_new (MIDORI_TYPE_BOOKMARKS, NULL);
|
||||||
|
|
||||||
|
return GTK_WIDGET (bookmarks);
|
||||||
|
}
|
43
panels/midori-bookmarks.h
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2009 Christian Dywan <christian@twotoasts.de>
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
See the file COPYING for the full license text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __MIDORI_BOOKMARKS_H__
|
||||||
|
#define __MIDORI_BOOKMARKS_H__
|
||||||
|
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define MIDORI_TYPE_BOOKMARKS \
|
||||||
|
(midori_bookmarks_get_type ())
|
||||||
|
#define MIDORI_BOOKMARKS(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_CAST ((obj), MIDORI_TYPE_BOOKMARKS, MidoriBookmarks))
|
||||||
|
#define MIDORI_BOOKMARKS_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_CAST ((klass), MIDORI_TYPE_BOOKMARKS, MidoriBookmarksClass))
|
||||||
|
#define MIDORI_IS_BOOKMARKS(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), MIDORI_TYPE_BOOKMARKS))
|
||||||
|
#define MIDORI_IS_BOOKMARKS_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_TYPE ((klass), MIDORI_TYPE_BOOKMARKS))
|
||||||
|
#define MIDORI_BOOKMARKS_GET_CLASS(obj) \
|
||||||
|
(G_TYPE_INSTANCE_GET_CLASS ((obj), MIDORI_TYPE_BOOKMARKS, MidoriBookmarksClass))
|
||||||
|
|
||||||
|
typedef struct _MidoriBookmarks MidoriBookmarks;
|
||||||
|
typedef struct _MidoriBookmarksClass MidoriBookmarksClass;
|
||||||
|
|
||||||
|
GType
|
||||||
|
midori_bookmarks_get_type (void);
|
||||||
|
|
||||||
|
GtkWidget*
|
||||||
|
midori_bookmarks_new (void);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __MIDORI_BOOKMARKS_H__ */
|
362
panels/midori-console.c
Normal file
|
@ -0,0 +1,362 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2008-2009 Christian Dywan <christian@twotoasts.de>
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
See the file COPYING for the full license text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "midori-console.h"
|
||||||
|
|
||||||
|
#include "midori-app.h"
|
||||||
|
#include "midori-browser.h"
|
||||||
|
#include "midori-stock.h"
|
||||||
|
#include "midori-view.h"
|
||||||
|
|
||||||
|
#include "sokoke.h"
|
||||||
|
#include <glib/gi18n.h>
|
||||||
|
|
||||||
|
struct _MidoriConsole
|
||||||
|
{
|
||||||
|
GtkVBox parent_instance;
|
||||||
|
|
||||||
|
GtkWidget* toolbar;
|
||||||
|
GtkWidget* treeview;
|
||||||
|
MidoriApp* app;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _MidoriConsoleClass
|
||||||
|
{
|
||||||
|
GtkVBoxClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_console_viewable_iface_init (MidoriViewableIface* iface);
|
||||||
|
|
||||||
|
G_DEFINE_TYPE_WITH_CODE (MidoriConsole, midori_console, GTK_TYPE_VBOX,
|
||||||
|
G_IMPLEMENT_INTERFACE (MIDORI_TYPE_VIEWABLE,
|
||||||
|
midori_console_viewable_iface_init));
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
PROP_0,
|
||||||
|
|
||||||
|
PROP_APP
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_console_set_property (GObject* object,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue* value,
|
||||||
|
GParamSpec* pspec);
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_console_get_property (GObject* object,
|
||||||
|
guint prop_id,
|
||||||
|
GValue* value,
|
||||||
|
GParamSpec* pspec);
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_console_class_init (MidoriConsoleClass* class)
|
||||||
|
{
|
||||||
|
GObjectClass* gobject_class;
|
||||||
|
GParamFlags flags;
|
||||||
|
|
||||||
|
gobject_class = G_OBJECT_CLASS (class);
|
||||||
|
gobject_class->set_property = midori_console_set_property;
|
||||||
|
gobject_class->get_property = midori_console_get_property;
|
||||||
|
|
||||||
|
flags = G_PARAM_READWRITE | G_PARAM_CONSTRUCT;
|
||||||
|
|
||||||
|
g_object_class_install_property (gobject_class,
|
||||||
|
PROP_APP,
|
||||||
|
g_param_spec_object (
|
||||||
|
"app",
|
||||||
|
"App",
|
||||||
|
"The app",
|
||||||
|
MIDORI_TYPE_APP,
|
||||||
|
flags));
|
||||||
|
}
|
||||||
|
|
||||||
|
static const gchar*
|
||||||
|
midori_console_get_label (MidoriViewable* viewable)
|
||||||
|
{
|
||||||
|
return _("Console");
|
||||||
|
}
|
||||||
|
|
||||||
|
static const gchar*
|
||||||
|
midori_console_get_stock_id (MidoriViewable* viewable)
|
||||||
|
{
|
||||||
|
return STOCK_CONSOLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_console_viewable_iface_init (MidoriViewableIface* iface)
|
||||||
|
{
|
||||||
|
iface->get_stock_id = midori_console_get_stock_id;
|
||||||
|
iface->get_label = midori_console_get_label;
|
||||||
|
iface->get_toolbar = midori_console_get_toolbar;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_view_console_message_cb (GtkWidget* view,
|
||||||
|
const gchar* message,
|
||||||
|
gint line,
|
||||||
|
const gchar* source_id,
|
||||||
|
MidoriConsole* console)
|
||||||
|
{
|
||||||
|
midori_console_add (console, message, line, source_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_console_browser_add_tab_cb (MidoriBrowser* browser,
|
||||||
|
MidoriView* view,
|
||||||
|
MidoriConsole* console)
|
||||||
|
{
|
||||||
|
g_signal_connect (view, "console-message",
|
||||||
|
G_CALLBACK (midori_view_console_message_cb), console);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_console_set_property (GObject* object,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue* value,
|
||||||
|
GParamSpec* pspec)
|
||||||
|
{
|
||||||
|
MidoriConsole* console = MIDORI_CONSOLE (object);
|
||||||
|
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_APP:
|
||||||
|
console->app = g_value_get_object (value);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_console_get_property (GObject* object,
|
||||||
|
guint prop_id,
|
||||||
|
GValue* value,
|
||||||
|
GParamSpec* pspec)
|
||||||
|
{
|
||||||
|
MidoriConsole* console = MIDORI_CONSOLE (object);
|
||||||
|
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_APP:
|
||||||
|
g_value_set_object (value, console->app);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_console_button_copy_clicked_cb (GtkToolItem* toolitem,
|
||||||
|
MidoriConsole* console)
|
||||||
|
{
|
||||||
|
GtkTreeModel* model;
|
||||||
|
GtkTreeIter iter;
|
||||||
|
|
||||||
|
if (katze_tree_view_get_selected_iter (GTK_TREE_VIEW (console->treeview),
|
||||||
|
&model, &iter))
|
||||||
|
{
|
||||||
|
GdkDisplay* display;
|
||||||
|
GtkClipboard* clipboard;
|
||||||
|
gchar* text;
|
||||||
|
gchar* message;
|
||||||
|
gint line;
|
||||||
|
gchar* source_id;
|
||||||
|
|
||||||
|
display = gtk_widget_get_display (GTK_WIDGET (console));
|
||||||
|
clipboard = gtk_clipboard_get_for_display (display, GDK_SELECTION_CLIPBOARD);
|
||||||
|
gtk_tree_model_get (model, &iter, 0, &message, 1, &line, 2, &source_id, -1);
|
||||||
|
text = g_strdup_printf ("%d @ %s: %s", line, source_id, message);
|
||||||
|
g_free (source_id);
|
||||||
|
g_free (message);
|
||||||
|
gtk_clipboard_set_text (clipboard, text, -1);
|
||||||
|
g_free (text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_console_button_clear_clicked_cb (GtkToolItem* toolitem,
|
||||||
|
MidoriConsole* console)
|
||||||
|
{
|
||||||
|
GtkTreeModel* model = gtk_tree_view_get_model (
|
||||||
|
GTK_TREE_VIEW (console->treeview));
|
||||||
|
gtk_tree_store_clear (GTK_TREE_STORE (model));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_console_treeview_render_icon_cb (GtkTreeViewColumn* column,
|
||||||
|
GtkCellRenderer* renderer,
|
||||||
|
GtkTreeModel* model,
|
||||||
|
GtkTreeIter* iter,
|
||||||
|
GtkWidget* treeview)
|
||||||
|
{
|
||||||
|
g_object_set (renderer, "stock-id", GTK_STOCK_DIALOG_WARNING, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_console_treeview_render_text_cb (GtkTreeViewColumn* column,
|
||||||
|
GtkCellRenderer* renderer,
|
||||||
|
GtkTreeModel* model,
|
||||||
|
GtkTreeIter* iter,
|
||||||
|
GtkWidget* treeview)
|
||||||
|
{
|
||||||
|
gchar* message;
|
||||||
|
gint line;
|
||||||
|
gchar* source_id;
|
||||||
|
gchar* text;
|
||||||
|
|
||||||
|
gtk_tree_model_get (model, iter, 0, &message, 1, &line, 2, &source_id, -1);
|
||||||
|
|
||||||
|
text = g_strdup_printf ("%d @ %s\n%s", line, source_id, message);
|
||||||
|
g_object_set (renderer, "text", text, NULL);
|
||||||
|
g_free (text);
|
||||||
|
|
||||||
|
g_free (message);
|
||||||
|
g_free (source_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
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))
|
||||||
|
g_signal_connect (browser, "add-tab",
|
||||||
|
G_CALLBACK (midori_console_browser_add_tab_cb), console);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_console_init (MidoriConsole* console)
|
||||||
|
{
|
||||||
|
/* Create the treeview */
|
||||||
|
GtkTreeViewColumn* column;
|
||||||
|
GtkCellRenderer* renderer_text;
|
||||||
|
GtkCellRenderer* renderer_pixbuf;
|
||||||
|
GtkTreeStore* treestore = gtk_tree_store_new (3, G_TYPE_STRING,
|
||||||
|
G_TYPE_INT,
|
||||||
|
G_TYPE_STRING);
|
||||||
|
console->treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (treestore));
|
||||||
|
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (console->treeview), FALSE);
|
||||||
|
column = gtk_tree_view_column_new ();
|
||||||
|
renderer_pixbuf = gtk_cell_renderer_pixbuf_new ();
|
||||||
|
gtk_tree_view_column_pack_start (column, renderer_pixbuf, FALSE);
|
||||||
|
gtk_tree_view_column_set_cell_data_func (column, renderer_pixbuf,
|
||||||
|
(GtkTreeCellDataFunc)midori_console_treeview_render_icon_cb,
|
||||||
|
console->treeview, NULL);
|
||||||
|
renderer_text = gtk_cell_renderer_text_new ();
|
||||||
|
gtk_tree_view_column_pack_start (column, renderer_text, FALSE);
|
||||||
|
gtk_tree_view_column_set_cell_data_func (column, renderer_text,
|
||||||
|
(GtkTreeCellDataFunc)midori_console_treeview_render_text_cb,
|
||||||
|
console->treeview, NULL);
|
||||||
|
gtk_tree_view_append_column (GTK_TREE_VIEW (console->treeview), column);
|
||||||
|
g_object_unref (treestore);
|
||||||
|
gtk_widget_show (console->treeview);
|
||||||
|
gtk_box_pack_start (GTK_BOX (console), console->treeview, TRUE, TRUE, 0);
|
||||||
|
|
||||||
|
g_signal_connect (console, "hierarchy-changed",
|
||||||
|
G_CALLBACK (midori_console_hierarchy_changed_cb), NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* midori_console_new:
|
||||||
|
*
|
||||||
|
* Creates a new empty console.
|
||||||
|
*
|
||||||
|
* Return value: a new #MidoriConsole
|
||||||
|
**/
|
||||||
|
GtkWidget*
|
||||||
|
midori_console_new (void)
|
||||||
|
{
|
||||||
|
MidoriConsole* console = g_object_new (MIDORI_TYPE_CONSOLE,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
return GTK_WIDGET (console);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* midori_console_get_toolbar:
|
||||||
|
* @console: a #MidoriConsole
|
||||||
|
*
|
||||||
|
* Retrieves the toolbar of the console. A new widget is created on
|
||||||
|
* the first call of this function.
|
||||||
|
*
|
||||||
|
* Return value: a toolbar widget
|
||||||
|
*
|
||||||
|
* Deprecated: 0.1.2: Use midori_viewable_get_toolbar() instead.
|
||||||
|
**/
|
||||||
|
GtkWidget*
|
||||||
|
midori_console_get_toolbar (MidoriViewable* console)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (MIDORI_IS_CONSOLE (console), NULL);
|
||||||
|
|
||||||
|
if (!MIDORI_CONSOLE (console)->toolbar)
|
||||||
|
{
|
||||||
|
GtkWidget* toolbar;
|
||||||
|
GtkToolItem* toolitem;
|
||||||
|
|
||||||
|
toolbar = gtk_toolbar_new ();
|
||||||
|
gtk_toolbar_set_style (GTK_TOOLBAR (toolbar), GTK_TOOLBAR_BOTH_HORIZ);
|
||||||
|
gtk_toolbar_set_icon_size (GTK_TOOLBAR (toolbar), GTK_ICON_SIZE_BUTTON);
|
||||||
|
toolitem = gtk_tool_button_new_from_stock (GTK_STOCK_COPY);
|
||||||
|
gtk_tool_item_set_is_important (toolitem, TRUE);
|
||||||
|
g_signal_connect (toolitem, "clicked",
|
||||||
|
G_CALLBACK (midori_console_button_copy_clicked_cb), console);
|
||||||
|
gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1);
|
||||||
|
gtk_widget_show (GTK_WIDGET (toolitem));
|
||||||
|
/* TODO: What about a find entry here that filters e.g. by url? */
|
||||||
|
toolitem = gtk_separator_tool_item_new ();
|
||||||
|
gtk_separator_tool_item_set_draw (GTK_SEPARATOR_TOOL_ITEM (toolitem),
|
||||||
|
FALSE);
|
||||||
|
gtk_tool_item_set_expand (toolitem, TRUE);
|
||||||
|
gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1);
|
||||||
|
gtk_widget_show (GTK_WIDGET (toolitem));
|
||||||
|
toolitem = gtk_tool_button_new_from_stock (GTK_STOCK_CLEAR);
|
||||||
|
gtk_tool_item_set_is_important (toolitem, TRUE);
|
||||||
|
g_signal_connect (toolitem, "clicked",
|
||||||
|
G_CALLBACK (midori_console_button_clear_clicked_cb), console);
|
||||||
|
gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1);
|
||||||
|
gtk_widget_show (GTK_WIDGET (toolitem));
|
||||||
|
MIDORI_CONSOLE (console)->toolbar = toolbar;
|
||||||
|
}
|
||||||
|
|
||||||
|
return MIDORI_CONSOLE (console)->toolbar;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* midori_console_add:
|
||||||
|
* @console: a #MidoriConsole
|
||||||
|
* @message: a descriptive message
|
||||||
|
* @line: the line in the source file
|
||||||
|
* @source_id: the source
|
||||||
|
*
|
||||||
|
* Adds a new message to the console.
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
midori_console_add (MidoriConsole* console,
|
||||||
|
const gchar* message,
|
||||||
|
gint line,
|
||||||
|
const gchar* source_id)
|
||||||
|
{
|
||||||
|
GtkTreeView* treeview;
|
||||||
|
GtkTreeModel* model;
|
||||||
|
|
||||||
|
g_return_if_fail (MIDORI_IS_CONSOLE (console));
|
||||||
|
|
||||||
|
treeview = GTK_TREE_VIEW (console->treeview);
|
||||||
|
model = gtk_tree_view_get_model (treeview);
|
||||||
|
gtk_tree_store_insert_with_values (GTK_TREE_STORE (model),
|
||||||
|
NULL, NULL, G_MAXINT,
|
||||||
|
0, message, 1, line, 2, source_id, -1);
|
||||||
|
}
|
56
panels/midori-console.h
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2008 Christian Dywan <christian@twotoasts.de>
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
See the file COPYING for the full license text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __MIDORI_CONSOLE_H__
|
||||||
|
#define __MIDORI_CONSOLE_H__
|
||||||
|
|
||||||
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
|
#include <katze/katze.h>
|
||||||
|
|
||||||
|
#include "midori-viewable.h"
|
||||||
|
|
||||||
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
#define MIDORI_TYPE_CONSOLE \
|
||||||
|
(midori_console_get_type ())
|
||||||
|
#define MIDORI_CONSOLE(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_CAST ((obj), MIDORI_TYPE_CONSOLE, MidoriConsole))
|
||||||
|
#define MIDORI_CONSOLE_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_CAST ((klass), MIDORI_TYPE_CONSOLE, MidoriConsoleClass))
|
||||||
|
#define MIDORI_IS_CONSOLE(obj) \
|
||||||
|
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), MIDORI_TYPE_CONSOLE))
|
||||||
|
#define MIDORI_IS_CONSOLE_CLASS(klass) \
|
||||||
|
(G_TYPE_CHECK_CLASS_TYPE ((klass), MIDORI_TYPE_CONSOLE))
|
||||||
|
#define MIDORI_CONSOLE_GET_CLASS(obj) \
|
||||||
|
(G_TYPE_INSTANCE_GET_CLASS ((obj), MIDORI_TYPE_CONSOLE, MidoriConsoleClass))
|
||||||
|
|
||||||
|
typedef struct _MidoriConsole MidoriConsole;
|
||||||
|
typedef struct _MidoriConsoleClass MidoriConsoleClass;
|
||||||
|
|
||||||
|
GType
|
||||||
|
midori_console_get_type (void);
|
||||||
|
|
||||||
|
GtkWidget*
|
||||||
|
midori_console_new (void);
|
||||||
|
|
||||||
|
GtkWidget*
|
||||||
|
midori_console_get_toolbar (MidoriViewable* console);
|
||||||
|
|
||||||
|
void
|
||||||
|
midori_console_add (MidoriConsole* console,
|
||||||
|
const gchar* message,
|
||||||
|
gint line,
|
||||||
|
const gchar* source_id);
|
||||||
|
|
||||||
|
G_END_DECLS
|
||||||
|
|
||||||
|
#endif /* __MIDORI_CONSOLE_H__ */
|
390
panels/midori-extensions.c
Normal file
|
@ -0,0 +1,390 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2008 Christian Dywan <christian@twotoasts.de>
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
See the file COPYING for the full license text.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "midori-extensions.h"
|
||||||
|
|
||||||
|
#include "midori-app.h"
|
||||||
|
#include "midori-extension.h"
|
||||||
|
#include "midori-stock.h"
|
||||||
|
#include "midori-viewable.h"
|
||||||
|
|
||||||
|
#include "sokoke.h"
|
||||||
|
#include <glib/gi18n.h>
|
||||||
|
|
||||||
|
struct _MidoriExtensions
|
||||||
|
{
|
||||||
|
GtkVBox parent_instance;
|
||||||
|
|
||||||
|
GtkWidget* toolbar;
|
||||||
|
GtkWidget* treeview;
|
||||||
|
MidoriApp* app;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _MidoriExtensionsClass
|
||||||
|
{
|
||||||
|
GtkVBoxClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_extensions_viewable_iface_init (MidoriViewableIface* iface);
|
||||||
|
|
||||||
|
G_DEFINE_TYPE_WITH_CODE (MidoriExtensions, midori_extensions, GTK_TYPE_VBOX,
|
||||||
|
G_IMPLEMENT_INTERFACE (MIDORI_TYPE_VIEWABLE,
|
||||||
|
midori_extensions_viewable_iface_init));
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
PROP_0,
|
||||||
|
|
||||||
|
PROP_APP
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_extensions_set_property (GObject* object,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue* value,
|
||||||
|
GParamSpec* pspec);
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_extensions_get_property (GObject* object,
|
||||||
|
guint prop_id,
|
||||||
|
GValue* value,
|
||||||
|
GParamSpec* pspec);
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_extensions_class_init (MidoriExtensionsClass* class)
|
||||||
|
{
|
||||||
|
GObjectClass* gobject_class;
|
||||||
|
GParamFlags flags;
|
||||||
|
|
||||||
|
gobject_class = G_OBJECT_CLASS (class);
|
||||||
|
gobject_class->set_property = midori_extensions_set_property;
|
||||||
|
gobject_class->get_property = midori_extensions_get_property;
|
||||||
|
|
||||||
|
flags = G_PARAM_READWRITE | G_PARAM_CONSTRUCT;
|
||||||
|
|
||||||
|
g_object_class_install_property (gobject_class,
|
||||||
|
PROP_APP,
|
||||||
|
g_param_spec_object (
|
||||||
|
"app",
|
||||||
|
"App",
|
||||||
|
"The app",
|
||||||
|
MIDORI_TYPE_APP,
|
||||||
|
flags));
|
||||||
|
}
|
||||||
|
|
||||||
|
static const gchar*
|
||||||
|
midori_extensions_get_label (MidoriViewable* viewable)
|
||||||
|
{
|
||||||
|
return _("Extensions");
|
||||||
|
}
|
||||||
|
|
||||||
|
static const gchar*
|
||||||
|
midori_extensions_get_stock_id (MidoriViewable* viewable)
|
||||||
|
{
|
||||||
|
return STOCK_EXTENSIONS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_extensions_button_status_clicked_cb (GtkToolItem* toolitem,
|
||||||
|
MidoriExtensions* extensions)
|
||||||
|
{
|
||||||
|
GtkTreeView* treeview;
|
||||||
|
GtkTreeModel* model;
|
||||||
|
GtkTreeIter iter;
|
||||||
|
MidoriExtension* extension;
|
||||||
|
|
||||||
|
treeview = GTK_TREE_VIEW (extensions->treeview);
|
||||||
|
|
||||||
|
if (katze_tree_view_get_selected_iter (treeview, &model, &iter))
|
||||||
|
{
|
||||||
|
GtkToolItem* button_enable = gtk_toolbar_get_nth_item (
|
||||||
|
GTK_TOOLBAR (extensions->toolbar), 1);
|
||||||
|
GtkToolItem* button_disable = gtk_toolbar_get_nth_item (
|
||||||
|
GTK_TOOLBAR (extensions->toolbar), 2);
|
||||||
|
|
||||||
|
gtk_tree_model_get (model, &iter, 0, &extension, -1);
|
||||||
|
if (toolitem == button_enable)
|
||||||
|
g_signal_emit_by_name (extension, "activate", extensions->app);
|
||||||
|
else if (toolitem == button_disable)
|
||||||
|
midori_extension_deactivate (extension);
|
||||||
|
|
||||||
|
gtk_widget_set_sensitive (GTK_WIDGET (button_enable),
|
||||||
|
!midori_extension_is_active (extension));
|
||||||
|
gtk_widget_set_sensitive (GTK_WIDGET (button_disable),
|
||||||
|
midori_extension_is_active (extension));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static GtkWidget*
|
||||||
|
midori_extensions_get_toolbar (MidoriViewable* extensions)
|
||||||
|
{
|
||||||
|
if (!MIDORI_EXTENSIONS (extensions)->toolbar)
|
||||||
|
{
|
||||||
|
GtkWidget* toolbar;
|
||||||
|
GtkToolItem* toolitem;
|
||||||
|
|
||||||
|
toolbar = gtk_toolbar_new ();
|
||||||
|
gtk_toolbar_set_style (GTK_TOOLBAR (toolbar), GTK_TOOLBAR_BOTH_HORIZ);
|
||||||
|
gtk_toolbar_set_icon_size (GTK_TOOLBAR (toolbar), GTK_ICON_SIZE_BUTTON);
|
||||||
|
toolitem = gtk_tool_item_new ();
|
||||||
|
gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1);
|
||||||
|
gtk_widget_show (GTK_WIDGET (toolitem));
|
||||||
|
|
||||||
|
/* enable button */
|
||||||
|
toolitem = gtk_tool_button_new_from_stock (GTK_STOCK_YES);
|
||||||
|
gtk_tool_button_set_label (GTK_TOOL_BUTTON (toolitem), _("_Enable"));
|
||||||
|
gtk_widget_set_tooltip_text (GTK_WIDGET (toolitem), _("Enable"));
|
||||||
|
g_signal_connect (toolitem, "clicked",
|
||||||
|
G_CALLBACK (midori_extensions_button_status_clicked_cb), extensions);
|
||||||
|
gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1);
|
||||||
|
gtk_widget_set_sensitive (GTK_WIDGET (toolitem), FALSE);
|
||||||
|
gtk_widget_show (GTK_WIDGET (toolitem));
|
||||||
|
|
||||||
|
/* disable button */
|
||||||
|
toolitem = gtk_tool_button_new_from_stock (GTK_STOCK_NO);
|
||||||
|
gtk_tool_button_set_label (GTK_TOOL_BUTTON (toolitem), _("_Disable"));
|
||||||
|
gtk_widget_set_tooltip_text (GTK_WIDGET (toolitem), _("Disable"));
|
||||||
|
g_signal_connect (toolitem, "clicked",
|
||||||
|
G_CALLBACK (midori_extensions_button_status_clicked_cb), extensions);
|
||||||
|
gtk_toolbar_insert (GTK_TOOLBAR (toolbar), toolitem, -1);
|
||||||
|
gtk_widget_set_sensitive (GTK_WIDGET (toolitem), FALSE);
|
||||||
|
gtk_widget_show (GTK_WIDGET (toolitem));
|
||||||
|
|
||||||
|
MIDORI_EXTENSIONS (extensions)->toolbar = toolbar;
|
||||||
|
}
|
||||||
|
|
||||||
|
return MIDORI_EXTENSIONS (extensions)->toolbar;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_extensions_viewable_iface_init (MidoriViewableIface* iface)
|
||||||
|
{
|
||||||
|
iface->get_stock_id = midori_extensions_get_stock_id;
|
||||||
|
iface->get_label = midori_extensions_get_label;
|
||||||
|
iface->get_toolbar = midori_extensions_get_toolbar;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_extensions_add_item_cb (KatzeArray* array,
|
||||||
|
MidoriExtension* extension,
|
||||||
|
MidoriExtensions* extensions)
|
||||||
|
{
|
||||||
|
GtkTreeIter iter;
|
||||||
|
GtkTreeModel* model;
|
||||||
|
|
||||||
|
model = gtk_tree_view_get_model (GTK_TREE_VIEW (extensions->treeview));
|
||||||
|
gtk_list_store_append (GTK_LIST_STORE (model), &iter);
|
||||||
|
gtk_list_store_set (GTK_LIST_STORE (model), &iter, 0, extension, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_extensions_set_property (GObject* object,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue* value,
|
||||||
|
GParamSpec* pspec)
|
||||||
|
{
|
||||||
|
MidoriExtensions* extensions = MIDORI_EXTENSIONS (object);
|
||||||
|
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_APP:
|
||||||
|
{
|
||||||
|
KatzeArray* array;
|
||||||
|
guint i, n;
|
||||||
|
|
||||||
|
/* FIXME: Handle NULL and subsequent assignments */
|
||||||
|
extensions->app = g_value_get_object (value);
|
||||||
|
array = katze_object_get_object (extensions->app, "extensions");
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_extensions_get_property (GObject* object,
|
||||||
|
guint prop_id,
|
||||||
|
GValue* value,
|
||||||
|
GParamSpec* pspec)
|
||||||
|
{
|
||||||
|
MidoriExtensions* extensions = MIDORI_EXTENSIONS (object);
|
||||||
|
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_APP:
|
||||||
|
g_value_set_object (value, extensions->app);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_extensions_treeview_render_icon_cb (GtkTreeViewColumn* column,
|
||||||
|
GtkCellRenderer* renderer,
|
||||||
|
GtkTreeModel* model,
|
||||||
|
GtkTreeIter* iter,
|
||||||
|
GtkWidget* treeview)
|
||||||
|
{
|
||||||
|
g_object_set (renderer, "stock-id", GTK_STOCK_EXECUTE, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_extensions_treeview_render_text_cb (GtkTreeViewColumn* column,
|
||||||
|
GtkCellRenderer* renderer,
|
||||||
|
GtkTreeModel* model,
|
||||||
|
GtkTreeIter* iter,
|
||||||
|
GtkWidget* treeview)
|
||||||
|
{
|
||||||
|
MidoriExtension* extension;
|
||||||
|
gchar* name;
|
||||||
|
gchar* version;
|
||||||
|
gchar* desc;
|
||||||
|
gchar* text;
|
||||||
|
|
||||||
|
gtk_tree_model_get (model, iter, 0, &extension, -1);
|
||||||
|
|
||||||
|
name = katze_object_get_string (extension, "name");
|
||||||
|
version = katze_object_get_string (extension, "version");
|
||||||
|
desc = katze_object_get_string (extension, "description");
|
||||||
|
text = g_strdup_printf ("%s %s\n%s", name, version, desc);
|
||||||
|
g_free (name);
|
||||||
|
g_free (version);
|
||||||
|
g_free (desc);
|
||||||
|
g_object_set (renderer, "text", text, NULL);
|
||||||
|
g_free (text);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_extensions_treeview_row_activated_cb (GtkTreeView* treeview,
|
||||||
|
GtkTreePath* path,
|
||||||
|
GtkTreeViewColumn* column,
|
||||||
|
MidoriExtensions* extensions)
|
||||||
|
{
|
||||||
|
GtkToolItem* button_enable;
|
||||||
|
GtkToolItem* button_disable;
|
||||||
|
GtkTreeModel* model;
|
||||||
|
GtkTreeIter iter;
|
||||||
|
|
||||||
|
model = gtk_tree_view_get_model (treeview);
|
||||||
|
button_enable = gtk_toolbar_get_nth_item (
|
||||||
|
GTK_TOOLBAR (extensions->toolbar), 1);
|
||||||
|
button_disable = gtk_toolbar_get_nth_item (
|
||||||
|
GTK_TOOLBAR (extensions->toolbar), 2);
|
||||||
|
if (gtk_tree_model_get_iter (model, &iter, path))
|
||||||
|
{
|
||||||
|
MidoriExtension* extension;
|
||||||
|
|
||||||
|
gtk_tree_model_get (model, &iter, 0, &extension, -1);
|
||||||
|
if (midori_extension_is_active (extension))
|
||||||
|
midori_extension_deactivate (extension);
|
||||||
|
else
|
||||||
|
g_signal_emit_by_name (extension, "activate", extensions->app);
|
||||||
|
gtk_widget_set_sensitive (GTK_WIDGET (button_enable),
|
||||||
|
!midori_extension_is_active (extension));
|
||||||
|
gtk_widget_set_sensitive (GTK_WIDGET (button_disable),
|
||||||
|
midori_extension_is_active (extension));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_extensions_treeview_cursor_changed_cb (GtkTreeView* treeview,
|
||||||
|
MidoriExtensions* extensions)
|
||||||
|
{
|
||||||
|
GtkTreeModel* model;
|
||||||
|
GtkTreePath* path;
|
||||||
|
GtkTreeIter iter;
|
||||||
|
GtkToolItem* button_enable;
|
||||||
|
GtkToolItem* button_disable;
|
||||||
|
|
||||||
|
gtk_tree_view_get_cursor (treeview, &path, NULL);
|
||||||
|
model = gtk_tree_view_get_model (treeview);
|
||||||
|
button_enable = gtk_toolbar_get_nth_item (
|
||||||
|
GTK_TOOLBAR (extensions->toolbar), 1);
|
||||||
|
button_disable = gtk_toolbar_get_nth_item (
|
||||||
|
GTK_TOOLBAR (extensions->toolbar), 2);
|
||||||
|
if (gtk_tree_model_get_iter (model, &iter, path))
|
||||||
|
{
|
||||||
|
MidoriExtension* extension;
|
||||||
|
|
||||||
|
if (katze_tree_view_get_selected_iter (treeview, &model, &iter))
|
||||||
|
{
|
||||||
|
gtk_tree_model_get (model, &iter, 0, &extension, -1);
|
||||||
|
gtk_widget_set_sensitive (GTK_WIDGET (button_enable),
|
||||||
|
!midori_extension_is_active (extension));
|
||||||
|
gtk_widget_set_sensitive (GTK_WIDGET (button_disable),
|
||||||
|
midori_extension_is_active (extension));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
midori_extensions_init (MidoriExtensions* extensions)
|
||||||
|
{
|
||||||
|
/* Create the treeview */
|
||||||
|
GtkTreeViewColumn* column;
|
||||||
|
GtkCellRenderer* renderer_text;
|
||||||
|
GtkCellRenderer* renderer_pixbuf;
|
||||||
|
GtkListStore* liststore = gtk_list_store_new (1, G_TYPE_OBJECT);
|
||||||
|
extensions->treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (liststore));
|
||||||
|
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (extensions->treeview), FALSE);
|
||||||
|
column = gtk_tree_view_column_new ();
|
||||||
|
renderer_pixbuf = gtk_cell_renderer_pixbuf_new ();
|
||||||
|
gtk_tree_view_column_pack_start (column, renderer_pixbuf, FALSE);
|
||||||
|
gtk_tree_view_column_set_cell_data_func (column, renderer_pixbuf,
|
||||||
|
(GtkTreeCellDataFunc)midori_extensions_treeview_render_icon_cb,
|
||||||
|
extensions->treeview, NULL);
|
||||||
|
renderer_text = gtk_cell_renderer_text_new ();
|
||||||
|
gtk_tree_view_column_pack_start (column, renderer_text, FALSE);
|
||||||
|
gtk_tree_view_column_set_cell_data_func (column, renderer_text,
|
||||||
|
(GtkTreeCellDataFunc)midori_extensions_treeview_render_text_cb,
|
||||||
|
extensions->treeview, NULL);
|
||||||
|
gtk_tree_view_append_column (GTK_TREE_VIEW (extensions->treeview), column);
|
||||||
|
g_object_unref (liststore);
|
||||||
|
g_signal_connect (extensions->treeview, "row-activated",
|
||||||
|
G_CALLBACK (midori_extensions_treeview_row_activated_cb),
|
||||||
|
extensions);
|
||||||
|
g_signal_connect (extensions->treeview, "cursor-changed",
|
||||||
|
G_CALLBACK (midori_extensions_treeview_cursor_changed_cb),
|
||||||
|
extensions);
|
||||||
|
gtk_widget_show (extensions->treeview);
|
||||||
|
gtk_box_pack_start (GTK_BOX (extensions), extensions->treeview, TRUE, TRUE, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* midori_extensions_new:
|
||||||
|
*
|
||||||
|
* Creates a new empty extensions.
|
||||||
|
*
|
||||||
|
* Return value: a new #MidoriExtensions
|
||||||
|
*
|
||||||
|
* Since: 0.1.2
|
||||||
|
**/
|
||||||
|
GtkWidget*
|
||||||
|
midori_extensions_new (void)
|
||||||
|
{
|
||||||
|
MidoriExtensions* extensions = g_object_new (MIDORI_TYPE_EXTENSIONS,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
return GTK_WIDGET (extensions);
|
||||||
|
}
|