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);
|
||||
}
|