Compare commits
1 Commits
3.38.2
...
NAUTILUS_S
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
52f36c58a4 |
38
.cvsignore
@@ -1,38 +0,0 @@
|
||||
ABOUT-NLS
|
||||
.new.ltmain.sh
|
||||
Makefile
|
||||
Makefile.in
|
||||
aclocal.m4
|
||||
autom4te.cache
|
||||
config.cache
|
||||
config.guess
|
||||
config.h
|
||||
config.h.in
|
||||
config.log
|
||||
config.status
|
||||
config.sub
|
||||
configure
|
||||
configure.scan
|
||||
intl
|
||||
libtool
|
||||
ltconfig
|
||||
ltmain.sh
|
||||
missing
|
||||
mkinstalldirs
|
||||
install-sh
|
||||
stamp-h
|
||||
stamp-h.in
|
||||
version.h
|
||||
intl
|
||||
macros
|
||||
INSTALL
|
||||
control-center.spec
|
||||
my_control_center_idl
|
||||
*.tar.gz
|
||||
Gnome.directory
|
||||
intltool-*
|
||||
confdefs.h
|
||||
libgswitchit
|
||||
libsound
|
||||
depcomp
|
||||
stamp-h1
|
||||
340
COPYING
@@ -1,340 +0,0 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, 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 or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
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 give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
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 Program or any portion
|
||||
of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
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 Program, 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 Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) 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; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, 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 executable. However, as a
|
||||
special exception, the source code 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.
|
||||
|
||||
If distribution of executable or 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 counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program 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.
|
||||
|
||||
5. 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 Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program 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 to
|
||||
this License.
|
||||
|
||||
7. 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 Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program 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 Program.
|
||||
|
||||
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.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program 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.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the 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 Program
|
||||
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 Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, 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
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. 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 PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), 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 Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. 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 program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) year name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
Public License instead of this License.
|
||||
@@ -1,2 +0,0 @@
|
||||
Email: jody@gnome.org
|
||||
Email: jrb@gnome.org
|
||||
23
Makefile.am
@@ -1,23 +0,0 @@
|
||||
SUBDIRS = po libsounds libbackground libwindow-settings libgswitchit libkbdraw gnome-settings-daemon capplets control-center vfs-methods idl schemas $(TYPING_BREAK)
|
||||
|
||||
#I removed the root-manager for now
|
||||
#
|
||||
# it generated this error :
|
||||
# root-manager.c:55:31: security/pam_appl.h: No such file or directory
|
||||
# while compiling. I guess we need to check for pam or something
|
||||
# in the configure.in file. Since we are not using it now, i will
|
||||
# remove it from the default build. Chema
|
||||
|
||||
dist-hook: control-center.spec
|
||||
cp control-center.spec $(distdir)
|
||||
|
||||
DISTCLEANFILES = \
|
||||
intltool-extract \
|
||||
intltool-merge \
|
||||
intltool-update
|
||||
|
||||
EXTRA_DIST = \
|
||||
control-center.spec.in \
|
||||
intltool-extract.in \
|
||||
intltool-merge.in \
|
||||
intltool-update.in
|
||||
439
NEWS
@@ -1,439 +0,0 @@
|
||||
gnome-control-center 2.11.3
|
||||
|
||||
- fix mute handling, particularly for devices without hardware mute support
|
||||
or with applications that use volume=0 for mute (Ronald S. Bultje)
|
||||
- clipboard manager (Anders Carlsson)
|
||||
- canvas a11y support (Carlos Garnacho Parro)
|
||||
- name and description to the object information (Rodrigo Moya)
|
||||
|
||||
|
||||
translator:
|
||||
|
||||
Vladimir Petkov (bg)
|
||||
Miloslav Trmac (cs)
|
||||
Rhys Jones (cy)
|
||||
Martin Willemoes Hansen (da)
|
||||
Adam Weinberger (en_CA)
|
||||
Alessio Dessì (it)
|
||||
Takeshi AIHANA (ja)
|
||||
Kjartan Maraas (nb)
|
||||
Kjartan Maraas (no)
|
||||
Elian Myftiu (sq)
|
||||
Theppitak Karoonboonyanan (th)
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
gnome-control-center 2.11.1
|
||||
|
||||
- allow to configure the menubar shortcut (Sebastien Bacher)
|
||||
- new shell layout code (Carlos Garnacho Parro)
|
||||
- port of the font capplet to gtk_font_button and some cleanup (Paolo Borelli)
|
||||
- make proxy settings HIG compliant (Jorn Baayen)
|
||||
- lot of cleanups (Kjartan Maraas)
|
||||
- don't list themes using the Hidden property (Shakti Sen).
|
||||
- fix the theme preview crasher with xorg/composite (Colin Gibbs)
|
||||
|
||||
translators:
|
||||
|
||||
Vladimir Petkov (bg)
|
||||
Miloslav Trmac (cs)
|
||||
Kostas Papadimas (el)
|
||||
Adam Weinberger (en_CA)
|
||||
Ivar Smolin (et)
|
||||
Iñaki Larrañaga Murgoitio (eu)
|
||||
Gabor Kelemen (hu)
|
||||
Elian Myftiu (sq)
|
||||
Maxim Dziumanenko (uk)
|
||||
Canonical Ltd (xh)
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
gnome-control-center 2.10.0
|
||||
|
||||
background:
|
||||
- fix the crashes with non-UTF8 names (Rodney Dawes)
|
||||
|
||||
general:
|
||||
- do not warn vnc users that their XKB does not work. We already know.
|
||||
(Jody Goldberg)
|
||||
|
||||
translators:
|
||||
|
||||
Vladimir Petkov (bg)
|
||||
Jordi Mallach (ca)
|
||||
Miloslav Trmac (cs)
|
||||
Martin Willemoes Hansen (da)
|
||||
Frank Arnold (de)
|
||||
Kostas Papadimas (el)
|
||||
Adam Weinberger (en_CA)
|
||||
David Lodge (en_GB)
|
||||
Francisco Javier F. Serrador (es)
|
||||
Priit Laes (et)
|
||||
Pauli Virtanen (fi)
|
||||
Simon Manlay (fr)
|
||||
Ankit Patel (gu)
|
||||
Gabor Kelemen (hu)
|
||||
Alessio Dessì (it)
|
||||
Takeshi AIHANA (ja)
|
||||
Changwoo Ryu (ko)
|
||||
Žygimantas BeruÄ<75>ka (lt)
|
||||
Kjartan Maraas (nb)
|
||||
Reinout van Schouwen (nl)
|
||||
Kjartan Maraas (no)
|
||||
Gnome PL Team (pl)
|
||||
Raphael Higino (pt_BR)
|
||||
Duarte Loreto (pt)
|
||||
Dan Damian (ro)
|
||||
Leonid Kanter (ru)
|
||||
Marcel Telka (sk)
|
||||
Elian Myftiu (sq)
|
||||
Veljko M. Stanojevic (sr)
|
||||
Christian Rose (sv)
|
||||
Theppitak Karoonboonyanan (th)
|
||||
Maxim Dziumanenko (uk)
|
||||
Woodman Tuen (zh_TW)
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
gnome-control-center 2.9.91
|
||||
|
||||
general:
|
||||
- check for xmodmap files, and offer to load them (#143487)
|
||||
- changing the default value for "handleIndicators" to false (#161343)
|
||||
(Sergey V. Udaltsov)
|
||||
- check for screensaver functionality in libXext.so also when deciding
|
||||
to build typing-break (#155461) (Leena Gunda)
|
||||
- providing ability to suppress the "x sysconfig changed" warning message
|
||||
(#150435) (Sergey V. Udaltsov).
|
||||
- handle the modmap settings (#143487) (Shakti Sen)
|
||||
- fix number of leaks (Kjartan Maraas)
|
||||
|
||||
background:
|
||||
- use the boolean argument to specify if we want to update gconf or not.
|
||||
Always get the colors for both primary and secondary and update the thumbnail
|
||||
(#166486) (Rodney Dawes)
|
||||
- force using the GTK backend (#154978) (Rodney Dawes)
|
||||
|
||||
common:
|
||||
- leak fixes, use GtkIconTheme (#166267) (Kjartan Maraas)
|
||||
|
||||
network:
|
||||
- adding/removing the host name instantly to/from gconf (#166233) (Shakti Sen)
|
||||
|
||||
theme-switcher:
|
||||
- new install procedure (#102216) (David Sedeño)
|
||||
- some string fixes (#166550) (David Lodge)
|
||||
- remove a load of leaks and make sure newly installed themes show up in the
|
||||
relevant lists without having to close/open the dialog again (#166267)
|
||||
(Kjartan Maraas)
|
||||
- fix an infinite loop that was bringing single-CPU systems to their
|
||||
knees (#160803) (Elijah Newren).
|
||||
|
||||
Translators:
|
||||
|
||||
Vladimir Petkov (bg)
|
||||
Miloslav Trmac (cs)
|
||||
Frank Arnold (de)
|
||||
Nikos Charonitakis (el)
|
||||
Adam Weinberger (en_CA)
|
||||
David Lodge (en_GB)
|
||||
Francisco Javier F. Serrador (es)
|
||||
Ivar Smolin (et)
|
||||
Pauli Virtanen (fi)
|
||||
Alessio Dessì (it)
|
||||
Takeshi AIHANA (ja)
|
||||
Changwoo Ryu (ko)
|
||||
Žygimantas BeruÄ<75>ka (lt)
|
||||
Kjartan Maraas (nb)
|
||||
rajeev shrestha (ne)
|
||||
Åsmund Skjæveland (nn)
|
||||
Kjartan Maraas (no)
|
||||
Raphael Higino (pt_BR)
|
||||
Duarte Loreto (pt)
|
||||
Leonid Kanter (ru)
|
||||
Elian Myftiu (sq)
|
||||
Christian Rose (sv)
|
||||
Theppitak Karoonboonyanan (th)
|
||||
Baris Cicek (tr)
|
||||
Funda Wang (zh_CN)
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
gnome-control-center 2.9.4
|
||||
|
||||
- fix the build out of the source dir (Closes: #158333).
|
||||
- don't set "close" as the default button for the differents capplets
|
||||
(Closes: #98202).
|
||||
- use a temporary filename to not overwrite existant files in ~/.themes
|
||||
(Closes: #97180).
|
||||
- theme-thumbnailer doesn't require an absolute path (Closes: #153203).
|
||||
- use ~/ instead of / as working directory for programs launched with the
|
||||
multimedia keys (Closes: #162069).
|
||||
- fixed the "locate pointer" feature (Closes: #149383).
|
||||
- load the translated descriptions in the backgrounds capplet
|
||||
(Closes: # 160700)
|
||||
- add a preview in the backgrounds fileselector (Closes: #139714).
|
||||
- add a proxy exclusion list configuration in the network capplet
|
||||
(Closes: #147666).
|
||||
- some bugs and leaks fixed.
|
||||
|
||||
Translators:
|
||||
|
||||
Vladimir Petkov (bg)
|
||||
Miloslav Trmac (cs)
|
||||
Kostas Papadimas (el)
|
||||
Adam Weinberger (en_CA)
|
||||
Francisco Javier F. Serrador (es)
|
||||
Takeshi AIHANA (ja)
|
||||
Žygimantas BeruÄ<75>ka (lt)
|
||||
Kjartan Maraas (nb)
|
||||
rajeev shrestha (ne)
|
||||
Kjartan Maraas (no)
|
||||
Leonid Kanter (ru)
|
||||
Elian Myftiu (sq)
|
||||
Christian Rose (sv)
|
||||
|
||||
|
||||
gnome-control-center 2.9.3
|
||||
|
||||
- Add a button to turn off a sound event (#14272).
|
||||
- Allow to use themes with the ".tgz" extension (#148895).
|
||||
- Don't nuke .Xdefaults when restarting g-s-d (#127050).
|
||||
- Fix the themes installation with the non GNU versions of tar (#114553).
|
||||
- Mask the "Text Editor" tab since the new mime system doesn't use this
|
||||
setting.
|
||||
- Updated the tooltips to respect the HIG.
|
||||
- Updated to use libnautilus-extensions.
|
||||
- Updated the menu entries for the new gnome-menus system.
|
||||
|
||||
gnome-control-center 2.8.1
|
||||
|
||||
- Some tweaking of the available default applications
|
||||
- Background capplet fixes (#154003)
|
||||
- keyboard patchs (#144490) (#153866)
|
||||
- Patch leak in XKB code
|
||||
- update translations
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
gnome-control-center 2.8.0
|
||||
|
||||
Jody Goldberg
|
||||
* Fixed float/int mismatch in peditor
|
||||
|
||||
Jonathan Blandford
|
||||
* Fix docs link for at-properties capplet.
|
||||
|
||||
Pierre Ossman
|
||||
* display the volume dialog in the correct place
|
||||
|
||||
Sergey V. Udaltsov
|
||||
* default switchcut (Alt*2) is introduced
|
||||
|
||||
Translations:
|
||||
* All translations updated
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
gnome-control-center 2.7.1
|
||||
|
||||
Translations:
|
||||
* Bosnian translation added.
|
||||
|
||||
Frederic Crozat:
|
||||
* Use themed icon for windows
|
||||
|
||||
Rodney Dawes:
|
||||
* Add "W x H pixels" to description, and remove file size for bg capplet
|
||||
|
||||
Sergey:
|
||||
* Fixes to keybinding capplet
|
||||
|
||||
Kjartan Maraas:
|
||||
* text cleanup
|
||||
|
||||
Jeroen Zwartepoorte:
|
||||
* Use the parent type in the G_DEFINE_TYPE
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
gnome-control-center 2.7.0
|
||||
* No NEWS file updates this time due to time pressures. 2.7.1
|
||||
should have a full change.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
gnome-control-center 2.6.1
|
||||
|
||||
Jody:
|
||||
* Add the ximian shell to the tarball and polish it up a bit
|
||||
|
||||
Michael Terry:
|
||||
* Fix ui-review comments for keybinding capplet
|
||||
|
||||
Sergey:
|
||||
* Add a hook to libgswitchit to notify when xkb is reloaded
|
||||
|
||||
Shailesh Mittal:
|
||||
http://bugzilla.gnome.org/show_bug.cgi?id=114832
|
||||
* IPV6 support in the file types capplet
|
||||
|
||||
Sergey V. Udaltsov:
|
||||
* Merged the keyboard preview branch. The keyboard capplet got another tab.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
gnome-control-center 2.6.1
|
||||
|
||||
Alex Larsson:
|
||||
https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=119494
|
||||
* Fix reverting a size change.
|
||||
|
||||
Chris Lahey:
|
||||
* Fix ordering of themes in theme manager
|
||||
* Fix sizing of svg backgrounds
|
||||
|
||||
Glynn:
|
||||
* Toplevel window icons should use the icon themes
|
||||
|
||||
Jody:
|
||||
http://bugzilla.gnome.org/show_bug.cgi?id=139190
|
||||
* Fix uniqueness test for binding special keys with no name
|
||||
* Fix theme manager selection when not running metacity
|
||||
http://bugzilla.gnome.org/show_bug.cgi?id=139605
|
||||
* Mouse buttons are not valid modifiers for keybindings
|
||||
* Force libxklavier 1.0.2 so that we can work with x.org and xfree86
|
||||
* Match nautilus' interpretation of icons in desktop files
|
||||
|
||||
Padraig O'Briain:
|
||||
http://bugzilla.gnome.org/show_bug.cgi?id=131538.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
gnome-control-center 2.6.0.3
|
||||
|
||||
Jody:
|
||||
http://bugzilla.gnome.org/show_bug.cgi?id=138701
|
||||
* Fix typo
|
||||
* Fix uniqueness test for keybindings
|
||||
* Merge in some build fixes for sun's forte and Irix
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
gnome-control-center 2.5.4
|
||||
|
||||
Dennis Cranston :
|
||||
http://bugzilla.gnome.org/show_bug.cgi?id=133715
|
||||
* Improve layout of display capplet
|
||||
|
||||
Alexander Winston :
|
||||
http://bugzilla.gnome.org/show_bug.cgi?id=133214
|
||||
* quote the AC_DEFUN properly
|
||||
|
||||
Jody :
|
||||
http://bugzilla.gnome.org/show_bug.cgi?id=124064
|
||||
* Add a test for ngettext
|
||||
* Delete some of the unused file cluttering the tree
|
||||
http://bugzilla.gnome.org/show_bug.cgi?id=134446
|
||||
* Trivial string consistency adjustment
|
||||
http://bugzilla.gnome.org/show_bug.cgi?id=128164
|
||||
* Handle sorted trees
|
||||
* Fix incorrect string in gnome-settings-daemon
|
||||
|
||||
Muktha Narayan :
|
||||
http://bugzilla.gnome.org/show_bug.cgi?id=124032
|
||||
* Do not popup the logout dialog when the close button (X)
|
||||
|
||||
Jan Arne Petersen :
|
||||
* Move a few capplets to the new file selector
|
||||
|
||||
Padraig O'Briain :
|
||||
* Fix the ATK relations for the file-type capplet
|
||||
|
||||
Julio M. Merino Vidal :
|
||||
* Make fontilus and themus respect the gconf install settings
|
||||
|
||||
Rodney Dawes:
|
||||
http://bugzilla.gnome.org/show_bug.cgi?id=134171
|
||||
* Fix transtions for titles of colour pickers.
|
||||
|
||||
Kaushal Kumar:
|
||||
http://bugzilla.gnome.org/show_bug.cgi?id=109091
|
||||
* Warn before deleting a type
|
||||
|
||||
Richard Hult:
|
||||
* Improve Dr Wright.
|
||||
|
||||
msuarezalvarez@arnet.com.ar :
|
||||
http://bugzilla.gnome.org/show_bug.cgi?id=134699
|
||||
* Another typo in the new a11y settings daemon extensions
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
gnome-control-center 2.5.1
|
||||
|
||||
Jody:
|
||||
http://bugzilla.gnome.org/show_bug.cgi?id=125899
|
||||
http://bugzilla.gnome.org/show_bug.cgi?id=125970
|
||||
* Fix the build and configure on older X servers.
|
||||
* Use icon themes
|
||||
|
||||
Sergey:
|
||||
* Merge gswitchit into gnome-settings-daemon and keyboard capplet
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
gnome-control-center 2.5.0
|
||||
|
||||
Jody:
|
||||
* Add libxklavier and prep for inclusion of gswitchit's
|
||||
xkb-properties-capplet
|
||||
* http://bugzilla.gnome.org/show_bug.cgi?id=120842 [HIGification broke accessx]
|
||||
* http://bugzilla.gnome.org/show_bug.cgi?id=106489 [protect against gconf failure]
|
||||
* http://bugzilla.gnome.org/show_bug.cgi?id=124513 [Handle TruColor Displays]
|
||||
* http://bugzilla.gnome.org/show_bug.cgi?id=116710 [smarter maximum dpi]
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
gnome-control-center 2.1.6
|
||||
|
||||
Jody:
|
||||
* gnome-keyboard-properties.c (accessibility_button_clicked) : fix
|
||||
minor typo that disables the error dialog in the event of failure.
|
||||
|
||||
Jonathan:
|
||||
* gnome-theme-info.c : Rewrite. Now working
|
||||
* gnome-theme-manager : Fix lots of bugs. Use the rewrite.
|
||||
|
||||
gnome-control-center 2.1.0.2
|
||||
|
||||
Jody:
|
||||
http://bugzilla.gnome.org/show_bug.cgi?id=93211
|
||||
* disable edit button when selecting mime catagory
|
||||
* Tidy labels and accelerators in file-type edit dialogs
|
||||
|
||||
Michael:
|
||||
http://bugzilla.gnome.org/show_bug.cgi?id=91535
|
||||
* Don't start esd just to stop it
|
||||
|
||||
Iain Holmes:
|
||||
* Add an image size label for background capplet.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
gnome-control-center 2.1.0.1
|
||||
|
||||
Jody:
|
||||
* Some minor ui tweaks for accessx.
|
||||
* Some aix portabiltiy patches
|
||||
* fix accelerators for ui-properties capplet.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
gnome-control-center 2.0.1
|
||||
|
||||
Chema:
|
||||
http://bugzilla.gnome.org/show_bug.cgi?id=86018
|
||||
* Only assign the filename to the label if the file is valid.
|
||||
|
||||
GMan:
|
||||
* Fix titles to use 'preferences' rather than 'properties'
|
||||
|
||||
Jody:
|
||||
* Clean up the handling of custom applications in mime type capplet.
|
||||
* Supply some decent defaults for new mime types.
|
||||
* Implement Background capplet UI recommendations.
|
||||
* Implement Font capplet UI recommendations.
|
||||
* Reorganize the AccessX UI.
|
||||
* Fix cmd line args for file-type capplet.
|
||||
|
||||
http://bugzilla.gnome.org/show_bug.cgi?id=84014
|
||||
* Handle Drag-n-Drop of uris with escaped characters.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
First split version of this package
|
||||
62
README
@@ -1,62 +0,0 @@
|
||||
GNOME Control Center
|
||||
====================
|
||||
|
||||
Requirements -
|
||||
|
||||
intltool >= 0.21
|
||||
gtk+ >= 2.3.0
|
||||
gconf >= 2.0.0
|
||||
libgnome >= 2.0.0
|
||||
libgnomeui >= 2.0.0
|
||||
libglade >= 2.0.0
|
||||
libbonobo >= 2.0.0
|
||||
libbonoboui >= 2.0.0
|
||||
libgnomevfs >= 2.0.0
|
||||
gnome-desktop >= 2.0.0
|
||||
gnome-icon-theme >= 1.1.3
|
||||
|
||||
Installation -
|
||||
|
||||
See the file 'INSTALL'
|
||||
|
||||
How to report bugs -
|
||||
|
||||
Bugs should be reported to the GNOME bug tracking system under the product
|
||||
control-center. It is available at http://bugzilla.gnome.org.
|
||||
|
||||
In the report please include the following information -
|
||||
|
||||
Operating system and version
|
||||
For Linux, version of the C library
|
||||
How to reproduce the bug if possible
|
||||
If the bug was a crash, include the exact text that was printed out
|
||||
A stacktrace where possible [see below]
|
||||
|
||||
How to get a stack trace -
|
||||
|
||||
If the crash is reproducible, it is possible to get a stack trace and
|
||||
attach it to the bug report. The following steps are used to obtain a
|
||||
stack trace -
|
||||
|
||||
Run the program in gdb [the GNU debugger] or any other debugger
|
||||
ie. gdb gnome-calculator
|
||||
Start the program
|
||||
ie. (gdb) run
|
||||
Reproduce the crash and the program will exit to the gdb prompt
|
||||
Get the back trace
|
||||
ie. (gdb) bt
|
||||
|
||||
Once you have the backtrace, copy and paste this either into the
|
||||
'Comments' field or attach a file with it included.
|
||||
|
||||
|
||||
Patches -
|
||||
|
||||
Patches should be submitted to bugzilla.gnome.org or emailed to one of
|
||||
the people listed in the MAINTAINERS file. If using bugzilla, attach
|
||||
the patch to a new bug report [or preferably, check to see if there is
|
||||
already a bug report that corresponds to your patch]. Bug reports
|
||||
containing patches should include the 'PATCH' keyword.
|
||||
|
||||
Patches should be created using the unified diff form.
|
||||
ie. cvs diff -u file-to-be-patched.c > patch.diff
|
||||
105
TODO
@@ -1,105 +0,0 @@
|
||||
|
||||
[ Things prefaced with GSD need to be fixed in the gnome-settings daemon
|
||||
and not the dialog ]
|
||||
|
||||
ACCESSIBILITY:
|
||||
* UI love
|
||||
* Figure out Keyboard/peripherals integration
|
||||
|
||||
BACKGROUND:
|
||||
* Seth love
|
||||
* Get actual GNOME backgrounds
|
||||
|
||||
DEFAULT APPLICATIONS PROPERTIES:
|
||||
* Merge in Window Manager selection
|
||||
|
||||
FILE TYPES:
|
||||
* Stability issues
|
||||
* UI Love
|
||||
|
||||
FONT AND THEME:
|
||||
* merge them
|
||||
|
||||
GNOME SETTINGS DAEMON:
|
||||
* disk monitor
|
||||
|
||||
KEYBOARD SHORTCUTS:
|
||||
* Not sure I like the name.
|
||||
* Needs icon
|
||||
* Add a way to add new ones
|
||||
|
||||
KEYBOARD PROPERTIES:
|
||||
* GSD: support keyboard bell
|
||||
* Remove awful jrb-art and replace with actual blinking cursor
|
||||
|
||||
MOUSE PROPERTIES:
|
||||
* GSD: Add support for devices other than CoreInput.
|
||||
|
||||
KEYBINDINGS:
|
||||
* Metacity keyboard merging. See what hp plans to do
|
||||
|
||||
PANEL:
|
||||
* UI love
|
||||
* port gconf-peditor functionality
|
||||
|
||||
SAWFISH????
|
||||
|
||||
SOUND:
|
||||
* Unknown
|
||||
* Buggy as heck
|
||||
|
||||
SCREENSAVER:
|
||||
* See what Jacob wants to do
|
||||
* xscreensaver release
|
||||
|
||||
UI-PROPERTIES:
|
||||
* Seems to be okay
|
||||
|
||||
GENERAL:
|
||||
* Where we have keys, add a restore to defaults context menu button.
|
||||
* Kill 'advanced'
|
||||
* Control center itself seems to be fine
|
||||
* Change buttons to use whatever the UI team comes up with
|
||||
* Make sure we handle 'locked down' keys
|
||||
* Make sure we handle all broken keys!
|
||||
|
||||
|
||||
GOING FORWARD:
|
||||
|
||||
Hardware Integration
|
||||
- hwbrowser??? Kde has one; should we?
|
||||
- peripherals (RH only?)
|
||||
- gphoto/sane/cd burning?? Userland hw.
|
||||
|
||||
Nautilus:
|
||||
- Move nautilus settings
|
||||
- Desktop should be a separate dialog
|
||||
|
||||
Background:
|
||||
- Merge nautilus pane and bg capplet;
|
||||
- possibly even popup a nautilus window of bg's for DnD
|
||||
- Integrate better w/ nautilus
|
||||
- per Workspace?
|
||||
|
||||
Workspace/Tasks
|
||||
- Set number and name of workspaces
|
||||
- Maybe something else?
|
||||
|
||||
Identification Capplet
|
||||
- GDM screen
|
||||
- Mail capplet
|
||||
|
||||
Password Capplet?
|
||||
- ssh/smb
|
||||
|
||||
Themes and Appearance:
|
||||
- blah
|
||||
|
||||
Sound:
|
||||
- blah
|
||||
|
||||
Bugzilla
|
||||
- Start using it better
|
||||
|
||||
|
||||
|
||||
19
TODO.xml
@@ -1,19 +0,0 @@
|
||||
<todo>
|
||||
<title>GNOME Control Center TODO list</title>
|
||||
<section>
|
||||
<title>Capplets</title>
|
||||
|
||||
<entry size="big" status="10%" target="1.4">
|
||||
<title>Screensaver XML descriptions</title>
|
||||
<description>
|
||||
<p>
|
||||
Create XML descriptions to allow dialog configuration of the various
|
||||
screensavers that come with XScreensaver. See
|
||||
capplets/new-screensaver-properties/screensavers/README for
|
||||
documentaiton.
|
||||
</p>
|
||||
</description>
|
||||
<contact>hovinen@helixcode.com</contact>
|
||||
</entry>
|
||||
</section> <!--Capplets-->
|
||||
</todo>
|
||||
@@ -1,18 +0,0 @@
|
||||
.deps
|
||||
.libs
|
||||
*.lo
|
||||
*.la
|
||||
Makefile
|
||||
ximia-archiver
|
||||
Makefile.in
|
||||
ximian-config-manager
|
||||
ximian_archiverConf.sh
|
||||
ximian-archiver
|
||||
bonobo-moniker-archiver
|
||||
config-archiver
|
||||
config_archiverConf.sh
|
||||
Bonobo_Moniker_archiver.oaf
|
||||
ConfigArchiver.h
|
||||
ConfigArchiver-stubs.c
|
||||
ConfigArchiver-skels.c
|
||||
ConfigArchiver-common.c
|
||||
@@ -1,35 +0,0 @@
|
||||
<oaf_info>
|
||||
|
||||
<oaf_server iid="OAFIID:Bonobo_Moniker_archiver_Factory" type="exe" location="bonobo-moniker-archiver">
|
||||
<oaf_attribute name="repo_ids" type="stringv">
|
||||
<item value="IDL:GNOME/GenericFactory:1.0"/>
|
||||
</oaf_attribute>
|
||||
|
||||
<oaf_attribute name="name" type="string" value="XML Database Moniker factory"/>
|
||||
</oaf_server>
|
||||
|
||||
<oaf_server iid="OAFIID:Bonobo_Moniker_archiverdb" type="factory"
|
||||
location="OAFIID:Bonobo_Moniker_archiver_Factory">
|
||||
<oaf_attribute name="repo_ids" type="stringv">
|
||||
<item value="IDL:Bonobo/Moniker:1.0"/>
|
||||
<item value="IDL:Bonobo/Unknown:1.0"/>
|
||||
</oaf_attribute>
|
||||
<oaf_attribute name="name" type="string" value="XML Database Moniker with archiver interface"/>
|
||||
<oaf_attribute name="bonobo:moniker" type="stringv">
|
||||
<item value="archiverdb:"/>
|
||||
</oaf_attribute>
|
||||
</oaf_server>
|
||||
|
||||
<oaf_server iid="OAFIID:Bonobo_Moniker_archive" type="factory"
|
||||
location="OAFIID:Bonobo_Moniker_archiver_Factory">
|
||||
<oaf_attribute name="repo_ids" type="stringv">
|
||||
<item value="IDL:Bonobo/Moniker:1.0"/>
|
||||
<item value="IDL:Bonobo/Unknown:1.0"/>
|
||||
</oaf_attribute>
|
||||
<oaf_attribute name="name" type="string" value="XML archiver interface"/>
|
||||
<oaf_attribute name="bonobo:moniker" type="stringv">
|
||||
<item value="archive:"/>
|
||||
</oaf_attribute>
|
||||
</oaf_server>
|
||||
|
||||
</oaf_info>
|
||||
1084
archiver/ChangeLog
@@ -1,99 +0,0 @@
|
||||
confexecdir = $(libdir)
|
||||
confexec_DATA = config_archiverConf.sh
|
||||
|
||||
Locationmetadir = $(datadir)/control-center/archiver
|
||||
Locationmeta_DATA = default-user.xml default-global.xml
|
||||
|
||||
includedir = $(prefix)/include/config-archiver
|
||||
|
||||
INCLUDES = \
|
||||
-DGNOMELOCALEDIR=\""$(prefix)/$(DATADIRNAME)/locale"\" \
|
||||
-I$(includedir) \
|
||||
$(GNOME_INCLUDEDIR) \
|
||||
-DVERSION=\""$(VERSION)"\" \
|
||||
-DG_LOG_DOMAIN=\"libconfig-archiver\" \
|
||||
-DCONFIGDIR=\""/etc"\" \
|
||||
-DLOCATION_DIR=\""$(datadir)/control-center/archiver"\" \
|
||||
-DGLADE_DIR=\""$(INTERFACES_DIR)"\" \
|
||||
-DXST_BACKEND_LOCATION=\""$(datadir)/setup-tool-backends/scripts"\" \
|
||||
@ARCHIVER_CFLAGS@ \
|
||||
@MONIKER_CFLAGS@
|
||||
|
||||
CORBA_SOURCE = \
|
||||
ConfigArchiver.h \
|
||||
ConfigArchiver-common.c \
|
||||
ConfigArchiver-stubs.c \
|
||||
ConfigArchiver-skels.c
|
||||
|
||||
idl_flags = `gnome-config --cflags idl`
|
||||
|
||||
$(CORBA_SOURCE): $(top_srcdir)/idl/ConfigArchiver.idl
|
||||
orbit-idl $(top_srcdir)/idl/ConfigArchiver.idl -I$(top_srcdir)/idl $(idl_flags)
|
||||
|
||||
bin_PROGRAMS = bonobo-moniker-archiver config-archiver
|
||||
|
||||
lib_LTLIBRARIES = libconfig_archiver.la
|
||||
|
||||
libconfig_archiver_la_SOURCES = \
|
||||
util.c util.h \
|
||||
archiver-client.c \
|
||||
$(CORBA_SOURCE)
|
||||
|
||||
libconfig_archiver_la_LIBADD = \
|
||||
@GNOME_XML_LIBS@
|
||||
|
||||
archiver-client.c: $(CORBA_SOURCE)
|
||||
|
||||
include_HEADERS = \
|
||||
ConfigArchiver.h \
|
||||
archiver-client.h
|
||||
|
||||
config_archiver_SOURCES = \
|
||||
config-archiver.c
|
||||
|
||||
config_archiver_LDADD = \
|
||||
@ARCHIVER_LIBS@ \
|
||||
libconfig_archiver.la
|
||||
|
||||
#
|
||||
# Create the config_archiverConf.sh file from the sh.in file
|
||||
#
|
||||
config_archiverConf.sh: config_archiverConf.sh.in Makefile
|
||||
sed -e 's?\@VERSION\@?$(VERSION)?' \
|
||||
-e 's?\@CONFIG_ARCHIVER_LIBDIR\@?$(CONFIG_ARCHIVER_LIBDIR)?g' \
|
||||
-e 's?\@CONFIG_ARCHIVER_LIBS\@?$(CONFIG_ARCHIVER_LIBS)?g' \
|
||||
-e 's?\@CONFIG_ARCHIVER_INCLUDEDIR\@?$(CONFIG_ARCHIVER_INCLUDEDIR)?g' \
|
||||
< $(srcdir)/config_archiverConf.sh.in > config_archiverConf.tmp \
|
||||
&& mv config_archiverConf.tmp config_archiverConf.sh
|
||||
|
||||
OAF_FILES = \
|
||||
Bonobo_Moniker_archiver.oaf
|
||||
|
||||
oafdir = $(datadir)/oaf
|
||||
oaf_DATA = $(OAF_FILES)
|
||||
|
||||
monikerdir = $(libdir)/bonobo/monikers
|
||||
|
||||
Bonobo_Moniker_archiver.oaf : $(srcdir)/Bonobo_Moniker_archiver.oaf.in $(top_builddir)/config.status
|
||||
sed -e "s|\@MONIKER_LIBDIR\@|$(monikerdir)|" \
|
||||
$(srcdir)/Bonobo_Moniker_archiver.oaf.in > Bonobo_Moniker_archiver.oaf
|
||||
|
||||
clean-local:
|
||||
-rm -f $(OAF_FILES) $(CORBA_SOURCE)
|
||||
|
||||
bonobo_moniker_archiver_SOURCES = \
|
||||
bonobo-config-archiver.c bonobo-config-archiver.h \
|
||||
archive.c archive.h \
|
||||
location.c location.h \
|
||||
config-log.c config-log.h \
|
||||
backend-list.c backend-list.h \
|
||||
cluster.c cluster.h \
|
||||
cluster-location.c cluster-location.h \
|
||||
bonobo-moniker-archiver.c
|
||||
|
||||
bonobo_moniker_archiver_LDADD = @MONIKER_LIBS@ libconfig_archiver.la
|
||||
|
||||
EXTRA_DIST = \
|
||||
$(Locationmeta_DATA) \
|
||||
config_archiverConf.sh.in \
|
||||
Bonobo_Moniker_archiver.oaf.in
|
||||
@@ -1,2 +0,0 @@
|
||||
This module is no longer built as a part of control-center.
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
* Add per-user master list
|
||||
* Archiving changes in location metadata
|
||||
* Fix race in lock handling and add timeout support (look in gnome-mime)
|
||||
* Support multiple backends from CLI
|
||||
* Add translateable backend description support
|
||||
* Some way to store the rollback time for each backend, for GUI purposes
|
||||
* Have defaults stored somewhere, to be restored when the user goes
|
||||
back before the first configuration edit
|
||||
|
||||
Long-term
|
||||
* Add clustering support:
|
||||
- Add Cluster class inheriting Archive class and overriding path
|
||||
semantics
|
||||
- Change location rollback functionality to send data through to
|
||||
clients if the archive is a cluster
|
||||
* Allow backend specs to identify an order in which they should be applied
|
||||
- Specify this in the master list; have each location look up that
|
||||
information before invoking multiple backends
|
||||
|
||||
Questions
|
||||
|
||||
Done
|
||||
* Global list of configs for a given archive
|
||||
* Location should store backend data in the location where it is valid
|
||||
* Add support for dumping XML to stdout rather than running the backend
|
||||
* Fix bug where EOF not sent through pipe
|
||||
* Changing the name of a location
|
||||
* Adding per-user/global backends
|
||||
- Don't try to write out contains list on toplevel locations
|
||||
- Give error if the user tries to add a backend to a toplevel location
|
||||
* Consistency check on adding and removing backends
|
||||
- Make sure the backend is included in the global metadata list before
|
||||
adding
|
||||
- When removing global and per-user backends, mark the backend
|
||||
"invalid" and exclude from location_foreach_backend,
|
||||
location_rollback_all_to, and location_contains.
|
||||
* Refactor master list into an attribute of Archive
|
||||
* Roll back x number of steps rather than by date
|
||||
* Try to factor out populate_locations_list to be common between the
|
||||
different dialogs
|
||||
@@ -1,781 +0,0 @@
|
||||
/* -*- mode: c; style: linux -*- */
|
||||
|
||||
/* archive.c
|
||||
* Copyright (C) 2000-2001 Ximian, Inc.
|
||||
*
|
||||
* Written by Bradford Hovinen (hovinen@ximian.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "archive.h"
|
||||
#include "util.h"
|
||||
|
||||
static GtkObjectClass *parent_class;
|
||||
|
||||
enum {
|
||||
ARG_0,
|
||||
ARG_PREFIX,
|
||||
ARG_IS_GLOBAL
|
||||
};
|
||||
|
||||
#define ARCHIVE_FROM_SERVANT(servant) (ARCHIVE (bonobo_object_from_servant (servant)))
|
||||
|
||||
static void archive_init (Archive *archive);
|
||||
static void archive_class_init (ArchiveClass *klass);
|
||||
|
||||
static void archive_destroy (GtkObject *object);
|
||||
|
||||
static void archive_set_arg (GtkObject *object,
|
||||
GtkArg *arg,
|
||||
guint arg_id);
|
||||
|
||||
static void archive_get_arg (GtkObject *object,
|
||||
GtkArg *arg,
|
||||
guint arg_id);
|
||||
|
||||
static void load_all_locations (Archive *archive);
|
||||
|
||||
/* CORBA interface methods */
|
||||
|
||||
static ConfigArchiver_Location
|
||||
impl_ConfigArchiver_Archive_getLocation (PortableServer_Servant servant,
|
||||
const CORBA_char *locid,
|
||||
CORBA_Environment *ev)
|
||||
{
|
||||
Location *loc;
|
||||
|
||||
loc = archive_get_location (ARCHIVE_FROM_SERVANT (servant), locid);
|
||||
|
||||
if (loc == NULL) {
|
||||
bonobo_exception_set (ev, ex_ConfigArchiver_Archive_LocationNotFound);
|
||||
return CORBA_OBJECT_NIL;
|
||||
} else {
|
||||
return CORBA_Object_duplicate (BONOBO_OBJREF (loc), ev);
|
||||
}
|
||||
}
|
||||
|
||||
static ConfigArchiver_Location
|
||||
impl_ConfigArchiver_Archive_createLocation (PortableServer_Servant servant,
|
||||
const CORBA_char *locid,
|
||||
const CORBA_char *label,
|
||||
const ConfigArchiver_Location parent_ref,
|
||||
CORBA_Environment *ev)
|
||||
{
|
||||
Location *loc;
|
||||
|
||||
loc = archive_create_location (ARCHIVE_FROM_SERVANT (servant), locid, label,
|
||||
LOCATION (bonobo_object_from_servant (parent_ref->servant)));
|
||||
|
||||
return CORBA_Object_duplicate (BONOBO_OBJREF (loc), ev);
|
||||
}
|
||||
|
||||
static ConfigArchiver_LocationSeq *
|
||||
impl_ConfigArchiver_Archive_getChildLocations (PortableServer_Servant servant,
|
||||
ConfigArchiver_Location location_ref,
|
||||
CORBA_Environment *ev)
|
||||
{
|
||||
ConfigArchiver_LocationSeq *ret;
|
||||
Archive *archive;
|
||||
Location *location;
|
||||
GList *locs, *tmp;
|
||||
guint i = 0;
|
||||
|
||||
archive = ARCHIVE_FROM_SERVANT (servant);
|
||||
|
||||
if (location_ref == CORBA_OBJECT_NIL)
|
||||
location = NULL;
|
||||
else
|
||||
location = LOCATION (bonobo_object_from_servant (location_ref->servant));
|
||||
|
||||
locs = archive_get_child_locations (archive, location);
|
||||
|
||||
ret = ConfigArchiver_LocationSeq__alloc ();
|
||||
ret->_length = g_list_length (locs);
|
||||
ret->_buffer = CORBA_sequence_ConfigArchiver_Location_allocbuf (ret->_length);
|
||||
|
||||
for (tmp = locs; tmp != NULL; tmp = tmp->next)
|
||||
ret->_buffer[i++] = CORBA_Object_duplicate (BONOBO_OBJREF (tmp->data), ev);
|
||||
|
||||
g_list_free (locs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static CORBA_char *
|
||||
impl_ConfigArchiver_Archive__get_prefix (PortableServer_Servant servant,
|
||||
CORBA_Environment *ev)
|
||||
{
|
||||
return CORBA_string_dup (ARCHIVE_FROM_SERVANT (servant)->prefix);
|
||||
}
|
||||
|
||||
static CORBA_boolean
|
||||
impl_ConfigArchiver_Archive__get_isGlobal (PortableServer_Servant servant,
|
||||
CORBA_Environment *ev)
|
||||
{
|
||||
return ARCHIVE_FROM_SERVANT (servant)->is_global;
|
||||
}
|
||||
|
||||
static ConfigArchiver_BackendList
|
||||
impl_ConfigArchiver_Archive__get_backendList (PortableServer_Servant servant,
|
||||
CORBA_Environment *ev)
|
||||
{
|
||||
return bonobo_object_dup_ref (BONOBO_OBJREF (ARCHIVE_FROM_SERVANT (servant)->backend_list), ev);
|
||||
}
|
||||
|
||||
static ConfigArchiver_Location
|
||||
impl_ConfigArchiver_Archive__get_currentLocation (PortableServer_Servant servant,
|
||||
CORBA_Environment *ev)
|
||||
{
|
||||
return CORBA_Object_duplicate (BONOBO_OBJREF (archive_get_current_location (ARCHIVE_FROM_SERVANT (servant))), ev);
|
||||
}
|
||||
|
||||
static void
|
||||
impl_ConfigArchiver_Archive__set_currentLocation (PortableServer_Servant servant,
|
||||
ConfigArchiver_Location location_ref,
|
||||
CORBA_Environment *ev)
|
||||
{
|
||||
Archive *archive = ARCHIVE_FROM_SERVANT (servant);
|
||||
Location *location;
|
||||
|
||||
location = LOCATION (bonobo_object_from_servant (location_ref->servant));
|
||||
|
||||
if (location == NULL)
|
||||
bonobo_exception_set (ev, ex_ConfigArchiver_Archive_LocationNotFound);
|
||||
else
|
||||
archive_set_current_location (archive, location);
|
||||
}
|
||||
|
||||
static void
|
||||
impl_ConfigArchiver_Archive__set_currentLocationId (PortableServer_Servant servant,
|
||||
const CORBA_char *locid,
|
||||
CORBA_Environment *ev)
|
||||
{
|
||||
archive_set_current_location_id (ARCHIVE_FROM_SERVANT (servant), locid);
|
||||
}
|
||||
|
||||
CORBA_char *
|
||||
impl_ConfigArchiver_Archive__get_currentLocationId (PortableServer_Servant servant,
|
||||
CORBA_Environment *ev)
|
||||
{
|
||||
return CORBA_string_dup (archive_get_current_location_id (ARCHIVE_FROM_SERVANT (servant)));
|
||||
}
|
||||
|
||||
BONOBO_X_TYPE_FUNC_FULL (Archive, ConfigArchiver_Archive, BONOBO_X_OBJECT_TYPE, archive);
|
||||
|
||||
static void
|
||||
archive_init (Archive *archive)
|
||||
{
|
||||
archive->prefix = NULL;
|
||||
archive->locations = g_tree_new ((GCompareFunc) strcmp);
|
||||
archive->current_location_id = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
archive_class_init (ArchiveClass *klass)
|
||||
{
|
||||
GtkObjectClass *object_class;
|
||||
|
||||
object_class = GTK_OBJECT_CLASS (klass);
|
||||
|
||||
object_class->destroy = archive_destroy;
|
||||
object_class->set_arg = archive_set_arg;
|
||||
object_class->get_arg = archive_get_arg;
|
||||
|
||||
gtk_object_add_arg_type ("Archive::prefix",
|
||||
GTK_TYPE_POINTER,
|
||||
GTK_ARG_READWRITE | GTK_ARG_CONSTRUCT_ONLY,
|
||||
ARG_PREFIX);
|
||||
gtk_object_add_arg_type ("Archive::is-global",
|
||||
GTK_TYPE_INT,
|
||||
GTK_ARG_READWRITE | GTK_ARG_CONSTRUCT_ONLY,
|
||||
ARG_IS_GLOBAL);
|
||||
|
||||
klass->epv.getLocation = impl_ConfigArchiver_Archive_getLocation;
|
||||
klass->epv.createLocation = impl_ConfigArchiver_Archive_createLocation;
|
||||
klass->epv.getChildLocations = impl_ConfigArchiver_Archive_getChildLocations;
|
||||
|
||||
klass->epv._get_prefix = impl_ConfigArchiver_Archive__get_prefix;
|
||||
klass->epv._get_isGlobal = impl_ConfigArchiver_Archive__get_isGlobal;
|
||||
klass->epv._get_backendList = impl_ConfigArchiver_Archive__get_backendList;
|
||||
klass->epv._get_currentLocation = impl_ConfigArchiver_Archive__get_currentLocation;
|
||||
klass->epv._get_currentLocationId = impl_ConfigArchiver_Archive__get_currentLocationId;
|
||||
|
||||
klass->epv._set_currentLocation = impl_ConfigArchiver_Archive__set_currentLocation;
|
||||
klass->epv._set_currentLocationId = impl_ConfigArchiver_Archive__set_currentLocationId;
|
||||
|
||||
parent_class = gtk_type_class (BONOBO_X_OBJECT_TYPE);
|
||||
}
|
||||
|
||||
static void
|
||||
archive_set_arg (GtkObject *object, GtkArg *arg, guint arg_id)
|
||||
{
|
||||
Archive *archive;
|
||||
|
||||
g_return_if_fail (object != NULL);
|
||||
g_return_if_fail (IS_ARCHIVE (object));
|
||||
g_return_if_fail (arg != NULL);
|
||||
|
||||
archive = ARCHIVE (object);
|
||||
|
||||
switch (arg_id) {
|
||||
case ARG_PREFIX:
|
||||
if (GTK_VALUE_POINTER (*arg) != NULL)
|
||||
archive->prefix = g_strdup (GTK_VALUE_POINTER (*arg));
|
||||
break;
|
||||
|
||||
case ARG_IS_GLOBAL:
|
||||
archive->is_global = GTK_VALUE_INT (*arg);
|
||||
archive->backend_list =
|
||||
BACKEND_LIST (backend_list_new (archive->is_global));
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
archive_get_arg (GtkObject *object, GtkArg *arg, guint arg_id)
|
||||
{
|
||||
Archive *archive;
|
||||
|
||||
g_return_if_fail (object != NULL);
|
||||
g_return_if_fail (IS_ARCHIVE (object));
|
||||
g_return_if_fail (arg != NULL);
|
||||
|
||||
archive = ARCHIVE (object);
|
||||
|
||||
switch (arg_id) {
|
||||
case ARG_PREFIX:
|
||||
GTK_VALUE_POINTER (*arg) = archive->prefix;
|
||||
break;
|
||||
|
||||
case ARG_IS_GLOBAL:
|
||||
GTK_VALUE_INT (*arg) = archive->is_global;
|
||||
break;
|
||||
|
||||
default:
|
||||
arg->type = GTK_TYPE_INVALID;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* archive_construct:
|
||||
* @archive:
|
||||
* @is_new: TRUE iff this is a new archive
|
||||
*
|
||||
* Load the archive information from disk
|
||||
*
|
||||
* Returns: TRUE on success and FALSE on failure
|
||||
*/
|
||||
|
||||
gboolean
|
||||
archive_construct (Archive *archive, gboolean is_new)
|
||||
{
|
||||
gint ret = 0;
|
||||
|
||||
g_return_val_if_fail (archive != NULL, FALSE);
|
||||
g_return_val_if_fail (IS_ARCHIVE (archive), FALSE);
|
||||
g_return_val_if_fail (archive->prefix != NULL, FALSE);
|
||||
|
||||
if (is_new) {
|
||||
if (g_file_exists (archive->prefix))
|
||||
return FALSE;
|
||||
|
||||
ret = mkdir (archive->prefix, S_IREAD | S_IWRITE | S_IEXEC);
|
||||
if (ret == -1) return FALSE;
|
||||
} else {
|
||||
if (!g_file_test (archive->prefix, G_FILE_TEST_ISDIR))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* archive_load:
|
||||
* @is_global: TRUE iff we should load the global archive
|
||||
*
|
||||
* Load either the global or per-user configuration archive
|
||||
*
|
||||
* Return value: Reference to archive
|
||||
**/
|
||||
|
||||
BonoboObject *
|
||||
archive_load (gboolean is_global)
|
||||
{
|
||||
BonoboObject *object;
|
||||
gchar *prefix;
|
||||
|
||||
if (is_global)
|
||||
prefix = "/var/ximian-setup-tools";
|
||||
else
|
||||
prefix = g_concat_dir_and_file (g_get_home_dir (),
|
||||
".gnome/capplet-archive");
|
||||
|
||||
object = BONOBO_OBJECT (gtk_object_new (archive_get_type (),
|
||||
"prefix", prefix,
|
||||
"is-global", is_global,
|
||||
NULL));
|
||||
|
||||
if (!is_global)
|
||||
g_free (prefix);
|
||||
|
||||
if (archive_construct (ARCHIVE (object), FALSE) == FALSE &&
|
||||
archive_construct (ARCHIVE (object), TRUE) == FALSE)
|
||||
{
|
||||
bonobo_object_unref (object);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
static gint
|
||||
free_location_cb (gchar *locid, BonoboObject *location)
|
||||
{
|
||||
bonobo_object_unref (location);
|
||||
g_free (locid);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
archive_destroy (GtkObject *object)
|
||||
{
|
||||
Archive *archive;
|
||||
|
||||
g_return_if_fail (object != NULL);
|
||||
g_return_if_fail (IS_ARCHIVE (object));
|
||||
|
||||
DEBUG_MSG ("Enter");
|
||||
|
||||
archive = ARCHIVE (object);
|
||||
|
||||
g_tree_traverse (archive->locations,
|
||||
(GTraverseFunc) free_location_cb,
|
||||
G_IN_ORDER,
|
||||
NULL);
|
||||
|
||||
g_tree_destroy (archive->locations);
|
||||
|
||||
if (archive->current_location_id != NULL)
|
||||
g_free (archive->current_location_id);
|
||||
|
||||
if (archive->backend_list != NULL)
|
||||
bonobo_object_unref (BONOBO_OBJECT (archive->backend_list));
|
||||
|
||||
GTK_OBJECT_CLASS (parent_class)->destroy (GTK_OBJECT (archive));
|
||||
}
|
||||
|
||||
/**
|
||||
* archive_get_location:
|
||||
* @locid:
|
||||
*
|
||||
* Get a reference to the location with the given name.
|
||||
*
|
||||
* Return value: Reference to location, NULL if no such location exists
|
||||
**/
|
||||
|
||||
Location *
|
||||
archive_get_location (Archive *archive,
|
||||
const gchar *locid)
|
||||
{
|
||||
BonoboObject *loc_obj;
|
||||
gchar *tmp;
|
||||
|
||||
g_return_val_if_fail (archive != NULL, NULL);
|
||||
g_return_val_if_fail (IS_ARCHIVE (archive), NULL);
|
||||
g_return_val_if_fail (locid != NULL, NULL);
|
||||
|
||||
/* Stupid borken glib... */
|
||||
tmp = g_strdup (locid);
|
||||
loc_obj = g_tree_lookup (archive->locations, tmp);
|
||||
g_free (tmp);
|
||||
|
||||
if (loc_obj == NULL) {
|
||||
loc_obj = location_open (archive, locid);
|
||||
|
||||
if (loc_obj == NULL)
|
||||
return NULL;
|
||||
else
|
||||
g_tree_insert (archive->locations,
|
||||
g_strdup (locid), loc_obj);
|
||||
} else {
|
||||
bonobo_object_ref (loc_obj);
|
||||
}
|
||||
|
||||
return LOCATION (loc_obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* archive_create_location:
|
||||
* @archive:
|
||||
* @location:
|
||||
*
|
||||
* Creates a new location
|
||||
*/
|
||||
|
||||
Location *
|
||||
archive_create_location (Archive *archive,
|
||||
const gchar *locid,
|
||||
const gchar *label,
|
||||
Location *parent)
|
||||
{
|
||||
Location *location;
|
||||
|
||||
g_return_val_if_fail (archive != NULL, NULL);
|
||||
g_return_val_if_fail (IS_ARCHIVE (archive), NULL);
|
||||
g_return_val_if_fail (locid != NULL, NULL);
|
||||
g_return_val_if_fail (label != NULL, NULL);
|
||||
g_return_val_if_fail (parent == NULL || IS_LOCATION (parent), NULL);
|
||||
|
||||
location = LOCATION (location_new (archive, locid, label, parent));
|
||||
|
||||
if (location == NULL)
|
||||
return NULL;
|
||||
|
||||
g_tree_insert (archive->locations, g_strdup (locid), location);
|
||||
return location;
|
||||
}
|
||||
|
||||
/**
|
||||
* archive_unregister_location:
|
||||
* @archive:
|
||||
* @location:
|
||||
*
|
||||
* Unregisters a location from the archive
|
||||
**/
|
||||
|
||||
void
|
||||
archive_unregister_location (Archive *archive, Location *location)
|
||||
{
|
||||
gchar *tmp;
|
||||
|
||||
g_return_if_fail (archive != NULL);
|
||||
g_return_if_fail (IS_ARCHIVE (archive));
|
||||
g_return_if_fail (location != NULL);
|
||||
g_return_if_fail (IS_LOCATION (location));
|
||||
|
||||
if (GTK_OBJECT_DESTROYED (archive)) return;
|
||||
|
||||
tmp = g_strdup (location_get_id (location));
|
||||
g_tree_remove (archive->locations, tmp);
|
||||
g_free (tmp);
|
||||
}
|
||||
|
||||
/**
|
||||
* archive_get_current_location:
|
||||
*
|
||||
* Convenience function to get a pointer to the current location
|
||||
*
|
||||
* Return value: Pointer to current location, or NULL if the current location
|
||||
* does not exist and a default location could not be created
|
||||
**/
|
||||
|
||||
Location *
|
||||
archive_get_current_location (Archive *archive)
|
||||
{
|
||||
const gchar *locid;
|
||||
|
||||
g_return_val_if_fail (archive != NULL, NULL);
|
||||
g_return_val_if_fail (IS_ARCHIVE (archive), NULL);
|
||||
|
||||
locid = archive_get_current_location_id (archive);
|
||||
|
||||
if (locid == NULL)
|
||||
return NULL;
|
||||
else
|
||||
return archive_get_location (archive, locid);
|
||||
}
|
||||
|
||||
/**
|
||||
* archive_set_current_location:
|
||||
* @location: Location to which to set archive
|
||||
*
|
||||
* Set the current location in an archive to the location given; apply
|
||||
* configuration for the new location to all backends necessary
|
||||
**/
|
||||
|
||||
void
|
||||
archive_set_current_location (Archive *archive,
|
||||
Location *location)
|
||||
{
|
||||
Location *old_location;
|
||||
GList *backends;
|
||||
|
||||
g_return_if_fail (archive != NULL);
|
||||
g_return_if_fail (IS_ARCHIVE (archive));
|
||||
g_return_if_fail (location != NULL);
|
||||
g_return_if_fail (IS_LOCATION (location));
|
||||
|
||||
old_location = archive_get_current_location (archive);
|
||||
|
||||
archive_set_current_location_id (archive, location_get_id (location));
|
||||
|
||||
backends = location_get_changed_backends (location, old_location);
|
||||
location_rollback_backends_to (location, NULL, 0, backends, TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* archive_set_current_location_id:
|
||||
* @name:
|
||||
*
|
||||
* Sets the current location's name, but does not invoke any rollback
|
||||
**/
|
||||
|
||||
void
|
||||
archive_set_current_location_id (Archive *archive,
|
||||
const gchar *locid)
|
||||
{
|
||||
g_return_if_fail (archive != NULL);
|
||||
g_return_if_fail (IS_ARCHIVE (archive));
|
||||
g_return_if_fail (locid != NULL);
|
||||
|
||||
if (archive->current_location_id != NULL)
|
||||
g_free (archive->current_location_id);
|
||||
|
||||
archive->current_location_id = g_strdup (locid);
|
||||
|
||||
if (archive->is_global)
|
||||
gnome_config_set_string
|
||||
("/ximian-setup-tools/config/current/global-location",
|
||||
archive->current_location_id);
|
||||
else
|
||||
gnome_config_set_string
|
||||
("/capplet-archive/config/current/location",
|
||||
archive->current_location_id);
|
||||
|
||||
gnome_config_sync ();
|
||||
}
|
||||
|
||||
/**
|
||||
* archive_get_current_location_id:
|
||||
*
|
||||
* Get the name of the current location
|
||||
*
|
||||
* Return value: String containing current location, should not be freed, or
|
||||
* NULL if no current location exists and the default location could not be
|
||||
* created
|
||||
**/
|
||||
|
||||
const gchar *
|
||||
archive_get_current_location_id (Archive *archive)
|
||||
{
|
||||
gboolean def;
|
||||
Location *loc;
|
||||
Location *current_location;
|
||||
|
||||
g_return_val_if_fail (archive != NULL, NULL);
|
||||
g_return_val_if_fail (IS_ARCHIVE (archive), NULL);
|
||||
|
||||
if (archive->current_location_id == NULL) {
|
||||
if (archive->is_global)
|
||||
archive->current_location_id =
|
||||
gnome_config_get_string_with_default
|
||||
("/ximian-setup-tools/config/current/global-location=default", &def);
|
||||
else
|
||||
archive->current_location_id =
|
||||
gnome_config_get_string_with_default
|
||||
("/capplet-archive/config/current/location=default", &def);
|
||||
|
||||
/* Create default location if it does not exist */
|
||||
if (def) {
|
||||
current_location =
|
||||
archive_get_location (archive, archive->current_location_id);
|
||||
|
||||
if (current_location == NULL) {
|
||||
loc = archive_create_location (archive, archive->current_location_id,
|
||||
_("Default location"), NULL);
|
||||
if (archive->is_global &&
|
||||
location_store_full_snapshot (loc) < 0)
|
||||
{
|
||||
location_delete (loc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bonobo_object_unref (BONOBO_OBJECT (loc));
|
||||
} else {
|
||||
bonobo_object_unref (BONOBO_OBJECT (current_location));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return archive->current_location_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* archive_get_prefix:
|
||||
* @archive:
|
||||
*
|
||||
* Get the prefix for locations in this archive
|
||||
*
|
||||
* Return value: String containing prefix; should not be freed
|
||||
**/
|
||||
|
||||
const gchar *
|
||||
archive_get_prefix (Archive *archive)
|
||||
{
|
||||
g_return_val_if_fail (archive != NULL, FALSE);
|
||||
g_return_val_if_fail (IS_ARCHIVE (archive), FALSE);
|
||||
|
||||
return archive->prefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* archive_is_global:
|
||||
* @archive:
|
||||
*
|
||||
* Tell whether the archive is global or per-user
|
||||
*
|
||||
* Return value: TRUE if global, FALSE if per-user
|
||||
**/
|
||||
|
||||
gboolean
|
||||
archive_is_global (Archive *archive)
|
||||
{
|
||||
g_return_val_if_fail (archive != NULL, FALSE);
|
||||
g_return_val_if_fail (IS_ARCHIVE (archive), FALSE);
|
||||
|
||||
return archive->is_global;
|
||||
}
|
||||
|
||||
/**
|
||||
* archive_get_backend_list:
|
||||
* @archive:
|
||||
*
|
||||
* Get the master backend list for this archive
|
||||
*
|
||||
* Return value: Reference to the master backend list
|
||||
**/
|
||||
|
||||
BackendList *
|
||||
archive_get_backend_list (Archive *archive)
|
||||
{
|
||||
g_return_val_if_fail (archive != NULL, FALSE);
|
||||
g_return_val_if_fail (IS_ARCHIVE (archive), FALSE);
|
||||
|
||||
return archive->backend_list;
|
||||
}
|
||||
|
||||
/**
|
||||
* archive_foreach_child_location:
|
||||
* @archive:
|
||||
* @callback: Callback to invoke
|
||||
* @parent: Iterate through the children of this location; iterate through
|
||||
* toplevel locations if this is NULL
|
||||
* @data: Arbitrary data to pass to the callback
|
||||
*
|
||||
* Invoke the given callback for each location that inherits the given
|
||||
* location, or for each toplevel location if the parent given is
|
||||
* NULL. Terminate the iteration if any child returns a nonzero value
|
||||
**/
|
||||
|
||||
static gint
|
||||
foreach_build_list_cb (gchar *key, Location *value, GList **node)
|
||||
{
|
||||
if (!location_is_deleted (value))
|
||||
*node = g_list_prepend (*node, value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
GList *
|
||||
archive_get_child_locations (Archive *archive,
|
||||
Location *parent)
|
||||
{
|
||||
GList *list = NULL, *node, *tmp;
|
||||
Location *loc;
|
||||
|
||||
g_return_val_if_fail (archive != NULL, NULL);
|
||||
g_return_val_if_fail (IS_ARCHIVE (archive), NULL);
|
||||
|
||||
load_all_locations (archive);
|
||||
|
||||
g_tree_traverse (archive->locations,
|
||||
(GTraverseFunc) foreach_build_list_cb,
|
||||
G_IN_ORDER,
|
||||
&list);
|
||||
|
||||
node = list;
|
||||
|
||||
while (node != NULL) {
|
||||
loc = node->data;
|
||||
tmp = node->next;
|
||||
|
||||
if (location_get_parent (loc) != parent) {
|
||||
list = g_list_remove_link (list, node);
|
||||
g_list_free_1 (node);
|
||||
bonobo_object_unref (BONOBO_OBJECT (loc));
|
||||
}
|
||||
|
||||
node = tmp;
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
/* Load and register all the locations for this archive */
|
||||
|
||||
static void
|
||||
load_all_locations (Archive *archive)
|
||||
{
|
||||
DIR *archive_dir;
|
||||
struct dirent entry, *entryp;
|
||||
gchar *filename;
|
||||
Location *location;
|
||||
|
||||
archive_dir = opendir (archive->prefix);
|
||||
|
||||
if (archive_dir == NULL) {
|
||||
g_warning ("load_all_locations: %s", g_strerror (errno));
|
||||
return;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
if (readdir_r (archive_dir, &entry, &entryp)) {
|
||||
g_warning ("load_all_locations: %s",
|
||||
g_strerror (errno));
|
||||
break;
|
||||
}
|
||||
|
||||
if (entryp == NULL) break;
|
||||
|
||||
if (strcmp (entry.d_name, ".") &&
|
||||
strcmp (entry.d_name, ".."))
|
||||
{
|
||||
filename = g_concat_dir_and_file (archive->prefix,
|
||||
entry.d_name);
|
||||
if (g_file_test (filename, G_FILE_TEST_ISDIR)) {
|
||||
location = archive_get_location (archive, entry.d_name);
|
||||
if (location_is_deleted (location))
|
||||
bonobo_object_unref (BONOBO_OBJECT (location));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
/* -*- mode: c; style: linux -*- */
|
||||
|
||||
/* archive.h
|
||||
* Copyright (C) 2000-2001 Ximian, Inc.
|
||||
*
|
||||
* Written by Bradford Hovinen (hovinen@ximian.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __ARCHIVE_H
|
||||
#define __ARCHIVE_H
|
||||
|
||||
#include <gnome.h>
|
||||
|
||||
#include "ConfigArchiver.h"
|
||||
|
||||
#include "location.h"
|
||||
#include "backend-list.h"
|
||||
|
||||
#define ARCHIVE(obj) GTK_CHECK_CAST (obj, archive_get_type (), Archive)
|
||||
#define ARCHIVE_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, archive_get_type (), ArchiveClass)
|
||||
#define IS_ARCHIVE(obj) GTK_CHECK_TYPE (obj, archive_get_type ())
|
||||
|
||||
typedef struct _ArchiveClass ArchiveClass;
|
||||
|
||||
struct _Archive
|
||||
{
|
||||
BonoboXObject object;
|
||||
|
||||
gchar *prefix;
|
||||
GTree *locations;
|
||||
gboolean is_global;
|
||||
|
||||
gchar *current_location_id;
|
||||
|
||||
BackendList *backend_list;
|
||||
};
|
||||
|
||||
struct _ArchiveClass
|
||||
{
|
||||
BonoboXObjectClass parent;
|
||||
|
||||
POA_ConfigArchiver_Archive__epv epv;
|
||||
};
|
||||
|
||||
GType archive_get_type (void);
|
||||
|
||||
gboolean archive_construct (Archive *archive,
|
||||
gboolean is_new);
|
||||
|
||||
BonoboObject *archive_load (gboolean is_global);
|
||||
|
||||
void archive_close (Archive *archive);
|
||||
|
||||
Location *archive_get_location (Archive *archive,
|
||||
const gchar *locid);
|
||||
Location *archive_create_location (Archive *archive,
|
||||
const gchar *locid,
|
||||
const gchar *label,
|
||||
Location *parent);
|
||||
void archive_unregister_location (Archive *archive,
|
||||
Location *location);
|
||||
|
||||
Location *archive_get_current_location (Archive *archive);
|
||||
void archive_set_current_location (Archive *archive,
|
||||
Location *location);
|
||||
|
||||
const gchar *archive_get_current_location_id (Archive *archive);
|
||||
void archive_set_current_location_id (Archive *archive,
|
||||
const gchar *locid);
|
||||
|
||||
const gchar *archive_get_prefix (Archive *archive);
|
||||
gboolean archive_is_global (Archive *archive);
|
||||
|
||||
BackendList *archive_get_backend_list (Archive *archive);
|
||||
|
||||
GList *archive_get_child_locations (Archive *archive,
|
||||
Location *parent);
|
||||
|
||||
#endif /* __ARCHIVE */
|
||||
@@ -1,442 +0,0 @@
|
||||
/* -*- mode: c; style: linux -*- */
|
||||
|
||||
/* archiver-client.c
|
||||
* Copyright (C) 2000-2001 Ximian, Inc.
|
||||
*
|
||||
* Written by Bradford Hovinen (hovinen@ximian.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <libbonobo.h>
|
||||
#include <gnome-xml/parser.h>
|
||||
|
||||
#include "archiver-client.h"
|
||||
#include "util.h"
|
||||
|
||||
static void merge_xml_docs (xmlDocPtr child_doc,
|
||||
xmlDocPtr parent_doc);
|
||||
static void subtract_xml_doc (xmlDocPtr child_doc,
|
||||
xmlDocPtr parent_doc,
|
||||
gboolean strict);
|
||||
static void merge_xml_nodes (xmlNodePtr node1,
|
||||
xmlNodePtr node2);
|
||||
static xmlNodePtr subtract_xml_node (xmlNodePtr node1,
|
||||
xmlNodePtr node2,
|
||||
gboolean strict);
|
||||
static gboolean compare_xml_nodes (xmlNodePtr node1, xmlNodePtr node2);
|
||||
|
||||
/**
|
||||
* location_client_load_rollback_data
|
||||
* @location:
|
||||
* @date:
|
||||
* @steps:
|
||||
* @backend_id:
|
||||
* @parent_chain:
|
||||
*
|
||||
* Loads the XML data for rolling back as specified and returns the document
|
||||
* object
|
||||
**/
|
||||
|
||||
xmlDocPtr
|
||||
location_client_load_rollback_data (ConfigArchiver_Location location,
|
||||
const struct tm *date,
|
||||
guint steps,
|
||||
const gchar *backend_id,
|
||||
gboolean parent_chain,
|
||||
CORBA_Environment *opt_ev)
|
||||
{
|
||||
gchar *filename;
|
||||
struct tm *date_c;
|
||||
time_t time_g;
|
||||
|
||||
xmlDocPtr doc = NULL;
|
||||
xmlDocPtr parent_doc = NULL;
|
||||
ConfigArchiver_ContainmentType type = ConfigArchiver_CONTAIN_FULL;
|
||||
ConfigArchiver_Location parent = CORBA_OBJECT_NIL;
|
||||
|
||||
CORBA_Environment my_ev;
|
||||
|
||||
g_return_val_if_fail (location != CORBA_OBJECT_NIL, NULL);
|
||||
|
||||
if (opt_ev == NULL) {
|
||||
opt_ev = &my_ev;
|
||||
CORBA_exception_init (opt_ev);
|
||||
}
|
||||
|
||||
if (date != NULL) {
|
||||
date_c = dup_date (date);
|
||||
time_g = mktime (date_c);
|
||||
#ifdef __USE_BSD
|
||||
time_g += date_c->tm_gmtoff;
|
||||
#endif /* __USE_BSD */
|
||||
if (date_c->tm_isdst) time_g -= 3600;
|
||||
g_free (date_c);
|
||||
} else {
|
||||
time_g = 0;
|
||||
}
|
||||
|
||||
filename = ConfigArchiver_Location_getRollbackFilename
|
||||
(location, time_g, steps, backend_id, parent_chain, opt_ev);
|
||||
|
||||
if (!BONOBO_EX (opt_ev) && filename != NULL)
|
||||
DEBUG_MSG ("Loading rollback data: %s", filename);
|
||||
|
||||
if (!BONOBO_EX (opt_ev) && filename != NULL)
|
||||
doc = xmlParseFile (filename);
|
||||
else if (parent_chain)
|
||||
type = ConfigArchiver_Location_contains (location, backend_id, opt_ev);
|
||||
|
||||
if (type == ConfigArchiver_CONTAIN_PARTIAL)
|
||||
parent = ConfigArchiver_Location__get_parent (location, opt_ev);
|
||||
|
||||
if (parent != CORBA_OBJECT_NIL) {
|
||||
parent_doc = location_client_load_rollback_data
|
||||
(parent, date, steps, backend_id, TRUE, opt_ev);
|
||||
bonobo_object_release_unref (parent, NULL);
|
||||
}
|
||||
|
||||
if (doc != NULL && parent_doc != NULL)
|
||||
merge_xml_docs (doc, parent_doc);
|
||||
else if (parent_doc != NULL)
|
||||
doc = parent_doc;
|
||||
|
||||
if (opt_ev == &my_ev)
|
||||
CORBA_exception_free (opt_ev);
|
||||
|
||||
return doc;
|
||||
}
|
||||
|
||||
/**
|
||||
* location_client_store_xml:
|
||||
* @location:
|
||||
* @backend_id:
|
||||
* @input:
|
||||
* @store_type: STORE_FULL means blindly store the data, without
|
||||
* modification. STORE_COMPARE_PARENT means subtract the settings the parent
|
||||
* has that are different and store the result. STORE_MASK_PREVIOUS means
|
||||
* store only those settings that are reflected in the previous logged data;
|
||||
* if there do not exist such data, act as in STORE_COMPARE_PARENT
|
||||
* @opt_ev:
|
||||
*
|
||||
* Store configuration data from the given XML document object in the location
|
||||
* under the given backend id
|
||||
**/
|
||||
|
||||
void
|
||||
location_client_store_xml (ConfigArchiver_Location location,
|
||||
const gchar *backend_id,
|
||||
xmlDocPtr xml_doc,
|
||||
ConfigArchiver_StoreType store_type,
|
||||
CORBA_Environment *opt_ev)
|
||||
{
|
||||
xmlDocPtr parent_doc;
|
||||
xmlDocPtr prev_doc = NULL;
|
||||
char *filename;
|
||||
ConfigArchiver_ContainmentType contain_type;
|
||||
ConfigArchiver_Location parent;
|
||||
CORBA_Environment my_ev;
|
||||
|
||||
g_return_if_fail (location != CORBA_OBJECT_NIL);
|
||||
g_return_if_fail (xml_doc != NULL);
|
||||
|
||||
if (opt_ev == NULL) {
|
||||
opt_ev = &my_ev;
|
||||
CORBA_exception_init (opt_ev);
|
||||
}
|
||||
|
||||
contain_type = ConfigArchiver_Location_contains (location, backend_id, opt_ev);
|
||||
parent = ConfigArchiver_Location__get_parent (location, opt_ev);
|
||||
|
||||
if (contain_type == ConfigArchiver_CONTAIN_NONE) {
|
||||
if (parent == CORBA_OBJECT_NIL) {
|
||||
fprintf (stderr, "Could not find a location in the " \
|
||||
"tree ancestry that stores this " \
|
||||
"backend: %s.\n", backend_id);
|
||||
} else {
|
||||
location_client_store_xml (parent, backend_id, xml_doc, store_type, opt_ev);
|
||||
bonobo_object_release_unref (parent, NULL);
|
||||
}
|
||||
|
||||
if (opt_ev == &my_ev)
|
||||
CORBA_exception_free (opt_ev);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (contain_type == ConfigArchiver_CONTAIN_PARTIAL && store_type != ConfigArchiver_STORE_FULL && parent != CORBA_OBJECT_NIL) {
|
||||
g_assert (store_type == ConfigArchiver_STORE_MASK_PREVIOUS ||
|
||||
store_type == ConfigArchiver_STORE_COMPARE_PARENT);
|
||||
|
||||
parent_doc = location_client_load_rollback_data
|
||||
(parent, NULL, 0, backend_id, TRUE, opt_ev);
|
||||
|
||||
if (store_type == ConfigArchiver_STORE_MASK_PREVIOUS)
|
||||
prev_doc = location_client_load_rollback_data (location, NULL, 0, backend_id, FALSE, opt_ev);
|
||||
|
||||
if (store_type == ConfigArchiver_STORE_COMPARE_PARENT) {
|
||||
subtract_xml_doc (xml_doc, parent_doc, FALSE);
|
||||
} else {
|
||||
subtract_xml_doc (parent_doc, prev_doc, FALSE);
|
||||
subtract_xml_doc (xml_doc, parent_doc, TRUE);
|
||||
}
|
||||
|
||||
xmlFreeDoc (parent_doc);
|
||||
|
||||
if (prev_doc != NULL)
|
||||
xmlFreeDoc (prev_doc);
|
||||
}
|
||||
|
||||
if (parent != CORBA_OBJECT_NIL)
|
||||
bonobo_object_release_unref (parent, NULL);
|
||||
|
||||
filename = ConfigArchiver_Location_getStorageFilename
|
||||
(location, backend_id, store_type == ConfigArchiver_STORE_DEFAULT, opt_ev);
|
||||
|
||||
if (!BONOBO_EX (opt_ev) && filename != NULL) {
|
||||
xmlSaveFile (filename, xml_doc);
|
||||
ConfigArchiver_Location_storageComplete (location, filename, opt_ev);
|
||||
CORBA_free (filename);
|
||||
}
|
||||
|
||||
if (opt_ev == &my_ev)
|
||||
CORBA_exception_free (opt_ev);
|
||||
}
|
||||
|
||||
static void
|
||||
merge_xml_docs (xmlDocPtr child_doc, xmlDocPtr parent_doc)
|
||||
{
|
||||
merge_xml_nodes (xmlDocGetRootElement (child_doc),
|
||||
xmlDocGetRootElement (parent_doc));
|
||||
}
|
||||
|
||||
static void
|
||||
subtract_xml_doc (xmlDocPtr child_doc, xmlDocPtr parent_doc, gboolean strict)
|
||||
{
|
||||
subtract_xml_node (xmlDocGetRootElement (child_doc),
|
||||
xmlDocGetRootElement (parent_doc), strict);
|
||||
}
|
||||
|
||||
/* Merge contents of node1 and node2, where node1 overrides node2 as
|
||||
* appropriate
|
||||
*
|
||||
* Notes: Two XML nodes are considered to be "the same" iff their names and
|
||||
* all names and values of their attributes are the same. If that is not the
|
||||
* case, they are considered "different" and will both be present in the
|
||||
* merged node. If nodes are "the same", then this algorithm is called
|
||||
* recursively. If nodes are CDATA, then node1 overrides node2 and the
|
||||
* resulting node is just node1. The node merging is order-independent; child
|
||||
* node from one tree are compared with all child nodes of the other tree
|
||||
* regardless of the order they appear in. Hence one may have documents with
|
||||
* different node orderings and the algorithm should still run correctly. It
|
||||
* will not, however, run correctly in cases when the agent using this
|
||||
* facility depends on the nodes being in a particular order.
|
||||
*
|
||||
* This XML node merging/comparison facility requires that the following
|
||||
* standard be set for DTDs:
|
||||
*
|
||||
* Attributes' sole purpose is to identify a node. For example, a network
|
||||
* configuration DTD might have an element like <interface name="eth0"> with a
|
||||
* bunch of child nodes to configure that interface. The attribute "name" does
|
||||
* not specify the configuration for the interface. It differentiates the node
|
||||
* from the configuration for, say, interface eth1. Conversely, a node must be
|
||||
* completely identified by its attributes. One cannot include identification
|
||||
* information in the node's children, since otherwise the merging and
|
||||
* subtraction algorithms will not know what to look for.
|
||||
*
|
||||
* As a corollary to the above, all configuration information must ultimately
|
||||
* be in text nodes. For example, a text string might be stored as
|
||||
* <configuration-item>my-value</configuration-item> but never as
|
||||
* <configuration-item value="my-value"/>. As an example, if the latter is
|
||||
* used, a child location might override a parent's setting for
|
||||
* configuration-item. This algorithm will interpret those as different nodes
|
||||
* and include them both in the merged result, since it will not have any way
|
||||
* of knowing that they are really the same node with different
|
||||
* configuration.
|
||||
*/
|
||||
|
||||
static void
|
||||
merge_xml_nodes (xmlNodePtr node1, xmlNodePtr node2)
|
||||
{
|
||||
xmlNodePtr child, tmp, iref;
|
||||
GList *node1_children = NULL, *i;
|
||||
gboolean found;
|
||||
|
||||
if (node1->type == XML_TEXT_NODE)
|
||||
return;
|
||||
|
||||
for (child = node1->childs; child != NULL; child = child->next)
|
||||
node1_children = g_list_prepend (node1_children, child);
|
||||
|
||||
node1_children = g_list_reverse (node1_children);
|
||||
|
||||
child = node2->childs;
|
||||
|
||||
while (child != NULL) {
|
||||
tmp = child->next;
|
||||
|
||||
i = node1_children; found = FALSE;
|
||||
|
||||
while (i != NULL) {
|
||||
iref = (xmlNodePtr) i->data;
|
||||
|
||||
if (compare_xml_nodes (iref, child)) {
|
||||
merge_xml_nodes (iref, child);
|
||||
if (i == node1_children)
|
||||
node1_children = node1_children->next;
|
||||
g_list_remove_link (node1_children, i);
|
||||
g_list_free_1 (i);
|
||||
found = TRUE;
|
||||
break;
|
||||
} else {
|
||||
i = i->next;
|
||||
}
|
||||
}
|
||||
|
||||
if (found == FALSE) {
|
||||
xmlUnlinkNode (child);
|
||||
xmlAddChild (node1, child);
|
||||
}
|
||||
|
||||
child = tmp;
|
||||
}
|
||||
|
||||
g_list_free (node1_children);
|
||||
}
|
||||
|
||||
/* Modifies node1 so that it only contains the parts different from node2;
|
||||
* returns the modified node or NULL if the node should be destroyed
|
||||
*
|
||||
* strict determines whether the settings themselves are compared; it should
|
||||
* be set to FALSE when the trees are being compared for the purpose of
|
||||
* seeing what settings should be included in a tree and TRUE when one wants
|
||||
* to restrict the settings included in a tree to those that have already been
|
||||
* specified
|
||||
*/
|
||||
|
||||
static xmlNodePtr
|
||||
subtract_xml_node (xmlNodePtr node1, xmlNodePtr node2, gboolean strict)
|
||||
{
|
||||
xmlNodePtr child, tmp, iref;
|
||||
GList *node2_children = NULL, *i;
|
||||
gboolean found, same, all_same = TRUE;
|
||||
|
||||
if (node1->type == XML_TEXT_NODE) {
|
||||
if (node2->type == XML_TEXT_NODE &&
|
||||
(strict || !strcmp (xmlNodeGetContent (node1),
|
||||
xmlNodeGetContent (node2))))
|
||||
return NULL;
|
||||
else
|
||||
return node1;
|
||||
}
|
||||
|
||||
if (node1->childs == NULL && node2->childs == NULL)
|
||||
return NULL;
|
||||
|
||||
for (child = node2->childs; child != NULL; child = child->next)
|
||||
node2_children = g_list_prepend (node2_children, child);
|
||||
|
||||
node2_children = g_list_reverse (node2_children);
|
||||
|
||||
child = node1->childs;
|
||||
|
||||
while (child != NULL) {
|
||||
tmp = child->next;
|
||||
i = node2_children; found = FALSE; all_same = TRUE;
|
||||
|
||||
while (i != NULL) {
|
||||
iref = (xmlNodePtr) i->data;
|
||||
|
||||
if (compare_xml_nodes (child, iref)) {
|
||||
same = (subtract_xml_node
|
||||
(child, iref, strict) == NULL);
|
||||
all_same = all_same && same;
|
||||
|
||||
if (same) {
|
||||
xmlUnlinkNode (child);
|
||||
xmlFreeNode (child);
|
||||
}
|
||||
|
||||
if (i == node2_children)
|
||||
node2_children = node2_children->next;
|
||||
g_list_remove_link (node2_children, i);
|
||||
g_list_free_1 (i);
|
||||
found = TRUE;
|
||||
break;
|
||||
} else {
|
||||
i = i->next;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
all_same = FALSE;
|
||||
|
||||
child = tmp;
|
||||
}
|
||||
|
||||
g_list_free (node2_children);
|
||||
|
||||
if (all_same)
|
||||
return NULL;
|
||||
else
|
||||
return node1;
|
||||
}
|
||||
|
||||
/* Return TRUE iff node1 and node2 are "the same" in the sense defined above */
|
||||
|
||||
static gboolean
|
||||
compare_xml_nodes (xmlNodePtr node1, xmlNodePtr node2)
|
||||
{
|
||||
xmlAttrPtr attr;
|
||||
gint count = 0;
|
||||
|
||||
if (strcmp (node1->name, node2->name))
|
||||
return FALSE;
|
||||
|
||||
/* FIXME: This is worst case O(n^2), which can add up. Could we
|
||||
* optimize for the case where people have attributes in the same
|
||||
* order, or does not not matter? It probably does not matter, though,
|
||||
* since people don't generally have more than one or two attributes
|
||||
* in a tag anyway.
|
||||
*/
|
||||
|
||||
for (attr = node1->properties; attr != NULL; attr = attr->next) {
|
||||
g_assert (xmlNodeIsText (attr->val));
|
||||
|
||||
if (strcmp (xmlNodeGetContent (attr->val),
|
||||
xmlGetProp (node2, attr->name)))
|
||||
return FALSE;
|
||||
|
||||
count++;
|
||||
}
|
||||
|
||||
/* FIXME: Is checking if the two nodes have the same number of
|
||||
* attributes the correct policy here? Should we instead merge the
|
||||
* attribute(s) that node1 is missing?
|
||||
*/
|
||||
|
||||
for (attr = node2->properties; attr != NULL; attr = attr->next)
|
||||
count--;
|
||||
|
||||
if (count == 0)
|
||||
return TRUE;
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
/* -*- mode: c; style: linux -*- */
|
||||
|
||||
/* archiver-client.h
|
||||
* Copyright (C) 2001 Ximian, Inc.
|
||||
*
|
||||
* Written by Bradford Hovinen (hovinen@ximian.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __ARCHIVER_CLIENT_H
|
||||
#define __ARCHIVER_CLIENT_H
|
||||
|
||||
#include <gnome.h>
|
||||
#include <gnome-xml/tree.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "ConfigArchiver.h"
|
||||
|
||||
xmlDocPtr location_client_load_rollback_data (ConfigArchiver_Location location,
|
||||
const struct tm *date,
|
||||
guint steps,
|
||||
const gchar *backend_id,
|
||||
gboolean parent_chain,
|
||||
CORBA_Environment *opt_ev);
|
||||
|
||||
void location_client_store_xml (ConfigArchiver_Location location,
|
||||
const gchar *backend_id,
|
||||
xmlDocPtr xml_doc,
|
||||
ConfigArchiver_StoreType store_type,
|
||||
CORBA_Environment *opt_ev);
|
||||
|
||||
#endif /* __ARCHIVER_CLIENT_H */
|
||||
@@ -1,122 +0,0 @@
|
||||
Rollback archiving internals
|
||||
Copyright (C) 2001 Ximian Code, Inc.
|
||||
Written by Bradford Hovinen <hovinen@ximian.com>
|
||||
|
||||
1. Directory format
|
||||
|
||||
Diagram:
|
||||
|
||||
+ toplevel
|
||||
|-+ Location 1
|
||||
| |- <id>.xml
|
||||
| | .
|
||||
| | .
|
||||
| | .
|
||||
| |- metadata.log:
|
||||
| | [<id> <date> <time> <backend> ] ^
|
||||
| | [ . ] | Time
|
||||
| | [ . ] |
|
||||
| | [ . ] |
|
||||
| \- metadata.xml:
|
||||
| [... ]
|
||||
| [<inherits>location</inherits> ]
|
||||
| [<contains backend-id="backend" type="full|partial"/> ]
|
||||
| [... ]
|
||||
|-+ Location 2
|
||||
| ...
|
||||
|
||||
There is one toplevel directory for each archive. This directory
|
||||
contains one or more location directories. Each location directory
|
||||
must contain two files: an XML file describing the location and a log
|
||||
of changes made in that location. Each change corresponds to an XML
|
||||
file containing a snapshot of the configuration as modified. There is
|
||||
one XML file per backend. Each change has an id number that is
|
||||
incremented atomicall by the archiving script when it stores
|
||||
configuration changes. The id number, as well as the date and time of
|
||||
storage, form a filename that uniquely identifies each configuration
|
||||
change. The archiving script must also store in the log file a line
|
||||
with the id number, date and time of storage, and backend used
|
||||
whenever it stores XML data. New entries are stored at the head of the
|
||||
file, so that during rollback, the file may be foreward scanned to
|
||||
find the appropriate identifier for the configuration file. The
|
||||
per-location XML configuration file contains information on what the
|
||||
location's parent is and what configurations that location defines.
|
||||
|
||||
For now, the backend shall be referred to by its executable name. When
|
||||
the backends gain CORBA interfaces, I suggest that the OAF id be used
|
||||
instead. This reduces the problem of setting a backend's configuration
|
||||
to a simple object activation and method invocation. The OAF id may
|
||||
also be used to resolve the backend's human-readable name.
|
||||
|
||||
2. Meta-configuration details
|
||||
|
||||
In order that this system be complete, there must be a way to
|
||||
ascertain the current location and to roll back changes in location. I
|
||||
propose that there be a special archive in the configuration hierarchy
|
||||
that contains location history in the same format as other
|
||||
locations. The archiver can then be a single script that accepts
|
||||
command-line arguments describing the request action: `archive this
|
||||
data', `roll back this backend's configuration', and `switch to this
|
||||
location'. It then handles all the details of interfacing with the
|
||||
archive and applying the changes in the correct order. Conceptually,
|
||||
the archiver becomes a backend in and of itself, where the frontend is
|
||||
located in the GUI of HCM. It would therefore be adviseable to use the
|
||||
same standards for the archiver as for other backends and hence make
|
||||
it a CORBA service, where the tool-specific interface is as described
|
||||
above.
|
||||
|
||||
3. Fine-grained location management
|
||||
|
||||
A slight modification of the basic location management system allows
|
||||
individual settings to be covered by a location as well as entire
|
||||
backends. The contains tag in a location's metadata file contains the
|
||||
attribute type, which may either by "full" or "partial". In the former
|
||||
case, rollback proceeds as described above. If it is the latter, the
|
||||
archiver, upon rolling back or setting configuration for the relevant
|
||||
backend in that location, first retrieves the required configuration
|
||||
from both the location and its parent using the same algorithm. It
|
||||
then uses an XML merging algorithm to combine the two XML files into
|
||||
one, allowing the child location's data to override its parent's
|
||||
data. This can be accomplished using the same technique as Bonobo uses
|
||||
to allow components to override toolbars and menus in the container.
|
||||
|
||||
When a child location partially defines the data for a particular
|
||||
backend, it must store only those configuration settings that the user
|
||||
explicitly changed when updating that backend's configuration under
|
||||
that location. If the frontend simply dumped its entire XML snapshot
|
||||
to the log, all of the configuration settings would be reflected in
|
||||
that snapshot, and under the method indicated above, partial
|
||||
containment would be equivalent to full containment. Therefore, when a
|
||||
frontend stores its configuration under partial containment, the
|
||||
archiver must run a node-for-node comparison between the XML data of
|
||||
the parent location (retrieved using the method indicated above) and
|
||||
that of the child location. Only those nodes that are different are
|
||||
actually stored in the configuration log.
|
||||
|
||||
When comparing XML nodes, there must be a way to identify distinct
|
||||
nodes for comparison. For example, in a network configuration backend,
|
||||
there might be one node for each interface. If, under the parent
|
||||
location, the nodes are ordered with interface "eth0" before interface
|
||||
"eth1", while under the child location, they are in reverse order, but
|
||||
the configuration is otherwise identical, it is not the intention of
|
||||
the user that child location should override any configuration data of
|
||||
the parent location. Therefore, the best method for comparing XML data
|
||||
is to compare each child of a given node in one source to all the
|
||||
children of the relevant node in the other source. If any child in the
|
||||
other source matches, then the XML node is a duplicate and may be
|
||||
thrown out. If there is another node such that the name and attributes
|
||||
are the same, but the children are different, then the algorithm
|
||||
should be invoked recursively to determine the differences among the
|
||||
children. If there is no such node, then the node should be included.
|
||||
|
||||
4. Future directions
|
||||
|
||||
The metafile log structure may run into scalability problems for
|
||||
installations have have been in place for a long time. An alternative
|
||||
structure that uses binary indexing might be in order. A command line
|
||||
utility (with GUI interface) could be written to recover the file in
|
||||
the case of corruption; such a utility could simply introspect each of
|
||||
the XML files in a directory. Provided that each XML file contains
|
||||
enough information to create a file entry, which is trivial, recovery
|
||||
is assured.
|
||||
|
||||
@@ -1,363 +0,0 @@
|
||||
/* -*- mode: c; style: linux -*- */
|
||||
|
||||
/* backend-list.c
|
||||
* Copyright (C) 2000-2001 Ximian, Inc.
|
||||
*
|
||||
* Written by Bradford Hovinen <hovinen@ximian.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <parser.h>
|
||||
#include <tree.h>
|
||||
|
||||
#include "backend-list.h"
|
||||
|
||||
enum {
|
||||
ARG_0,
|
||||
ARG_IS_GLOBAL
|
||||
};
|
||||
|
||||
struct _BackendListPrivate
|
||||
{
|
||||
gboolean is_global;
|
||||
gchar *filename;
|
||||
GList *backend_ids;
|
||||
};
|
||||
|
||||
#define BACKEND_LIST_FROM_SERVANT(servant) (BACKEND_LIST (bonobo_object_from_servant (servant)))
|
||||
|
||||
static BonoboXObjectClass *parent_class;
|
||||
|
||||
static void backend_list_init (BackendList *backend_list);
|
||||
static void backend_list_class_init (BackendListClass *class);
|
||||
|
||||
static void backend_list_set_arg (GtkObject *object,
|
||||
GtkArg *arg,
|
||||
guint arg_id);
|
||||
static void backend_list_get_arg (GtkObject *object,
|
||||
GtkArg *arg,
|
||||
guint arg_id);
|
||||
|
||||
static void backend_list_finalize (GtkObject *object);
|
||||
|
||||
static void do_load (BackendList *backend_list);
|
||||
static void do_save (BackendList *backend_list);
|
||||
|
||||
/* CORBA interface methods */
|
||||
|
||||
static CORBA_boolean
|
||||
impl_ConfigArchiver_BackendList_contains (PortableServer_Servant servant,
|
||||
const CORBA_char *backend_id,
|
||||
CORBA_Environment *ev)
|
||||
{
|
||||
return backend_list_contains (BACKEND_LIST_FROM_SERVANT (servant), backend_id);
|
||||
}
|
||||
|
||||
static void
|
||||
impl_ConfigArchiver_BackendList_add (PortableServer_Servant servant,
|
||||
const CORBA_char *backend_id,
|
||||
CORBA_Environment *ev)
|
||||
{
|
||||
backend_list_add (BACKEND_LIST_FROM_SERVANT (servant), backend_id);
|
||||
}
|
||||
|
||||
static void
|
||||
impl_ConfigArchiver_BackendList_remove (PortableServer_Servant servant,
|
||||
const CORBA_char *backend_id,
|
||||
CORBA_Environment *ev)
|
||||
{
|
||||
backend_list_remove (BACKEND_LIST_FROM_SERVANT (servant), backend_id);
|
||||
}
|
||||
|
||||
static void
|
||||
impl_ConfigArchiver_BackendList_save (PortableServer_Servant servant,
|
||||
CORBA_Environment *ev)
|
||||
{
|
||||
backend_list_save (BACKEND_LIST_FROM_SERVANT (servant));
|
||||
}
|
||||
|
||||
static ConfigArchiver_StringSeq *
|
||||
impl_ConfigArchiver_BackendList__get_backends (PortableServer_Servant servant,
|
||||
CORBA_Environment *ev)
|
||||
{
|
||||
ConfigArchiver_StringSeq *seq;
|
||||
BackendList *backend_list = BACKEND_LIST_FROM_SERVANT (servant);
|
||||
guint i = 0;
|
||||
GList *node;
|
||||
|
||||
g_return_val_if_fail (backend_list != NULL, NULL);
|
||||
g_return_val_if_fail (IS_BACKEND_LIST (backend_list), NULL);
|
||||
|
||||
seq = ConfigArchiver_StringSeq__alloc ();
|
||||
seq->_length = g_list_length (backend_list->p->backend_ids);
|
||||
seq->_buffer = CORBA_sequence_CORBA_string_allocbuf (seq->_length);
|
||||
CORBA_sequence_set_release (seq, TRUE);
|
||||
|
||||
for (node = backend_list->p->backend_ids; node != NULL; node = node->next)
|
||||
seq->_buffer[i++] = CORBA_string_dup (node->data);
|
||||
|
||||
return seq;
|
||||
}
|
||||
|
||||
BONOBO_X_TYPE_FUNC_FULL (BackendList, ConfigArchiver_BackendList, BONOBO_X_OBJECT_TYPE, backend_list);
|
||||
|
||||
static void
|
||||
backend_list_init (BackendList *backend_list)
|
||||
{
|
||||
backend_list->p = g_new0 (BackendListPrivate, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
backend_list_class_init (BackendListClass *class)
|
||||
{
|
||||
GtkObjectClass *object_class;
|
||||
|
||||
gtk_object_add_arg_type ("BackendList::is-global",
|
||||
GTK_TYPE_INT,
|
||||
GTK_ARG_CONSTRUCT_ONLY | GTK_ARG_READWRITE,
|
||||
ARG_IS_GLOBAL);
|
||||
|
||||
object_class = GTK_OBJECT_CLASS (class);
|
||||
object_class->finalize = backend_list_finalize;
|
||||
object_class->set_arg = backend_list_set_arg;
|
||||
object_class->get_arg = backend_list_get_arg;
|
||||
|
||||
class->epv.contains = impl_ConfigArchiver_BackendList_contains;
|
||||
class->epv.add = impl_ConfigArchiver_BackendList_add;
|
||||
class->epv.remove = impl_ConfigArchiver_BackendList_remove;
|
||||
class->epv.save = impl_ConfigArchiver_BackendList_save;
|
||||
|
||||
class->epv._get_backends = impl_ConfigArchiver_BackendList__get_backends;
|
||||
|
||||
parent_class = BONOBO_X_OBJECT_CLASS
|
||||
(gtk_type_class (BONOBO_X_OBJECT_TYPE));
|
||||
}
|
||||
|
||||
static void
|
||||
backend_list_set_arg (GtkObject *object, GtkArg *arg, guint arg_id)
|
||||
{
|
||||
BackendList *backend_list;
|
||||
|
||||
g_return_if_fail (object != NULL);
|
||||
g_return_if_fail (IS_BACKEND_LIST (object));
|
||||
|
||||
backend_list = BACKEND_LIST (object);
|
||||
|
||||
switch (arg_id) {
|
||||
case ARG_IS_GLOBAL:
|
||||
backend_list->p->is_global = GTK_VALUE_INT (*arg);
|
||||
|
||||
backend_list->p->filename = backend_list->p->is_global ?
|
||||
LOCATION_DIR "/default-global.xml" :
|
||||
LOCATION_DIR "/default-user.xml";
|
||||
do_load (backend_list);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
g_warning ("Bad argument set");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
backend_list_get_arg (GtkObject *object, GtkArg *arg, guint arg_id)
|
||||
{
|
||||
BackendList *backend_list;
|
||||
|
||||
g_return_if_fail (object != NULL);
|
||||
g_return_if_fail (IS_BACKEND_LIST (object));
|
||||
|
||||
backend_list = BACKEND_LIST (object);
|
||||
|
||||
switch (arg_id) {
|
||||
case ARG_IS_GLOBAL:
|
||||
GTK_VALUE_INT (*arg) = backend_list->p->is_global;
|
||||
break;
|
||||
|
||||
default:
|
||||
g_warning ("Bad argument get");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
backend_list_finalize (GtkObject *object)
|
||||
{
|
||||
BackendList *backend_list;
|
||||
|
||||
g_return_if_fail (object != NULL);
|
||||
g_return_if_fail (IS_BACKEND_LIST (object));
|
||||
|
||||
backend_list = BACKEND_LIST (object);
|
||||
|
||||
g_list_foreach (backend_list->p->backend_ids, (GFunc) g_free, NULL);
|
||||
g_list_free (backend_list->p->backend_ids);
|
||||
g_free (backend_list->p);
|
||||
|
||||
GTK_OBJECT_CLASS (parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
BonoboObject *
|
||||
backend_list_new (gboolean is_global)
|
||||
{
|
||||
return BONOBO_OBJECT
|
||||
(gtk_object_new (backend_list_get_type (),
|
||||
"is-global", is_global,
|
||||
NULL));
|
||||
}
|
||||
|
||||
gboolean
|
||||
backend_list_contains (BackendList *backend_list, const gchar *backend_id)
|
||||
{
|
||||
GList *node;
|
||||
|
||||
g_return_val_if_fail (backend_list != NULL, FALSE);
|
||||
g_return_val_if_fail (IS_BACKEND_LIST (backend_list), FALSE);
|
||||
|
||||
for (node = backend_list->p->backend_ids; node != NULL;
|
||||
node = node->next)
|
||||
if (!strcmp (node->data, backend_id))
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* backend_list_foreach:
|
||||
* @backend_list:
|
||||
* @callback:
|
||||
* @data:
|
||||
*
|
||||
* Iterates through all the backends, invoking the callback given and aborting
|
||||
* if any callback returns a nonzero value
|
||||
*
|
||||
* Return value: TRUE iff no callback issued a nonzero value, FALSE otherwise
|
||||
**/
|
||||
|
||||
gboolean
|
||||
backend_list_foreach (BackendList *backend_list, BackendCB callback,
|
||||
gpointer data)
|
||||
{
|
||||
GList *node;
|
||||
|
||||
g_return_val_if_fail (backend_list != NULL, FALSE);
|
||||
g_return_val_if_fail (IS_BACKEND_LIST (backend_list), FALSE);
|
||||
g_return_val_if_fail (callback != NULL, FALSE);
|
||||
|
||||
for (node = backend_list->p->backend_ids; node; node = node->next)
|
||||
if (callback (backend_list, node->data, data)) return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
backend_list_add (BackendList *backend_list, const gchar *backend_id)
|
||||
{
|
||||
g_return_if_fail (backend_list != NULL);
|
||||
g_return_if_fail (IS_BACKEND_LIST (backend_list));
|
||||
g_return_if_fail (backend_id != NULL);
|
||||
|
||||
backend_list->p->backend_ids =
|
||||
g_list_prepend (backend_list->p->backend_ids, g_strdup (backend_id));
|
||||
}
|
||||
|
||||
void
|
||||
backend_list_remove (BackendList *backend_list, const gchar *backend_id)
|
||||
{
|
||||
gchar *tmp;
|
||||
GList *node;
|
||||
|
||||
g_return_if_fail (backend_list != NULL);
|
||||
g_return_if_fail (IS_BACKEND_LIST (backend_list));
|
||||
g_return_if_fail (backend_id != NULL);
|
||||
|
||||
tmp = g_strdup (backend_id);
|
||||
node = g_list_find (backend_list->p->backend_ids, tmp);
|
||||
backend_list->p->backend_ids =
|
||||
g_list_remove_link (backend_list->p->backend_ids, node);
|
||||
g_free (node->data);
|
||||
g_free (tmp);
|
||||
g_list_free_1 (node);
|
||||
}
|
||||
|
||||
void
|
||||
backend_list_save (BackendList *backend_list)
|
||||
{
|
||||
g_return_if_fail (backend_list != NULL);
|
||||
g_return_if_fail (IS_BACKEND_LIST (backend_list));
|
||||
|
||||
do_save (backend_list);
|
||||
}
|
||||
|
||||
static void
|
||||
do_load (BackendList *backend_list)
|
||||
{
|
||||
xmlNodePtr root_node, node;
|
||||
xmlDocPtr doc;
|
||||
GList *list_tail = NULL;
|
||||
gchar *contains_str;
|
||||
|
||||
doc = xmlParseFile (backend_list->p->filename);
|
||||
if (doc == NULL) return;
|
||||
root_node = xmlDocGetRootElement (doc);
|
||||
|
||||
for (node = root_node->childs; node; node = node->next) {
|
||||
if (!strcmp (node->name, "contains")) {
|
||||
contains_str = xmlGetProp (node, "backend");
|
||||
|
||||
if (contains_str != NULL) {
|
||||
contains_str = g_strdup (contains_str);
|
||||
list_tail = g_list_append (list_tail,
|
||||
contains_str);
|
||||
if (backend_list->p->backend_ids == NULL)
|
||||
backend_list->p->backend_ids =
|
||||
list_tail;
|
||||
else
|
||||
list_tail = list_tail->next;
|
||||
} else {
|
||||
g_warning ("Bad backends list: " \
|
||||
"contains element with no " \
|
||||
"backend attribute");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
do_save (BackendList *backend_list)
|
||||
{
|
||||
xmlNodePtr root_node, child_node;
|
||||
xmlDocPtr doc;
|
||||
GList *node;
|
||||
|
||||
doc = xmlNewDoc ("1.0");
|
||||
root_node = xmlNewDocNode (doc, NULL, "location", NULL);
|
||||
|
||||
for (node = backend_list->p->backend_ids; node; node = node->next) {
|
||||
child_node = xmlNewChild (root_node, NULL, "contains", NULL);
|
||||
xmlNewProp (child_node, "backend", node->data);
|
||||
}
|
||||
|
||||
xmlDocSetRootElement (doc, root_node);
|
||||
xmlSaveFile (backend_list->p->filename, doc);
|
||||
xmlFreeDoc (doc);
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
/* -*- mode: c; style: linux -*- */
|
||||
|
||||
/* backend-list.h
|
||||
* Copyright (C) 2000-2001 Ximian, Inc.
|
||||
*
|
||||
* Written by Bradford Hovinen <hovinen@ximian.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __BACKEND_LIST_H
|
||||
#define __BACKEND_LIST_H
|
||||
|
||||
#include <gnome.h>
|
||||
#include <bonobo.h>
|
||||
|
||||
#include "ConfigArchiver.h"
|
||||
|
||||
BEGIN_GNOME_DECLS
|
||||
|
||||
#define BACKEND_LIST(obj) GTK_CHECK_CAST (obj, backend_list_get_type (), BackendList)
|
||||
#define BACKEND_LIST_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, backend_list_get_type (), BackendListClass)
|
||||
#define IS_BACKEND_LIST(obj) GTK_CHECK_TYPE (obj, backend_list_get_type ())
|
||||
|
||||
typedef struct _BackendList BackendList;
|
||||
typedef struct _BackendListClass BackendListClass;
|
||||
typedef struct _BackendListPrivate BackendListPrivate;
|
||||
|
||||
typedef gint (*BackendCB) (BackendList *, gchar *, gpointer);
|
||||
|
||||
struct _BackendList
|
||||
{
|
||||
BonoboXObject parent;
|
||||
|
||||
BackendListPrivate *p;
|
||||
};
|
||||
|
||||
struct _BackendListClass
|
||||
{
|
||||
BonoboXObjectClass parent_class;
|
||||
|
||||
POA_ConfigArchiver_BackendList__epv epv;
|
||||
};
|
||||
|
||||
GType backend_list_get_type (void);
|
||||
|
||||
BonoboObject *backend_list_new (gboolean is_global);
|
||||
|
||||
gboolean backend_list_contains (BackendList *backend_list,
|
||||
const gchar *backend_id);
|
||||
|
||||
gboolean backend_list_foreach (BackendList *backend_list,
|
||||
BackendCB callback,
|
||||
gpointer data);
|
||||
|
||||
void backend_list_add (BackendList *backend_list,
|
||||
const gchar *backend_id);
|
||||
void backend_list_remove (BackendList *backend_list,
|
||||
const gchar *backend_id);
|
||||
|
||||
void backend_list_save (BackendList *backend_list);
|
||||
|
||||
END_GNOME_DECLS
|
||||
|
||||
#endif /* __BACKEND_LIST_H */
|
||||
@@ -1,942 +0,0 @@
|
||||
/**
|
||||
* bonobo-config-archiver.c: XML configuration database with an interface to
|
||||
* the XML archiver
|
||||
*
|
||||
* Author:
|
||||
* Dietmar Maurer (dietmar@ximian.com)
|
||||
* Bradford Hovinen <hovinen@ximian.com>
|
||||
*
|
||||
* Copyright 2000, 2001 Ximian, Inc.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
#include <bonobo.h>
|
||||
#include <bonobo-conf/bonobo-config-utils.h>
|
||||
#include <gnome-xml/xmlmemory.h>
|
||||
#include <gtk/gtkmain.h>
|
||||
|
||||
#include "util.h"
|
||||
#include "bonobo-config-archiver.h"
|
||||
|
||||
static GtkObjectClass *parent_class = NULL;
|
||||
|
||||
#define CLASS(o) BONOBO_CONFIG_ARCHIVER_CLASS (GTK_OBJECT(o)->klass)
|
||||
|
||||
#define PARENT_TYPE BONOBO_CONFIG_DATABASE_TYPE
|
||||
#define FLUSH_INTERVAL 30 /* 30 seconds */
|
||||
|
||||
/* Small Bonobo bug here... */
|
||||
|
||||
#undef BONOBO_RET_EX
|
||||
#define BONOBO_RET_EX(ev) \
|
||||
G_STMT_START{ \
|
||||
if (BONOBO_EX (ev)) \
|
||||
return; \
|
||||
}G_STMT_END
|
||||
|
||||
extern int daytime;
|
||||
|
||||
static DirEntry *
|
||||
dir_lookup_entry (DirData *dir,
|
||||
char *name,
|
||||
gboolean create)
|
||||
{
|
||||
GSList *l;
|
||||
DirEntry *de;
|
||||
|
||||
l = dir->entries;
|
||||
|
||||
while (l) {
|
||||
de = (DirEntry *)l->data;
|
||||
|
||||
if (!strcmp (de->name, name))
|
||||
return de;
|
||||
|
||||
l = l->next;
|
||||
}
|
||||
|
||||
if (create) {
|
||||
|
||||
de = g_new0 (DirEntry, 1);
|
||||
|
||||
de->dir = dir;
|
||||
|
||||
de->name = g_strdup (name);
|
||||
|
||||
dir->entries = g_slist_prepend (dir->entries, de);
|
||||
|
||||
return de;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static DirData *
|
||||
dir_lookup_subdir (DirData *dir,
|
||||
char *name,
|
||||
gboolean create)
|
||||
{
|
||||
GSList *l;
|
||||
DirData *dd;
|
||||
|
||||
l = dir->subdirs;
|
||||
|
||||
while (l) {
|
||||
dd = (DirData *)l->data;
|
||||
|
||||
if (!strcmp (dd->name, name))
|
||||
return dd;
|
||||
|
||||
l = l->next;
|
||||
}
|
||||
|
||||
if (create) {
|
||||
|
||||
dd = g_new0 (DirData, 1);
|
||||
|
||||
dd->dir = dir;
|
||||
|
||||
dd->name = g_strdup (name);
|
||||
|
||||
dir->subdirs = g_slist_prepend (dir->subdirs, dd);
|
||||
|
||||
return dd;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static DirData *
|
||||
lookup_dir (DirData *dir,
|
||||
const char *path,
|
||||
gboolean create)
|
||||
{
|
||||
const char *s, *e;
|
||||
char *name;
|
||||
DirData *dd = dir;
|
||||
|
||||
s = path;
|
||||
while (*s == '/') s++;
|
||||
|
||||
if (*s == '\0')
|
||||
return dir;
|
||||
|
||||
if ((e = strchr (s, '/')))
|
||||
name = g_strndup (s, e - s);
|
||||
else
|
||||
name = g_strdup (s);
|
||||
|
||||
if ((dd = dir_lookup_subdir (dd, name, create))) {
|
||||
if (e)
|
||||
dd = lookup_dir (dd, e, create);
|
||||
|
||||
g_free (name);
|
||||
return dd;
|
||||
|
||||
} else {
|
||||
g_free (name);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
static DirEntry *
|
||||
lookup_dir_entry (BonoboConfigArchiver *archiver_db,
|
||||
const char *key,
|
||||
gboolean create)
|
||||
{
|
||||
char *dir_name;
|
||||
char *leaf_name;
|
||||
DirEntry *de;
|
||||
DirData *dd;
|
||||
|
||||
if ((dir_name = bonobo_config_dir_name (key))) {
|
||||
dd = lookup_dir (archiver_db->dir, dir_name, create);
|
||||
|
||||
if (dd && !dd->node) {
|
||||
dd->node = xmlNewChild (archiver_db->doc->root, NULL,
|
||||
"section", NULL);
|
||||
|
||||
xmlSetProp (dd->node, "path", dir_name);
|
||||
}
|
||||
|
||||
g_free (dir_name);
|
||||
|
||||
} else {
|
||||
dd = archiver_db->dir;
|
||||
|
||||
if (!dd->node)
|
||||
dd->node = xmlNewChild (archiver_db->doc->root, NULL,
|
||||
"section", NULL);
|
||||
}
|
||||
|
||||
if (!dd)
|
||||
return NULL;
|
||||
|
||||
if (!(leaf_name = bonobo_config_leaf_name (key)))
|
||||
return NULL;
|
||||
|
||||
de = dir_lookup_entry (dd, leaf_name, create);
|
||||
|
||||
g_free (leaf_name);
|
||||
|
||||
return de;
|
||||
}
|
||||
|
||||
static CORBA_any *
|
||||
real_get_value (BonoboConfigDatabase *db,
|
||||
const CORBA_char *key,
|
||||
const CORBA_char *locale,
|
||||
CORBA_Environment *ev)
|
||||
{
|
||||
BonoboConfigArchiver *archiver_db = BONOBO_CONFIG_ARCHIVER (db);
|
||||
DirEntry *de;
|
||||
CORBA_any *value = NULL;
|
||||
|
||||
de = lookup_dir_entry (archiver_db, key, FALSE);
|
||||
if (!de) {
|
||||
bonobo_exception_set (ev, ex_Bonobo_ConfigDatabase_NotFound);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (de->value)
|
||||
return bonobo_arg_copy (de->value);
|
||||
|
||||
/* localized value */
|
||||
if (de->node && de->node->childs && de->node->childs->next)
|
||||
value = bonobo_config_xml_decode_any ((BonoboUINode *)de->node,
|
||||
locale, ev);
|
||||
|
||||
if (!value)
|
||||
bonobo_exception_set (ev, ex_Bonobo_ConfigDatabase_NotFound);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/* Produce a new, dynamically allocated string with the OAF IID of the listener
|
||||
* associated with the given backend id
|
||||
*/
|
||||
|
||||
static gchar *
|
||||
get_listener_oafiid (const gchar *backend_id)
|
||||
{
|
||||
gchar *oafiid, *tmp, *tmp1;
|
||||
|
||||
tmp = g_strdup (backend_id);
|
||||
if ((tmp1 = strstr (tmp, "-properties")) != NULL) *tmp1 = '\0';
|
||||
oafiid = g_strconcat ("OAFIID:Bonobo_Listener_Config_", tmp, NULL);
|
||||
g_free (tmp);
|
||||
|
||||
return oafiid;
|
||||
}
|
||||
|
||||
static void
|
||||
real_sync (BonoboConfigDatabase *db,
|
||||
CORBA_Environment *ev)
|
||||
{
|
||||
BonoboConfigArchiver *archiver_db = BONOBO_CONFIG_ARCHIVER (db);
|
||||
BonoboArg *arg;
|
||||
|
||||
gchar *listener_oafiid;
|
||||
Bonobo_Listener listener;
|
||||
|
||||
if (!db->writeable)
|
||||
return;
|
||||
|
||||
/* FIXME: This will not work correctly in the pathlogical case that two
|
||||
* ConfigArchiver objects sync at almost exactly the same time.
|
||||
*/
|
||||
|
||||
archiver_db->is_up_to_date = TRUE;
|
||||
location_client_store_xml (archiver_db->location, archiver_db->backend_id,
|
||||
archiver_db->doc, ConfigArchiver_STORE_MASK_PREVIOUS, ev);
|
||||
|
||||
BONOBO_RET_EX (ev);
|
||||
|
||||
/* Try to find a listener to apply the settings. If we can't, don't
|
||||
* worry about it
|
||||
*/
|
||||
|
||||
listener_oafiid = get_listener_oafiid (archiver_db->backend_id);
|
||||
listener = bonobo_get_object (listener_oafiid, "IDL:Bonobo/Listener:1.0", ev);
|
||||
g_free (listener_oafiid);
|
||||
|
||||
if (BONOBO_EX (ev)) {
|
||||
listener = CORBA_OBJECT_NIL;
|
||||
CORBA_exception_init (ev);
|
||||
}
|
||||
|
||||
arg = bonobo_arg_new (BONOBO_ARG_NULL);
|
||||
bonobo_event_source_notify_listeners (archiver_db->es, "Bonobo/ConfigDatabase:sync", arg, ev);
|
||||
bonobo_arg_release (arg);
|
||||
|
||||
if (listener != CORBA_OBJECT_NIL)
|
||||
bonobo_object_release_unref (listener, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
notify_listeners (BonoboConfigArchiver *archiver_db,
|
||||
const char *key,
|
||||
const CORBA_any *value)
|
||||
{
|
||||
CORBA_Environment ev;
|
||||
char *dir_name;
|
||||
char *leaf_name;
|
||||
char *ename;
|
||||
|
||||
if (GTK_OBJECT_DESTROYED (archiver_db))
|
||||
return;
|
||||
|
||||
if (!key)
|
||||
return;
|
||||
|
||||
CORBA_exception_init (&ev);
|
||||
|
||||
ename = g_strconcat ("Bonobo/Property:change:", key, NULL);
|
||||
|
||||
bonobo_event_source_notify_listeners (archiver_db->es, ename, value, &ev);
|
||||
|
||||
g_free (ename);
|
||||
|
||||
if (!(dir_name = bonobo_config_dir_name (key)))
|
||||
dir_name = g_strdup ("");
|
||||
|
||||
if (!(leaf_name = bonobo_config_leaf_name (key)))
|
||||
leaf_name = g_strdup ("");
|
||||
|
||||
ename = g_strconcat ("Bonobo/ConfigDatabase:change", dir_name, ":",
|
||||
leaf_name, NULL);
|
||||
|
||||
bonobo_event_source_notify_listeners (archiver_db->es, ename, value, &ev);
|
||||
|
||||
CORBA_exception_free (&ev);
|
||||
|
||||
g_free (ename);
|
||||
g_free (dir_name);
|
||||
g_free (leaf_name);
|
||||
}
|
||||
|
||||
static void
|
||||
real_set_value (BonoboConfigDatabase *db,
|
||||
const CORBA_char *key,
|
||||
const CORBA_any *value,
|
||||
CORBA_Environment *ev)
|
||||
{
|
||||
BonoboConfigArchiver *archiver_db = BONOBO_CONFIG_ARCHIVER (db);
|
||||
DirEntry *de;
|
||||
char *name;
|
||||
|
||||
de = lookup_dir_entry (archiver_db, key, TRUE);
|
||||
|
||||
if (de->value)
|
||||
CORBA_free (de->value);
|
||||
|
||||
de->value = bonobo_arg_copy (value);
|
||||
|
||||
if (de->node) {
|
||||
xmlUnlinkNode (de->node);
|
||||
xmlFreeNode (de->node);
|
||||
}
|
||||
|
||||
name = bonobo_config_leaf_name (key);
|
||||
|
||||
de->node = (xmlNodePtr) bonobo_config_xml_encode_any (value, name, ev);
|
||||
|
||||
g_free (name);
|
||||
|
||||
bonobo_ui_node_add_child ((BonoboUINode *)de->dir->node,
|
||||
(BonoboUINode *)de->node);
|
||||
|
||||
notify_listeners (archiver_db, key, value);
|
||||
}
|
||||
|
||||
static Bonobo_KeyList *
|
||||
real_list_dirs (BonoboConfigDatabase *db,
|
||||
const CORBA_char *dir,
|
||||
CORBA_Environment *ev)
|
||||
{
|
||||
BonoboConfigArchiver *archiver_db = BONOBO_CONFIG_ARCHIVER (db);
|
||||
Bonobo_KeyList *key_list;
|
||||
DirData *dd, *sub;
|
||||
GSList *l;
|
||||
int len;
|
||||
|
||||
key_list = Bonobo_KeyList__alloc ();
|
||||
key_list->_length = 0;
|
||||
|
||||
if (!(dd = lookup_dir (archiver_db->dir, dir, FALSE)))
|
||||
return key_list;
|
||||
|
||||
if (!(len = g_slist_length (dd->subdirs)))
|
||||
return key_list;
|
||||
|
||||
key_list->_buffer = CORBA_sequence_CORBA_string_allocbuf (len);
|
||||
CORBA_sequence_set_release (key_list, TRUE);
|
||||
|
||||
for (l = dd->subdirs; l != NULL; l = l->next) {
|
||||
sub = (DirData *)l->data;
|
||||
|
||||
key_list->_buffer [key_list->_length] =
|
||||
CORBA_string_dup (sub->name);
|
||||
key_list->_length++;
|
||||
}
|
||||
|
||||
return key_list;
|
||||
}
|
||||
|
||||
static Bonobo_KeyList *
|
||||
real_list_keys (BonoboConfigDatabase *db,
|
||||
const CORBA_char *dir,
|
||||
CORBA_Environment *ev)
|
||||
{
|
||||
BonoboConfigArchiver *archiver_db = BONOBO_CONFIG_ARCHIVER (db);
|
||||
Bonobo_KeyList *key_list;
|
||||
DirData *dd;
|
||||
DirEntry *de;
|
||||
GSList *l;
|
||||
int len;
|
||||
|
||||
key_list = Bonobo_KeyList__alloc ();
|
||||
key_list->_length = 0;
|
||||
|
||||
if (!(dd = lookup_dir (archiver_db->dir, dir, FALSE)))
|
||||
return key_list;
|
||||
|
||||
if (!(len = g_slist_length (dd->entries)))
|
||||
return key_list;
|
||||
|
||||
key_list->_buffer = CORBA_sequence_CORBA_string_allocbuf (len);
|
||||
CORBA_sequence_set_release (key_list, TRUE);
|
||||
|
||||
for (l = dd->entries; l != NULL; l = l->next) {
|
||||
de = (DirEntry *)l->data;
|
||||
|
||||
key_list->_buffer [key_list->_length] =
|
||||
CORBA_string_dup (de->name);
|
||||
key_list->_length++;
|
||||
}
|
||||
|
||||
return key_list;
|
||||
}
|
||||
|
||||
static CORBA_boolean
|
||||
real_dir_exists (BonoboConfigDatabase *db,
|
||||
const CORBA_char *dir,
|
||||
CORBA_Environment *ev)
|
||||
{
|
||||
BonoboConfigArchiver *archiver_db = BONOBO_CONFIG_ARCHIVER (db);
|
||||
|
||||
if (lookup_dir (archiver_db->dir, dir, FALSE))
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
delete_dir_entry (DirEntry *de)
|
||||
{
|
||||
CORBA_free (de->value);
|
||||
|
||||
if (de->node) {
|
||||
xmlUnlinkNode (de->node);
|
||||
xmlFreeNode (de->node);
|
||||
}
|
||||
|
||||
g_free (de->name);
|
||||
g_free (de);
|
||||
}
|
||||
|
||||
static void
|
||||
real_remove_value (BonoboConfigDatabase *db,
|
||||
const CORBA_char *key,
|
||||
CORBA_Environment *ev)
|
||||
{
|
||||
BonoboConfigArchiver *archiver_db = BONOBO_CONFIG_ARCHIVER (db);
|
||||
DirEntry *de;
|
||||
|
||||
if (!(de = lookup_dir_entry (archiver_db, key, FALSE)))
|
||||
return;
|
||||
|
||||
de->dir->entries = g_slist_remove (de->dir->entries, de);
|
||||
|
||||
delete_dir_entry (de);
|
||||
}
|
||||
|
||||
static void
|
||||
delete_dir_data (DirData *dd, gboolean is_root)
|
||||
{
|
||||
GSList *l;
|
||||
|
||||
for (l = dd->subdirs; l; l = l->next)
|
||||
delete_dir_data ((DirData *)l->data, FALSE);
|
||||
|
||||
g_slist_free (dd->subdirs);
|
||||
|
||||
dd->subdirs = NULL;
|
||||
|
||||
for (l = dd->entries; l; l = l->next)
|
||||
delete_dir_entry ((DirEntry *)l->data);
|
||||
|
||||
g_slist_free (dd->entries);
|
||||
|
||||
dd->entries = NULL;
|
||||
|
||||
if (!is_root) {
|
||||
g_free (dd->name);
|
||||
|
||||
if (dd->node) {
|
||||
xmlUnlinkNode (dd->node);
|
||||
xmlFreeNode (dd->node);
|
||||
}
|
||||
|
||||
g_free (dd);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
real_remove_dir (BonoboConfigDatabase *db,
|
||||
const CORBA_char *dir,
|
||||
CORBA_Environment *ev)
|
||||
{
|
||||
BonoboConfigArchiver *archiver_db = BONOBO_CONFIG_ARCHIVER (db);
|
||||
DirData *dd;
|
||||
|
||||
if (!(dd = lookup_dir (archiver_db->dir, dir, FALSE)))
|
||||
return;
|
||||
|
||||
if (dd != archiver_db->dir && dd->dir)
|
||||
dd->dir->subdirs = g_slist_remove (dd->dir->subdirs, dd);
|
||||
|
||||
delete_dir_data (dd, dd == archiver_db->dir);
|
||||
}
|
||||
|
||||
static void
|
||||
pb_get_fn (BonoboPropertyBag *bag, BonoboArg *arg,
|
||||
guint arg_id, CORBA_Environment *ev,
|
||||
gpointer user_data)
|
||||
{
|
||||
BonoboConfigArchiver *archiver_db = BONOBO_CONFIG_ARCHIVER (user_data);
|
||||
time_t val;
|
||||
|
||||
val = ConfigArchiver_Location_getModificationTime
|
||||
(archiver_db->location, archiver_db->backend_id, ev);
|
||||
|
||||
BONOBO_ARG_SET_GENERAL (arg, val, TC_ulonglong, CORBA_unsigned_long_long, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
pb_set_fn (BonoboPropertyBag *bag, const BonoboArg *arg,
|
||||
guint arg_id, CORBA_Environment *ev,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
static void
|
||||
bonobo_config_archiver_destroy (GtkObject *object)
|
||||
{
|
||||
BonoboConfigArchiver *archiver_db = BONOBO_CONFIG_ARCHIVER (object);
|
||||
CORBA_Environment ev;
|
||||
|
||||
DEBUG_MSG ("Enter");
|
||||
|
||||
CORBA_exception_init (&ev);
|
||||
|
||||
if (archiver_db->moniker != NULL) {
|
||||
bonobo_url_unregister ("BONOBO_CONF:ARCHIVER", archiver_db->moniker, &ev);
|
||||
g_free (archiver_db->moniker);
|
||||
|
||||
if (BONOBO_EX (&ev)) {
|
||||
g_critical ("Could not unregister the archiver URL");
|
||||
CORBA_exception_init (&ev);
|
||||
}
|
||||
}
|
||||
|
||||
if (archiver_db->listener_id != 0) {
|
||||
bonobo_event_source_client_remove_listener
|
||||
(archiver_db->location, archiver_db->listener_id, &ev);
|
||||
|
||||
if (BONOBO_EX (&ev))
|
||||
g_critical ("Could not remove the rollback data listener");
|
||||
}
|
||||
|
||||
CORBA_exception_free (&ev);
|
||||
|
||||
if (archiver_db->doc != NULL) {
|
||||
delete_dir_data (archiver_db->dir, TRUE);
|
||||
archiver_db->dir = NULL;
|
||||
xmlFreeDoc (archiver_db->doc);
|
||||
}
|
||||
|
||||
if (archiver_db->filename != NULL)
|
||||
g_free (archiver_db->filename);
|
||||
|
||||
if (archiver_db->fp != NULL)
|
||||
fclose (archiver_db->fp);
|
||||
|
||||
if (archiver_db->location != CORBA_OBJECT_NIL)
|
||||
bonobo_object_release_unref (archiver_db->location, NULL);
|
||||
|
||||
if (archiver_db->archive != CORBA_OBJECT_NIL)
|
||||
bonobo_object_release_unref (archiver_db->archive, NULL);
|
||||
|
||||
parent_class->destroy (object);
|
||||
|
||||
DEBUG_MSG ("Exit");
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
bonobo_config_archiver_class_init (BonoboConfigDatabaseClass *class)
|
||||
{
|
||||
GtkObjectClass *object_class = (GtkObjectClass *) class;
|
||||
BonoboConfigDatabaseClass *cd_class;
|
||||
|
||||
parent_class = gtk_type_class (PARENT_TYPE);
|
||||
|
||||
object_class->destroy = bonobo_config_archiver_destroy;
|
||||
|
||||
cd_class = BONOBO_CONFIG_DATABASE_CLASS (class);
|
||||
|
||||
cd_class->get_value = real_get_value;
|
||||
cd_class->set_value = real_set_value;
|
||||
cd_class->list_dirs = real_list_dirs;
|
||||
cd_class->list_keys = real_list_keys;
|
||||
cd_class->dir_exists = real_dir_exists;
|
||||
cd_class->remove_value = real_remove_value;
|
||||
cd_class->remove_dir = real_remove_dir;
|
||||
cd_class->sync = real_sync;
|
||||
}
|
||||
|
||||
static void
|
||||
bonobo_config_archiver_init (BonoboConfigArchiver *archiver_db)
|
||||
{
|
||||
archiver_db->dir = g_new0 (DirData, 1);
|
||||
|
||||
/* This will always be writeable */
|
||||
BONOBO_CONFIG_DATABASE (archiver_db)->writeable = TRUE;
|
||||
}
|
||||
|
||||
BONOBO_X_TYPE_FUNC (BonoboConfigArchiver, PARENT_TYPE, bonobo_config_archiver);
|
||||
|
||||
static void
|
||||
read_section (DirData *dd)
|
||||
{
|
||||
CORBA_Environment ev;
|
||||
DirEntry *de;
|
||||
xmlNodePtr s;
|
||||
gchar *name;
|
||||
|
||||
CORBA_exception_init (&ev);
|
||||
|
||||
s = dd->node->childs;
|
||||
|
||||
while (s) {
|
||||
if (s->type == XML_ELEMENT_NODE &&
|
||||
!strcmp (s->name, "entry") &&
|
||||
(name = xmlGetProp(s, "name"))) {
|
||||
|
||||
de = dir_lookup_entry (dd, name, TRUE);
|
||||
|
||||
de->node = s;
|
||||
|
||||
/* we only decode it if it is a single value,
|
||||
* multiple (localized) values are decoded in the
|
||||
* get_value function */
|
||||
if (!(s->childs && s->childs->next))
|
||||
de->value = bonobo_config_xml_decode_any
|
||||
((BonoboUINode *)s, NULL, &ev);
|
||||
|
||||
xmlFree (name);
|
||||
}
|
||||
s = s->next;
|
||||
}
|
||||
|
||||
CORBA_exception_free (&ev);
|
||||
}
|
||||
|
||||
static void
|
||||
fill_cache (BonoboConfigArchiver *archiver_db)
|
||||
{
|
||||
xmlNodePtr n;
|
||||
gchar *path;
|
||||
DirData *dd;
|
||||
|
||||
n = archiver_db->doc->root->childs;
|
||||
|
||||
while (n) {
|
||||
if (n->type == XML_ELEMENT_NODE &&
|
||||
!strcmp (n->name, "section")) {
|
||||
|
||||
path = xmlGetProp(n, "path");
|
||||
|
||||
if (!path || !strcmp (path, "")) {
|
||||
dd = archiver_db->dir;
|
||||
} else
|
||||
dd = lookup_dir (archiver_db->dir, path, TRUE);
|
||||
|
||||
if (!dd->node)
|
||||
dd->node = n;
|
||||
|
||||
read_section (dd);
|
||||
|
||||
xmlFree (path);
|
||||
}
|
||||
n = n->next;
|
||||
}
|
||||
}
|
||||
|
||||
/* parse_name
|
||||
*
|
||||
* Given a moniker with a backend id and (possibly) a location id encoded
|
||||
* therein, parse out the backend id and the location id and set the pointers
|
||||
* given to them.
|
||||
*
|
||||
* FIXME: Is this encoding really the way we want to do this? Ask Dietmar and
|
||||
* Michael.
|
||||
*/
|
||||
|
||||
static gboolean
|
||||
parse_name (const gchar *name, gchar **backend_id, gchar **location, struct tm **date)
|
||||
{
|
||||
gchar *e, *e1, *time_str = NULL;
|
||||
|
||||
*date = NULL;
|
||||
|
||||
if (name[0] == '[') {
|
||||
e = strchr (name + 1, '|');
|
||||
|
||||
if (e != NULL) {
|
||||
*location = g_strndup (name + 1, e - (name + 1));
|
||||
e1 = strchr (e + 1, ']');
|
||||
|
||||
if (e1 != NULL) {
|
||||
time_str = g_strndup (e + 1, e1 - (e + 1));
|
||||
*date = parse_date (time_str);
|
||||
g_free (time_str);
|
||||
}
|
||||
|
||||
*backend_id = g_strdup (e1 + 1);
|
||||
} else {
|
||||
e = strchr (name + 1, ']');
|
||||
|
||||
if (e != NULL)
|
||||
*location = g_strndup (name + 1, e - (name + 1));
|
||||
else
|
||||
return FALSE;
|
||||
|
||||
*backend_id = g_strdup (e + 1);
|
||||
}
|
||||
} else {
|
||||
*backend_id = g_strdup (name);
|
||||
*location = NULL;
|
||||
}
|
||||
|
||||
if (*location != NULL && **location == '\0') {
|
||||
g_free (*location);
|
||||
*location = NULL;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
new_rollback_cb (BonoboListener *listener,
|
||||
gchar *event_name,
|
||||
CORBA_any *any,
|
||||
CORBA_Environment *ev,
|
||||
BonoboConfigArchiver *archiver_db)
|
||||
{
|
||||
BonoboArg *arg;
|
||||
|
||||
if (archiver_db->is_up_to_date) {
|
||||
archiver_db->is_up_to_date = FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
if (archiver_db->dir != NULL) {
|
||||
delete_dir_data (archiver_db->dir, TRUE);
|
||||
g_free (archiver_db->dir->name);
|
||||
g_free (archiver_db->dir);
|
||||
archiver_db->dir = g_new0 (DirData, 1);
|
||||
}
|
||||
|
||||
if (archiver_db->doc != NULL)
|
||||
xmlFreeDoc (archiver_db->doc);
|
||||
|
||||
archiver_db->doc = location_client_load_rollback_data
|
||||
(archiver_db->location, NULL, 0, archiver_db->backend_id, TRUE, ev);
|
||||
|
||||
if (archiver_db->doc == NULL)
|
||||
g_critical ("Could not load new rollback data");
|
||||
else
|
||||
fill_cache (archiver_db);
|
||||
|
||||
arg = bonobo_arg_new (BONOBO_ARG_NULL);
|
||||
bonobo_event_source_notify_listeners (archiver_db->es, "Bonobo/ConfigDatabase:sync", arg, ev);
|
||||
bonobo_arg_release (arg);
|
||||
}
|
||||
|
||||
Bonobo_ConfigDatabase
|
||||
bonobo_config_archiver_new (Bonobo_Moniker parent,
|
||||
const Bonobo_ResolveOptions *options,
|
||||
const char *moniker,
|
||||
CORBA_Environment *ev)
|
||||
{
|
||||
BonoboConfigArchiver *archiver_db;
|
||||
Bonobo_ConfigDatabase db;
|
||||
ConfigArchiver_Archive archive;
|
||||
ConfigArchiver_Location location;
|
||||
gchar *moniker_tmp;
|
||||
gchar *backend_id;
|
||||
gchar *location_id;
|
||||
struct tm *date;
|
||||
|
||||
g_return_val_if_fail (backend_id != NULL, NULL);
|
||||
|
||||
/* Check the Bonobo URL database to see if this archiver database has
|
||||
* already been created, and return it if it has */
|
||||
|
||||
moniker_tmp = g_strdup (moniker);
|
||||
db = bonobo_url_lookup ("BONOBO_CONF:ARCHIVER", moniker_tmp, ev);
|
||||
g_free (moniker_tmp);
|
||||
|
||||
if (BONOBO_EX (ev)) {
|
||||
db = CORBA_OBJECT_NIL;
|
||||
CORBA_exception_init (ev);
|
||||
}
|
||||
|
||||
if (db != CORBA_OBJECT_NIL)
|
||||
return bonobo_object_dup_ref (db, NULL);
|
||||
|
||||
/* Parse out the backend id, location id, and rollback date from the
|
||||
* moniker given */
|
||||
|
||||
if (parse_name (moniker, &backend_id, &location_id, &date) < 0) {
|
||||
EX_SET_NOT_FOUND (ev);
|
||||
return CORBA_OBJECT_NIL;
|
||||
}
|
||||
|
||||
/* Resolve the parent archive and the location */
|
||||
|
||||
archive = Bonobo_Moniker_resolve (parent, options, "IDL:ConfigArchiver/Archive:1.0", ev);
|
||||
|
||||
if (BONOBO_EX (ev) || archive == CORBA_OBJECT_NIL) {
|
||||
g_free (location_id);
|
||||
g_free (date);
|
||||
return CORBA_OBJECT_NIL;
|
||||
}
|
||||
|
||||
if (location_id == NULL || *location_id == '\0')
|
||||
location = ConfigArchiver_Archive__get_currentLocation (archive, ev);
|
||||
else
|
||||
location = ConfigArchiver_Archive_getLocation (archive, location_id, ev);
|
||||
|
||||
g_free (location_id);
|
||||
|
||||
if (location == CORBA_OBJECT_NIL) {
|
||||
g_free (date);
|
||||
bonobo_object_release_unref (archive, NULL);
|
||||
return CORBA_OBJECT_NIL;
|
||||
}
|
||||
|
||||
/* Construct the database object proper and fill in its values */
|
||||
|
||||
if ((archiver_db = gtk_type_new (BONOBO_CONFIG_ARCHIVER_TYPE)) == NULL) {
|
||||
g_free (date);
|
||||
return CORBA_OBJECT_NIL;
|
||||
}
|
||||
|
||||
archiver_db->backend_id = backend_id;
|
||||
archiver_db->moniker = g_strdup (moniker);
|
||||
archiver_db->archive = archive;
|
||||
archiver_db->location = location;
|
||||
|
||||
/* Load the XML data, or use the defaults file if none are present */
|
||||
|
||||
archiver_db->doc = location_client_load_rollback_data
|
||||
(archiver_db->location, date, 0, archiver_db->backend_id, TRUE, ev);
|
||||
g_free (date);
|
||||
|
||||
if (BONOBO_EX (ev) || archiver_db->doc == NULL) {
|
||||
gchar *filename;
|
||||
|
||||
filename = g_strconcat (GNOMECC_DEFAULTS_DIR "/", archiver_db->backend_id, ".xml", NULL);
|
||||
archiver_db->doc = xmlParseFile (filename);
|
||||
g_free (filename);
|
||||
|
||||
if (archiver_db->doc == NULL) {
|
||||
bonobo_object_release_unref (archiver_db->location, NULL);
|
||||
bonobo_object_release_unref (archiver_db->archive, NULL);
|
||||
bonobo_object_unref (BONOBO_OBJECT (archiver_db));
|
||||
return CORBA_OBJECT_NIL;
|
||||
}
|
||||
|
||||
CORBA_exception_init (ev);
|
||||
}
|
||||
|
||||
/* Load data from the XML file */
|
||||
|
||||
if (archiver_db->doc->root == NULL)
|
||||
archiver_db->doc->root =
|
||||
xmlNewDocNode (archiver_db->doc, NULL, "bonobo-config", NULL);
|
||||
|
||||
if (strcmp (archiver_db->doc->root->name, "bonobo-config")) {
|
||||
xmlFreeDoc (archiver_db->doc);
|
||||
archiver_db->doc = xmlNewDoc("1.0");
|
||||
archiver_db->doc->root =
|
||||
xmlNewDocNode (archiver_db->doc, NULL, "bonobo-config", NULL);
|
||||
}
|
||||
|
||||
fill_cache (archiver_db);
|
||||
|
||||
/* Construct the associated property bag and event source */
|
||||
|
||||
#if 0
|
||||
archiver_db->es = bonobo_event_source_new ();
|
||||
|
||||
bonobo_object_add_interface (BONOBO_OBJECT (archiver_db),
|
||||
BONOBO_OBJECT (archiver_db->es));
|
||||
#endif
|
||||
|
||||
archiver_db->pb = bonobo_property_bag_new (pb_get_fn,
|
||||
pb_set_fn,
|
||||
archiver_db);
|
||||
|
||||
bonobo_object_add_interface (BONOBO_OBJECT (archiver_db),
|
||||
BONOBO_OBJECT (archiver_db->pb));
|
||||
|
||||
archiver_db->es = archiver_db->pb->es;
|
||||
|
||||
bonobo_property_bag_add (archiver_db->pb,
|
||||
"last_modified", 1, TC_ulonglong, NULL,
|
||||
"Date (time_t) of modification",
|
||||
BONOBO_PROPERTY_READABLE);
|
||||
|
||||
/* Listen for events pertaining to new rollback data */
|
||||
|
||||
if (date == NULL && location_id == NULL)
|
||||
archiver_db->listener_id =
|
||||
bonobo_event_source_client_add_listener
|
||||
(location, (BonoboListenerCallbackFn) new_rollback_cb,
|
||||
"ConfigArchiver/Location:newRollbackData", ev, archiver_db);
|
||||
else
|
||||
archiver_db->listener_id = 0;
|
||||
|
||||
/* Prepare to return the database object */
|
||||
|
||||
db = CORBA_Object_duplicate (BONOBO_OBJREF (archiver_db), NULL);
|
||||
|
||||
moniker_tmp = g_strdup (moniker);
|
||||
bonobo_url_register ("BONOBO_CONF:ARCHIVER", moniker_tmp, NULL, db, ev);
|
||||
g_free (moniker_tmp);
|
||||
|
||||
return db;
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
/**
|
||||
* bonobo-config-archiver.h: xml configuration database implementation, with
|
||||
* interface to the archiver
|
||||
*
|
||||
* Author:
|
||||
* Dietmar Maurer (dietmar@ximian.com)
|
||||
* Bradford Hovinen <hovinen@ximian.com>
|
||||
*
|
||||
* Copyright 2000 Ximian, Inc.
|
||||
*/
|
||||
#ifndef __BONOBO_CONFIG_ARCHIVER_H__
|
||||
#define __BONOBO_CONFIG_ARCHIVER_H__
|
||||
|
||||
#include <stdio.h>
|
||||
#include <bonobo-conf/bonobo-config-database.h>
|
||||
#include <gnome-xml/tree.h>
|
||||
#include <gnome-xml/parser.h>
|
||||
#include <bonobo/bonobo-event-source.h>
|
||||
#include <bonobo/bonobo-property-bag.h>
|
||||
|
||||
#include "archiver-client.h"
|
||||
|
||||
BEGIN_GNOME_DECLS
|
||||
|
||||
#define EX_SET_NOT_FOUND(ev) bonobo_exception_set (ev, ex_Bonobo_Moniker_InterfaceNotFound)
|
||||
|
||||
#define BONOBO_CONFIG_ARCHIVER_TYPE (bonobo_config_archiver_get_type ())
|
||||
#define BONOBO_CONFIG_ARCHIVER(o) (GTK_CHECK_CAST ((o), BONOBO_CONFIG_ARCHIVER_TYPE, BonoboConfigArchiver))
|
||||
#define BONOBO_CONFIG_ARCHIVER_CLASS(k) (GTK_CHECK_CLASS_CAST((k), BONOBO_CONFIG_ARCHIVER_TYPE, BonoboConfigArchiverClass))
|
||||
#define BONOBO_IS_CONFIG_ARCHIVER(o) (GTK_CHECK_TYPE ((o), BONOBO_CONFIG_ARCHIVER_TYPE))
|
||||
#define BONOBO_IS_CONFIG_ARCHIVER_CLASS(k) (GTK_CHECK_CLASS_TYPE ((k), BONOBO_CONFIG_ARCHIVER_TYPE))
|
||||
|
||||
typedef struct _DirData DirData;
|
||||
|
||||
struct _DirData {
|
||||
char *name;
|
||||
GSList *entries;
|
||||
GSList *subdirs;
|
||||
xmlNodePtr node;
|
||||
DirData *dir;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
char *name;
|
||||
CORBA_any *value;
|
||||
xmlNodePtr node;
|
||||
DirData *dir;
|
||||
} DirEntry;
|
||||
|
||||
typedef struct _BonoboConfigArchiver BonoboConfigArchiver;
|
||||
|
||||
struct _BonoboConfigArchiver {
|
||||
BonoboConfigDatabase base;
|
||||
|
||||
char *filename;
|
||||
FILE *fp;
|
||||
xmlDocPtr doc;
|
||||
DirData *dir;
|
||||
guint time_id;
|
||||
|
||||
ConfigArchiver_Archive archive;
|
||||
ConfigArchiver_Location location;
|
||||
gchar *backend_id;
|
||||
gchar *moniker;
|
||||
|
||||
BonoboEventSource *es;
|
||||
BonoboPropertyBag *pb;
|
||||
|
||||
Bonobo_EventSource_ListenerId listener_id;
|
||||
gboolean is_up_to_date;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
BonoboConfigDatabaseClass parent_class;
|
||||
} BonoboConfigArchiverClass;
|
||||
|
||||
|
||||
GtkType
|
||||
bonobo_config_archiver_get_type (void);
|
||||
|
||||
Bonobo_ConfigDatabase
|
||||
bonobo_config_archiver_new (Bonobo_Moniker parent,
|
||||
const Bonobo_ResolveOptions *options,
|
||||
const char *moniker,
|
||||
CORBA_Environment *ev);
|
||||
|
||||
END_GNOME_DECLS
|
||||
|
||||
#endif /* ! __BONOBO_CONFIG_ARCHIVER_H__ */
|
||||
@@ -1,146 +0,0 @@
|
||||
/*
|
||||
* bonobo-moniker-archiver.c: archiver xml database moniker implementation
|
||||
*
|
||||
* Author:
|
||||
* Dietmar Maurer (dietmar@ximian.com)
|
||||
* Bradford Hovinen <hovinen@ximian.com>
|
||||
*
|
||||
* Copyright 2001 Ximian, Inc.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <bonobo.h>
|
||||
|
||||
#include "bonobo-config-archiver.h"
|
||||
#include "archive.h"
|
||||
#include "util.h"
|
||||
|
||||
static Archive *user_archive = NULL;
|
||||
static Archive *global_archive = NULL;
|
||||
|
||||
static void
|
||||
archive_destroy_cb (Archive *archive)
|
||||
{
|
||||
if (archive == global_archive)
|
||||
global_archive = NULL;
|
||||
else if (archive == user_archive)
|
||||
user_archive = NULL;
|
||||
}
|
||||
|
||||
static Bonobo_Unknown
|
||||
archive_resolve (BonoboMoniker *moniker,
|
||||
const Bonobo_ResolveOptions *options,
|
||||
const CORBA_char *requested_interface,
|
||||
CORBA_Environment *ev)
|
||||
{
|
||||
const gchar *name;
|
||||
|
||||
Bonobo_Unknown ret;
|
||||
|
||||
if (strcmp (requested_interface, "IDL:ConfigArchiver/Archive:1.0")) {
|
||||
EX_SET_NOT_FOUND (ev);
|
||||
return CORBA_OBJECT_NIL;
|
||||
}
|
||||
|
||||
name = bonobo_moniker_get_name (moniker);
|
||||
|
||||
if (!strcmp (name, "global-archive")) {
|
||||
if (global_archive == NULL) {
|
||||
global_archive = ARCHIVE (archive_load (TRUE));
|
||||
gtk_signal_connect (GTK_OBJECT (global_archive), "destroy", GTK_SIGNAL_FUNC (archive_destroy_cb), NULL);
|
||||
ret = CORBA_Object_duplicate (BONOBO_OBJREF (global_archive), ev);
|
||||
} else {
|
||||
ret = bonobo_object_dup_ref (BONOBO_OBJREF (global_archive), ev);
|
||||
}
|
||||
|
||||
if (BONOBO_EX (ev)) {
|
||||
g_critical ("Cannot duplicate object");
|
||||
bonobo_object_release_unref (ret, NULL);
|
||||
ret = CORBA_OBJECT_NIL;
|
||||
}
|
||||
}
|
||||
else if (!strcmp (name, "user-archive")) {
|
||||
if (user_archive == NULL) {
|
||||
user_archive = ARCHIVE (archive_load (FALSE));
|
||||
gtk_signal_connect (GTK_OBJECT (user_archive), "destroy", GTK_SIGNAL_FUNC (archive_destroy_cb), NULL);
|
||||
ret = CORBA_Object_duplicate (BONOBO_OBJREF (user_archive), ev);
|
||||
} else {
|
||||
ret = bonobo_object_dup_ref (BONOBO_OBJREF (user_archive), ev);
|
||||
}
|
||||
|
||||
if (BONOBO_EX (ev)) {
|
||||
g_critical ("Cannot duplicate object");
|
||||
bonobo_object_release_unref (ret, NULL);
|
||||
ret = CORBA_OBJECT_NIL;
|
||||
}
|
||||
} else {
|
||||
EX_SET_NOT_FOUND (ev);
|
||||
ret = CORBA_OBJECT_NIL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static Bonobo_Unknown
|
||||
archiverdb_resolve (BonoboMoniker *moniker,
|
||||
const Bonobo_ResolveOptions *options,
|
||||
const CORBA_char *requested_interface,
|
||||
CORBA_Environment *ev)
|
||||
{
|
||||
Bonobo_Moniker parent;
|
||||
Bonobo_ConfigDatabase db;
|
||||
const gchar *name;
|
||||
|
||||
if (strcmp (requested_interface, "IDL:Bonobo/ConfigDatabase:1.0")) {
|
||||
EX_SET_NOT_FOUND (ev);
|
||||
return CORBA_OBJECT_NIL;
|
||||
}
|
||||
|
||||
parent = bonobo_moniker_get_parent (moniker, ev);
|
||||
if (BONOBO_EX (ev))
|
||||
return CORBA_OBJECT_NIL;
|
||||
|
||||
if (parent == CORBA_OBJECT_NIL) {
|
||||
EX_SET_NOT_FOUND (ev);
|
||||
return CORBA_OBJECT_NIL;
|
||||
}
|
||||
|
||||
name = bonobo_moniker_get_name (moniker);
|
||||
|
||||
db = bonobo_config_archiver_new (parent, options, name, ev);
|
||||
|
||||
if (db == CORBA_OBJECT_NIL || BONOBO_EX (ev))
|
||||
EX_SET_NOT_FOUND (ev);
|
||||
|
||||
bonobo_object_release_unref (parent, NULL);
|
||||
|
||||
return db;
|
||||
}
|
||||
|
||||
|
||||
static BonoboObject *
|
||||
bonobo_moniker_archiver_factory (BonoboGenericFactory *this,
|
||||
const char *object_id,
|
||||
void *closure)
|
||||
{
|
||||
if (!strcmp (object_id, "OAFIID:Bonobo_Moniker_archiverdb")) {
|
||||
return BONOBO_OBJECT (bonobo_moniker_simple_new
|
||||
("archiverdb:", archiverdb_resolve));
|
||||
}
|
||||
else if (!strcmp (object_id, "OAFIID:Bonobo_Moniker_archive")) {
|
||||
return BONOBO_OBJECT (bonobo_moniker_simple_new
|
||||
("archive:", archive_resolve));
|
||||
} else {
|
||||
g_warning ("Failing to manufacture a '%s'", object_id);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BONOBO_OAF_FACTORY_MULTI ("OAFIID:Bonobo_Moniker_archiver_Factory",
|
||||
"bonobo xml archiver database moniker", "1.0",
|
||||
bonobo_moniker_archiver_factory,
|
||||
NULL);
|
||||
@@ -1,222 +0,0 @@
|
||||
/* -*- mode: c; style: linux -*- */
|
||||
|
||||
/* cluster-location.c
|
||||
* Copyright (C) 2000 Ximian, Inc.
|
||||
*
|
||||
* Written by Bradford Hovinen <hovinen@helixcode.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include "cluster.h"
|
||||
#include "cluster-location.h"
|
||||
|
||||
typedef struct _pair_t pair_t;
|
||||
|
||||
enum {
|
||||
ARG_0,
|
||||
ARG_SAMPLE
|
||||
};
|
||||
|
||||
struct _ClusterLocationPrivate
|
||||
{
|
||||
/* Private data members */
|
||||
};
|
||||
|
||||
struct _pair_t
|
||||
{
|
||||
gpointer a, b;
|
||||
};
|
||||
|
||||
static LocationClass *parent_class;
|
||||
|
||||
static void cluster_location_init (ClusterLocation *cluster_location);
|
||||
static void cluster_location_class_init (ClusterLocationClass *class);
|
||||
|
||||
static void cluster_location_set_arg (GtkObject *object,
|
||||
GtkArg *arg,
|
||||
guint arg_id);
|
||||
static void cluster_location_get_arg (GtkObject *object,
|
||||
GtkArg *arg,
|
||||
guint arg_id);
|
||||
|
||||
static void cluster_location_finalize (GtkObject *object);
|
||||
|
||||
static gboolean cluster_location_do_rollback (Location *location,
|
||||
gchar *backend_id,
|
||||
xmlDocPtr doc);
|
||||
|
||||
static gboolean host_cb (Cluster *cluster,
|
||||
gchar *hostname,
|
||||
pair_t *pair);
|
||||
|
||||
GType
|
||||
cluster_location_get_type (void)
|
||||
{
|
||||
static GType cluster_location_type = 0;
|
||||
|
||||
if (!cluster_location_type) {
|
||||
GtkTypeInfo cluster_location_info = {
|
||||
"ClusterLocation",
|
||||
sizeof (ClusterLocation),
|
||||
sizeof (ClusterLocationClass),
|
||||
(GtkClassInitFunc) cluster_location_class_init,
|
||||
(GtkObjectInitFunc) cluster_location_init,
|
||||
(GtkArgSetFunc) NULL,
|
||||
(GtkArgGetFunc) NULL
|
||||
};
|
||||
|
||||
cluster_location_type =
|
||||
gtk_type_unique (location_get_type (),
|
||||
&cluster_location_info);
|
||||
}
|
||||
|
||||
return cluster_location_type;
|
||||
}
|
||||
|
||||
static void
|
||||
cluster_location_init (ClusterLocation *cluster_location)
|
||||
{
|
||||
cluster_location->p = g_new0 (ClusterLocationPrivate, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
cluster_location_class_init (ClusterLocationClass *class)
|
||||
{
|
||||
GtkObjectClass *object_class;
|
||||
LocationClass *location_class;
|
||||
|
||||
gtk_object_add_arg_type ("ClusterLocation::sample",
|
||||
GTK_TYPE_POINTER,
|
||||
GTK_ARG_READWRITE,
|
||||
ARG_SAMPLE);
|
||||
|
||||
object_class = GTK_OBJECT_CLASS (class);
|
||||
object_class->finalize = cluster_location_finalize;
|
||||
object_class->set_arg = cluster_location_set_arg;
|
||||
object_class->get_arg = cluster_location_get_arg;
|
||||
|
||||
location_class = LOCATION_CLASS (class);
|
||||
location_class->do_rollback = cluster_location_do_rollback;
|
||||
|
||||
parent_class = LOCATION_CLASS
|
||||
(gtk_type_class (location_get_type ()));
|
||||
}
|
||||
|
||||
static void
|
||||
cluster_location_set_arg (GtkObject *object, GtkArg *arg, guint arg_id)
|
||||
{
|
||||
ClusterLocation *cluster_location;
|
||||
|
||||
g_return_if_fail (object != NULL);
|
||||
g_return_if_fail (IS_CLUSTER_LOCATION (object));
|
||||
|
||||
cluster_location = CLUSTER_LOCATION (object);
|
||||
|
||||
switch (arg_id) {
|
||||
case ARG_SAMPLE:
|
||||
break;
|
||||
|
||||
default:
|
||||
g_warning ("Bad argument set");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cluster_location_get_arg (GtkObject *object, GtkArg *arg, guint arg_id)
|
||||
{
|
||||
ClusterLocation *cluster_location;
|
||||
|
||||
g_return_if_fail (object != NULL);
|
||||
g_return_if_fail (IS_CLUSTER_LOCATION (object));
|
||||
|
||||
cluster_location = CLUSTER_LOCATION (object);
|
||||
|
||||
switch (arg_id) {
|
||||
case ARG_SAMPLE:
|
||||
break;
|
||||
|
||||
default:
|
||||
g_warning ("Bad argument get");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cluster_location_finalize (GtkObject *object)
|
||||
{
|
||||
ClusterLocation *cluster_location;
|
||||
|
||||
g_return_if_fail (object != NULL);
|
||||
g_return_if_fail (IS_CLUSTER_LOCATION (object));
|
||||
|
||||
cluster_location = CLUSTER_LOCATION (object);
|
||||
|
||||
g_free (cluster_location->p);
|
||||
|
||||
GTK_OBJECT_CLASS (parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
GtkObject *
|
||||
cluster_location_new (void)
|
||||
{
|
||||
return gtk_object_new (cluster_location_get_type (),
|
||||
NULL);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
cluster_location_do_rollback (Location *location, gchar *backend_id,
|
||||
xmlDocPtr doc)
|
||||
{
|
||||
Cluster *cluster;
|
||||
pair_t pair;
|
||||
|
||||
g_return_val_if_fail (location != NULL, FALSE);
|
||||
g_return_val_if_fail (IS_CLUSTER_LOCATION (location), FALSE);
|
||||
g_return_val_if_fail (backend_id != NULL, FALSE);
|
||||
g_return_val_if_fail (doc != NULL, FALSE);
|
||||
|
||||
gtk_object_get (GTK_OBJECT (location), "archive", &cluster, NULL);
|
||||
pair.a = doc;
|
||||
pair.b = backend_id;
|
||||
cluster_foreach_host (cluster, (ClusterHostCB) host_cb, &pair);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
host_cb (Cluster *cluster, gchar *hostname, pair_t *pair)
|
||||
{
|
||||
xmlDocPtr doc;
|
||||
gchar *backend_id, *command;
|
||||
FILE *output;
|
||||
|
||||
doc = pair->a;
|
||||
backend_id = pair->b;
|
||||
command = g_strconcat ("ssh ", hostname, " ", backend_id, " --set",
|
||||
NULL);
|
||||
output = popen (command, "w");
|
||||
xmlDocDump (output, doc);
|
||||
pclose (output);
|
||||
g_free (command);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
/* -*- mode: c; style: linux -*- */
|
||||
|
||||
/* cluster-location.h
|
||||
* Copyright (C) 2000 Ximian, Inc.
|
||||
*
|
||||
* Written by Bradford Hovinen <hovinen@helixcode.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __CLUSTER_LOCATION_H
|
||||
#define __CLUSTER_LOCATION_H
|
||||
|
||||
#include <gnome.h>
|
||||
|
||||
#include "location.h"
|
||||
|
||||
BEGIN_GNOME_DECLS
|
||||
|
||||
#define CLUSTER_LOCATION(obj) GTK_CHECK_CAST (obj, cluster_location_get_type (), ClusterLocation)
|
||||
#define CLUSTER_LOCATION_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, cluster_location_get_type (), ClusterLocationClass)
|
||||
#define IS_CLUSTER_LOCATION(obj) GTK_CHECK_TYPE (obj, cluster_location_get_type ())
|
||||
|
||||
typedef struct _ClusterLocation ClusterLocation;
|
||||
typedef struct _ClusterLocationClass ClusterLocationClass;
|
||||
typedef struct _ClusterLocationPrivate ClusterLocationPrivate;
|
||||
|
||||
struct _ClusterLocation
|
||||
{
|
||||
Location parent;
|
||||
|
||||
ClusterLocationPrivate *p;
|
||||
};
|
||||
|
||||
struct _ClusterLocationClass
|
||||
{
|
||||
LocationClass location_class;
|
||||
};
|
||||
|
||||
GType cluster_location_get_type (void);
|
||||
|
||||
GtkObject *cluster_location_new (void);
|
||||
|
||||
END_GNOME_DECLS
|
||||
|
||||
#endif /* __CLUSTER_LOCATION_H */
|
||||
@@ -1,437 +0,0 @@
|
||||
/* -*- mode: c; style: linux -*- */
|
||||
|
||||
/* cluster.c
|
||||
* Copyright (C) 2000 Ximian, Inc.
|
||||
*
|
||||
* Written by Bradford Hovinen <hovinen@helixcode.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <parser.h>
|
||||
|
||||
#include "cluster.h"
|
||||
|
||||
enum {
|
||||
ARG_0,
|
||||
ARG_SAMPLE
|
||||
};
|
||||
|
||||
typedef struct _SlaveHost SlaveHost;
|
||||
|
||||
struct _SlaveHost
|
||||
{
|
||||
gchar *hostname;
|
||||
};
|
||||
|
||||
struct _ClusterPrivate
|
||||
{
|
||||
GList *slave_hosts;
|
||||
};
|
||||
|
||||
static ArchiveClass *parent_class;
|
||||
|
||||
static void cluster_init (Cluster *cluster);
|
||||
static void cluster_class_init (ClusterClass *class);
|
||||
|
||||
static void cluster_set_arg (GtkObject *object,
|
||||
GtkArg *arg,
|
||||
guint arg_id);
|
||||
static void cluster_get_arg (GtkObject *object,
|
||||
GtkArg *arg,
|
||||
guint arg_id);
|
||||
|
||||
static void cluster_destroy (GtkObject *object);
|
||||
static void cluster_finalize (GtkObject *object);
|
||||
|
||||
static gboolean cluster_construct (Cluster *cluster,
|
||||
gboolean is_new);
|
||||
|
||||
static gboolean load_metadata (Cluster *cluster);
|
||||
static void save_metadata (Cluster *cluster);
|
||||
|
||||
static void cluster_add_slave_host (Cluster *cluster,
|
||||
SlaveHost *slave_host);
|
||||
static void cluster_remove_slave_host (Cluster *cluster,
|
||||
SlaveHost *slave_host);
|
||||
|
||||
static SlaveHost *find_slave_host (Cluster *cluster,
|
||||
gchar *hostname);
|
||||
static gchar *get_metadata_filename (Cluster *cluster);
|
||||
|
||||
static SlaveHost *slave_host_new (gchar *hostname);
|
||||
static SlaveHost *slave_host_read_xml (xmlNodePtr node);
|
||||
static xmlNodePtr slave_host_write_xml (SlaveHost *host);
|
||||
|
||||
GType
|
||||
cluster_get_type (void)
|
||||
{
|
||||
static GType cluster_type = 0;
|
||||
|
||||
if (!cluster_type) {
|
||||
GtkTypeInfo cluster_info = {
|
||||
"Cluster",
|
||||
sizeof (Cluster),
|
||||
sizeof (ClusterClass),
|
||||
(GtkClassInitFunc) cluster_class_init,
|
||||
(GtkObjectInitFunc) cluster_init,
|
||||
(GtkArgSetFunc) NULL,
|
||||
(GtkArgGetFunc) NULL
|
||||
};
|
||||
|
||||
cluster_type =
|
||||
gtk_type_unique (archive_get_type (),
|
||||
&cluster_info);
|
||||
}
|
||||
|
||||
return cluster_type;
|
||||
}
|
||||
|
||||
static void
|
||||
cluster_init (Cluster *cluster)
|
||||
{
|
||||
cluster->p = g_new0 (ClusterPrivate, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
cluster_class_init (ClusterClass *class)
|
||||
{
|
||||
GtkObjectClass *object_class;
|
||||
|
||||
gtk_object_add_arg_type ("Cluster::sample",
|
||||
GTK_TYPE_POINTER,
|
||||
GTK_ARG_READWRITE,
|
||||
ARG_SAMPLE);
|
||||
|
||||
object_class = GTK_OBJECT_CLASS (class);
|
||||
object_class->destroy = cluster_destroy;
|
||||
object_class->finalize = cluster_finalize;
|
||||
object_class->set_arg = cluster_set_arg;
|
||||
object_class->get_arg = cluster_get_arg;
|
||||
|
||||
parent_class = ARCHIVE_CLASS
|
||||
(gtk_type_class (archive_get_type ()));
|
||||
}
|
||||
|
||||
static void
|
||||
cluster_set_arg (GtkObject *object, GtkArg *arg, guint arg_id)
|
||||
{
|
||||
Cluster *cluster;
|
||||
|
||||
g_return_if_fail (object != NULL);
|
||||
g_return_if_fail (IS_CLUSTER (object));
|
||||
|
||||
cluster = CLUSTER (object);
|
||||
|
||||
switch (arg_id) {
|
||||
case ARG_SAMPLE:
|
||||
break;
|
||||
|
||||
default:
|
||||
g_warning ("Bad argument set");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cluster_get_arg (GtkObject *object, GtkArg *arg, guint arg_id)
|
||||
{
|
||||
Cluster *cluster;
|
||||
|
||||
g_return_if_fail (object != NULL);
|
||||
g_return_if_fail (IS_CLUSTER (object));
|
||||
|
||||
cluster = CLUSTER (object);
|
||||
|
||||
switch (arg_id) {
|
||||
case ARG_SAMPLE:
|
||||
break;
|
||||
|
||||
default:
|
||||
g_warning ("Bad argument get");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cluster_destroy (GtkObject *object)
|
||||
{
|
||||
Cluster *cluster;
|
||||
|
||||
g_return_if_fail (object != NULL);
|
||||
g_return_if_fail (IS_CLUSTER (object));
|
||||
|
||||
cluster = CLUSTER (object);
|
||||
|
||||
save_metadata (cluster);
|
||||
|
||||
GTK_OBJECT_CLASS (parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static void
|
||||
cluster_finalize (GtkObject *object)
|
||||
{
|
||||
Cluster *cluster;
|
||||
|
||||
g_return_if_fail (object != NULL);
|
||||
g_return_if_fail (IS_CLUSTER (object));
|
||||
|
||||
cluster = CLUSTER (object);
|
||||
|
||||
g_free (cluster->p);
|
||||
|
||||
GTK_OBJECT_CLASS (parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
GtkObject *
|
||||
cluster_new (gchar *prefix)
|
||||
{
|
||||
GtkObject *object;
|
||||
|
||||
object = gtk_object_new (cluster_get_type (),
|
||||
"prefix", prefix,
|
||||
"is-global", TRUE,
|
||||
NULL);
|
||||
|
||||
if (cluster_construct (CLUSTER (object), TRUE) == FALSE) {
|
||||
gtk_object_destroy (object);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
GtkObject *
|
||||
cluster_load (gchar *prefix)
|
||||
{
|
||||
GtkObject *object;
|
||||
|
||||
object = gtk_object_new (cluster_get_type (),
|
||||
"prefix", prefix,
|
||||
"is-global", TRUE,
|
||||
NULL);
|
||||
|
||||
if (cluster_construct (CLUSTER (object), FALSE) == FALSE) {
|
||||
gtk_object_destroy (object);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
void
|
||||
cluster_foreach_host (Cluster *cluster, ClusterHostCB callback, gpointer data)
|
||||
{
|
||||
GList *node;
|
||||
SlaveHost *host;
|
||||
|
||||
g_return_if_fail (cluster != NULL);
|
||||
g_return_if_fail (IS_CLUSTER (cluster));
|
||||
g_return_if_fail (callback != NULL);
|
||||
|
||||
for (node = cluster->p->slave_hosts; node; node = node->next) {
|
||||
host = node->data;
|
||||
if (callback (cluster, host->hostname, data)) break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
cluster_add_host (Cluster *cluster, gchar *hostname)
|
||||
{
|
||||
g_return_if_fail (cluster != NULL);
|
||||
g_return_if_fail (IS_CLUSTER (cluster));
|
||||
g_return_if_fail (hostname != NULL);
|
||||
|
||||
cluster_add_slave_host (cluster, slave_host_new (hostname));
|
||||
}
|
||||
|
||||
void
|
||||
cluster_remove_host (Cluster *cluster, gchar *hostname)
|
||||
{
|
||||
g_return_if_fail (cluster != NULL);
|
||||
g_return_if_fail (IS_CLUSTER (cluster));
|
||||
g_return_if_fail (hostname != NULL);
|
||||
|
||||
cluster_remove_slave_host (cluster,
|
||||
find_slave_host (cluster, hostname));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
cluster_construct (Cluster *cluster, gboolean is_new)
|
||||
{
|
||||
if (archive_construct (ARCHIVE (cluster), is_new) == FALSE)
|
||||
return FALSE;
|
||||
|
||||
if (!is_new) {
|
||||
if (load_metadata (cluster) == FALSE)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Loads the metadata associated with the cluster; returns TRUE on success and
|
||||
* FALSE on failure
|
||||
*/
|
||||
|
||||
static gboolean
|
||||
load_metadata (Cluster *cluster)
|
||||
{
|
||||
xmlDocPtr doc;
|
||||
xmlNodePtr root_node, node;
|
||||
gchar *filename;
|
||||
SlaveHost *new_host;
|
||||
|
||||
filename = get_metadata_filename (cluster);
|
||||
doc = xmlParseFile (filename);
|
||||
g_free (filename);
|
||||
|
||||
if (doc == NULL) return FALSE;
|
||||
|
||||
root_node = xmlDocGetRootElement (doc);
|
||||
if (strcmp (root_node->name, "cluster")) {
|
||||
xmlFreeDoc (doc);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
for (node = root_node->childs; node != NULL; node = node->next) {
|
||||
if (!strcmp (node->name, "host")) {
|
||||
new_host = slave_host_read_xml (node);
|
||||
if (new_host != NULL)
|
||||
cluster_add_slave_host (cluster, new_host);
|
||||
}
|
||||
}
|
||||
|
||||
xmlFreeDoc (doc);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
save_metadata (Cluster *cluster)
|
||||
{
|
||||
xmlDocPtr doc;
|
||||
xmlNodePtr root_node;
|
||||
GList *list_node;
|
||||
gchar *filename;
|
||||
|
||||
doc = xmlNewDoc ("1.0");
|
||||
root_node = xmlNewDocNode (doc, NULL, "cluster", NULL);
|
||||
|
||||
for (list_node = cluster->p->slave_hosts; list_node != NULL;
|
||||
list_node = list_node->next)
|
||||
{
|
||||
xmlAddChild (root_node,
|
||||
slave_host_write_xml (list_node->data));
|
||||
}
|
||||
|
||||
xmlDocSetRootElement (doc, root_node);
|
||||
|
||||
filename = get_metadata_filename (cluster);
|
||||
xmlSaveFile (filename, doc);
|
||||
g_free (filename);
|
||||
}
|
||||
|
||||
/* Adds a slave host to the list of slave hosts for this cluster */
|
||||
|
||||
static void
|
||||
cluster_add_slave_host (Cluster *cluster, SlaveHost *slave_host)
|
||||
{
|
||||
if (slave_host == NULL) return;
|
||||
|
||||
cluster->p->slave_hosts =
|
||||
g_list_append (cluster->p->slave_hosts, slave_host);
|
||||
}
|
||||
|
||||
static void
|
||||
cluster_remove_slave_host (Cluster *cluster, SlaveHost *slave_host)
|
||||
{
|
||||
if (slave_host == NULL) return;
|
||||
|
||||
cluster->p->slave_hosts =
|
||||
g_list_remove (cluster->p->slave_hosts, slave_host);
|
||||
}
|
||||
|
||||
static SlaveHost *
|
||||
find_slave_host (Cluster *cluster, gchar *hostname)
|
||||
{
|
||||
SlaveHost *host;
|
||||
GList *node;
|
||||
|
||||
g_return_val_if_fail (hostname != NULL, NULL);
|
||||
|
||||
for (node = cluster->p->slave_hosts; node != NULL; node = node->next) {
|
||||
host = node->data;
|
||||
|
||||
if (!strcmp (host->hostname, hostname))
|
||||
return host;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Returns the filename of the metadata file (should be freed after use) */
|
||||
|
||||
static gchar *
|
||||
get_metadata_filename (Cluster *cluster)
|
||||
{
|
||||
return g_concat_dir_and_file
|
||||
(archive_get_prefix (ARCHIVE (cluster)), "cluster.xml");
|
||||
}
|
||||
|
||||
/* Constructs a new slave host structure */
|
||||
|
||||
static SlaveHost *
|
||||
slave_host_new (gchar *hostname)
|
||||
{
|
||||
SlaveHost *new_host;
|
||||
|
||||
new_host = g_new0 (SlaveHost, 1);
|
||||
new_host->hostname = g_strdup (hostname);
|
||||
|
||||
return new_host;
|
||||
}
|
||||
|
||||
/* Constructs a new slave host structure from an XML node */
|
||||
|
||||
static SlaveHost *
|
||||
slave_host_read_xml (xmlNodePtr node)
|
||||
{
|
||||
gchar *hostname;
|
||||
|
||||
hostname = xmlGetProp (node, "name");
|
||||
|
||||
if (hostname != NULL)
|
||||
return slave_host_new (hostname);
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Constructs an XML node for the slave host */
|
||||
|
||||
static xmlNodePtr
|
||||
slave_host_write_xml (SlaveHost *host)
|
||||
{
|
||||
xmlNodePtr node;
|
||||
|
||||
node = xmlNewNode (NULL, "host");
|
||||
xmlNewProp (node, "name", host->hostname);
|
||||
return node;
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
/* -*- mode: c; style: linux -*- */
|
||||
|
||||
/* cluster.h
|
||||
* Copyright (C) 2000 Ximian, Inc.
|
||||
*
|
||||
* Written by Bradford Hovinen <hovinen@helixcode.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __CLUSTER_H
|
||||
#define __CLUSTER_H
|
||||
|
||||
#include <gnome.h>
|
||||
|
||||
#include "archive.h"
|
||||
|
||||
BEGIN_GNOME_DECLS
|
||||
|
||||
#define CLUSTER(obj) GTK_CHECK_CAST (obj, cluster_get_type (), Cluster)
|
||||
#define CLUSTER_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, cluster_get_type (), ClusterClass)
|
||||
#define IS_CLUSTER(obj) GTK_CHECK_TYPE (obj, cluster_get_type ())
|
||||
|
||||
typedef struct _Cluster Cluster;
|
||||
typedef struct _ClusterClass ClusterClass;
|
||||
typedef struct _ClusterPrivate ClusterPrivate;
|
||||
|
||||
typedef gboolean (*ClusterHostCB) (Cluster *, gchar *, gpointer);
|
||||
|
||||
struct _Cluster
|
||||
{
|
||||
Archive parent;
|
||||
|
||||
ClusterPrivate *p;
|
||||
};
|
||||
|
||||
struct _ClusterClass
|
||||
{
|
||||
ArchiveClass archive_class;
|
||||
};
|
||||
|
||||
GType cluster_get_type (void);
|
||||
|
||||
GtkObject *cluster_new (gchar *prefix);
|
||||
GtkObject *cluster_load (gchar *prefix);
|
||||
|
||||
void cluster_foreach_host (Cluster *cluster,
|
||||
ClusterHostCB callback,
|
||||
gpointer data);
|
||||
|
||||
void cluster_add_host (Cluster *cluster,
|
||||
gchar *hostname);
|
||||
void cluster_remove_host (Cluster *cluster,
|
||||
gchar *hostname);
|
||||
|
||||
END_GNOME_DECLS
|
||||
|
||||
#endif /* __CLUSTER_H */
|
||||
@@ -1,439 +0,0 @@
|
||||
/* -*- mode: c; style: linux -*- */
|
||||
|
||||
/* main.c
|
||||
* Copyright (C) 2000-2001 Ximian, Inc.
|
||||
*
|
||||
* Written by Bradford Hovinen (hovinen@ximian.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/file.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <gnome.h>
|
||||
#include <bonobo.h>
|
||||
|
||||
#include <gnome-xml/parser.h>
|
||||
|
||||
#include "archiver-client.h"
|
||||
#include "util.h"
|
||||
|
||||
/* Variables resulting from command line parsing */
|
||||
|
||||
static gboolean store;
|
||||
static gboolean rollback;
|
||||
static gboolean change_location;
|
||||
static gboolean rename_location;
|
||||
static gboolean push_config;
|
||||
static gboolean garbage_collect;
|
||||
|
||||
static gboolean add_location;
|
||||
static gboolean remove_location;
|
||||
static gboolean add_backend;
|
||||
static gboolean remove_backend;
|
||||
|
||||
static gboolean global;
|
||||
static const gchar *location_id;
|
||||
|
||||
static gchar *backend_id;
|
||||
|
||||
static gboolean compare_parent;
|
||||
static gboolean mask_previous;
|
||||
|
||||
static gchar *date_str;
|
||||
static gboolean all;
|
||||
static gchar *revision_id;
|
||||
static gboolean last;
|
||||
static guint steps;
|
||||
static gboolean show;
|
||||
|
||||
static gchar *parent_str;
|
||||
static gchar *new_name;
|
||||
|
||||
static gboolean contain_full;
|
||||
static gboolean contain_partial;
|
||||
static gboolean master;
|
||||
|
||||
static struct poptOption archiver_operations[] = {
|
||||
{"store", 's', POPT_ARG_NONE, &store, 0,
|
||||
N_("Store XML data in the archive")},
|
||||
{"rollback", 'r', POPT_ARG_NONE, &rollback, 0,
|
||||
N_("Roll back the configuration to a given point")},
|
||||
{"change-location", 'c', POPT_ARG_NONE, &change_location, 0,
|
||||
N_("Change the location profile to the given one")},
|
||||
{"push-config", 'p', POPT_ARG_NONE, &push_config, 0,
|
||||
N_("Push configuration data out to client machines (UNIMPLEMENTED)")},
|
||||
{"rename-location", '\0', POPT_ARG_NONE, &rename_location, 0,
|
||||
N_("Rename a location to a new name")},
|
||||
{"add-location", '\0', POPT_ARG_NONE, &add_location, 0,
|
||||
N_("Add a new location to the archive")},
|
||||
{"remove-location", '\0', POPT_ARG_NONE, &remove_location, 0,
|
||||
N_("Remove a location from the archive")},
|
||||
{"add-backend", '\0', POPT_ARG_NONE, &add_backend, 0,
|
||||
N_("Add a given backend to the given location")},
|
||||
{"remove-backend", '\0', POPT_ARG_NONE, &remove_backend, 0,
|
||||
N_("Remove the given backend from the given location")},
|
||||
{"garbage-collect", '\0', POPT_ARG_NONE, &garbage_collect, 0,
|
||||
N_("Perform garbage collection on the given location")},
|
||||
{NULL, '\0', 0, NULL, 0}
|
||||
};
|
||||
|
||||
static struct poptOption global_options[] = {
|
||||
{"global", 'g', POPT_ARG_NONE, &global, 0,
|
||||
N_("Use the global repository")},
|
||||
{"location", 'l', POPT_ARG_STRING, &location_id, 0,
|
||||
N_("Identifier of location profile on which to operate"),
|
||||
N_("LOCATION")},
|
||||
{"backend", 'b', POPT_ARG_STRING, &backend_id, 0,
|
||||
N_("Backend being used for this operation"), N_("BACKEND_ID")},
|
||||
{NULL, '\0', 0, NULL, 0}
|
||||
};
|
||||
|
||||
static struct poptOption store_options[] = {
|
||||
{"compare-parent", '\0', POPT_ARG_NONE, &compare_parent, 0,
|
||||
N_("Store only the differences with the parent location's config")},
|
||||
{"mask-previous", '\0', POPT_ARG_NONE, &mask_previous, 0,
|
||||
N_("Store only those settings set in the previous config")},
|
||||
{NULL, '\0', 0, NULL, 0}
|
||||
};
|
||||
|
||||
static struct poptOption rollback_options[] = {
|
||||
{"date", 'd', POPT_ARG_STRING, &date_str, 0,
|
||||
N_("Date to which to roll back"), N_("DATE")},
|
||||
{"all", 'a', POPT_ARG_NONE, &all, 0,
|
||||
N_("Roll back all configuration items")},
|
||||
{"revision-id", 'i', POPT_ARG_INT, &revision_id, 0,
|
||||
N_("Roll back to the revision REVISION_ID"), N_("REVISION_ID")},
|
||||
{"last", 't', POPT_ARG_NONE, &last, 0,
|
||||
N_("Roll back to the last known revision")},
|
||||
{"steps", '\0', POPT_ARG_INT, &steps, 0,
|
||||
N_("Roll back by STEPS revisions"), N_("STEPS")},
|
||||
{"show", 'h', POPT_ARG_NONE, &show, 0,
|
||||
N_("Don't run the backend, just dump the output")},
|
||||
{NULL, '\0', 0, NULL, 0}
|
||||
};
|
||||
|
||||
static struct poptOption add_rename_location_options[] = {
|
||||
{"parent", '\0', POPT_ARG_STRING, &parent_str, 0,
|
||||
N_("Parent location for the new location"), N_("PARENT")},
|
||||
{"new-name", '\0', POPT_ARG_STRING, &new_name, 0,
|
||||
N_("New name to assign to the location"), N_("NEW_NAME")},
|
||||
{NULL, '\0', 0, NULL, 0}
|
||||
};
|
||||
|
||||
static struct poptOption add_remove_backend_options[] = {
|
||||
{"master", '\0', POPT_ARG_NONE, &master, 0,
|
||||
N_("Add/remove this backend to/from the master backend list")},
|
||||
{"full", '\0', POPT_ARG_NONE, &contain_full, 0,
|
||||
N_("Full containment")},
|
||||
{"partial", '\0', POPT_ARG_NONE, &contain_partial, 0,
|
||||
N_("Partial containment")},
|
||||
{NULL, '\0', 0, NULL, 0}
|
||||
};
|
||||
|
||||
static xmlDocPtr
|
||||
xml_load_from_stream (FILE *stream)
|
||||
{
|
||||
GString *str;
|
||||
gchar buffer[4097];
|
||||
xmlDocPtr doc;
|
||||
size_t t;
|
||||
|
||||
str = g_string_new ("");
|
||||
|
||||
while (!feof (stream)) {
|
||||
t = fread (buffer, sizeof (char), 4096, stream);
|
||||
buffer[t] = '\0';
|
||||
g_string_append (str, buffer);
|
||||
}
|
||||
|
||||
doc = xmlParseDoc (str->str);
|
||||
g_string_free (str, TRUE);
|
||||
return doc;
|
||||
}
|
||||
|
||||
static ConfigArchiver_StringSeq *
|
||||
make_backend_id_seq (gchar *backend_id, ...)
|
||||
{
|
||||
ConfigArchiver_StringSeq *seq;
|
||||
|
||||
seq = ConfigArchiver_StringSeq__alloc ();
|
||||
seq->_length = 1;
|
||||
seq->_buffer = CORBA_sequence_CORBA_string_allocbuf (1);
|
||||
seq->_buffer[0] = CORBA_string_dup (backend_id);
|
||||
|
||||
return seq;
|
||||
}
|
||||
|
||||
static void
|
||||
do_store (ConfigArchiver_Location location, CORBA_Environment *ev)
|
||||
{
|
||||
ConfigArchiver_StoreType type;
|
||||
xmlDocPtr doc;
|
||||
|
||||
if (!backend_id) {
|
||||
fprintf (stderr, "No backend specified\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (mask_previous)
|
||||
type = ConfigArchiver_STORE_MASK_PREVIOUS;
|
||||
else if (compare_parent)
|
||||
type = ConfigArchiver_STORE_COMPARE_PARENT;
|
||||
else
|
||||
type = ConfigArchiver_STORE_FULL;
|
||||
|
||||
doc = xml_load_from_stream (stdin);
|
||||
|
||||
location_client_store_xml (location, backend_id, doc, type, ev);
|
||||
}
|
||||
|
||||
static void
|
||||
do_rollback (ConfigArchiver_Location location, CORBA_Environment *ev)
|
||||
{
|
||||
struct tm *date = NULL;
|
||||
ConfigArchiver_StringSeq *seq;
|
||||
ConfigArchiver_Time tm;
|
||||
xmlDocPtr doc;
|
||||
|
||||
if (date_str)
|
||||
date = parse_date (date_str);
|
||||
else if (last || steps > 0)
|
||||
date = NULL;
|
||||
else if (!revision_id) {
|
||||
fprintf (stderr, "No date specified\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (backend_id != NULL && (date != NULL || last)) {
|
||||
/* FIXME: Need to support specifying multiple backends */
|
||||
if (show) {
|
||||
doc = location_client_load_rollback_data (location, date, 0, backend_id, TRUE, ev);
|
||||
xmlDocDump (stdout, doc);
|
||||
xmlFreeDoc (doc);
|
||||
} else {
|
||||
tm = mktime (date);
|
||||
seq = make_backend_id_seq (backend_id, NULL);
|
||||
ConfigArchiver_Location_rollbackBackends (location, tm, 0, seq, TRUE, ev);
|
||||
CORBA_free (seq);
|
||||
}
|
||||
}
|
||||
else if (backend_id != NULL && steps != 0) {
|
||||
if (show) {
|
||||
doc = location_client_load_rollback_data (location, date, steps, backend_id, TRUE, ev);
|
||||
xmlDocDump (stdout, doc);
|
||||
xmlFreeDoc (doc);
|
||||
} else {
|
||||
seq = make_backend_id_seq (backend_id, NULL);
|
||||
ConfigArchiver_Location_rollbackBackends (location, 0, steps, seq, TRUE, ev);
|
||||
CORBA_free (seq);
|
||||
}
|
||||
} else {
|
||||
g_message ("No backend specified\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
do_change_location (ConfigArchiver_Archive archive, ConfigArchiver_Location location, CORBA_Environment *ev)
|
||||
{
|
||||
ConfigArchiver_Archive__set_currentLocation (archive, location, ev);
|
||||
}
|
||||
|
||||
static void
|
||||
do_rename_location (ConfigArchiver_Archive archive, ConfigArchiver_Location location, CORBA_Environment *ev)
|
||||
{
|
||||
gboolean is_current;
|
||||
CORBA_char *locid, *cid;
|
||||
|
||||
if (new_name == NULL) {
|
||||
fprintf (stderr, "You did not specify a new name. Try --help\n");
|
||||
} else {
|
||||
locid = ConfigArchiver_Location__get_id (location, ev);
|
||||
cid = ConfigArchiver_Archive__get_currentLocationId (archive, ev);
|
||||
|
||||
if (!strcmp (locid, cid))
|
||||
is_current = TRUE;
|
||||
else
|
||||
is_current = FALSE;
|
||||
|
||||
CORBA_free (locid);
|
||||
CORBA_free (cid);
|
||||
|
||||
ConfigArchiver_Location__set_id (location, new_name, ev);
|
||||
|
||||
if (is_current)
|
||||
ConfigArchiver_Archive__set_currentLocationId (archive, new_name, ev);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
do_add_location (ConfigArchiver_Archive archive, CORBA_Environment *ev)
|
||||
{
|
||||
ConfigArchiver_Location parent_location = CORBA_OBJECT_NIL;
|
||||
|
||||
if (location_id == NULL) {
|
||||
fprintf (stderr, "Error: You did not specify a location name\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (parent_str != NULL) {
|
||||
parent_location = ConfigArchiver_Archive_getLocation (archive, parent_str, ev);
|
||||
|
||||
if (parent_location == NULL && !strcmp (parent_str, "default"))
|
||||
parent_location =
|
||||
ConfigArchiver_Archive_createLocation (archive, "default", _("Default Location"),
|
||||
CORBA_OBJECT_NIL, ev);
|
||||
}
|
||||
|
||||
ConfigArchiver_Archive_createLocation (archive, location_id, location_id, parent_location, ev);
|
||||
}
|
||||
|
||||
static void
|
||||
do_remove_location (ConfigArchiver_Location location, CORBA_Environment *ev)
|
||||
{
|
||||
ConfigArchiver_Location_delete (location, ev);
|
||||
}
|
||||
|
||||
static void
|
||||
do_add_backend (ConfigArchiver_Location location, CORBA_Environment *ev)
|
||||
{
|
||||
ConfigArchiver_ContainmentType type;
|
||||
|
||||
if (contain_full && contain_partial) {
|
||||
fprintf (stderr, "Error: Cannot have both full and partial "
|
||||
"containment\n");
|
||||
return;
|
||||
}
|
||||
else if (contain_partial) {
|
||||
type = ConfigArchiver_CONTAIN_PARTIAL;
|
||||
} else {
|
||||
type = ConfigArchiver_CONTAIN_FULL;
|
||||
}
|
||||
|
||||
ConfigArchiver_Location_addBackend (location, backend_id, type, ev);
|
||||
}
|
||||
|
||||
static void
|
||||
do_remove_backend (ConfigArchiver_Location location, CORBA_Environment *ev)
|
||||
{
|
||||
ConfigArchiver_Location_removeBackend (location, backend_id, ev);
|
||||
}
|
||||
|
||||
static void
|
||||
do_garbage_collect (ConfigArchiver_Location location, CORBA_Environment *ev)
|
||||
{
|
||||
ConfigArchiver_Location_garbageCollect (location, ev);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
CORBA_ORB orb;
|
||||
ConfigArchiver_Archive archive;
|
||||
ConfigArchiver_Location location = CORBA_OBJECT_NIL;
|
||||
CORBA_Environment ev;
|
||||
|
||||
/* For Electric Fence */
|
||||
free (malloc (1));
|
||||
|
||||
bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
|
||||
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
|
||||
textdomain (GETTEXT_PACKAGE);
|
||||
|
||||
CORBA_exception_init (&ev);
|
||||
|
||||
gnomelib_register_popt_table (global_options,
|
||||
_("Global archiver options"));
|
||||
gnomelib_register_popt_table (archiver_operations,
|
||||
_("Archiver commands"));
|
||||
gnomelib_register_popt_table (store_options,
|
||||
_("Options for storing data"));
|
||||
gnomelib_register_popt_table (rollback_options,
|
||||
_("Options for rolling back"));
|
||||
gnomelib_register_popt_table (add_rename_location_options,
|
||||
_("Options for adding or renaming " \
|
||||
"locations"));
|
||||
gnomelib_register_popt_table (add_remove_backend_options,
|
||||
_("Options for adding and removing " \
|
||||
"backends"));
|
||||
|
||||
gtk_type_init ();
|
||||
gnomelib_init ("archiver", VERSION);
|
||||
gnomelib_parse_args (argc, argv, 0);
|
||||
|
||||
orb = oaf_init (argc, argv);
|
||||
|
||||
if (bonobo_init (orb, CORBA_OBJECT_NIL, CORBA_OBJECT_NIL) == FALSE)
|
||||
g_error ("Cannot initialize Bonobo");
|
||||
|
||||
if (global)
|
||||
archive = bonobo_get_object ("archive:global-archive", "IDL:ConfigArchiver/Archive:1.0", &ev);
|
||||
else
|
||||
archive = bonobo_get_object ("archive:user-archive", "IDL:ConfigArchiver/Archive:1.0", &ev);
|
||||
|
||||
if (archive == CORBA_OBJECT_NIL) {
|
||||
g_critical ("Could not open archive\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!add_location) {
|
||||
if (location_id == NULL)
|
||||
location_id = ConfigArchiver_Archive__get_currentLocationId (archive, &ev);
|
||||
|
||||
location = ConfigArchiver_Archive_getLocation (archive, location_id, &ev);
|
||||
|
||||
if (location == CORBA_OBJECT_NIL) {
|
||||
g_critical ("Error: Could not open location %s\n", location_id);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (store)
|
||||
do_store (location, &ev);
|
||||
else if (rollback)
|
||||
do_rollback (location, &ev);
|
||||
else if (change_location)
|
||||
do_change_location (archive, location, &ev);
|
||||
else if (rename_location)
|
||||
do_rename_location (archive, location, &ev);
|
||||
else if (add_location)
|
||||
do_add_location (archive, &ev);
|
||||
else if (remove_location)
|
||||
do_remove_location (location, &ev);
|
||||
else if (add_backend)
|
||||
do_add_backend (location, &ev);
|
||||
else if (remove_backend)
|
||||
do_remove_backend (location, &ev);
|
||||
else if (garbage_collect)
|
||||
do_garbage_collect (location, &ev);
|
||||
|
||||
bonobo_object_release_unref (archive, NULL);
|
||||
|
||||
if (location != CORBA_OBJECT_NIL)
|
||||
bonobo_object_release_unref (location, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,90 +0,0 @@
|
||||
/* -*- mode: c; style: linux -*- */
|
||||
|
||||
/* config-log.h
|
||||
* Copyright (C) 2000-2001 Ximian, Inc.
|
||||
*
|
||||
* Written by Bradford Hovinen (hovinen@ximian.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __CONFIG_LOG_H
|
||||
#define __CONFIG_LOG_H
|
||||
|
||||
#include <gnome.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
|
||||
#define CONFIG_LOG(obj) GTK_CHECK_CAST (obj, config_log_get_type (), ConfigLog)
|
||||
#define CONFIG_LOG_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, config_log_get_type (), ConfigLogClass)
|
||||
#define IS_CONFIG_LOG(obj) GTK_CHECK_TYPE (obj, config_log_get_type ())
|
||||
|
||||
typedef struct _ConfigLog ConfigLog;
|
||||
typedef struct _ConfigLogClass ConfigLogClass;
|
||||
typedef struct _ConfigLogPrivate ConfigLogPrivate;
|
||||
|
||||
typedef struct _Location Location;
|
||||
|
||||
typedef gint (*ConfigLogIteratorCB) (ConfigLog *, gint, gchar *,
|
||||
struct tm *, gpointer);
|
||||
typedef void (*GarbageCollectCB) (ConfigLog *, gchar *, gint, gpointer);
|
||||
|
||||
struct _ConfigLog
|
||||
{
|
||||
GtkObject object;
|
||||
|
||||
ConfigLogPrivate *p;
|
||||
};
|
||||
|
||||
struct _ConfigLogClass
|
||||
{
|
||||
GtkObjectClass parent;
|
||||
};
|
||||
|
||||
GType config_log_get_type (void);
|
||||
|
||||
GtkObject *config_log_open (Location *location);
|
||||
void config_log_delete (ConfigLog *config_log);
|
||||
|
||||
gint config_log_get_rollback_id_for_date (ConfigLog *config_log,
|
||||
struct tm *date,
|
||||
const gchar *backend_id);
|
||||
gint config_log_get_rollback_id_by_steps (ConfigLog *config_log,
|
||||
guint steps,
|
||||
const gchar *backend_id);
|
||||
|
||||
const gchar *config_log_get_backend_id_for_id (ConfigLog *config_log,
|
||||
gint id);
|
||||
const struct tm *config_log_get_date_for_id (ConfigLog *config_log,
|
||||
gint id);
|
||||
|
||||
gint config_log_write_entry (ConfigLog *config_log,
|
||||
const gchar *backend_id,
|
||||
gboolean is_default_data);
|
||||
|
||||
void config_log_iterate (ConfigLog *config_log,
|
||||
ConfigLogIteratorCB callback,
|
||||
gpointer data);
|
||||
|
||||
void config_log_reset_filenames (ConfigLog *config_log);
|
||||
void config_log_reload (ConfigLog *config_log);
|
||||
|
||||
void config_log_garbage_collect (ConfigLog *config_log,
|
||||
gchar *backend_id,
|
||||
GarbageCollectCB callback,
|
||||
gpointer data);
|
||||
|
||||
#endif /* __CONFIG_LOG */
|
||||
@@ -1,54 +0,0 @@
|
||||
/* -*- mode: c; style: linux -*- */
|
||||
|
||||
/* config-manager.c
|
||||
* Copyright (C) 2000-2001 Ximian, Inc.
|
||||
*
|
||||
* Written by Bradford Hovinen <hovinen@ximian.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <gnome.h>
|
||||
#include <glade/glade.h>
|
||||
|
||||
#include "config-manager-dialog.h"
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
GtkWidget *dialog;
|
||||
|
||||
bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
|
||||
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
|
||||
textdomain (GETTEXT_PACKAGE);
|
||||
|
||||
gnome_init ("config-manager", VERSION, argc, argv);
|
||||
glade_gnome_init ();
|
||||
|
||||
dialog = config_manager_dialog_new (CM_DIALOG_USER_ONLY);
|
||||
gtk_widget_show (dialog);
|
||||
|
||||
gtk_signal_connect (GTK_OBJECT (dialog), "destroy",
|
||||
gtk_main_quit, NULL);
|
||||
|
||||
gtk_main ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
CONFIG_ARCHIVER_LIBDIR="@CONFIG_ARCHIVER_LIBDIR@"
|
||||
CONFIG_ARCHIVER_LIBS="@CONFIG_ARCHIVER_LIBS@"
|
||||
CONFIG_ARCHIVER_INCLUDEDIR="@CONFIG_ARCHIVER_INCLUDEDIR@"
|
||||
MODULE_VERSION="config-archiver-@VERSION@"
|
||||
@@ -1,13 +0,0 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
|
||||
<location>
|
||||
<contains backend="boot-conf"/>
|
||||
<contains backend="disks-conf"/>
|
||||
<contains backend="memory-conf"/>
|
||||
<contains backend="network-conf"/>
|
||||
<contains backend="print-conf"/>
|
||||
<contains backend="shares-conf"/>
|
||||
<contains backend="time-conf"/>
|
||||
<contains backend="users-conf"/>
|
||||
<contains backend="display-conf"/>
|
||||
</location>
|
||||
@@ -1,10 +0,0 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
|
||||
<location>
|
||||
<contains backend="background-properties"/>
|
||||
<contains backend="bell-properties-capplet"/>
|
||||
<contains backend="sound-properties"/>
|
||||
<contains backend="keyboard-properties"/>
|
||||
<contains backend="mouse-properties"/>
|
||||
<contains backend="screensaver-properties-capplet"/>
|
||||
</location>
|
||||
@@ -1,95 +0,0 @@
|
||||
Changes to the Helix Configuration Manager
|
||||
Copyright (C) 2000 Ximian, Inc.
|
||||
Written by Bradford Hovinen <hovinen@ximian.com>
|
||||
|
||||
As it stands, capplets and Ximian Setup Tools are both run as separate
|
||||
processes through the exec() facility. It is planned that the capplets
|
||||
shall become Bonobo controls in the future, once the OAF/gnorba
|
||||
compatibility problems are worked out. This changes the design of the
|
||||
configuration system considerably, and several things should be done
|
||||
to take full advantage of these changes.
|
||||
|
||||
1. Capplets become Bonobo controls
|
||||
|
||||
It stands to reason that the front ends for Ximian Setup Tools should
|
||||
become Bonobo controls at the same time as capplets. They can each
|
||||
implement the same interface (say, Bonobo::Capplet) with methods
|
||||
getXML(), setXML(), ok(), cancel(), and init() and hence look the same
|
||||
to the shell. This means that the front ends for the Ximian Setup Tools
|
||||
run as the same user as XCM and respond in the same way as capplets do
|
||||
to requests to embed them in the XCM shell window. This is essential
|
||||
for a consistent user interface that will not result in end-user
|
||||
confusion [1]. XCM itself may then export an interface that includes
|
||||
the method runBackend(), to which the frontend supplies a stream of
|
||||
XML that XCM passes through the root manager to the backend via a
|
||||
standard pipe [2]. The backend is then responsible for running the
|
||||
program that archives the XML -- there is no other way to place that
|
||||
XML in a central, system-wide repository. I suggest, therefore, that
|
||||
we modify the design of the current system to make that change, so
|
||||
that we do not have to undo existing work later.
|
||||
|
||||
2. Backends get CORBA interfaces through Perl/ORBit
|
||||
|
||||
At this point, there must be a way for the root manager to forward
|
||||
CORBA sockets to the user securely. This could be done by modifying
|
||||
ORBit so as to give the running program very precise control over the
|
||||
nature of the socket. Access could be granted specifically to the user
|
||||
running the root manager by placing the socket in a directory owned by
|
||||
that user with permissions no more lax than 0700. When the CORBA
|
||||
interfaces are created, applications will be able to make use of it to
|
||||
make system-wide changes as necessary (say, to add a new user during
|
||||
the installation of a piece of software). This means that the
|
||||
traditional rollback facilities must be extended to allow users to
|
||||
roll back changes made by applications. In addition, the application
|
||||
must treat the backend as a black box -- it should never be expected
|
||||
to do anything unusual to support rollback, since buggy or
|
||||
poorly-written applications would otherwise cause trouble for
|
||||
unsuspecting users.
|
||||
|
||||
At this point I suggest that each backend export two interfaces: one
|
||||
that is universal to all backends and one that is specific to that
|
||||
particular tool. The former may include the methods getXML(),
|
||||
setXML(), and commit(). When changes are made through the
|
||||
tool-specific interface, the tool decides whether or not to apply
|
||||
those changes immediately or to queue them up until a commit() is
|
||||
invoked. If changes are made through the backend's CORBA interface and
|
||||
it is deactivated before a commit(), the backend must roll back those
|
||||
changes under the assumption that they are not intended to be
|
||||
permanent.
|
||||
|
||||
Of course, this makes implementation of the cancel() interface on the
|
||||
frontends very easy -- simply deactivate the backend without
|
||||
commit()ing. ok() can be implemented by flushing any remaining
|
||||
changes, calling commit(), and then deactivating the backend. The
|
||||
frontend can and should use the CORBA interface to invoke changes
|
||||
whenever they are made, as long as it makes sense. It is then the
|
||||
backend that sets the policy of whether or not the updates are live,
|
||||
as described above. The frontend must still be able to read XML,
|
||||
though, since it is through that that it will get an initial
|
||||
description of the setup with which to fill in the dialog. In
|
||||
addition, since the frontend may be invoked to make changes to an
|
||||
inactive location, it should be able to write out an XML description
|
||||
of the dialog's contents so that those changes may be archived rather
|
||||
than applied immediately.
|
||||
|
||||
Notes
|
||||
|
||||
[1] A visual cue that signals to the user that he is running a
|
||||
system-wide configuration tool rather than a personal one would be
|
||||
advantageous. Such could take the form of an icon on the dialog, a
|
||||
layout or formatting convention for the dialog proper, or some sort of
|
||||
coloring convention of some of the controls. However, simply having
|
||||
the tool run with root's Gtk+ theme and ignoring the embedding
|
||||
preference, as would be the case if we do not Bonobize the HST
|
||||
frontends, is inconsistent as many users will leave their themes as
|
||||
the default and elect not to embed capplets -- eliminating all visual
|
||||
cues. In addition, it is not particularly lucid and many users will
|
||||
merely be confused by the inconsistent interface. One may imagine many
|
||||
users filing bug reports in the belief that the behavior is
|
||||
erroneous. Hence, that solution is insufficient.
|
||||
|
||||
[2] There must then be a method of multiplexing I/O throught the root
|
||||
manager, as there may be multiple backends running concurrently. A
|
||||
simple protocol could be implemented to do this, or a named pipe could
|
||||
be created if done very carefully as to ensure a high degree of
|
||||
security.
|
||||
1889
archiver/location.c
@@ -1,144 +0,0 @@
|
||||
/* -*- mode: c; style: linux -*- */
|
||||
|
||||
/* location.h
|
||||
* Copyright (C) 2000-2001 Ximian, Inc.
|
||||
*
|
||||
* Written by Bradford Hovinen (hovinen@ximian.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __LOCATION_H
|
||||
#define __LOCATION_H
|
||||
|
||||
#include <gnome.h>
|
||||
#include <tree.h>
|
||||
#include <bonobo.h>
|
||||
|
||||
#include "ConfigArchiver.h"
|
||||
|
||||
#include "config-log.h"
|
||||
|
||||
#define LOCATION(obj) GTK_CHECK_CAST (obj, location_get_type (), Location)
|
||||
#define LOCATION_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, location_get_type (), LocationClass)
|
||||
#define IS_LOCATION(obj) GTK_CHECK_TYPE (obj, location_get_type ())
|
||||
|
||||
typedef struct _LocationClass LocationClass;
|
||||
typedef struct _LocationPrivate LocationPrivate;
|
||||
typedef struct _Archive Archive;
|
||||
|
||||
typedef ConfigArchiver_ContainmentType ContainmentType;
|
||||
typedef ConfigArchiver_StoreType StoreType;
|
||||
|
||||
typedef int (*LocationBackendCB) (Location *, gchar *, gpointer);
|
||||
|
||||
struct _Location
|
||||
{
|
||||
BonoboXObject object;
|
||||
|
||||
LocationPrivate *p;
|
||||
};
|
||||
|
||||
struct _LocationClass
|
||||
{
|
||||
BonoboXObjectClass parent;
|
||||
|
||||
POA_ConfigArchiver_Location__epv epv;
|
||||
|
||||
gboolean (*do_rollback) (Location *location,
|
||||
gchar *backend_id,
|
||||
xmlDocPtr xml_doc);
|
||||
};
|
||||
|
||||
GType location_get_type (void);
|
||||
|
||||
BonoboObject *location_new (Archive *archive,
|
||||
const gchar *locid,
|
||||
const gchar *label,
|
||||
Location *parent);
|
||||
BonoboObject *location_open (Archive *archive,
|
||||
const gchar *locid);
|
||||
|
||||
void location_delete (Location *location);
|
||||
|
||||
gchar *location_get_storage_filename (Location *location,
|
||||
const gchar *backend_id,
|
||||
gboolean is_default);
|
||||
gchar *location_get_rollback_filename (Location *location,
|
||||
struct tm *date,
|
||||
gint steps,
|
||||
const gchar *backend_id,
|
||||
gboolean parent_chain);
|
||||
|
||||
void location_storage_complete (Location *location,
|
||||
const gchar *filename);
|
||||
|
||||
gint location_store (Location *location,
|
||||
gchar *backend_id,
|
||||
FILE *input,
|
||||
ConfigArchiver_StoreType store_type);
|
||||
void location_store_xml (Location *location,
|
||||
gchar *backend_id,
|
||||
xmlDocPtr xml_doc,
|
||||
ConfigArchiver_StoreType store_type);
|
||||
|
||||
void location_rollback_backends_to (Location *location,
|
||||
struct tm *date,
|
||||
gint steps,
|
||||
GList *backends,
|
||||
gboolean parent_chain);
|
||||
|
||||
const struct tm *location_get_modification_time (Location *location,
|
||||
const gchar *backend_id);
|
||||
|
||||
ContainmentType location_contains (Location *location,
|
||||
const gchar *backend_id);
|
||||
gint location_add_backend (Location *location,
|
||||
const gchar *backend_id,
|
||||
ContainmentType type);
|
||||
void location_remove_backend (Location *location,
|
||||
const gchar *backend_id);
|
||||
|
||||
void location_foreach_backend (Location *location,
|
||||
LocationBackendCB callback,
|
||||
gpointer data);
|
||||
|
||||
GList *location_find_path_from_common_parent (Location *location,
|
||||
Location *location2);
|
||||
|
||||
Location *location_get_parent (Location *location);
|
||||
const gchar *location_get_path (Location *location);
|
||||
const gchar *location_get_label (Location *location);
|
||||
const gchar *location_get_id (Location *location);
|
||||
|
||||
void location_set_id (Location *location,
|
||||
const gchar *locid);
|
||||
|
||||
gint location_store_full_snapshot (Location *location);
|
||||
|
||||
GList *location_get_changed_backends (Location *location,
|
||||
Location *location1);
|
||||
gboolean location_does_backend_change (Location *location,
|
||||
Location *location1,
|
||||
const gchar *backend_id);
|
||||
|
||||
ConfigLog *location_get_config_log (Location *location);
|
||||
|
||||
void location_garbage_collect (Location *location);
|
||||
|
||||
gboolean location_is_deleted (const Location *location);
|
||||
|
||||
#endif /* __LOCATION */
|
||||
384
archiver/main.c
@@ -1,384 +0,0 @@
|
||||
/* -*- mode: c; style: linux -*- */
|
||||
|
||||
/* main.c
|
||||
* Copyright (C) 2000-2001 Ximian, Inc.
|
||||
*
|
||||
* Written by Bradford Hovinen (hovinen@ximian.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/file.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <gnome.h>
|
||||
|
||||
#include "util.h"
|
||||
#include "archive.h"
|
||||
|
||||
/* Variables resulting from command line parsing */
|
||||
|
||||
static gboolean store;
|
||||
static gboolean rollback;
|
||||
static gboolean change_location;
|
||||
static gboolean rename_location;
|
||||
static gboolean push_config;
|
||||
static gboolean garbage_collect;
|
||||
|
||||
static gboolean add_location;
|
||||
static gboolean remove_location;
|
||||
static gboolean add_backend;
|
||||
static gboolean remove_backend;
|
||||
|
||||
static gboolean global;
|
||||
static const gchar *location_id;
|
||||
|
||||
static gchar *backend_id;
|
||||
|
||||
static gboolean compare_parent;
|
||||
static gboolean mask_previous;
|
||||
|
||||
static gchar *date_str;
|
||||
static gboolean all;
|
||||
static gchar *revision_id;
|
||||
static gboolean last;
|
||||
static guint steps;
|
||||
static gboolean show;
|
||||
|
||||
static gchar *parent_str;
|
||||
static gchar *new_name;
|
||||
|
||||
static gboolean contain_full;
|
||||
static gboolean contain_partial;
|
||||
static gboolean master;
|
||||
|
||||
static struct poptOption archiver_operations[] = {
|
||||
{"store", 's', POPT_ARG_NONE, &store, 0,
|
||||
N_("Store XML data in the archive")},
|
||||
{"rollback", 'r', POPT_ARG_NONE, &rollback, 0,
|
||||
N_("Roll back the configuration to a given point")},
|
||||
{"change-location", 'c', POPT_ARG_NONE, &change_location, 0,
|
||||
N_("Change the location profile to the given one")},
|
||||
{"push-config", 'p', POPT_ARG_NONE, &push_config, 0,
|
||||
N_("Push configuration data out to client machines (UNIMPLEMENTED)")},
|
||||
{"rename-location", '\0', POPT_ARG_NONE, &rename_location, 0,
|
||||
N_("Rename a location to a new name")},
|
||||
{"add-location", '\0', POPT_ARG_NONE, &add_location, 0,
|
||||
N_("Add a new location to the archive")},
|
||||
{"remove-location", '\0', POPT_ARG_NONE, &remove_location, 0,
|
||||
N_("Remove a location from the archive")},
|
||||
{"add-backend", '\0', POPT_ARG_NONE, &add_backend, 0,
|
||||
N_("Add a given backend to the given location")},
|
||||
{"remove-backend", '\0', POPT_ARG_NONE, &remove_backend, 0,
|
||||
N_("Remove the given backend from the given location")},
|
||||
{"garbage-collect", '\0', POPT_ARG_NONE, &garbage_collect, 0,
|
||||
N_("Perform garbage collection on the given location")},
|
||||
{NULL, '\0', 0, NULL, 0}
|
||||
};
|
||||
|
||||
static struct poptOption global_options[] = {
|
||||
{"global", 'g', POPT_ARG_NONE, &global, 0,
|
||||
N_("Use the global repository")},
|
||||
{"location", 'l', POPT_ARG_STRING, &location_id, 0,
|
||||
N_("Identifier of location profile on which to operate"),
|
||||
N_("LOCATION")},
|
||||
{"backend", 'b', POPT_ARG_STRING, &backend_id, 0,
|
||||
N_("Backend being used for this operation"), N_("BACKEND_ID")},
|
||||
{NULL, '\0', 0, NULL, 0}
|
||||
};
|
||||
|
||||
static struct poptOption store_options[] = {
|
||||
{"compare-parent", '\0', POPT_ARG_NONE, &compare_parent, 0,
|
||||
N_("Store only the differences with the parent location's config")},
|
||||
{"mask-previous", '\0', POPT_ARG_NONE, &mask_previous, 0,
|
||||
N_("Store only those settings set in the previous config")},
|
||||
{NULL, '\0', 0, NULL, 0}
|
||||
};
|
||||
|
||||
static struct poptOption rollback_options[] = {
|
||||
{"date", 'd', POPT_ARG_STRING, &date_str, 0,
|
||||
N_("Date to which to roll back"), N_("DATE")},
|
||||
{"all", 'a', POPT_ARG_NONE, &all, 0,
|
||||
N_("Roll back all configuration items")},
|
||||
{"revision-id", 'i', POPT_ARG_INT, &revision_id, 0,
|
||||
N_("Roll back to the revision REVISION_ID"), N_("REVISION_ID")},
|
||||
{"last", 't', POPT_ARG_NONE, &last, 0,
|
||||
N_("Roll back to the last known revision")},
|
||||
{"steps", '\0', POPT_ARG_INT, &steps, 0,
|
||||
N_("Roll back by STEPS revisions"), N_("STEPS")},
|
||||
{"show", 'h', POPT_ARG_NONE, &show, 0,
|
||||
N_("Don't run the backend, just dump the output")},
|
||||
{NULL, '\0', 0, NULL, 0}
|
||||
};
|
||||
|
||||
static struct poptOption add_rename_location_options[] = {
|
||||
{"parent", '\0', POPT_ARG_STRING, &parent_str, 0,
|
||||
N_("Parent location for the new location"), N_("PARENT")},
|
||||
{"new-name", '\0', POPT_ARG_STRING, &new_name, 0,
|
||||
N_("New name to assign to the location"), N_("NEW_NAME")},
|
||||
{NULL, '\0', 0, NULL, 0}
|
||||
};
|
||||
|
||||
static struct poptOption add_remove_backend_options[] = {
|
||||
{"master", '\0', POPT_ARG_NONE, &master, 0,
|
||||
N_("Add/remove this backend to/from the master backend list")},
|
||||
{"full", '\0', POPT_ARG_NONE, &contain_full, 0,
|
||||
N_("Full containment")},
|
||||
{"partial", '\0', POPT_ARG_NONE, &contain_partial, 0,
|
||||
N_("Partial containment")},
|
||||
{NULL, '\0', 0, NULL, 0}
|
||||
};
|
||||
|
||||
static void
|
||||
do_store (Location *location)
|
||||
{
|
||||
StoreType type;
|
||||
|
||||
if (!backend_id) {
|
||||
fprintf (stderr, "No backend specified\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (mask_previous)
|
||||
type = STORE_MASK_PREVIOUS;
|
||||
else if (compare_parent)
|
||||
type = STORE_COMPARE_PARENT;
|
||||
else
|
||||
type = STORE_FULL;
|
||||
|
||||
location_store (location, backend_id, stdin, type);
|
||||
}
|
||||
|
||||
static void
|
||||
do_rollback (Location *location)
|
||||
{
|
||||
gint id;
|
||||
struct tm *date = NULL;
|
||||
|
||||
if (date_str)
|
||||
date = parse_date (date_str);
|
||||
else if (last || steps > 0)
|
||||
date = NULL;
|
||||
else if (!revision_id) {
|
||||
fprintf (stderr, "No date specified\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (all) {
|
||||
location_rollback_all_to (location, date, TRUE);
|
||||
}
|
||||
else if (backend_id && (date || last)) {
|
||||
/* FIXME: Need to support specifying multiple backends */
|
||||
if (show)
|
||||
location_dump_rollback_data (location, date, 0,
|
||||
backend_id, TRUE, stdout);
|
||||
else
|
||||
location_rollback_backend_to (location, date,
|
||||
backend_id, TRUE);
|
||||
}
|
||||
else if (backend_id && steps) {
|
||||
if (show)
|
||||
location_dump_rollback_data (location, NULL, steps,
|
||||
backend_id, TRUE, stdout);
|
||||
else
|
||||
location_rollback_backend_by (location, steps,
|
||||
backend_id, TRUE);
|
||||
}
|
||||
else if (revision_id) {
|
||||
sscanf (revision_id, "%x", &id);
|
||||
if (id >= 0)
|
||||
location_rollback_id (location, id);
|
||||
else
|
||||
fprintf (stderr, "Bad id specified\n");
|
||||
} else {
|
||||
g_message ("No backend specified\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
do_change_location (Archive *archive, Location *location)
|
||||
{
|
||||
archive_set_current_location (archive, location);
|
||||
}
|
||||
|
||||
static void
|
||||
do_rename_location (Archive *archive, Location *location)
|
||||
{
|
||||
gboolean is_current;
|
||||
|
||||
if (new_name == NULL) {
|
||||
fprintf (stderr,
|
||||
"You did not specify a new name. Try --help\n");
|
||||
} else {
|
||||
if (!strcmp (location_get_id (location),
|
||||
archive_get_current_location_id (archive)))
|
||||
is_current = TRUE;
|
||||
else
|
||||
is_current = FALSE;
|
||||
|
||||
location_set_id (location, new_name);
|
||||
|
||||
if (is_current)
|
||||
archive_set_current_location_id (archive, new_name);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
do_add_location (Archive *archive)
|
||||
{
|
||||
GtkObject *location;
|
||||
Location *parent_location = NULL;
|
||||
|
||||
if (location_id == NULL) {
|
||||
fprintf (stderr,
|
||||
"Error: You did not specify a location name\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (parent_str != NULL) {
|
||||
parent_location = archive_get_location (archive, parent_str);
|
||||
|
||||
if (parent_location == NULL && !strcmp (parent_str, "default"))
|
||||
parent_location =
|
||||
LOCATION
|
||||
(location_new (archive, "default", NULL));
|
||||
}
|
||||
|
||||
location = location_new (archive, location_id, parent_location);
|
||||
}
|
||||
|
||||
static void
|
||||
do_remove_location (Location *location)
|
||||
{
|
||||
location_delete (location);
|
||||
}
|
||||
|
||||
static void
|
||||
do_add_backend (Location *location)
|
||||
{
|
||||
ContainmentType type;
|
||||
|
||||
if (contain_full && contain_partial) {
|
||||
fprintf (stderr, "Error: Cannot have both full and partial "
|
||||
"containment\n");
|
||||
return;
|
||||
}
|
||||
else if (contain_partial) {
|
||||
type = CONTAIN_PARTIAL;
|
||||
} else {
|
||||
type = CONTAIN_FULL;
|
||||
}
|
||||
|
||||
location_add_backend (location, backend_id, type);
|
||||
}
|
||||
|
||||
static void
|
||||
do_remove_backend (Location *location)
|
||||
{
|
||||
location_remove_backend (location, backend_id);
|
||||
}
|
||||
|
||||
static void
|
||||
do_garbage_collect (Location *location)
|
||||
{
|
||||
location_garbage_collect (location);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
Archive *archive;
|
||||
Location *location = NULL;
|
||||
|
||||
/* For Electric Fence */
|
||||
free (malloc (1));
|
||||
|
||||
bindtextdomain (PACKAGE, GNOMELOCALEDIR);
|
||||
bind_textdomain_codeset (PACKAGE, "UTF-8");
|
||||
textdomain (PACKAGE);
|
||||
|
||||
gnomelib_register_popt_table (global_options,
|
||||
_("Global archiver options"));
|
||||
gnomelib_register_popt_table (archiver_operations,
|
||||
_("Archiver commands"));
|
||||
gnomelib_register_popt_table (store_options,
|
||||
_("Options for storing data"));
|
||||
gnomelib_register_popt_table (rollback_options,
|
||||
_("Options for rolling back"));
|
||||
gnomelib_register_popt_table (add_rename_location_options,
|
||||
_("Options for adding or renaming " \
|
||||
"locations"));
|
||||
gnomelib_register_popt_table (add_remove_backend_options,
|
||||
_("Options for adding and removing " \
|
||||
"backends"));
|
||||
|
||||
gtk_type_init ();
|
||||
gnomelib_init ("archiver", VERSION);
|
||||
gnomelib_parse_args (argc, argv, 0);
|
||||
|
||||
archive = ARCHIVE (archive_load (global));
|
||||
|
||||
if (archive == NULL) {
|
||||
fprintf (stderr, "Could not open archive\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!add_location) {
|
||||
if (location_id == NULL)
|
||||
location_id =
|
||||
archive_get_current_location_id (archive);
|
||||
|
||||
location = archive_get_location (archive, location_id);
|
||||
|
||||
if (location == NULL) {
|
||||
fprintf (stderr, "Error: Could not open location %s\n",
|
||||
location_id);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (store)
|
||||
do_store (location);
|
||||
else if (rollback)
|
||||
do_rollback (location);
|
||||
else if (change_location)
|
||||
do_change_location (archive, location);
|
||||
else if (rename_location)
|
||||
do_rename_location (archive, location);
|
||||
else if (add_location)
|
||||
do_add_location (archive);
|
||||
else if (remove_location)
|
||||
do_remove_location (location);
|
||||
else if (add_backend)
|
||||
do_add_backend (location);
|
||||
else if (remove_backend)
|
||||
do_remove_backend (location);
|
||||
else if (garbage_collect)
|
||||
do_garbage_collect (location);
|
||||
|
||||
archive_close (archive);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,125 +0,0 @@
|
||||
2004-10-14 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* Release 2.8.1
|
||||
|
||||
2004-04-15 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* Release 2.6.1
|
||||
|
||||
2004-04-01 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* Release 2.6.0.3
|
||||
|
||||
2004-03-30 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* Release 2.6.0.1
|
||||
|
||||
2004-03-23 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* Release 2.6.0
|
||||
|
||||
2004-03-11 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* Release 2.5.4
|
||||
|
||||
2004-02-13 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* Release 2.5.3
|
||||
|
||||
2004-01-14 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* Release 2.5.2
|
||||
|
||||
2003-12-30 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* Release 2.5.1.1
|
||||
|
||||
2003-12-30 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* Release 2.5.1
|
||||
|
||||
2003-10-28 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* Release 2.5.0
|
||||
|
||||
2003-07-07 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* Release 2.3.4
|
||||
|
||||
2003-06-24 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* Release 2.3.3
|
||||
|
||||
2003-05-07 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* Release 2.3.1
|
||||
|
||||
Tue Feb 4 17:09:18 2003 Jonathan Blandford <jrb@redhat.com>
|
||||
|
||||
* Release 2.2.0.1
|
||||
|
||||
Tue Jan 21 01:15:14 2003 Jonathan Blandford <jrb@gnome.org>
|
||||
|
||||
* Release 2.2.0
|
||||
|
||||
Thu Jan 16 02:41:09 2003 Jonathan Blandford <jrb@gnome.org>
|
||||
|
||||
* Release 2.1.7
|
||||
|
||||
2003-01-10 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* Release 2.1.6
|
||||
|
||||
2002-12-18 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* Release 2.1.5
|
||||
|
||||
2002-11-23 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* Release 2.1.3
|
||||
|
||||
2002-11-02 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* Release 2.1.2
|
||||
|
||||
2002-10-21 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* Release 2.1.1
|
||||
|
||||
2002-10-01 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* Release 2.1.0.1
|
||||
|
||||
2002-08-21 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* Release 2.1.0
|
||||
|
||||
2002-06-17 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* Release 2.0.0
|
||||
|
||||
2001-07-27 Bradford Hovinen <hovinen@ximian.com>
|
||||
|
||||
* RELEASE : 1.5.2
|
||||
|
||||
2001-07-20 Chema Celorio <chema@celorio.com>
|
||||
|
||||
* RELEASE : 1.5.0
|
||||
|
||||
2001-05-24 Arturo Espinosa Aldama <arturo@ximian.com>
|
||||
|
||||
* 0.5 RELEASE
|
||||
|
||||
2001-05-09 Arturo Espinosa Aldama <arturo@ximian.com>
|
||||
|
||||
* 0.4 RELEASE
|
||||
|
||||
2001-02-20 Bradford Hovinen <hovinen@ximian.com>
|
||||
|
||||
* test-3.sh: Created
|
||||
* test-2.sh: Removed parts dealing with partial containment
|
||||
|
||||
2001-02-19 Bradford Hovinen <hovinen@ximian.com>
|
||||
|
||||
* Added test-1.sh and test-2.sh, the first two tests in the test suite
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
This is a test suite for the archiver. It is designed to ease the pain
|
||||
of formulating the (rather complex) tests the check all the
|
||||
functionality of the archiver. Simply loading up the GUI and playing
|
||||
around with it is not enough, since one wrong move can destroy a
|
||||
person's configuration.
|
||||
|
||||
Tests: The test suite checks the following functionality:
|
||||
|
||||
1. On an account or machine where data have never been
|
||||
archived, the default location and archive are properly
|
||||
and automatically set up without user intervention.
|
||||
|
||||
2. Locations inheriting the default location are created
|
||||
and destroyed properly.
|
||||
|
||||
3. Backends can be added and removed from non-toplevel
|
||||
locations, with both full and partial containment. Any
|
||||
attempt to do so on a toplevel location results in an
|
||||
error.
|
||||
|
||||
4. Rollback data may be stored on both the base and derived
|
||||
locations. When stored in the derived location where the
|
||||
backend is marked with partial containment, the rollback
|
||||
data represent only the differences between the derived and
|
||||
parent configurations. The most recent configuration from
|
||||
the parent location is used for making this determination.
|
||||
|
||||
5. When rolling a backend back in a derived location, if the
|
||||
backend is not marked as contained in the derived location,
|
||||
the data are retrieved from the location's parent
|
||||
recursively. If the backend is marked as partially
|
||||
contained, then the XML data are merged with the parent's
|
||||
data.
|
||||
|
||||
6. Changing the current location correctly invokes the
|
||||
rollback algorithm
|
||||
|
||||
7. Rolling back by date and by number of steps works in a
|
||||
manner similar to the above.
|
||||
|
||||
8. Logs accurately represent the data archived.
|
||||
|
||||
9. Backends are invoked properly and data are sent to them
|
||||
properly.
|
||||
|
||||
10. All erroneous input should result in an error and not a
|
||||
crash. The program should return an appropriate error
|
||||
condition.
|
||||
@@ -1,187 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# test-1.sh
|
||||
# Copyright (C) 2001 Ximian, Inc.
|
||||
# Written by Bradford Hovinen <hovinen@ximian.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program 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 General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
# 02111-1307, USA.
|
||||
#
|
||||
# Test suite, part I
|
||||
#
|
||||
# Given an archive to work with (global or per-user):
|
||||
#
|
||||
# - Destroy the entire archive forcibly (rm -rf)
|
||||
# - Store backend data in the archive
|
||||
# - Check to see that a new archive has been created with default
|
||||
# location "Default", and that the data have been properly stored
|
||||
# there
|
||||
|
||||
XIMIAN_ARCHIVER=${XIMIAN_ARCHIVER:-'../ximian-archiver'}
|
||||
|
||||
function get_unused_tmpfile () {
|
||||
tmp_file_no=0
|
||||
|
||||
while [ -e "/tmp/$1-$tmp_file_no" ]; do
|
||||
let 'tmp_file_no=tmp_file_no+1'
|
||||
done
|
||||
|
||||
echo "/tmp/$1-$tmp_file_no";
|
||||
}
|
||||
|
||||
function run_command () {
|
||||
if [ "x$use_gdb" == "xyes" ]; then
|
||||
commands_file=`get_unused_tmpfile gdb-commands-file`
|
||||
echo "set args $extra_args $@" >$commands_file
|
||||
gdb ../.libs/lt-ximian-archiver -x $commands_file
|
||||
else
|
||||
echo "Running archiver program with the following command line:"
|
||||
echo $XIMIAN_ARCHIVER $extra_args $@
|
||||
$XIMIAN_ARCHIVER $extra_args $@
|
||||
echo
|
||||
fi
|
||||
}
|
||||
|
||||
if [ "x$1" == "x" ]; then
|
||||
echo "Usage: test-1.sh --global|--per-user [--gdb]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for test_option; do
|
||||
case "$test_option" in
|
||||
--global)
|
||||
extra_args="--global"
|
||||
archive_dir=/usr/share/ximian-config
|
||||
;;
|
||||
|
||||
--per-user)
|
||||
extra_args=""
|
||||
archive_dir=$HOME/.gnome/ximian-config
|
||||
;;
|
||||
|
||||
--gdb)
|
||||
use_gdb=yes
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "Usage: test-1.sh --global|--per-user [--gdb]"
|
||||
exit 1
|
||||
esac
|
||||
done
|
||||
|
||||
if [ -d $archive_dir ]; then
|
||||
mv $archive_dir "$archive_dir-backup"
|
||||
fi
|
||||
|
||||
##############################################################################
|
||||
# Test proper
|
||||
##############################################################################
|
||||
|
||||
archiver_test_data_file=`get_unused_tmpfile ximian-archiver-test-data`;
|
||||
|
||||
cat >$archiver_test_data_file <<EOF
|
||||
<?xml version="1.0"?>
|
||||
<background-properties>
|
||||
<bg-color1>#111128</bg-color1>
|
||||
<bg-color2>#796dff</bg-color2>
|
||||
<enabled/>
|
||||
<wallpaper/>
|
||||
<gradient/>
|
||||
<orientation>vertical</orientation>
|
||||
<wallpaper-type>0</wallpaper-type>
|
||||
<wallpaper-filename>/home/hovinen/media/Propaganda/Vol3/9a.jpg</wallpaper-filename>
|
||||
<wallpaper-sel-path>./</wallpaper-sel-path>
|
||||
<auto-apply/>
|
||||
<adjust-opacity/>
|
||||
<opacity>172</opacity>
|
||||
</background-properties>
|
||||
EOF
|
||||
|
||||
run_command --store --backend=background-properties-capplet \
|
||||
<$archiver_test_data_file
|
||||
|
||||
##############################################################################
|
||||
# Results check
|
||||
##############################################################################
|
||||
|
||||
echo -n "Checking whether default location was created properly..."
|
||||
|
||||
if [ -d "$archive_dir/default" ]; then
|
||||
echo "yes -- good"
|
||||
else
|
||||
echo "no -- error"
|
||||
fi
|
||||
|
||||
echo -n "Checking whether the XML data snapshot was created..."
|
||||
|
||||
if [ -f "$archive_dir/default/00000000.xml" ]; then
|
||||
echo "yes -- good"
|
||||
else
|
||||
echo "no -- error"
|
||||
fi
|
||||
|
||||
echo -n "Checking whether the XML data match the XML data given..."
|
||||
|
||||
differences_file=`get_unused_tmpfile differences`
|
||||
|
||||
diff -u $archive_dir/default/00000000.xml $archiver_test_data_file \
|
||||
>$differences_file
|
||||
|
||||
if [ ! -s $differences_file ]; then
|
||||
echo "yes -- good"
|
||||
else
|
||||
echo "no -- error"
|
||||
echo "Differences are as follows:"
|
||||
cat $differences_file
|
||||
echo
|
||||
fi
|
||||
|
||||
rm -f $differences_file
|
||||
|
||||
echo -n "Checking if the config log data are correct..."
|
||||
|
||||
config_log_id=`awk '{print $1}' $archive_dir/default/config.log`
|
||||
config_log_backend=`awk '{print $4}' $archive_dir/default/config.log`
|
||||
|
||||
if [ "x$config_log_id" == "x00000000" -a \
|
||||
"x$config_log_backend" == "xbackground-properties-capplet" ]; then
|
||||
echo "yes -- good"
|
||||
else
|
||||
echo "no -- error"
|
||||
echo "Config log is as follows:"
|
||||
cat $archive_dir/default/config.log
|
||||
echo
|
||||
fi
|
||||
|
||||
##############################################################################
|
||||
# Putting the results together
|
||||
##############################################################################
|
||||
|
||||
rm -f $archiver_test_data_file
|
||||
|
||||
results_dir="ximian-config-results-`date +%Y%m%d`"
|
||||
results_dir=`get_unused_tmpfile $results_dir`
|
||||
mkdir $results_dir
|
||||
|
||||
(cd $archive_dir && tar cf - *) | (cd $results_dir && tar xf -)
|
||||
rm -rf $archive_dir
|
||||
|
||||
if [ -d "$archive_dir-backup" ]; then
|
||||
mv "$archive_dir-backup" $archive_dir
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "Test complete"
|
||||
echo "Resulting archive data in $results_dir"
|
||||
@@ -1,219 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# test-2.sh
|
||||
# Copyright (C) 2001 Ximian, Inc.
|
||||
# Written by Bradford Hovinen <hovinen@ximian.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program 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 General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
# 02111-1307, USA.
|
||||
#
|
||||
# Test suite, part II
|
||||
#
|
||||
# Given an archive to work with (global or per-user):
|
||||
#
|
||||
# - Destroy the entire archive forcibly (rm -rf)
|
||||
# - Create a new location inheriting from the default location
|
||||
# (the default location should be created automatically in this case)
|
||||
# - Sets the new location as the current one
|
||||
# - Stores data for a backend not contained in the new location
|
||||
# (this should pass the data through to default)
|
||||
# - Adds a backend to the new location (full containment)
|
||||
# - Stores data for that backend in the new location
|
||||
|
||||
XIMIAN_ARCHIVER=${XIMIAN_ARCHIVER:-'../ximian-archiver'}
|
||||
|
||||
function get_unused_tmpfile () {
|
||||
tmp_file_no=0
|
||||
|
||||
while [ -e "/tmp/$1-$tmp_file_no" ]; do
|
||||
let 'tmp_file_no=tmp_file_no+1'
|
||||
done
|
||||
|
||||
echo "/tmp/$1-$tmp_file_no";
|
||||
}
|
||||
|
||||
function run_command () {
|
||||
input_param=$1
|
||||
shift
|
||||
|
||||
if [ "x$use_gdb" == "xyes" ]; then
|
||||
commands_file=`get_unused_tmpfile gdb-commands-file`
|
||||
echo "set args $extra_args $@ <$input_param" >$commands_file
|
||||
gdb ../.libs/ximian-archiver -x $commands_file
|
||||
rm -f $commands_file
|
||||
else
|
||||
echo "Running archiver program with the following command line:" >&2
|
||||
echo "$XIMIAN_ARCHIVER $extra_args $@ <$input_param" >&2
|
||||
$XIMIAN_ARCHIVER $extra_args $@ <$input_param
|
||||
echo
|
||||
fi
|
||||
}
|
||||
|
||||
if [ "x$1" == "x" ]; then
|
||||
echo "Usage: test-2.sh --global|--per-user [--gdb]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for test_option; do
|
||||
case "$test_option" in
|
||||
--global)
|
||||
extra_args="--global"
|
||||
archive_dir=/usr/share/ximian-config
|
||||
;;
|
||||
|
||||
--per-user)
|
||||
extra_args=""
|
||||
archive_dir=$HOME/.gnome/ximian-config
|
||||
;;
|
||||
|
||||
--gdb)
|
||||
use_gdb=yes
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "Error -- invalid option: $test_option"
|
||||
exit 1
|
||||
esac
|
||||
done
|
||||
|
||||
if [ -d $archive_dir ]; then
|
||||
mv $archive_dir "$archive_dir-backup"
|
||||
fi
|
||||
|
||||
##############################################################################
|
||||
# Test proper
|
||||
##############################################################################
|
||||
|
||||
# Test 1: Creating a new location
|
||||
|
||||
run_command /dev/null --add-location --parent=default --location=Boston-Office
|
||||
run_command /dev/null --change-location --location=Boston-Office
|
||||
|
||||
# Test 2: Storing data that should "pass through" to the parent
|
||||
|
||||
archiver_test_data_file1=`get_unused_tmpfile ximian-archiver-test-data`;
|
||||
|
||||
cat >$archiver_test_data_file1 <<EOF
|
||||
<?xml version="1.0"?>
|
||||
<background-properties>
|
||||
<bg-color1>#111128</bg-color1>
|
||||
<bg-color2>#796dff</bg-color2>
|
||||
<enabled/>
|
||||
<wallpaper/>
|
||||
<gradient/>
|
||||
<orientation>vertical</orientation>
|
||||
<wallpaper-type>0</wallpaper-type>
|
||||
<wallpaper-filename>/home/hovinen/media/Propaganda/Vol3/9a.jpg</wallpaper-filename>
|
||||
<wallpaper-sel-path>./</wallpaper-sel-path>
|
||||
<auto-apply/>
|
||||
<adjust-opacity/>
|
||||
<opacity>172</opacity>
|
||||
</background-properties>
|
||||
|
||||
EOF
|
||||
|
||||
run_command $archiver_test_data_file1 \
|
||||
--store --backend=background-properties-capplet
|
||||
|
||||
# Test 3: Adding a backend (full containment) and storing data that
|
||||
# should be stored in the child location
|
||||
|
||||
run_command /dev/null --add-backend --full \
|
||||
--backend=keyboard-properties-capplet
|
||||
|
||||
archiver_test_data_file2=`get_unused_tmpfile ximian-archiver-test-data`;
|
||||
|
||||
cat >$archiver_test_data_file2 <<EOF
|
||||
<?xml version="1.0"?>
|
||||
<keyboard-properties>
|
||||
<rate>255</rate>
|
||||
<delay>0</delay>
|
||||
<repeat/>
|
||||
<volume>0</volume>
|
||||
</keyboard-properties>
|
||||
|
||||
EOF
|
||||
|
||||
run_command $archiver_test_data_file2 \
|
||||
--store --backend=keyboard-properties-capplet
|
||||
|
||||
# Test 5: Retrieve the background properties data previously stored
|
||||
# and compare it with the data we have here to see if everything is ok
|
||||
|
||||
archiver_test_data_file3=`get_unused_tmpfile ximian-archiver-test-data`
|
||||
|
||||
run_command /dev/null --rollback --show --last \
|
||||
--backend=background-properties-capplet \
|
||||
>$archiver_test_data_file3
|
||||
|
||||
##############################################################################
|
||||
# Results check
|
||||
##############################################################################
|
||||
|
||||
echo -n "Checking whether default location was created properly..."
|
||||
|
||||
if [ -d "$archive_dir/default" ]; then
|
||||
echo "yes -- good"
|
||||
else
|
||||
echo "no -- error"
|
||||
fi
|
||||
|
||||
echo -n "Checking whether derived location was created properly..."
|
||||
|
||||
if [ -d "$archive_dir/Boston-Office" ]; then
|
||||
echo "yes -- good"
|
||||
else
|
||||
echo "no -- error"
|
||||
fi
|
||||
|
||||
echo -n "Checking whether the XML data retrieved match the XML data given..."
|
||||
|
||||
differences_file=`get_unused_tmpfile differences`
|
||||
|
||||
diff -u $archiver_test_data_file3 $archiver_test_data_file1 >$differences_file
|
||||
|
||||
if [ ! -s $differences_file ]; then
|
||||
echo "yes -- good"
|
||||
else
|
||||
echo "no -- error"
|
||||
echo "Differences are as follows:"
|
||||
cat $differences_file
|
||||
echo
|
||||
fi
|
||||
|
||||
rm -f $differences_file
|
||||
|
||||
##############################################################################
|
||||
# Putting the results together
|
||||
##############################################################################
|
||||
|
||||
rm -f $archiver_test_data_file1
|
||||
rm -f $archiver_test_data_file2
|
||||
rm -f $archiver_test_data_file3
|
||||
|
||||
results_dir="ximian-config-results-`date +%Y%m%d`"
|
||||
results_dir=`get_unused_tmpfile $results_dir`
|
||||
mkdir $results_dir
|
||||
|
||||
(cd $archive_dir && tar cf - *) | (cd $results_dir && tar xf -)
|
||||
rm -rf $archive_dir
|
||||
|
||||
if [ -d "$archive_dir-backup" ]; then
|
||||
mv "$archive_dir-backup" $archive_dir
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "Test complete"
|
||||
echo "Resulting archive data in $results_dir"
|
||||
@@ -1,245 +0,0 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# test-3.sh
|
||||
# Copyright (C) 2001 Ximian, Inc.
|
||||
# Written by Bradford Hovinen <hovinen@ximian.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program 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 General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
# 02111-1307, USA.
|
||||
#
|
||||
# Test suite, part III
|
||||
#
|
||||
# Given an archive to work with (global or per-user):
|
||||
#
|
||||
# - Destroy the entire archive forcibly (rm -rf)
|
||||
# - Create a new location inheriting from the default location
|
||||
# (the default location should be created automatically in this case)
|
||||
# - Sets the new location as the current one
|
||||
# - Stores data for a particular backend, so that it should pass
|
||||
# through to the parent location
|
||||
# - Adds that backend to the new location (partial containment)
|
||||
# - Stores data for that backend in the new location, so that the
|
||||
# nodes should be subtracted
|
||||
# - Retrieves the data for that backend from the new location, so
|
||||
# that the nodes should be merged
|
||||
|
||||
XIMIAN_ARCHIVER=${XIMIAN_ARCHIVER:-'../ximian-archiver'}
|
||||
|
||||
function get_unused_tmpfile () {
|
||||
tmp_file_no=0
|
||||
|
||||
while [ -e "/tmp/$1-$tmp_file_no" ]; do
|
||||
let 'tmp_file_no=tmp_file_no+1'
|
||||
done
|
||||
|
||||
echo "/tmp/$1-$tmp_file_no";
|
||||
}
|
||||
|
||||
function run_command () {
|
||||
input_param=$1
|
||||
shift
|
||||
|
||||
if [ "x$use_gdb" == "xyes" ]; then
|
||||
commands_file=`get_unused_tmpfile gdb-commands-file`
|
||||
echo "set args $extra_args $@ <$input_param" >$commands_file
|
||||
gdb ../.libs/ximian-archiver -x $commands_file
|
||||
rm -f $commands_file
|
||||
else
|
||||
echo "Running archiver program with the following command line:" >&2
|
||||
echo "$XIMIAN_ARCHIVER $extra_args $@ <$input_param" >&2
|
||||
$XIMIAN_ARCHIVER $extra_args $@ <$input_param
|
||||
echo
|
||||
fi
|
||||
}
|
||||
|
||||
if [ "x$1" == "x" ]; then
|
||||
echo "Usage: test-2.sh --global|--per-user [--gdb]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for test_option; do
|
||||
case "$test_option" in
|
||||
--global)
|
||||
extra_args="--global"
|
||||
archive_dir=/usr/share/ximian-config
|
||||
;;
|
||||
|
||||
--per-user)
|
||||
extra_args=""
|
||||
archive_dir=$HOME/.gnome/ximian-config
|
||||
;;
|
||||
|
||||
--gdb)
|
||||
use_gdb=yes
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "Error -- invalid option: $test_option"
|
||||
exit 1
|
||||
esac
|
||||
done
|
||||
|
||||
if [ -d $archive_dir ]; then
|
||||
mv $archive_dir "$archive_dir-backup"
|
||||
fi
|
||||
|
||||
##############################################################################
|
||||
# Test proper
|
||||
##############################################################################
|
||||
|
||||
run_command /dev/null --add-location --parent=default --location=Boston-Office
|
||||
run_command /dev/null --change-location --location=Boston-Office
|
||||
|
||||
# Test 1: Adding a backend (partial containment) and storing data that
|
||||
# should be stored in the child location
|
||||
#
|
||||
# Note: These are not real data
|
||||
|
||||
archiver_test_data_file1=`get_unused_tmpfile ximian-archiver-test-data`;
|
||||
|
||||
cat >$archiver_test_data_file1 <<EOF
|
||||
<?xml version="1.0"?>
|
||||
<mouse-properties>
|
||||
<acceleration>7</acceleration>
|
||||
<threshold>1</threshold>
|
||||
<fake-node id="1">
|
||||
<another-node>data</another-node>
|
||||
</fake-node>
|
||||
<fake-node id="2">
|
||||
<my-node>blah blah blah</my-node>
|
||||
<another-node>more data</another-node>
|
||||
</fake-node>
|
||||
</mouse-properties>
|
||||
|
||||
EOF
|
||||
|
||||
run_command $archiver_test_data_file1 \
|
||||
--store --backend=mouse-properties-capplet
|
||||
|
||||
run_command /dev/null --add-backend --partial \
|
||||
--backend=mouse-properties-capplet
|
||||
|
||||
archiver_test_data_file2=`get_unused_tmpfile ximian-archiver-test-data`;
|
||||
|
||||
cat >$archiver_test_data_file2 <<EOF
|
||||
<?xml version="1.0"?>
|
||||
<mouse-properties>
|
||||
<acceleration>7</acceleration>
|
||||
<threshold>3</threshold>
|
||||
<fake-node id="1">
|
||||
<another-node>data</another-node>
|
||||
</fake-node>
|
||||
<fake-node id="2">
|
||||
<my-node>blah blah blah</my-node>
|
||||
<another-node>different data</another-node>
|
||||
</fake-node>
|
||||
</mouse-properties>
|
||||
|
||||
EOF
|
||||
|
||||
run_command $archiver_test_data_file2 \
|
||||
--store --backend=mouse-properties-capplet --compare-parent
|
||||
|
||||
# This should be the resulting file:
|
||||
|
||||
archiver_test_data_file2_correct=`get_unused_tmpfile ximian-archiver-check`;
|
||||
|
||||
cat >$archiver_test_data_file2_correct <<EOF
|
||||
<?xml version="1.0"?>
|
||||
<mouse-properties>
|
||||
<threshold>3</threshold>
|
||||
<fake-node id="2">
|
||||
<another-node>different data</another-node>
|
||||
</fake-node>
|
||||
</mouse-properties>
|
||||
EOF
|
||||
|
||||
# Test 2: Retrieve the mouse properties data from the location manager
|
||||
# to see if node merging works properly
|
||||
|
||||
archiver_test_data_file3=`get_unused_tmpfile ximian-archiver-test-data`
|
||||
|
||||
run_command /dev/null --rollback --last --show \
|
||||
--backend=mouse-properties-capplet >$archiver_test_data_file3
|
||||
|
||||
##############################################################################
|
||||
# Results check
|
||||
##############################################################################
|
||||
|
||||
echo -n "Checking whether the XML data match the XML data given..."
|
||||
|
||||
differences_file=`get_unused_tmpfile differences`
|
||||
|
||||
diff -u "$archive_dir/Boston-Office/00000000.xml" \
|
||||
$archiver_test_data_file2_correct \
|
||||
>$differences_file
|
||||
|
||||
if [ ! -s $differences_file ]; then
|
||||
echo "yes -- good"
|
||||
else
|
||||
echo "no -- error"
|
||||
echo "Differences are as follows:"
|
||||
cat $differences_file
|
||||
echo
|
||||
fi
|
||||
|
||||
rm -f $differences_file
|
||||
|
||||
echo -n "Checking whether the XML data retrieved match the XML data given..."
|
||||
|
||||
differences_file=`get_unused_tmpfile differences`
|
||||
|
||||
diff -u $archiver_test_data_file3 $archiver_test_data_file2 >$differences_file
|
||||
|
||||
if [ ! -s $differences_file ]; then
|
||||
echo "yes -- good"
|
||||
else
|
||||
echo "no -- error"
|
||||
echo "Check manually to see whether this is correct. Nodes may be"
|
||||
echo "out of order."
|
||||
echo "File retrieved is as follows:"
|
||||
cat $archiver_test_data_file3
|
||||
echo
|
||||
echo "File is supposed to be as follows:"
|
||||
cat $archiver_test_data_file2
|
||||
echo
|
||||
fi
|
||||
|
||||
rm -f $differences_file
|
||||
|
||||
##############################################################################
|
||||
# Putting the results together
|
||||
##############################################################################
|
||||
|
||||
rm -f $archiver_test_data_file1
|
||||
rm -f $archiver_test_data_file2
|
||||
rm -f $archiver_test_data_file3
|
||||
rm -f $archiver_test_data_file4
|
||||
rm -f $archiver_test_data_file5
|
||||
|
||||
results_dir="ximian-config-results-`date +%Y%m%d`"
|
||||
results_dir=`get_unused_tmpfile $results_dir`
|
||||
mkdir $results_dir
|
||||
|
||||
(cd $archive_dir && tar cf - *) | (cd $results_dir && tar xf -)
|
||||
rm -rf $archive_dir
|
||||
|
||||
if [ -d "$archive_dir-backup" ]; then
|
||||
mv "$archive_dir-backup" $archive_dir
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "Test complete"
|
||||
echo "Resulting archive data in $results_dir"
|
||||
113
archiver/util.c
@@ -1,113 +0,0 @@
|
||||
/* -*- mode: c; style: linux -*- */
|
||||
|
||||
/* util.c
|
||||
* Copyright (C) 2000-2001 Ximian, Inc.
|
||||
*
|
||||
* Written by Bradford Hovinen (hovinen@ximian.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "util.h"
|
||||
|
||||
/* Read a fixed-digit number from a string, advancing the string
|
||||
* pointer. Return TRUE if the extraction was successful, FALSE if
|
||||
* there was no number to extract or if the number was too short.
|
||||
*/
|
||||
|
||||
gboolean
|
||||
extract_number (char **str, int *number, int digits)
|
||||
{
|
||||
char buf[64];
|
||||
|
||||
if (!isdigit (**str)) return FALSE;
|
||||
if (digits > 63) digits = 63;
|
||||
|
||||
strncpy (buf, *str, digits);
|
||||
buf[digits] = '\0';
|
||||
*number = atoi (buf);
|
||||
if (strlen (buf) < digits) return FALSE;
|
||||
*str += digits;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
struct tm *
|
||||
parse_date (char *str)
|
||||
{
|
||||
struct tm *date;
|
||||
gboolean ok;
|
||||
gint value;
|
||||
|
||||
ok = extract_number (&str, &value, 4);
|
||||
if (!ok) return NULL;
|
||||
|
||||
date = g_new (struct tm, 1);
|
||||
date->tm_isdst = 0;
|
||||
date->tm_year = value - 1900;
|
||||
date->tm_mon = 11;
|
||||
date->tm_mday = 31;
|
||||
date->tm_hour = 23;
|
||||
date->tm_min = 59;
|
||||
date->tm_sec = 59;
|
||||
|
||||
if (extract_number (&str, &value, 2))
|
||||
date->tm_mon = value - 1;
|
||||
else
|
||||
return date;
|
||||
|
||||
if (extract_number (&str, &value, 2))
|
||||
date->tm_mday = value;
|
||||
else
|
||||
return date;
|
||||
|
||||
if (extract_number (&str, &value, 2))
|
||||
date->tm_hour = value;
|
||||
else
|
||||
return date;
|
||||
|
||||
if (extract_number (&str, &value, 2))
|
||||
date->tm_min = value;
|
||||
else
|
||||
return date;
|
||||
|
||||
if (extract_number (&str, &value, 2))
|
||||
date->tm_sec = value;
|
||||
|
||||
#ifdef __USE_BSD
|
||||
date->tm_zone = "GMT";
|
||||
date->tm_gmtoff = 0;
|
||||
#endif
|
||||
|
||||
return date;
|
||||
}
|
||||
|
||||
struct tm *
|
||||
dup_date (const struct tm *date)
|
||||
{
|
||||
struct tm *date1;
|
||||
|
||||
date1 = g_new (struct tm, 1);
|
||||
memcpy (date1, date, sizeof (struct tm));
|
||||
return date1;
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
/* -*- mode: c; style: linux -*- */
|
||||
|
||||
/* util.h
|
||||
* Copyright (C) 2000-2001 Ximian, Inc.
|
||||
*
|
||||
* Written by Bradford Hovinen (hovinen@ximian.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __UTIL_H
|
||||
#define __UTIL_H
|
||||
|
||||
#include <time.h>
|
||||
#include <glib.h>
|
||||
|
||||
/* Uncomment this if you want debugs: */
|
||||
#define DEBUG_ME_MORE
|
||||
|
||||
#ifdef DEBUG_ME_MORE
|
||||
# ifdef __GNUC__
|
||||
# define DEBUG_MSG(str, args...) \
|
||||
g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, "(%d:%s) " str, \
|
||||
getpid (), __FUNCTION__ , ## args)
|
||||
# else
|
||||
# define DEBUG_MSG(str, args...)
|
||||
# endif
|
||||
#else
|
||||
/* This was redefined here because it was messing with the frontend->backend
|
||||
* talk. Arturo */
|
||||
# define DEBUG_MSG(str, args...)
|
||||
#endif
|
||||
|
||||
gboolean extract_number (char **str, int *number, int digits);
|
||||
struct tm *parse_date (char *str);
|
||||
struct tm *dup_date (const struct tm *date);
|
||||
|
||||
#endif /* __UTIL_H */
|
||||
@@ -1,193 +0,0 @@
|
||||
Configuration rollback, location management, and cluster support
|
||||
Copyright (C) 2001 Ximian, Inc.
|
||||
Written by Bradford Hovinen <hovinen@ximian.com>
|
||||
|
||||
I. Basic architecture
|
||||
|
||||
A. Components
|
||||
|
||||
1. Ximian Configuration Manager
|
||||
|
||||
The GUI shell, here referred to as the Ximian Configuration Manager
|
||||
(XCM), acts as launching point for the capplets and Ximian Tools,
|
||||
and a control center for managing rollback, location management, and
|
||||
clustering. It launches other components and knows how to find
|
||||
archived configuration data for rollback. When rollback or a change of
|
||||
location is required, it invokes the required backends or capplets
|
||||
with the --set option and feeds the required XML to them.
|
||||
|
||||
2. Capplets
|
||||
|
||||
Capplets handle user configuration; they combine the front and back
|
||||
ends into one process. They will eventually run as Bonobo controls
|
||||
implementing the Bonobo::Capplet interface, but for now they are run
|
||||
as regular processes. They all support the --get and --set command
|
||||
line options (which will be methods in the Bonobo::Capplet
|
||||
interface). --get returns an XML description of the capplet's state
|
||||
for archival purposes and --set takes an XML description of the
|
||||
capplet's state and applies those settings to the desktop.
|
||||
|
||||
3. Ximian Setup Tools (XSTs)
|
||||
|
||||
These programs are for system-wide configuration and must run as root
|
||||
in order to apply changes. They may also run as a regular user in
|
||||
`read-only' mode. They have separate front- and backends, the former
|
||||
typically written in C and the latter normally written in Perl. This
|
||||
facilitates in-place modification of existing configuration files
|
||||
without the need for creating out own separate, incompatible way of
|
||||
configuring the system. The backends support the --get and --set
|
||||
arguments, analogous to the arguments in capplets mentioned above.
|
||||
|
||||
2. Root manager
|
||||
|
||||
The root manager process runs as root and is launched through
|
||||
gnome-su. It accepts on stdin a set of programs to launch, one per
|
||||
line, with command line arguments. XCM uses it to launch Ximian Setup
|
||||
Tools so that they run as root, without needing to ask the user for a
|
||||
password each time a tool is run. The root manager is run exactly once
|
||||
through console-helper the first time a tool that must be run as root
|
||||
is invoked. On subsequent occasions the command to start the tool is
|
||||
passed to the root manager through stdin.
|
||||
|
||||
3. The script do-changes
|
||||
|
||||
do-changes is responsible for archiving changes made to the system's
|
||||
configuration and passing them on to the backend, if appropriate. It
|
||||
accepts a stream of XML on stdin and stores this XML in the
|
||||
configuration archive directory. If a backend is specified on the
|
||||
command line, it also spawns the backend process with the --set option
|
||||
and feeds the XML to it through stdin.
|
||||
|
||||
II. Configuration process
|
||||
|
||||
When a user makes changes to either his own configuration or that of
|
||||
the system, those changes must be archived so that the system may be
|
||||
rolled back in the future. In the case of capplets, the capplet
|
||||
currently dumps an XML snapshot of its current state to the script
|
||||
do-changes when the user clicks `Ok'. do-changes then archives the
|
||||
state in ~/.gnome/config/<location>/<revision> where <location> is the
|
||||
name of the active location (cf. section IV) and <revision> is
|
||||
incremented after each change.
|
||||
|
||||
When the capplets are converted into Bonobo controls, the situation
|
||||
will be slightly different. XCM will be the recipient of the `Ok'
|
||||
signal, so it will invoke the OKClicked() method of the
|
||||
Bonobo::Capplet interface on the appropriate capplet. It will also
|
||||
invoke the GetXML() method of the same interface in order to retrieve
|
||||
an XML snapshot of the state and store that snapshot with
|
||||
do-changes. Hence, much of the action moves from the capplet to XCM.
|
||||
|
||||
In the case of Ximian Setup Tools, the frontend passes the XML through
|
||||
the do-changes script to the backend whenever the `Ok' button is
|
||||
clicked. It passes to do-changes the argument --backend <backend name>
|
||||
so that do-changes will also invoke the indicated backend and pass the
|
||||
XML to it.
|
||||
|
||||
III. Rollback process
|
||||
|
||||
From within the XCM, the user may elect to roll back either his
|
||||
personal configuration or that of the system to a particular
|
||||
date. XCM looks for a revision directory in the current location
|
||||
profile with the most recent modification date that is not more recent
|
||||
than the date specified by the user. XCM also has a list of what
|
||||
capplets (or XSTs) constitute a complete snapshot of the system's
|
||||
configuration. In order to perform a complete rollback, it backtracks
|
||||
through the revision directories, picking up XML snapshots of capplets
|
||||
until it has a complete set and applies them through the --set
|
||||
method. In the case of XSTs, the XCM knows how to invoke the backend
|
||||
and does so as necessary.
|
||||
|
||||
IV. Location management
|
||||
|
||||
The system may have one or more profiles, each giving different system
|
||||
configurations. For example, a user may own a laptop and wish to hook
|
||||
that laptop up to different networks at different times. Each network
|
||||
may be located in a different time zone, have different network
|
||||
configuration parameters (e.g., DHCP vs. static IPs), and use different
|
||||
default printers. When the user hooks his laptop up in a particular
|
||||
network, it would be advantageous to switch to that network's
|
||||
configuration with a minimum of hassle.
|
||||
|
||||
As mentioned above, configuration data is stored in separate
|
||||
directories corresponding to the name of a given location. XCM has the
|
||||
ability to apply a set of configuration files from a given location in
|
||||
a manner similar to the rollback procedure described above. When the
|
||||
user selects an alternative configuration, it simply goes through the
|
||||
revision history for that location, pulls a complete set of
|
||||
configuration files, and applies them. The procedure is similar for
|
||||
both capplets and XSTs.
|
||||
|
||||
In addition, locations may be expressed hierarchically. For example, a
|
||||
user might specify a location called `Boston' that describes language,
|
||||
time zone, currency, and other locale data, and another location called
|
||||
`Boston Office' that includes network parameters. `Boston Office'
|
||||
inherits its locale data from `Boston', overriding the latter's
|
||||
network configuration.
|
||||
|
||||
To implement this, each location directory contains some metadata that
|
||||
describes what configuration data is valid for it and what other
|
||||
configuration it inherits from. There are one or more root
|
||||
configurations that contain a complete set of data. When applying a
|
||||
new location, XCM looks first at that location's directory, pulling a
|
||||
complete set of all the configuration data defined by that location,
|
||||
and then goes to the next level up in the location hierarchy and does
|
||||
the same thing. It also keeps track of the common subtree root between
|
||||
the old and new locations so that only the configuration items that
|
||||
actually change are collected.
|
||||
|
||||
From a user's perspective, the XCM will present a tree showing the
|
||||
existing locations. Users may create a new location derived from an
|
||||
existing one. When the user elects to configure a particular location,
|
||||
the XCM shell includes icons that are grayed out, indicating that
|
||||
those configuration items are not set in this particular location. If
|
||||
the user attempts to change them, they become specific to that
|
||||
particular location and are recolored accordingly.
|
||||
|
||||
V. Clustering
|
||||
|
||||
A single server may archive the configuration for a large number of
|
||||
individual workstations, providing configuration data to each of the
|
||||
clients on demand. An administrator can then push configuration
|
||||
updates out to each machine with the press of a button, rather than
|
||||
having to go to each machine and update it manually.
|
||||
|
||||
To enable this, each client machine will run a daemon that accepts
|
||||
configuration data pushed out by the server. Some sort of public key
|
||||
signing will be implemented to ensure that this is done securely. On
|
||||
the server end, a series of host groups is maintained, each one
|
||||
containing a set of hosts. These form the top two levels of a
|
||||
configuration hierarchy not unlike what is described above. Each host
|
||||
may override certain configuration values for the cluster as a
|
||||
whole. The cluster may also have multiple `locations', e.g. for
|
||||
configuring a computer lab for computer science during one class and
|
||||
for math during another. Locations may be selected down to the
|
||||
granularity of a single host, or for the entire cluster at
|
||||
once. Cluster-wide configurations occur between the cluster and host
|
||||
level in the configuration hierarchy.
|
||||
|
||||
VI. Issues
|
||||
|
||||
1. We need a way to get an XML state without actually applying
|
||||
changes, so that the user can configure a location without switching
|
||||
to it.
|
||||
|
||||
2. Can we make the XST frontends Bonobo controls, and can we have them
|
||||
run as the regular user rather than as root? This would ensure that
|
||||
certain user interface preferences, such as themes, are kept
|
||||
consistent for a given user between capplets and XSTs. The way to
|
||||
implement this is to have a method on the XCM interface called
|
||||
RunBackend() which returns a BonoboObject referring to the backend
|
||||
that implements the Bonobo::XSTBackend interface, which is similar to
|
||||
the Bonobo::Capplet interface mentioned above. The interface defines
|
||||
the GetXML and SetXML methods. The object should also implement
|
||||
another, XST-specific interface to facilitate setting specific
|
||||
configuration variables, so that live update may be implemented. The
|
||||
root manager must then be extended to support some sort of secure
|
||||
forwarding, allowing the user to access that particular CORBA object.
|
||||
|
||||
3. If we make the XSTs into Bonobo controls, can we give them the same
|
||||
Bonobo::Capplet interface that is given to the Capplets? This would
|
||||
make everything a bit simpler from the XCM's perspective, since it
|
||||
then does not need to know the difference between Capplets and
|
||||
XSTs -- it then only needs to implement the RunBackend() method for
|
||||
the benefit of the XSTs.
|
||||
27
autogen.sh
@@ -1,27 +0,0 @@
|
||||
#!/bin/sh
|
||||
# Run this to generate all the initial makefiles, etc.
|
||||
|
||||
srcdir=`dirname $0`
|
||||
test -z "$srcdir" && srcdir=.
|
||||
|
||||
PKG_NAME="control-center"
|
||||
|
||||
(test -f $srcdir/configure.in \
|
||||
&& test -f $srcdir/autogen.sh \
|
||||
&& test -d $srcdir/control-center) || {
|
||||
echo -n "**Error**: Directory "\`$srcdir\'" does not look like the"
|
||||
echo " top-level $PKG_NAME directory"
|
||||
exit 1
|
||||
}
|
||||
|
||||
DIE=0
|
||||
|
||||
rm -f .using-gnome-libs-package
|
||||
|
||||
if ! which gnome-autogen.sh ; then
|
||||
echo "You need to install the gnome-common module and make"
|
||||
echo "sure the gnome-autogen.sh script is in your \$PATH."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
REQUIRED_AUTOMAKE_VERSION=1.7 . gnome-autogen.sh
|
||||
@@ -1,2 +0,0 @@
|
||||
Makefile.in
|
||||
Makefile
|
||||
@@ -1,17 +0,0 @@
|
||||
always_built_SUBDIRS = \
|
||||
common accessibility \
|
||||
default-applications font \
|
||||
background keyboard mouse sound \
|
||||
theme-switcher ui-properties \
|
||||
keybindings network windows
|
||||
|
||||
if HAVE_RANDR
|
||||
randr_SUBDIRS = display
|
||||
else
|
||||
randr_SUBDIRS =
|
||||
endif
|
||||
|
||||
SUBDIRS = $(always_built_SUBDIRS) $(randr_SUBDIRS)
|
||||
|
||||
DIST_SUBDIRS = \
|
||||
$(always_built_SUBDIRS) display
|
||||
@@ -1,2 +0,0 @@
|
||||
Diego Gonzalez Gonzalez <diego@pemas.net>
|
||||
Chris Toshok <toshok@ximian.com>
|
||||
@@ -1,22 +0,0 @@
|
||||
2005-05-16 Olav Vitters <olav@bkor.dhs.org>
|
||||
|
||||
* gnome-about-me.glade: Remove garbage text. Patch by Benjamin
|
||||
LeMasurier. Fixes bug #162492.
|
||||
|
||||
2005-04-01 Diego Gonzalez <diego@pemas.net>
|
||||
|
||||
* gnome-about-me.c: fix the case where the self uid is wrong
|
||||
and the edition when the self contact is created for the
|
||||
first time.
|
||||
|
||||
2005-03-29 Diego Gonzalez <diego@pemas.net>
|
||||
|
||||
* Makefile.am: fix tabs
|
||||
|
||||
2005-02-09 Sebastien Bacher <seb128@debian.org>
|
||||
|
||||
* Makefile.am: build e-util-marshal.c.
|
||||
|
||||
2004-12-23 Sebastien Bacher <seb128@debian.org>
|
||||
|
||||
* gnome-about-me.glade: fixed a typo (Closes: #162094).
|
||||
@@ -1,38 +0,0 @@
|
||||
bin_PROGRAMS = gnome-about-me
|
||||
|
||||
pixmapdir = $(GNOMECC_PIXMAPS_DIR)
|
||||
pixmap_DATA = \
|
||||
gnome-about-me.png
|
||||
|
||||
gnome_about_me_LDADD = $(GNOMECC_CAPPLETS_LIBS) $(LIBEBOOK_LIBS) -lutil
|
||||
gnome_about_me_SOURCES = \
|
||||
e-util-marshal.c \
|
||||
e-util-marshal.h \
|
||||
gnome-about-me-password.c \
|
||||
e-image-chooser.c \
|
||||
gnome-about-me.c
|
||||
|
||||
e-util-marshal.h: e-util-marshal.list
|
||||
( @GLIB_GENMARSHAL@ --prefix=e_util_marshal $(srcdir)/e-util-marshal.list \
|
||||
--header > util-marshal.tmp \
|
||||
&& mv util-marshal.tmp e-util-marshal.h ) \
|
||||
|| ( rm -f util-marshal.tmp && exit 1 )
|
||||
|
||||
e-util-marshal.c: e-util-marshal.h
|
||||
( @GLIB_GENMARSHAL@ --prefix=e_util_marshal $(srcdir)/e-util-marshal.list \
|
||||
--body > util-marshal.tmp \
|
||||
&& mv util-marshal.tmp e-util-marshal.c ) \
|
||||
|| ( rm -f util-marshal.tmp && exit 1 )
|
||||
|
||||
@INTLTOOL_DESKTOP_RULE@
|
||||
|
||||
desktopdir = $(datadir)/applications
|
||||
Desktop_in_files = gnome-about-me.desktop.in
|
||||
desktop_DATA = $(Desktop_in_files:.desktop.in=.desktop)
|
||||
|
||||
Gladedir = $(GNOMECC_GLADE_DIR)
|
||||
Glade_DATA = gnome-about-me.glade
|
||||
|
||||
INCLUDES = $(GNOMECC_CAPPLETS_CFLAGS) $(LIBEBOOK_CFLAGS)
|
||||
CLEANFILES = $(GNOMECC_CAPPLETS_CLEANFILES)
|
||||
EXTRA_DIST = e-util-marshal.list $(Glade_DATA) $(Desktop_in_files) $(pixmap_DATA)
|
||||
@@ -1,522 +0,0 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/* e-image-chooser.c
|
||||
* Copyright (C) 2004 Novell, Inc.
|
||||
* Author: Chris Toshok <toshok@ximian.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2 of the GNU General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU 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.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
#include <gtk/gtkalignment.h>
|
||||
#include <gtk/gtkframe.h>
|
||||
#include <gtk/gtkimage.h>
|
||||
#include <gtk/gtkbutton.h>
|
||||
#include <gtk/gtkdnd.h>
|
||||
|
||||
#include <libgnomevfs/gnome-vfs-ops.h>
|
||||
|
||||
#include "e-image-chooser.h"
|
||||
#include "e-util-marshal.h"
|
||||
|
||||
struct _EImageChooserPrivate {
|
||||
|
||||
GtkWidget *frame;
|
||||
GtkWidget *image;
|
||||
GtkWidget *browse_button;
|
||||
|
||||
char *image_buf;
|
||||
int image_buf_size;
|
||||
int image_width;
|
||||
int image_height;
|
||||
|
||||
gboolean editable;
|
||||
};
|
||||
|
||||
enum {
|
||||
CHANGED,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
|
||||
static gint image_chooser_signals [LAST_SIGNAL] = { 0 };
|
||||
|
||||
static void e_image_chooser_init (EImageChooser *chooser);
|
||||
static void e_image_chooser_class_init (EImageChooserClass *klass);
|
||||
#if 0
|
||||
static void e_image_chooser_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);
|
||||
static void e_image_chooser_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec);
|
||||
#endif
|
||||
static void e_image_chooser_dispose (GObject *object);
|
||||
|
||||
static gboolean image_drag_motion_cb (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
gint x, gint y, guint time, EImageChooser *chooser);
|
||||
static void image_drag_leave_cb (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
guint time, EImageChooser *chooser);
|
||||
static gboolean image_drag_drop_cb (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
gint x, gint y, guint time, EImageChooser *chooser);
|
||||
static void image_drag_data_received_cb (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
gint x, gint y,
|
||||
GtkSelectionData *selection_data,
|
||||
guint info, guint time, EImageChooser *chooser);
|
||||
|
||||
static GtkObjectClass *parent_class = NULL;
|
||||
#define PARENT_TYPE GTK_TYPE_VBOX
|
||||
|
||||
enum DndTargetType {
|
||||
DND_TARGET_TYPE_URI_LIST
|
||||
};
|
||||
#define URI_LIST_TYPE "text/uri-list"
|
||||
|
||||
static GtkTargetEntry image_drag_types[] = {
|
||||
{ URI_LIST_TYPE, 0, DND_TARGET_TYPE_URI_LIST },
|
||||
};
|
||||
static const int num_image_drag_types = sizeof (image_drag_types) / sizeof (image_drag_types[0]);
|
||||
|
||||
GtkWidget *
|
||||
e_image_chooser_new (void)
|
||||
{
|
||||
return g_object_new (E_TYPE_IMAGE_CHOOSER, NULL);
|
||||
}
|
||||
|
||||
GType
|
||||
e_image_chooser_get_type (void)
|
||||
{
|
||||
static GType eic_type = 0;
|
||||
|
||||
if (!eic_type) {
|
||||
static const GTypeInfo eic_info = {
|
||||
sizeof (EImageChooserClass),
|
||||
NULL, /* base_init */
|
||||
NULL, /* base_finalize */
|
||||
(GClassInitFunc) e_image_chooser_class_init,
|
||||
NULL, /* class_finalize */
|
||||
NULL, /* class_data */
|
||||
sizeof (EImageChooser),
|
||||
0, /* n_preallocs */
|
||||
(GInstanceInitFunc) e_image_chooser_init,
|
||||
};
|
||||
|
||||
eic_type = g_type_register_static (PARENT_TYPE, "EImageChooser", &eic_info, 0);
|
||||
}
|
||||
|
||||
return eic_type;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
e_image_chooser_class_init (EImageChooserClass *klass)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
parent_class = g_type_class_ref (PARENT_TYPE);
|
||||
|
||||
image_chooser_signals [CHANGED] =
|
||||
g_signal_new ("changed",
|
||||
G_OBJECT_CLASS_TYPE (object_class),
|
||||
G_SIGNAL_RUN_FIRST,
|
||||
G_STRUCT_OFFSET (EImageChooserClass, changed),
|
||||
NULL, NULL,
|
||||
e_util_marshal_NONE__NONE,
|
||||
GTK_TYPE_NONE, 0);
|
||||
|
||||
/*
|
||||
object_class->set_property = e_image_chooser_set_property;
|
||||
object_class->get_property = e_image_chooser_get_property;
|
||||
*/
|
||||
object_class->dispose = e_image_chooser_dispose;
|
||||
}
|
||||
|
||||
#if UI_CHANGE_OK
|
||||
static void
|
||||
browse_for_image_cb (GtkWidget *button, gpointer data)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
e_image_chooser_init (EImageChooser *chooser)
|
||||
{
|
||||
EImageChooserPrivate *priv;
|
||||
GtkWidget *alignment;
|
||||
|
||||
priv = chooser->priv = g_new0 (EImageChooserPrivate, 1);
|
||||
|
||||
alignment = gtk_alignment_new (0, 0, 0, 0);
|
||||
priv->frame = gtk_frame_new ("");
|
||||
priv->image = gtk_image_new ();
|
||||
|
||||
gtk_container_add (GTK_CONTAINER (alignment), priv->image);
|
||||
|
||||
#if UI_CHANGE_OK
|
||||
priv->browse_button = gtk_button_new_with_label (_("Choose Image"));
|
||||
#endif
|
||||
|
||||
gtk_frame_set_shadow_type (GTK_FRAME (priv->frame), GTK_SHADOW_NONE);
|
||||
|
||||
gtk_container_add (GTK_CONTAINER (priv->frame), alignment);
|
||||
gtk_box_set_homogeneous (GTK_BOX (chooser), FALSE);
|
||||
gtk_box_pack_start (GTK_BOX (chooser), priv->frame, TRUE, TRUE, 0);
|
||||
#if UI_CHANGE_OK
|
||||
gtk_box_pack_start (GTK_BOX (chooser), priv->browse_button, FALSE, FALSE, 0);
|
||||
|
||||
g_signal_connect (priv->browse_button, "clicked", G_CALLBACK (browse_for_image_cb), NULL);
|
||||
#endif
|
||||
|
||||
gtk_drag_dest_set (priv->image, 0, image_drag_types, num_image_drag_types, GDK_ACTION_COPY);
|
||||
g_signal_connect (priv->image,
|
||||
"drag_motion", G_CALLBACK (image_drag_motion_cb), chooser);
|
||||
g_signal_connect (priv->image,
|
||||
"drag_leave", G_CALLBACK (image_drag_leave_cb), chooser);
|
||||
g_signal_connect (priv->image,
|
||||
"drag_drop", G_CALLBACK (image_drag_drop_cb), chooser);
|
||||
g_signal_connect (priv->image,
|
||||
"drag_data_received", G_CALLBACK (image_drag_data_received_cb), chooser);
|
||||
|
||||
gtk_widget_show_all (priv->frame);
|
||||
#if UI_CHANGE_OK
|
||||
gtk_widget_show (priv->browse_button);
|
||||
#endif
|
||||
|
||||
/* we default to being editable */
|
||||
priv->editable = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
e_image_chooser_dispose (GObject *object)
|
||||
{
|
||||
EImageChooser *eic = E_IMAGE_CHOOSER (object);
|
||||
|
||||
if (eic->priv) {
|
||||
EImageChooserPrivate *priv = eic->priv;
|
||||
|
||||
if (priv->image_buf) {
|
||||
g_free (priv->image_buf);
|
||||
priv->image_buf = NULL;
|
||||
}
|
||||
|
||||
g_free (eic->priv);
|
||||
eic->priv = NULL;
|
||||
}
|
||||
|
||||
if (G_OBJECT_CLASS (parent_class)->dispose)
|
||||
(* G_OBJECT_CLASS (parent_class)->dispose) (object);
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
set_image_from_data (EImageChooser *chooser,
|
||||
char *data, int length)
|
||||
{
|
||||
gboolean rv = FALSE;
|
||||
GdkPixbufLoader *loader = gdk_pixbuf_loader_new ();
|
||||
GdkPixbuf *pixbuf;
|
||||
|
||||
gdk_pixbuf_loader_write (loader, data, length, NULL);
|
||||
|
||||
pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
|
||||
if (pixbuf)
|
||||
gdk_pixbuf_ref (pixbuf);
|
||||
gdk_pixbuf_loader_close (loader, NULL);
|
||||
g_object_unref (loader);
|
||||
|
||||
if (pixbuf) {
|
||||
GdkPixbuf *scaled;
|
||||
GdkPixbuf *composite;
|
||||
|
||||
float scale;
|
||||
int new_height, new_width;
|
||||
|
||||
new_height = gdk_pixbuf_get_height (pixbuf);
|
||||
new_width = gdk_pixbuf_get_width (pixbuf);
|
||||
|
||||
if (chooser->priv->image_height == 0
|
||||
&& chooser->priv->image_width == 0) {
|
||||
scale = 1.0;
|
||||
}
|
||||
else if (chooser->priv->image_height < new_height
|
||||
|| chooser->priv->image_width < new_width) {
|
||||
/* we need to scale down */
|
||||
if (new_height > new_width)
|
||||
scale = (float)chooser->priv->image_height / new_height;
|
||||
else
|
||||
scale = (float)chooser->priv->image_width / new_width;
|
||||
}
|
||||
else {
|
||||
/* we need to scale up */
|
||||
printf ("we need to scale up\n");
|
||||
if (new_height > new_width)
|
||||
scale = (float)new_height / chooser->priv->image_height;
|
||||
else
|
||||
scale = (float)new_width / chooser->priv->image_width;
|
||||
}
|
||||
|
||||
if (scale == 1.0) {
|
||||
gtk_image_set_from_pixbuf (GTK_IMAGE (chooser->priv->image), pixbuf);
|
||||
|
||||
chooser->priv->image_width = new_width;
|
||||
chooser->priv->image_height = new_height;
|
||||
}
|
||||
else {
|
||||
new_width *= scale;
|
||||
new_height *= scale;
|
||||
new_width = MIN (new_width, chooser->priv->image_width);
|
||||
new_height = MIN (new_height, chooser->priv->image_height);
|
||||
|
||||
scaled = gdk_pixbuf_scale_simple (pixbuf,
|
||||
new_width, new_height,
|
||||
GDK_INTERP_BILINEAR);
|
||||
|
||||
composite = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, gdk_pixbuf_get_bits_per_sample (pixbuf),
|
||||
chooser->priv->image_width, chooser->priv->image_height);
|
||||
|
||||
gdk_pixbuf_fill (composite, 0x00000000);
|
||||
|
||||
gdk_pixbuf_copy_area (scaled, 0, 0, new_width, new_height,
|
||||
composite,
|
||||
chooser->priv->image_width / 2 - new_width / 2,
|
||||
chooser->priv->image_height / 2 - new_height / 2);
|
||||
|
||||
gtk_image_set_from_pixbuf (GTK_IMAGE (chooser->priv->image), composite);
|
||||
gdk_pixbuf_unref (scaled);
|
||||
gdk_pixbuf_unref (composite);
|
||||
}
|
||||
|
||||
gdk_pixbuf_unref (pixbuf);
|
||||
|
||||
g_free (chooser->priv->image_buf);
|
||||
chooser->priv->image_buf = data;
|
||||
chooser->priv->image_buf_size = length;
|
||||
|
||||
g_signal_emit (chooser,
|
||||
image_chooser_signals [CHANGED], 0);
|
||||
|
||||
rv = TRUE;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
image_drag_motion_cb (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
gint x, gint y, guint time, EImageChooser *chooser)
|
||||
{
|
||||
GList *p;
|
||||
|
||||
if (!chooser->priv->editable)
|
||||
return FALSE;
|
||||
|
||||
for (p = context->targets; p != NULL; p = p->next) {
|
||||
char *possible_type;
|
||||
|
||||
possible_type = gdk_atom_name (GDK_POINTER_TO_ATOM (p->data));
|
||||
if (!strcmp (possible_type, URI_LIST_TYPE)) {
|
||||
g_free (possible_type);
|
||||
gdk_drag_status (context, GDK_ACTION_COPY, time);
|
||||
gtk_frame_set_shadow_type (GTK_FRAME (chooser->priv->frame), GTK_SHADOW_IN);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
g_free (possible_type);
|
||||
}
|
||||
|
||||
gtk_frame_set_shadow_type (GTK_FRAME (chooser->priv->frame), GTK_SHADOW_NONE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
image_drag_leave_cb (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
guint time, EImageChooser *chooser)
|
||||
{
|
||||
gtk_frame_set_shadow_type (GTK_FRAME (chooser->priv->frame), GTK_SHADOW_NONE);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
image_drag_drop_cb (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
gint x, gint y, guint time, EImageChooser *chooser)
|
||||
{
|
||||
GList *p;
|
||||
|
||||
if (!chooser->priv->editable)
|
||||
return FALSE;
|
||||
|
||||
if (context->targets == NULL) {
|
||||
gtk_frame_set_shadow_type (GTK_FRAME (chooser->priv->frame), GTK_SHADOW_NONE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
for (p = context->targets; p != NULL; p = p->next) {
|
||||
char *possible_type;
|
||||
|
||||
possible_type = gdk_atom_name (GDK_POINTER_TO_ATOM (p->data));
|
||||
if (!strcmp (possible_type, URI_LIST_TYPE)) {
|
||||
g_free (possible_type);
|
||||
gtk_drag_get_data (widget, context,
|
||||
GDK_POINTER_TO_ATOM (p->data),
|
||||
time);
|
||||
gtk_frame_set_shadow_type (GTK_FRAME (chooser->priv->frame), GTK_SHADOW_NONE);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
g_free (possible_type);
|
||||
}
|
||||
|
||||
gtk_frame_set_shadow_type (GTK_FRAME (chooser->priv->frame), GTK_SHADOW_NONE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
image_drag_data_received_cb (GtkWidget *widget,
|
||||
GdkDragContext *context,
|
||||
gint x, gint y,
|
||||
GtkSelectionData *selection_data,
|
||||
guint info, guint time, EImageChooser *chooser)
|
||||
{
|
||||
char *target_type;
|
||||
gboolean handled = FALSE;
|
||||
|
||||
target_type = gdk_atom_name (selection_data->target);
|
||||
|
||||
if (!strcmp (target_type, URI_LIST_TYPE)) {
|
||||
GnomeVFSResult result;
|
||||
GnomeVFSHandle *handle;
|
||||
char *uri;
|
||||
char *nl = strstr (selection_data->data, "\r\n");
|
||||
char *buf = NULL;
|
||||
GnomeVFSFileInfo info;
|
||||
|
||||
if (nl)
|
||||
uri = g_strndup (selection_data->data, nl - (char*)selection_data->data);
|
||||
else
|
||||
uri = g_strdup (selection_data->data);
|
||||
|
||||
printf ("uri == %s\n", uri);
|
||||
|
||||
result = gnome_vfs_open (&handle, uri, GNOME_VFS_OPEN_READ);
|
||||
if (result == GNOME_VFS_OK) {
|
||||
result = gnome_vfs_get_file_info_from_handle (handle, &info, GNOME_VFS_FILE_INFO_DEFAULT);
|
||||
if (result == GNOME_VFS_OK) {
|
||||
GnomeVFSFileSize num_left;
|
||||
GnomeVFSFileSize num_read;
|
||||
GnomeVFSFileSize total_read;
|
||||
|
||||
printf ("file size = %d\n", (int)info.size);
|
||||
buf = g_malloc (info.size);
|
||||
|
||||
num_left = info.size;
|
||||
total_read = 0;
|
||||
|
||||
while ((result = gnome_vfs_read (handle, buf + total_read, num_left, &num_read)) == GNOME_VFS_OK) {
|
||||
num_left -= num_read;
|
||||
total_read += num_read;
|
||||
}
|
||||
|
||||
printf ("read %d bytes\n", (int)total_read);
|
||||
if (set_image_from_data (chooser, buf, total_read)) {
|
||||
handled = TRUE;
|
||||
}
|
||||
else {
|
||||
/* XXX we should pop up a warning dialog here */
|
||||
g_free (buf);
|
||||
}
|
||||
}
|
||||
|
||||
gnome_vfs_close (handle);
|
||||
}
|
||||
else {
|
||||
printf ("gnome_vfs_open failed (%s)\n", gnome_vfs_result_to_string (result));
|
||||
}
|
||||
|
||||
g_free (uri);
|
||||
}
|
||||
|
||||
gtk_drag_finish (context, handled, FALSE, time);
|
||||
}
|
||||
|
||||
|
||||
|
||||
gboolean
|
||||
e_image_chooser_set_from_file (EImageChooser *chooser, const char *filename)
|
||||
{
|
||||
gchar *data;
|
||||
gsize data_length;
|
||||
|
||||
g_return_val_if_fail (E_IS_IMAGE_CHOOSER (chooser), FALSE);
|
||||
g_return_val_if_fail (filename, FALSE);
|
||||
|
||||
if (!g_file_get_contents (filename, &data, &data_length, NULL)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!set_image_from_data (chooser, data, data_length))
|
||||
g_free (data);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
e_image_chooser_set_editable (EImageChooser *chooser, gboolean editable)
|
||||
{
|
||||
g_return_if_fail (E_IS_IMAGE_CHOOSER (chooser));
|
||||
|
||||
chooser->priv->editable = editable;
|
||||
|
||||
gtk_widget_set_sensitive (chooser->priv->browse_button, editable);
|
||||
}
|
||||
|
||||
gboolean
|
||||
e_image_chooser_get_image_data (EImageChooser *chooser, char **data, gsize *data_length)
|
||||
{
|
||||
g_return_val_if_fail (E_IS_IMAGE_CHOOSER (chooser), FALSE);
|
||||
g_return_val_if_fail (data != NULL, FALSE);
|
||||
g_return_val_if_fail (data_length != NULL, FALSE);
|
||||
|
||||
*data_length = chooser->priv->image_buf_size;
|
||||
*data = g_malloc (*data_length);
|
||||
memcpy (*data, chooser->priv->image_buf, *data_length);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
e_image_chooser_set_image_data (EImageChooser *chooser, char *data, gsize data_length)
|
||||
{
|
||||
char *buf;
|
||||
|
||||
g_return_val_if_fail (E_IS_IMAGE_CHOOSER (chooser), FALSE);
|
||||
g_return_val_if_fail (data != NULL, FALSE);
|
||||
|
||||
/* yuck, a copy... */
|
||||
buf = g_malloc (data_length);
|
||||
memcpy (buf, data, data_length);
|
||||
|
||||
if (!set_image_from_data (chooser, buf, data_length)) {
|
||||
g_free (buf);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
|
||||
/* e-image-chooser.c
|
||||
* Copyright (C) 2004 Novell, Inc.
|
||||
* Author: Chris Toshok <toshok@ximian.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of version 2 of the GNU General Public
|
||||
* License as published by the Free Software Foundation.
|
||||
*
|
||||
* This program 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
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU 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 _E_IMAGE_CHOOSER_H_
|
||||
#define _E_IMAGE_CHOOSER_H_
|
||||
|
||||
#include <gtk/gtkvbox.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define E_TYPE_IMAGE_CHOOSER (e_image_chooser_get_type ())
|
||||
#define E_IMAGE_CHOOSER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_IMAGE_CHOOSER, EImageChooser))
|
||||
#define E_IMAGE_CHOOSER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_IMAGE_CHOOSER, EImageChooserClass))
|
||||
#define E_IS_IMAGE_CHOOSER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_IMAGE_CHOOSER))
|
||||
#define E_IS_IMAGE_CHOOSER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), E_TYPE_IMAGE_CHOOSER))
|
||||
|
||||
typedef struct _EImageChooser EImageChooser;
|
||||
typedef struct _EImageChooserClass EImageChooserClass;
|
||||
typedef struct _EImageChooserPrivate EImageChooserPrivate;
|
||||
|
||||
struct _EImageChooser
|
||||
{
|
||||
GtkVBox parent;
|
||||
|
||||
EImageChooserPrivate *priv;
|
||||
};
|
||||
|
||||
struct _EImageChooserClass
|
||||
{
|
||||
GtkVBoxClass parent_class;
|
||||
|
||||
/* signals */
|
||||
void (*changed) (EImageChooser *chooser);
|
||||
|
||||
|
||||
};
|
||||
|
||||
GtkWidget *e_image_chooser_new (void);
|
||||
GType e_image_chooser_get_type (void);
|
||||
|
||||
gboolean e_image_chooser_set_from_file (EImageChooser *chooser, const char *filename);
|
||||
gboolean e_image_chooser_set_image_data (EImageChooser *chooser, char *data, gsize data_length);
|
||||
void e_image_chooser_set_editable (EImageChooser *chooser, gboolean editable);
|
||||
|
||||
gboolean e_image_chooser_get_image_data (EImageChooser *chooser, char **data, gsize *data_length);
|
||||
|
||||
#endif /* _E_IMAGE_CHOOSER_H_ */
|
||||
@@ -1,3 +0,0 @@
|
||||
NONE:NONE
|
||||
NONE:INT
|
||||
NONE:POINTER
|
||||
@@ -1,333 +0,0 @@
|
||||
/* gnome-about-me.c
|
||||
* Copyright (C) 2002 Diego Gonzalez
|
||||
*
|
||||
* Written by: Diego Gonzalez <diego@pemas.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*
|
||||
* Parts of this code come from Gnome-System-Tools.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <gnome.h>
|
||||
#include <pwd.h>
|
||||
#include <glade/glade.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/wait.h>
|
||||
#include <termios.h>
|
||||
#include <pty.h>
|
||||
|
||||
#include "capplet-util.h"
|
||||
|
||||
typedef struct {
|
||||
GtkWidget *dialog;
|
||||
GtkWidget *old_password;
|
||||
GtkWidget *new_password;
|
||||
GtkWidget *retyped_password;
|
||||
|
||||
/* Communication with the passwd program */
|
||||
FILE *backend_stream;
|
||||
int backend_master_fd;
|
||||
int backend_pid;
|
||||
guint timeout_id;
|
||||
} PasswordDialog;
|
||||
|
||||
enum
|
||||
{
|
||||
RESPONSE_APPLY = 1,
|
||||
RESPONSE_CLOSE
|
||||
};
|
||||
|
||||
static void passdlg_set_busy (PasswordDialog *dlg, gboolean busy);
|
||||
|
||||
#define REDRAW_NCHARS 1
|
||||
|
||||
static gboolean
|
||||
wait_child (PasswordDialog *pdialog)
|
||||
{
|
||||
GtkWidget *dialog;
|
||||
gint status, pid;
|
||||
gchar *primary_text = NULL;
|
||||
gchar *secondary_text = NULL;
|
||||
|
||||
pid = waitpid (pdialog->backend_pid, &status, WNOHANG);
|
||||
|
||||
if (pid > 0) {
|
||||
|
||||
if (WIFEXITED (status) && (WEXITSTATUS(status) == 0)) {
|
||||
passdlg_set_busy (pdialog, FALSE);
|
||||
primary_text = g_strdup (_("Password changed successfully"));
|
||||
|
||||
dialog = gtk_message_dialog_new (NULL, GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
GTK_MESSAGE_INFO,
|
||||
GTK_BUTTONS_CLOSE,
|
||||
primary_text, secondary_text);
|
||||
g_signal_connect (G_OBJECT (dialog), "response",
|
||||
G_CALLBACK (gtk_widget_destroy), NULL);
|
||||
gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
|
||||
gtk_widget_show (dialog);
|
||||
|
||||
return FALSE;
|
||||
} else if ((WIFEXITED (status)) && (WEXITSTATUS (status)) && (WEXITSTATUS(status) < 255)) {
|
||||
/* the proccess was running su */
|
||||
primary_text = g_strdup (_("The entered password is invalid"));
|
||||
secondary_text = g_strdup (_("Check that you typed it correctly "
|
||||
"and that you haven't activated the \"caps lock\" key"));
|
||||
} else if ((WIFEXITED (status)) && (WEXITSTATUS (status)) && (WEXITSTATUS (status) == 255)) {
|
||||
primary_text = g_strdup (_("Could not run passwd"));
|
||||
secondary_text = g_strdup (_("Check that you have permissions to run this command"));
|
||||
} else {
|
||||
primary_text = g_strdup (_("An unexpected error has ocurred"));
|
||||
}
|
||||
|
||||
if (primary_text) {
|
||||
passdlg_set_busy (pdialog, FALSE);
|
||||
dialog = gtk_message_dialog_new (NULL,
|
||||
GTK_DIALOG_DESTROY_WITH_PARENT,
|
||||
GTK_MESSAGE_ERROR,
|
||||
GTK_BUTTONS_CLOSE,
|
||||
primary_text, secondary_text);
|
||||
|
||||
g_signal_connect (G_OBJECT (dialog), "response",
|
||||
G_CALLBACK (gtk_widget_destroy), NULL);
|
||||
gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
|
||||
gtk_widget_show (dialog);
|
||||
|
||||
g_free (primary_text);
|
||||
g_free (secondary_text);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
is_string_complete (gchar *str, GSList *list)
|
||||
{
|
||||
GSList *elem;
|
||||
|
||||
if (strlen (str) == 0)
|
||||
return FALSE;
|
||||
|
||||
for (elem = list; elem; elem = g_slist_next (elem))
|
||||
if (g_strrstr (str, elem->data) != NULL)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static char *
|
||||
read_from_backend_va (PasswordDialog *pdialog, gchar *needle, va_list ap)
|
||||
{
|
||||
GString *str = g_string_new ("");
|
||||
gboolean may_exit = FALSE;
|
||||
gint i = 0;
|
||||
gchar c, *ptr, *arg;
|
||||
GSList *list = NULL;
|
||||
|
||||
list = g_slist_prepend (list, needle);
|
||||
|
||||
while ((arg = va_arg (ap, char*)) != NULL)
|
||||
list = g_slist_prepend (list, arg);
|
||||
va_end (ap);
|
||||
|
||||
while (!is_string_complete (str->str, list)) {
|
||||
c = fgetc (pdialog->backend_stream);
|
||||
i++;
|
||||
|
||||
if (*str->str)
|
||||
g_string_append_c (str, c);
|
||||
else {
|
||||
/* the string is still empty, read with O_NONBLOCK until
|
||||
* it gets a char, this is done for not blocking the UI
|
||||
*/
|
||||
if (c != EOF) {
|
||||
g_string_append_c (str, c);
|
||||
fcntl (pdialog->backend_master_fd, F_SETFL, 0);
|
||||
}
|
||||
usleep (500);
|
||||
}
|
||||
|
||||
/* ugly hack for redrawing UI without too much overload */
|
||||
if (i == REDRAW_NCHARS) {
|
||||
while (gtk_events_pending ())
|
||||
gtk_main_iteration ();
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
fcntl (pdialog->backend_master_fd, F_SETFL, O_NONBLOCK);
|
||||
ptr = str->str;
|
||||
g_string_free (str, FALSE);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static gchar*
|
||||
read_from_backend (PasswordDialog *pdialog, gchar *needle, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
va_start (ap, needle);
|
||||
return read_from_backend_va (pdialog, needle, ap);
|
||||
}
|
||||
|
||||
static void
|
||||
write_to_backend (PasswordDialog *pdialog, char *str)
|
||||
{
|
||||
gint nread = 0;
|
||||
int ret;
|
||||
|
||||
/* turn the descriptor blocking for writing the configuration */
|
||||
fcntl (pdialog->backend_master_fd, F_SETFL, 0);
|
||||
|
||||
do {
|
||||
ret = fputc (str [nread], pdialog->backend_stream);
|
||||
|
||||
if (ret != EOF)
|
||||
nread++;
|
||||
|
||||
/* ugly hack for redrawing UI */
|
||||
if (nread % REDRAW_NCHARS == 0)
|
||||
while (gtk_events_pending ())
|
||||
gtk_main_iteration ();
|
||||
} while (nread < strlen (str));
|
||||
|
||||
while (fflush (pdialog->backend_stream) != 0);
|
||||
|
||||
fcntl (pdialog->backend_master_fd, F_SETFL, O_NONBLOCK);
|
||||
}
|
||||
|
||||
static void
|
||||
passdlg_set_busy (PasswordDialog *pdialog, gboolean busy)
|
||||
{
|
||||
GtkWindow *toplevel = GTK_WINDOW (pdialog->dialog);
|
||||
GdkCursor *cursor = NULL;
|
||||
GdkDisplay *display;
|
||||
|
||||
display = gtk_widget_get_display (GTK_WIDGET (toplevel));
|
||||
if (busy)
|
||||
cursor = gdk_cursor_new_for_display (display, GDK_WATCH);
|
||||
|
||||
gdk_window_set_cursor (GTK_WIDGET (toplevel)->window, cursor);
|
||||
gdk_display_flush (display);
|
||||
|
||||
if (busy)
|
||||
gdk_cursor_unref (cursor);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
passdlg_button_clicked_cb (GtkDialog *dialog, gint response_id, PasswordDialog *pdialog)
|
||||
{
|
||||
|
||||
char *new_password;
|
||||
char *retyped_password;
|
||||
char *old_password;
|
||||
char *args[2];
|
||||
gchar *s;
|
||||
|
||||
if (response_id == GTK_RESPONSE_OK) {
|
||||
/* */
|
||||
old_password = g_strdup_printf ("%s\n", gtk_entry_get_text (GTK_ENTRY (pdialog->old_password)));
|
||||
new_password = g_strdup_printf ("%s\n", gtk_entry_get_text (GTK_ENTRY (pdialog->new_password)));
|
||||
retyped_password = g_strdup_printf ("%s\n", gtk_entry_get_text (GTK_ENTRY (pdialog->retyped_password)));
|
||||
|
||||
/* Set the busy cursor as this can be a long process */
|
||||
passdlg_set_busy (pdialog, TRUE);
|
||||
|
||||
/* Prepare the execution environment of passwd */
|
||||
args[0] = "/usr/bin/passwd";
|
||||
args[1] = NULL;
|
||||
|
||||
pdialog->backend_pid = forkpty (&pdialog->backend_master_fd, NULL, NULL, NULL);
|
||||
if (pdialog->backend_pid < 0) {
|
||||
g_warning ("could not fork to backend");
|
||||
gtk_main_quit ();
|
||||
} else if (pdialog->backend_pid == 0) {
|
||||
execv (args[0], args);
|
||||
exit (255);
|
||||
} else {
|
||||
fcntl (pdialog->backend_master_fd, F_SETFL, O_NONBLOCK);
|
||||
pdialog->timeout_id = g_timeout_add (1000, (GSourceFunc) wait_child, pdialog);
|
||||
pdialog->backend_stream = fdopen (pdialog->backend_master_fd, "a+");
|
||||
}
|
||||
|
||||
/* Send current password to backend */
|
||||
s = read_from_backend (pdialog, "assword:", ": ", NULL);
|
||||
write_to_backend (pdialog, old_password);
|
||||
|
||||
s = read_from_backend (pdialog, "assword:", ": ", "\n", NULL);
|
||||
while (strlen(s) < 4) {
|
||||
usleep(1000);
|
||||
s = read_from_backend (pdialog, "assword:", ": ", "\n", NULL);
|
||||
}
|
||||
|
||||
/* Send new password to backend */
|
||||
write_to_backend (pdialog, new_password);
|
||||
|
||||
s = read_from_backend (pdialog, "assword:", ": ", "\n", NULL);
|
||||
while (strlen(s) < 4) {
|
||||
usleep(1000);
|
||||
s = read_from_backend (pdialog, "assword:", ": ", "\n", NULL);
|
||||
}
|
||||
|
||||
/* Send new and retyped password to backend */
|
||||
write_to_backend (pdialog, retyped_password);
|
||||
s = read_from_backend (pdialog, "assword:", ": ", "\n", NULL);
|
||||
while (strlen(s) < 4) {
|
||||
usleep(1000);
|
||||
s = read_from_backend (pdialog, "\n", NULL);
|
||||
}
|
||||
|
||||
} else {
|
||||
gtk_main_quit ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gnome_about_me_password (void)
|
||||
{
|
||||
PasswordDialog *pdialog;
|
||||
GladeXML *dialog;
|
||||
|
||||
pdialog = g_new0 (PasswordDialog, 1);
|
||||
|
||||
dialog = glade_xml_new (GNOMECC_DATA_DIR "/interfaces/gnome-about-me.glade", "change-password", NULL);
|
||||
|
||||
pdialog->dialog = WID ("change-password");
|
||||
g_signal_connect (G_OBJECT (pdialog->dialog), "response",
|
||||
G_CALLBACK (passdlg_button_clicked_cb), pdialog);
|
||||
|
||||
pdialog->old_password = WID ("old-password");
|
||||
pdialog->new_password = WID ("new-password");
|
||||
pdialog->retyped_password = WID ("retyped-password");
|
||||
|
||||
gtk_window_set_resizable (GTK_WINDOW (pdialog->dialog), FALSE);
|
||||
gtk_widget_show_all (pdialog->dialog);
|
||||
gtk_main ();
|
||||
|
||||
gtk_widget_destroy (pdialog->dialog);
|
||||
g_object_unref (G_OBJECT (dialog));
|
||||
g_free (pdialog);
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
#ifndef __GNOME_ABOUT_ME_PASSWORD_H__
|
||||
#define __GNOME_ABOUT_ME_PASSWORD_H__
|
||||
|
||||
void
|
||||
gnome_about_me_password (void);
|
||||
|
||||
#endif /* __GNOME_ABOUT_ME_PASSWORD_H__ */
|
||||
@@ -1,720 +0,0 @@
|
||||
/* gnome-about-me.c
|
||||
* Copyright (C) 2002 Diego Gonzalez
|
||||
*
|
||||
* Written by: Diego Gonzalez <diego@pemas.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <gnome.h>
|
||||
#include <pwd.h>
|
||||
#include <gconf/gconf-client.h>
|
||||
#include <glade/glade.h>
|
||||
#include <pwd.h>
|
||||
#include <unistd.h>
|
||||
#include <bonobo/bonobo-main.h>
|
||||
#include <libebook/e-book.h>
|
||||
|
||||
#include "e-image-chooser.h"
|
||||
#include "gnome-about-me-password.h"
|
||||
|
||||
#include "capplet-util.h"
|
||||
|
||||
typedef struct {
|
||||
EContact *contact;
|
||||
EBook *book;
|
||||
|
||||
GladeXML *dialog;
|
||||
|
||||
GtkWidget *fsel;
|
||||
GdkScreen *screen;
|
||||
GtkIconTheme *theme;
|
||||
|
||||
EContactAddress *addr1;
|
||||
EContactAddress *addr2;
|
||||
|
||||
gboolean have_image;
|
||||
gboolean image_changed;
|
||||
gboolean create_self;
|
||||
|
||||
gchar *person;
|
||||
} GnomeAboutMe;
|
||||
|
||||
static GnomeAboutMe *me;
|
||||
|
||||
struct WidToCid{
|
||||
gchar *wid;
|
||||
guint cid;
|
||||
};
|
||||
|
||||
enum {
|
||||
ADDRESS_STREET = 1,
|
||||
ADDRESS_POBOX,
|
||||
ADDRESS_LOCALITY,
|
||||
ADDRESS_CODE,
|
||||
ADDRESS_REGION,
|
||||
ADDRESS_COUNTRY
|
||||
};
|
||||
|
||||
#define ADDRESS_HOME 21
|
||||
#define ADDRESS_WORK 27
|
||||
|
||||
struct WidToCid ids[] = {
|
||||
|
||||
{ "email-work-e", E_CONTACT_EMAIL_1 }, /* 00 */
|
||||
{ "email-home-e", E_CONTACT_EMAIL_2 }, /* 01 */
|
||||
|
||||
{ "phone-home-e", E_CONTACT_PHONE_HOME }, /* 02 */
|
||||
{ "phone-mobile-e", E_CONTACT_PHONE_MOBILE }, /* 03 */
|
||||
{ "phone-work-e", E_CONTACT_PHONE_BUSINESS }, /* 04 */
|
||||
{ "phone-work-fax-e", E_CONTACT_PHONE_BUSINESS_FAX }, /* 05 */
|
||||
|
||||
{ "im-jabber-e", E_CONTACT_IM_JABBER_HOME_1 }, /* 06 */
|
||||
{ "im-msn-e", E_CONTACT_IM_MSN_HOME_1 }, /* 07 */
|
||||
{ "im-icq-e", E_CONTACT_IM_ICQ_HOME_1 }, /* 08 */
|
||||
{ "im-yahoo-e", E_CONTACT_IM_YAHOO_HOME_1 }, /* 09 */
|
||||
{ "im-aim-e", E_CONTACT_IM_AIM_HOME_1 }, /* 10 */
|
||||
{ "im-groupwise-e", E_CONTACT_IM_GROUPWISE_HOME_1 }, /* 11 */
|
||||
|
||||
{ "web-homepage-e", E_CONTACT_HOMEPAGE_URL }, /* 12 */
|
||||
{ "web-calendar-e", E_CONTACT_CALENDAR_URI }, /* 13 */
|
||||
{ "web-weblog-e", E_CONTACT_BLOG_URL }, /* 14 */
|
||||
|
||||
{ "job-profession-e", E_CONTACT_ROLE }, /* 15 */
|
||||
{ "job-title-e", E_CONTACT_TITLE }, /* 16 */
|
||||
{ "job-dept-e", E_CONTACT_ORG_UNIT }, /* 17 */
|
||||
{ "job-assistant-e", E_CONTACT_ASSISTANT }, /* 18 */
|
||||
{ "job-company-e", E_CONTACT_ORG }, /* 19 */
|
||||
{ "job-manager-e", E_CONTACT_MANAGER }, /* 20 */
|
||||
|
||||
{ "addr-street-1", ADDRESS_STREET }, /* 21 */
|
||||
{ "addr-po-1", ADDRESS_POBOX }, /* 22 */
|
||||
{ "addr-locality-1", ADDRESS_LOCALITY }, /* 23 */
|
||||
{ "addr-code-1", ADDRESS_CODE }, /* 24 */
|
||||
{ "addr-region-1", ADDRESS_REGION }, /* 25 */
|
||||
{ "addr-country-1", ADDRESS_COUNTRY }, /* 26 */
|
||||
|
||||
{ "addr-street-2", ADDRESS_STREET }, /* 27 */
|
||||
{ "addr-po-2", ADDRESS_POBOX }, /* 28 */
|
||||
{ "addr-locality-2", ADDRESS_LOCALITY }, /* 29 */
|
||||
{ "addr-code-2", ADDRESS_CODE }, /* 30 */
|
||||
{ "addr-region-2", ADDRESS_REGION }, /* 31 */
|
||||
{ "addr-country-2", ADDRESS_COUNTRY }, /* 32 */
|
||||
|
||||
{ NULL, 0 }
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
RESPONSE_APPLY = 1,
|
||||
RESPONSE_CLOSE
|
||||
};
|
||||
|
||||
static void about_me_set_address_field (EContactAddress *, guint, gchar *);
|
||||
|
||||
|
||||
/********************/
|
||||
static void
|
||||
about_me_commit (GnomeAboutMe *me)
|
||||
{
|
||||
GError *error = NULL;
|
||||
if (me->create_self) {
|
||||
e_contact_set (me->contact, E_CONTACT_FILE_AS, "asdffff");
|
||||
e_contact_set (me->contact, E_CONTACT_NICKNAME, "nickname");
|
||||
e_contact_set (me->contact, E_CONTACT_FULL_NAME, "fullname");
|
||||
}
|
||||
|
||||
if (me->create_self) {
|
||||
e_book_add_contact (me->book, me->contact, &error);
|
||||
e_book_set_self (me->book, me->contact, &error);
|
||||
} else {
|
||||
if (e_book_commit_contact (me->book, me->contact, &error) == FALSE)
|
||||
g_print ("There was an undeterminad error\n");
|
||||
}
|
||||
|
||||
me->create_self = FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
about_me_focus_out (GtkWidget *widget, GdkEventFocus *event, GnomeAboutMe *me)
|
||||
{
|
||||
gchar *str = NULL;
|
||||
const gchar *wid;
|
||||
gint i;
|
||||
|
||||
wid = glade_get_widget_name (widget);
|
||||
|
||||
for (i = 0; ids[i].wid != NULL; i++)
|
||||
if (g_ascii_strcasecmp (ids[i].wid, wid) == 0)
|
||||
break;
|
||||
|
||||
if (ids[i].cid == 0) {
|
||||
g_warning ("returning at invalid point\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (GTK_IS_ENTRY (widget)) {
|
||||
str = gtk_editable_get_chars (GTK_EDITABLE (widget), 0, -1);
|
||||
} else if (GTK_IS_TEXT_VIEW (widget)) {
|
||||
GtkTextBuffer *buffer;
|
||||
GtkTextIter iter_start;
|
||||
GtkTextIter iter_end;
|
||||
|
||||
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (widget));
|
||||
gtk_text_buffer_get_start_iter (buffer, &iter_start);
|
||||
iter_end = iter_start;
|
||||
gtk_text_iter_forward_to_end (&iter_end);
|
||||
str = gtk_text_iter_get_text (&iter_start, &iter_end);
|
||||
}
|
||||
|
||||
str = str ? str : "";
|
||||
|
||||
if (i >= ADDRESS_HOME && i < ADDRESS_WORK) {
|
||||
about_me_set_address_field (me->addr1, ids[i].cid, str);
|
||||
e_contact_set (me->contact, E_CONTACT_ADDRESS_HOME, me->addr1);
|
||||
} else if (i >= ADDRESS_WORK) {
|
||||
about_me_set_address_field (me->addr2, ids[i].cid, str);
|
||||
e_contact_set (me->contact, E_CONTACT_ADDRESS_WORK, me->addr2);
|
||||
} else {
|
||||
e_contact_set (me->contact, ids[i].cid, str);
|
||||
}
|
||||
|
||||
g_free (str);
|
||||
|
||||
about_me_commit (me);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/********************/
|
||||
|
||||
static char *
|
||||
get_user_login (void)
|
||||
{
|
||||
char buf[LINE_MAX * 4];
|
||||
struct passwd pwd, *err;
|
||||
|
||||
int i;
|
||||
i = getpwuid_r(getuid(), &pwd, buf, sizeof(buf), &err);
|
||||
return ((i == 0) && (err == &pwd)) ? g_strdup(pwd.pw_name) : NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Helpers
|
||||
*/
|
||||
|
||||
GtkWidget *
|
||||
about_me_get_widget (GladeXML *dialog, gchar *name, gint suffix)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
gchar *str;
|
||||
|
||||
str = g_strdup_printf ("%s-%d", name, suffix);
|
||||
widget = WID(str);
|
||||
g_free (str);
|
||||
|
||||
return widget;
|
||||
}
|
||||
|
||||
static gchar *
|
||||
about_me_get_address_field (EContactAddress *addr, guint cid)
|
||||
{
|
||||
gchar *str = NULL;
|
||||
|
||||
if (addr == NULL)
|
||||
return NULL;
|
||||
|
||||
switch (cid) {
|
||||
case ADDRESS_STREET:
|
||||
str = addr->street;
|
||||
break;
|
||||
case ADDRESS_POBOX:
|
||||
str = addr->po;
|
||||
break;
|
||||
case ADDRESS_LOCALITY:
|
||||
str = addr->locality;
|
||||
break;
|
||||
case ADDRESS_CODE:
|
||||
str = addr->code;
|
||||
break;
|
||||
case ADDRESS_REGION:
|
||||
str = addr->region;
|
||||
break;
|
||||
case ADDRESS_COUNTRY:
|
||||
str = addr->country;
|
||||
break;
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
static void
|
||||
about_me_set_address_field (EContactAddress *addr, guint cid, gchar *str)
|
||||
{
|
||||
switch (cid) {
|
||||
case ADDRESS_STREET:
|
||||
if (addr->street)
|
||||
g_free (addr->street);
|
||||
addr->street = g_strdup (str);
|
||||
break;
|
||||
case ADDRESS_POBOX:
|
||||
if (addr->po)
|
||||
g_free (addr->po);
|
||||
addr->po = g_strdup (str);
|
||||
break;
|
||||
case ADDRESS_LOCALITY:
|
||||
if (addr->locality)
|
||||
g_free (addr->locality);
|
||||
addr->locality = g_strdup (str);
|
||||
break;
|
||||
case ADDRESS_CODE:
|
||||
if (addr->code)
|
||||
g_free (addr->code);
|
||||
addr->code = g_strdup (str);
|
||||
break;
|
||||
case ADDRESS_REGION:
|
||||
if (addr->region)
|
||||
g_free (addr->region);
|
||||
addr->region = g_strdup (str);
|
||||
break;
|
||||
case ADDRESS_COUNTRY:
|
||||
if (addr->country)
|
||||
g_free (addr->country);
|
||||
addr->country = g_strdup (str);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* wid: glade widget name
|
||||
* cid: id of the field (EDS id)
|
||||
* aid: position in the array WidToCid
|
||||
**/
|
||||
|
||||
static void
|
||||
about_me_load_string_field (GnomeAboutMe *me, const gchar *wid, guint cid, guint aid)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
GladeXML *dialog;
|
||||
gchar *str;
|
||||
|
||||
dialog = me->dialog;
|
||||
|
||||
widget = WID (wid);
|
||||
|
||||
if (me->create_self == TRUE) {
|
||||
g_signal_connect (widget, "focus-out-event", G_CALLBACK (about_me_focus_out), me);
|
||||
return;
|
||||
}
|
||||
|
||||
if (aid >= ADDRESS_HOME && aid < ADDRESS_WORK) {
|
||||
str = about_me_get_address_field (me->addr1, cid);
|
||||
} else if (aid >= ADDRESS_WORK) {
|
||||
str = about_me_get_address_field (me->addr2, cid);
|
||||
} else {
|
||||
str = e_contact_get_const (me->contact, cid);
|
||||
}
|
||||
|
||||
str = str ? str : "";
|
||||
|
||||
if (GTK_IS_ENTRY (widget)) {
|
||||
gtk_entry_set_text (GTK_ENTRY (widget), str);
|
||||
} else if (GTK_IS_TEXT_VIEW (widget)) {
|
||||
GtkTextBuffer *buffer;
|
||||
|
||||
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (widget));
|
||||
gtk_text_buffer_set_text (buffer, str, -1);
|
||||
}
|
||||
|
||||
g_signal_connect (widget, "focus-out-event", G_CALLBACK (about_me_focus_out), me);
|
||||
}
|
||||
|
||||
static void
|
||||
about_me_load_photo (GnomeAboutMe *me, EContact *contact)
|
||||
{
|
||||
|
||||
GtkWidget *widget;
|
||||
GladeXML *dialog;
|
||||
EContactPhoto *photo;
|
||||
|
||||
dialog = me->dialog;
|
||||
|
||||
widget = WID("image-chooser");
|
||||
|
||||
e_image_chooser_set_from_file (E_IMAGE_CHOOSER (widget), me->person);
|
||||
|
||||
photo = e_contact_get (contact, E_CONTACT_PHOTO);
|
||||
|
||||
if (photo) {
|
||||
me->have_image = TRUE;
|
||||
e_image_chooser_set_image_data (E_IMAGE_CHOOSER (widget), photo->data, photo->length);
|
||||
e_contact_photo_free (photo);
|
||||
} else {
|
||||
me->have_image = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
about_me_update_photo (GnomeAboutMe *me)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
GladeXML *dialog;
|
||||
EContactPhoto *photo;
|
||||
gchar *file;
|
||||
FILE *fp;
|
||||
|
||||
dialog = me->dialog;
|
||||
|
||||
if (me->image_changed && me->have_image) {
|
||||
widget = WID ("image-chooser");
|
||||
|
||||
photo = g_new0 (EContactPhoto, 1);
|
||||
e_image_chooser_get_image_data (E_IMAGE_CHOOSER (widget), &photo->data, &photo->length);
|
||||
e_contact_set (me->contact, E_CONTACT_PHOTO, photo);
|
||||
|
||||
/* Save the image for GDM */
|
||||
file = g_strdup_printf ("%s/.gnome2/face.png", g_get_home_dir ());
|
||||
fp = fopen (file, "wb");
|
||||
fwrite (photo->data, 1, photo->length, fp);
|
||||
fclose (fp);
|
||||
|
||||
/* Update GDM configuration */
|
||||
gnome_config_set_string ("/gdmphotosetup/last/picture", file);
|
||||
gnome_config_set_string ("/gdm/face/picture", file);
|
||||
gnome_config_sync ();
|
||||
g_free (file);
|
||||
|
||||
e_contact_photo_free (photo);
|
||||
|
||||
} else if (me->image_changed && !me->have_image) {
|
||||
/* Update the image in the card */
|
||||
e_contact_set (me->contact, E_CONTACT_PHOTO, NULL);
|
||||
|
||||
/* Update GDM configuration */
|
||||
gnome_config_set_string ("/gdmphotosetup/last/picture", "");
|
||||
gnome_config_set_string ("/gdm/face/picture", "");
|
||||
gnome_config_sync ();
|
||||
}
|
||||
|
||||
about_me_commit (me);
|
||||
}
|
||||
|
||||
static void
|
||||
about_me_load_info (GnomeAboutMe *me)
|
||||
{
|
||||
gint i;
|
||||
|
||||
if (me->create_self == FALSE) {
|
||||
me->addr1 = e_contact_get (me->contact, E_CONTACT_ADDRESS_HOME);
|
||||
if (me->addr1 == NULL)
|
||||
me->addr1 = g_new0 (EContactAddress, 1);
|
||||
me->addr2 = e_contact_get (me->contact, E_CONTACT_ADDRESS_WORK);
|
||||
if (me->addr2 == NULL)
|
||||
me->addr2 = g_new0 (EContactAddress, 1);
|
||||
}
|
||||
|
||||
for (i = 0; ids[i].wid != NULL; i++) {
|
||||
about_me_load_string_field (me, ids[i].wid, ids[i].cid, i);
|
||||
}
|
||||
}
|
||||
|
||||
GtkWidget *
|
||||
eab_create_image_chooser_widget(gchar *name,
|
||||
gchar *string1, gchar *string2,
|
||||
gint int1, gint int2)
|
||||
{
|
||||
GtkWidget *w = NULL;
|
||||
|
||||
w = e_image_chooser_new ();
|
||||
gtk_widget_show_all (w);
|
||||
|
||||
return w;
|
||||
}
|
||||
|
||||
/*
|
||||
* Functions to handle the photo changing stuff
|
||||
*/
|
||||
|
||||
static void
|
||||
image_selected (GnomeAboutMe *me)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
GladeXML *dialog;
|
||||
gchar *image;
|
||||
|
||||
me->have_image = TRUE;
|
||||
me->image_changed = TRUE;
|
||||
|
||||
dialog = me->dialog;
|
||||
|
||||
widget = WID ("image-chooser");
|
||||
|
||||
/* obtener el fichero seleccionado */
|
||||
image = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (me->fsel));
|
||||
e_image_chooser_set_from_file (E_IMAGE_CHOOSER (widget), image);
|
||||
g_free (image);
|
||||
|
||||
about_me_update_photo (me);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
image_cleared (GnomeAboutMe *me)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
GladeXML *dialog;
|
||||
|
||||
me->have_image = FALSE;
|
||||
me->image_changed = TRUE;
|
||||
|
||||
dialog = me->dialog;
|
||||
|
||||
widget = WID ("image-chooser");
|
||||
|
||||
e_image_chooser_set_from_file (E_IMAGE_CHOOSER (widget), me->person);
|
||||
about_me_update_photo (me);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
about_me_file_chooser_response (GtkWidget *widget, gint response, GnomeAboutMe *me)
|
||||
{
|
||||
if (response == GTK_RESPONSE_ACCEPT)
|
||||
image_selected (me);
|
||||
else if (response == GTK_RESPONSE_NO)
|
||||
image_cleared (me);
|
||||
|
||||
gtk_widget_hide (me->fsel);
|
||||
}
|
||||
|
||||
static void
|
||||
about_me_image_clicked_cb (GtkWidget *button, GnomeAboutMe *me)
|
||||
{
|
||||
char *title = _("Select Image");
|
||||
char *noimage = _("No Image");
|
||||
|
||||
me->fsel = gtk_file_chooser_dialog_new (title, NULL,
|
||||
GTK_FILE_CHOOSER_ACTION_OPEN,
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
||||
GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
|
||||
noimage, GTK_RESPONSE_NO,
|
||||
NULL);
|
||||
gtk_dialog_set_default_response (GTK_DIALOG (me->fsel), GTK_RESPONSE_ACCEPT);
|
||||
|
||||
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (me->fsel), g_get_home_dir ());
|
||||
|
||||
g_signal_connect (me->fsel, "response",
|
||||
G_CALLBACK (about_me_file_chooser_response), me);
|
||||
|
||||
gtk_window_present (GTK_WINDOW (me->fsel));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* About Me Dialog Callbacks */
|
||||
|
||||
static void
|
||||
about_me_icon_theme_changed (GtkWindow *window,
|
||||
GtkIconTheme *theme)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
GtkIconInfo *icon;
|
||||
GladeXML *dialog;
|
||||
|
||||
icon = gtk_icon_theme_lookup_icon (me->theme, "stock_person", 80, 0);
|
||||
if (icon == NULL) {
|
||||
g_print ("Icon not found\n");
|
||||
}
|
||||
g_free (me->person);
|
||||
me->person = g_strdup (gtk_icon_info_get_filename (icon));
|
||||
|
||||
gtk_icon_info_free (icon);
|
||||
|
||||
if (me->have_image) {
|
||||
dialog = me->dialog;
|
||||
|
||||
widget = WID ("image-chooser");
|
||||
e_image_chooser_set_from_file (E_IMAGE_CHOOSER (widget), me->person);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
about_me_button_clicked_cb (GtkDialog *dialog, gint response_id, GnomeAboutMe *me)
|
||||
{
|
||||
if (response_id == GTK_RESPONSE_HELP)
|
||||
g_print ("Help goes here");
|
||||
else {
|
||||
e_contact_address_free (me->addr1);
|
||||
e_contact_address_free (me->addr2);
|
||||
|
||||
g_object_unref (me->contact);
|
||||
g_object_unref (me->book);
|
||||
g_object_unref (me->dialog);
|
||||
|
||||
g_free (me->person);
|
||||
g_free (me);
|
||||
|
||||
gtk_main_quit ();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
about_me_passwd_clicked_cb (GtkWidget *button, gpointer data)
|
||||
{
|
||||
gnome_about_me_password ();
|
||||
}
|
||||
|
||||
static void
|
||||
about_me_setup_dialog (void)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
GtkIconInfo *icon;
|
||||
GladeXML *dialog;
|
||||
GError *error = NULL;
|
||||
|
||||
struct passwd *pwent;
|
||||
char *user = NULL;
|
||||
gchar *str;
|
||||
|
||||
me = g_new0 (GnomeAboutMe, 1);
|
||||
|
||||
dialog = glade_xml_new (GNOMECC_DATA_DIR "/interfaces/gnome-about-me.glade",
|
||||
"about-me-dialog", NULL);
|
||||
|
||||
me->dialog = dialog;
|
||||
|
||||
/* Setup theme details */
|
||||
me->screen = gtk_window_get_screen (WID ("about-me-dialog"));
|
||||
me->theme = gtk_icon_theme_get_for_screen (me->screen);
|
||||
|
||||
icon = gtk_icon_theme_lookup_icon (me->theme, "stock_person", 80, 0);
|
||||
if (icon == NULL) {
|
||||
g_print ("Icon not found\n");
|
||||
}
|
||||
|
||||
me->person = g_strdup (gtk_icon_info_get_filename (icon));
|
||||
|
||||
gtk_icon_info_free (icon);
|
||||
|
||||
g_signal_connect_object (me->theme, "changed",
|
||||
G_CALLBACK (about_me_icon_theme_changed),
|
||||
GTK_WIDGET (WID("about-me-dialog")),
|
||||
G_CONNECT_SWAPPED);
|
||||
|
||||
/* Get the self contact */
|
||||
if (!e_book_get_self (&me->contact, &me->book, &error)) {
|
||||
me->create_self = TRUE;
|
||||
|
||||
me->contact = e_contact_new ();
|
||||
g_print ("%s\n", error->message);
|
||||
|
||||
g_clear_error (&error);
|
||||
|
||||
if (me->book == NULL) {
|
||||
me->book = e_book_new_system_addressbook (&error);
|
||||
if (me->book == NULL)
|
||||
g_print ("error message: %s\n", error->message);
|
||||
|
||||
if (e_book_open (me->book, FALSE, NULL) == FALSE)
|
||||
g_print ("unable to open book, bailing out\n");
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************/
|
||||
user = get_user_login ();
|
||||
setpwent ();
|
||||
pwent = getpwnam (user);
|
||||
if (pwent == NULL) {
|
||||
printf ("error\n");
|
||||
return ;
|
||||
}
|
||||
gchar **tok;
|
||||
tok = g_strsplit (pwent->pw_gecos, ",", 0);
|
||||
|
||||
/************************************************/
|
||||
|
||||
/* Fill in the blanks */
|
||||
|
||||
/* Contact Tab */
|
||||
about_me_load_photo (me, me->contact);
|
||||
|
||||
widget = WID ("fullname");
|
||||
if (tok[0] == NULL || strlen(tok[0]) == 0) {
|
||||
str = g_strdup ("<b><span size=\"xx-large\">COMO LO HAGO?</span></b>");
|
||||
} else {
|
||||
str = g_strdup_printf ("<b><span size=\"xx-large\">%s</span></b>", tok[0]);
|
||||
}
|
||||
gtk_label_set_markup (GTK_LABEL (widget), str);
|
||||
g_free (str);
|
||||
|
||||
widget = WID ("login");
|
||||
gtk_label_set_text (GTK_LABEL (widget), user);
|
||||
|
||||
widget = WID ("about-me-dialog");
|
||||
str = g_strdup_printf ("About %s", tok[0]);
|
||||
gtk_window_set_title (GTK_WINDOW (widget), str);
|
||||
g_free (str);
|
||||
|
||||
widget = WID("password");
|
||||
g_signal_connect (G_OBJECT (widget), "clicked",
|
||||
G_CALLBACK (about_me_passwd_clicked_cb), NULL);
|
||||
|
||||
widget = WID ("button-image");
|
||||
g_signal_connect (G_OBJECT (widget), "clicked",
|
||||
G_CALLBACK (about_me_image_clicked_cb), me);
|
||||
|
||||
about_me_load_info (me);
|
||||
|
||||
/* Connect the close button signal */
|
||||
widget = WID ("about-me-dialog");
|
||||
g_signal_connect (G_OBJECT (widget), "response",
|
||||
G_CALLBACK (about_me_button_clicked_cb), me);
|
||||
|
||||
/* TODO: Set dialog icon */
|
||||
gtk_window_set_resizable (GTK_WINDOW (widget), FALSE);
|
||||
|
||||
capplet_set_icon (widget, "gnome-about-me.png");
|
||||
|
||||
gtk_widget_show_all (widget);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
|
||||
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
|
||||
textdomain (GETTEXT_PACKAGE);
|
||||
|
||||
gnome_program_init ("gnome-about-me", VERSION,
|
||||
LIBGNOMEUI_MODULE, argc, argv,
|
||||
GNOME_PARAM_APP_DATADIR, GNOMECC_DATA_DIR,
|
||||
NULL);
|
||||
|
||||
if (bonobo_init (&argc, argv) == FALSE)
|
||||
g_error ("Could not initialize Bonobo");
|
||||
|
||||
about_me_setup_dialog ();
|
||||
gtk_main ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
[Desktop Entry]
|
||||
Encoding=UTF-8
|
||||
_Name=About me
|
||||
_Comment=Information about myself
|
||||
Exec=gnome-about-me
|
||||
Icon=gnome-about-me.png
|
||||
Terminal=false
|
||||
Type=Application
|
||||
StartupNotify=true
|
||||
Categories=GNOME;Application;Settings;
|
||||
X-GNOME-Bugzilla-Bugzilla=GNOME
|
||||
X-GNOME-Bugzilla-Product=control-center
|
||||
X-GNOME-Bugzilla-Component=other-capplets
|
||||
|
Before Width: | Height: | Size: 2.2 KiB |
@@ -1,2 +0,0 @@
|
||||
Makefile
|
||||
Makefile.in
|
||||
@@ -1 +0,0 @@
|
||||
SUBDIRS = keyboard at-properties
|
||||
@@ -1,5 +0,0 @@
|
||||
*.desktop
|
||||
Makefile
|
||||
Makefile.in
|
||||
gnome-at-properties
|
||||
at-properties.desktop.in
|
||||
@@ -1,99 +0,0 @@
|
||||
2004-11-09 Mark McLoughlin <mark@skynet.ie>
|
||||
|
||||
* Makefile.am: install the .desktop file in
|
||||
$(datadir)/applications.
|
||||
|
||||
* at-properties.desktop.in: add OnlyShowIn=GNOME;
|
||||
|
||||
2004-10-14 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* Release 2.8.1
|
||||
|
||||
Thu Sep 2 17:06:28 2004 Jonathan Blandford <jrb@redhat.com>
|
||||
|
||||
* main.c: (cb_dialog_response): Change to use help docs instead of
|
||||
the "foo"/"bar" that's there.
|
||||
|
||||
2004-08-20 Frederic Crozat <fcrozat@mandrakesoft.com>
|
||||
|
||||
* main.c: (setup_dialog):
|
||||
Use themed icon for window hint.
|
||||
|
||||
2004-04-15 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* Release 2.6.1
|
||||
|
||||
2004-04-01 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* Release 2.6.0.3
|
||||
|
||||
2004-03-30 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* Release 2.6.0.1
|
||||
|
||||
2004-03-23 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* Release 2.6.0
|
||||
|
||||
2004-03-11 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* Release 2.5.4
|
||||
|
||||
2003-11-27 Muktha <muktha.narayan@wipro.com>
|
||||
|
||||
* main.c: Do not popup the logout dialog when the close button (X) of
|
||||
window manager is clicked. Fixes bug #124032.
|
||||
|
||||
2004-02-13 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* Release 2.5.3
|
||||
|
||||
2004-01-14 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* Release 2.5.2
|
||||
|
||||
2003-12-30 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* Release 2.5.1.1
|
||||
|
||||
2003-12-30 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* Release 2.5.1
|
||||
|
||||
2003-10-28 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* Release 2.5.0
|
||||
|
||||
2003-08-01 Dennis Cranston <dennis_cranston at yahoo com>
|
||||
|
||||
* at-enable-dialog.glade: Patch to add two more pixels of spacing
|
||||
between action area and vbox of preferences dialog.
|
||||
|
||||
Fri Aug 1 14:28:52 2003 Jonathan Blandford <jrb@redhat.com>
|
||||
|
||||
* main.c (init_startup_state): remove markup tags from translated
|
||||
strings, #118801.
|
||||
|
||||
2003-07-18 Jonathan Blandford <jrb@gnome.org>
|
||||
|
||||
* main.c: Add a check to confirm that the AT's are installed. Add
|
||||
a warning message if they are not. Change widget naming scheme.
|
||||
|
||||
* at-enable-dialog.glade: Change widget naming scheme.
|
||||
|
||||
2003-07-16 Dennis Cranston <dennis_cranston at yahoo com>
|
||||
|
||||
* at-enable-dialog.glade: Make close the default button.
|
||||
|
||||
2003-07-16 Dennis Cranston <dennis_cranston at yahoo com>
|
||||
|
||||
* at-enable-dialog.glade: Adjust widget padding and remove
|
||||
separator per HIG.
|
||||
|
||||
2003-07-07 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* Release 2.3.4
|
||||
|
||||
2003-07-01 Daniel Baeyens <daniel.baeyens@hispalinux.es>
|
||||
* capplets/accessibility/at-properties/at-enable-dialog.glade:
|
||||
"Assistive" is misspelled.
|
||||
@@ -1,29 +0,0 @@
|
||||
bin_PROGRAMS = gnome-at-properties
|
||||
|
||||
gnome_at_properties_LDADD = $(AT_CAPPLET_LIBS) $(top_builddir)/capplets/common/libcommon.la
|
||||
gnome_at_properties_SOURCES = \
|
||||
main.c \
|
||||
at-startup-session.h \
|
||||
at-startup-session.c
|
||||
gnome_at_properties_LDFLAGS = -export-dynamic
|
||||
|
||||
@INTLTOOL_DESKTOP_RULE@
|
||||
|
||||
desktopdir = $(datadir)/applications
|
||||
Desktop_in_files = at-properties.desktop.in
|
||||
desktop_DATA = $(Desktop_in_files:.desktop.in=.desktop)
|
||||
|
||||
pixmapdir = $(GNOMECC_PIXMAPS_DIR)
|
||||
pixmap_DATA = \
|
||||
at-startup.png \
|
||||
at-support.png
|
||||
|
||||
gladedir = $(GNOMECC_GLADE_DIR)
|
||||
glade_DATA = at-enable-dialog.glade
|
||||
|
||||
INCLUDES = $(AT_CAPPLET_CFLAGS) \
|
||||
$(GNOMECC_CAPPLETS_CFLAGS) \
|
||||
-DGLADEDIR=\""$(gladedir)"\" \
|
||||
-DPIXMAPDIR=\""$(pixmapdir)"\"
|
||||
CLEANFILES = $(GNOMECC_CAPPLETS_CLEANFILES) $(Desktop_in_files) $(desktop_DATA)
|
||||
EXTRA_DIST = $(glade_DATA) $(pixmap_DATA)
|
||||
|
Before Width: | Height: | Size: 2.8 KiB |
@@ -1,465 +0,0 @@
|
||||
<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
|
||||
<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">
|
||||
|
||||
<glade-interface>
|
||||
<requires lib="gnome"/>
|
||||
|
||||
<widget class="GtkDialog" id="at_properties_dialog">
|
||||
<property name="border_width">5</property>
|
||||
<property name="title" translatable="yes">Assistive Technology Preferences</property>
|
||||
<property name="type">GTK_WINDOW_TOPLEVEL</property>
|
||||
<property name="window_position">GTK_WIN_POS_NONE</property>
|
||||
<property name="modal">False</property>
|
||||
<property name="resizable">False</property>
|
||||
<property name="destroy_with_parent">False</property>
|
||||
<property name="has_separator">False</property>
|
||||
|
||||
<child internal-child="vbox">
|
||||
<widget class="GtkVBox" id="dialog-vbox1">
|
||||
<property name="visible">True</property>
|
||||
<property name="homogeneous">False</property>
|
||||
<property name="spacing">2</property>
|
||||
|
||||
<child internal-child="action_area">
|
||||
<widget class="GtkHButtonBox" id="dialog-action_area1">
|
||||
<property name="visible">True</property>
|
||||
<property name="layout_style">GTK_BUTTONBOX_END</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkButton" id="at_help_button">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_default">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="label">gtk-help</property>
|
||||
<property name="use_stock">True</property>
|
||||
<property name="relief">GTK_RELIEF_NORMAL</property>
|
||||
<property name="response_id">-11</property>
|
||||
</widget>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkButton" id="at_close_logout_button">
|
||||
<property name="visible">True</property>
|
||||
<property name="sensitive">False</property>
|
||||
<property name="can_default">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="relief">GTK_RELIEF_NORMAL</property>
|
||||
<property name="response_id">0</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkAlignment" id="alignment3">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0.5</property>
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xscale">0</property>
|
||||
<property name="yscale">0</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox1">
|
||||
<property name="visible">True</property>
|
||||
<property name="homogeneous">False</property>
|
||||
<property name="spacing">2</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkImage" id="at_close_and_logout_image">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0.5</property>
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label5">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Close and _Log Out</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_markup">False</property>
|
||||
<property name="justify">GTK_JUSTIFY_LEFT</property>
|
||||
<property name="wrap">False</property>
|
||||
<property name="selectable">False</property>
|
||||
<property name="xalign">0.5</property>
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkButton" id="at_close_button">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_default">True</property>
|
||||
<property name="has_default">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="label">gtk-close</property>
|
||||
<property name="use_stock">True</property>
|
||||
<property name="relief">GTK_RELIEF_NORMAL</property>
|
||||
<property name="response_id">-7</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="pack_type">GTK_PACK_END</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkVBox" id="vbox1">
|
||||
<property name="border_width">5</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="homogeneous">False</property>
|
||||
<property name="spacing">18</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkVBox" id="at_support_frame">
|
||||
<property name="visible">True</property>
|
||||
<property name="homogeneous">False</property>
|
||||
<property name="spacing">0</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkVBox" id="vbox2">
|
||||
<property name="visible">True</property>
|
||||
<property name="homogeneous">False</property>
|
||||
<property name="spacing">6</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label4">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes"><b>Support</b></property>
|
||||
<property name="use_underline">False</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">GTK_JUSTIFY_LEFT</property>
|
||||
<property name="wrap">False</property>
|
||||
<property name="selectable">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox2">
|
||||
<property name="visible">True</property>
|
||||
<property name="homogeneous">False</property>
|
||||
<property name="spacing">12</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkImage" id="at_enable_image">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0.5</property>
|
||||
<property name="yalign">0</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkVBox" id="vbox3">
|
||||
<property name="visible">True</property>
|
||||
<property name="homogeneous">False</property>
|
||||
<property name="spacing">6</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkCheckButton" id="at_enable_toggle">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="label" translatable="yes">_Enable assistive technologies</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="relief">GTK_RELIEF_NORMAL</property>
|
||||
<property name="active">False</property>
|
||||
<property name="inconsistent">False</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkLabel" id="at_warning_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes"><small><i><b>Note:</b> Changes to this setting will not take effect until you next log in.</i></small></property>
|
||||
<property name="use_underline">False</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">GTK_JUSTIFY_LEFT</property>
|
||||
<property name="wrap">True</property>
|
||||
<property name="selectable">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkVBox" id="at_applications_frame">
|
||||
<property name="visible">True</property>
|
||||
<property name="homogeneous">False</property>
|
||||
<property name="spacing">0</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkVBox" id="vbox7">
|
||||
<property name="visible">True</property>
|
||||
<property name="homogeneous">False</property>
|
||||
<property name="spacing">6</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label3">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes"><b>Applications</b></property>
|
||||
<property name="use_underline">False</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">GTK_JUSTIFY_LEFT</property>
|
||||
<property name="wrap">False</property>
|
||||
<property name="selectable">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox3">
|
||||
<property name="visible">True</property>
|
||||
<property name="homogeneous">False</property>
|
||||
<property name="spacing">12</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkImage" id="at_applications_image">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0.5</property>
|
||||
<property name="yalign">0</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkVBox" id="vbox5">
|
||||
<property name="visible">True</property>
|
||||
<property name="homogeneous">False</property>
|
||||
<property name="spacing">6</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkLabel" id="at_applications_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Start these assistive technologies every time you log in:</property>
|
||||
<property name="use_underline">False</property>
|
||||
<property name="use_markup">False</property>
|
||||
<property name="justify">GTK_JUSTIFY_LEFT</property>
|
||||
<property name="wrap">False</property>
|
||||
<property name="selectable">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">6</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkCheckButton" id="at_screenreader_toggle">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="label" translatable="yes">_Screenreader</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="relief">GTK_RELIEF_NORMAL</property>
|
||||
<property name="active">False</property>
|
||||
<property name="inconsistent">False</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkCheckButton" id="at_magnifier_toggle">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="label" translatable="yes">_Magnifier</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="relief">GTK_RELIEF_NORMAL</property>
|
||||
<property name="active">False</property>
|
||||
<property name="inconsistent">False</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkCheckButton" id="at_keyboard_toggle">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="label" translatable="yes">_On-screen keyboard</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="relief">GTK_RELIEF_NORMAL</property>
|
||||
<property name="active">False</property>
|
||||
<property name="inconsistent">False</property>
|
||||
<property name="draw_indicator">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkHSeparator" id="at_applications_hseparator">
|
||||
<property name="visible">True</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkLabel" id="at_applications_warning_label">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes"></property>
|
||||
<property name="use_underline">False</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">GTK_JUSTIFY_LEFT</property>
|
||||
<property name="wrap">True</property>
|
||||
<property name="selectable">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
|
||||
</glade-interface>
|
||||
@@ -1,15 +0,0 @@
|
||||
[Desktop Entry]
|
||||
Encoding=UTF-8
|
||||
_Name=Assistive Technology Support
|
||||
_Comment=Enable support for GNOME assistive technologies at login
|
||||
Exec=gnome-at-properties
|
||||
Icon=gnome-settings-accessibility-technologies
|
||||
Terminal=false
|
||||
Type=Application
|
||||
StartupNotify=true
|
||||
Categories=GNOME;Settings;Accessibility;
|
||||
OnlyShowIn=GNOME;
|
||||
X-GNOME-Bugzilla-Bugzilla=GNOME
|
||||
X-GNOME-Bugzilla-Product=control-center
|
||||
X-GNOME-Bugzilla-Component=Assistive Technology Support
|
||||
X-GNOME-Bugzilla-Version=@VERSION@
|
||||
@@ -1,160 +0,0 @@
|
||||
#include <config.h>
|
||||
#include <string.h>
|
||||
#include <glib-object.h>
|
||||
#include <gconf/gconf-client.h>
|
||||
|
||||
#include "at-startup-session.h"
|
||||
|
||||
#define AT_STARTUP_KEY "/desktop/gnome/accessibility/startup/exec_ats"
|
||||
|
||||
#define GNOPERNICUS_MAGNIFIER_KEY "/apps/gnopernicus/srcore/mag_active"
|
||||
#define GNOPERNICUS_SPEECH_KEY "/apps/gnopernicus/srcore/sp_active"
|
||||
#define GNOPERNICUS_BRAILLE_KEY "/apps/gnopernicus/srcore/br_active"
|
||||
|
||||
static AtStartupState at_startup_state_recent;
|
||||
|
||||
static GSList *
|
||||
at_startup_get_list (GConfClient *client)
|
||||
{
|
||||
GError *error = NULL;
|
||||
GSList *at_list = gconf_client_get_list (client, AT_STARTUP_KEY, GCONF_VALUE_STRING, &error);
|
||||
if (error) {
|
||||
g_warning ("Error getting value of " AT_STARTUP_KEY ": %s", error->message);
|
||||
g_error_free (error);
|
||||
return NULL;
|
||||
}
|
||||
return at_list;
|
||||
}
|
||||
|
||||
gint
|
||||
at_startup_string_compare (gconstpointer s1, gconstpointer s2)
|
||||
{
|
||||
if (s1 && s2) {
|
||||
return strcmp (s1, s2);
|
||||
}
|
||||
else
|
||||
return ((char *)s2-(char *)s1);
|
||||
}
|
||||
|
||||
static GSList *
|
||||
at_startup_list_add (GSList *list, const gchar *exec_name)
|
||||
{
|
||||
GSList *l = g_slist_find_custom (list, exec_name, at_startup_string_compare);
|
||||
if (!l) {
|
||||
list = g_slist_append (list, g_strdup (exec_name));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
static GSList *
|
||||
at_startup_list_remove (GSList *list, const gchar *exec_name)
|
||||
{
|
||||
GSList *l = g_slist_find_custom (list, exec_name, at_startup_string_compare);
|
||||
if (l) {
|
||||
g_free (l->data);
|
||||
list = g_slist_delete_link (list, l);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
void
|
||||
at_startup_state_init (AtStartupState *startup_state)
|
||||
{
|
||||
gboolean mag_active, speech_active, braille_active;
|
||||
GSList *l;
|
||||
GConfClient *client = gconf_client_get_default ();
|
||||
GSList *at_list = at_startup_get_list (client);
|
||||
gchar *prog;
|
||||
|
||||
for (l = at_list; l; l = l->next) {
|
||||
gchar *exec_name = (char *) l->data;
|
||||
if (exec_name && !strcmp (exec_name, "gnopernicus")) {
|
||||
braille_active = gconf_client_get_bool (client,
|
||||
GNOPERNICUS_BRAILLE_KEY,
|
||||
NULL);
|
||||
mag_active = gconf_client_get_bool (client,
|
||||
GNOPERNICUS_MAGNIFIER_KEY,
|
||||
NULL);
|
||||
speech_active = gconf_client_get_bool (client,
|
||||
GNOPERNICUS_SPEECH_KEY,
|
||||
NULL);
|
||||
|
||||
startup_state->enabled.screenreader = (braille_active || speech_active);
|
||||
startup_state->enabled.magnifier = mag_active;
|
||||
}
|
||||
else if (exec_name && !strcmp(exec_name, "gok")) {
|
||||
startup_state->enabled.osk = TRUE;
|
||||
}
|
||||
g_free (exec_name);
|
||||
}
|
||||
|
||||
g_slist_free (at_list);
|
||||
g_object_unref (client);
|
||||
at_startup_state_recent.flags = startup_state->flags;
|
||||
|
||||
prog = g_find_program_in_path ("gok");
|
||||
if (prog != NULL) {
|
||||
startup_state->enabled.osk_installed = TRUE;
|
||||
g_free (prog);
|
||||
} else {
|
||||
startup_state->enabled.osk_installed = FALSE;
|
||||
}
|
||||
|
||||
prog = g_find_program_in_path ("gnopernicus");
|
||||
if (prog != NULL) {
|
||||
startup_state->enabled.magnifier_installed = TRUE;
|
||||
startup_state->enabled.screenreader_installed = TRUE;
|
||||
g_free (prog);
|
||||
} else {
|
||||
startup_state->enabled.magnifier_installed = FALSE;
|
||||
startup_state->enabled.screenreader_installed = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
at_startup_state_update (AtStartupState *startup_state)
|
||||
{
|
||||
GError *error = NULL;
|
||||
GConfClient *client = gconf_client_get_default ();
|
||||
GSList *at_list = at_startup_get_list (client);
|
||||
|
||||
if (startup_state->enabled.screenreader != at_startup_state_recent.enabled.screenreader) {
|
||||
gconf_client_set_bool (client, GNOPERNICUS_SPEECH_KEY,
|
||||
startup_state->enabled.screenreader, NULL);
|
||||
gconf_client_set_bool (client, GNOPERNICUS_BRAILLE_KEY,
|
||||
startup_state->enabled.screenreader, NULL);
|
||||
}
|
||||
|
||||
if (startup_state->enabled.magnifier != at_startup_state_recent.enabled.magnifier) {
|
||||
gconf_client_set_bool (client, GNOPERNICUS_MAGNIFIER_KEY,
|
||||
startup_state->enabled.magnifier, NULL);
|
||||
}
|
||||
|
||||
if (startup_state->enabled.screenreader || startup_state->enabled.magnifier) {
|
||||
if (!(at_startup_state_recent.enabled.screenreader ||
|
||||
at_startup_state_recent.enabled.magnifier))
|
||||
/* new state includes SR or magnifier, initial one did not */
|
||||
at_list = at_startup_list_add (at_list, "gnopernicus");
|
||||
}
|
||||
else {
|
||||
if (at_startup_state_recent.enabled.screenreader ||
|
||||
at_startup_state_recent.enabled.magnifier)
|
||||
at_list = at_startup_list_remove (at_list, "gnopernicus");
|
||||
}
|
||||
if (startup_state->enabled.osk) {
|
||||
if (!at_startup_state_recent.enabled.osk)
|
||||
at_list = at_startup_list_add (at_list, "gok");
|
||||
}
|
||||
else {
|
||||
if (at_startup_state_recent.enabled.osk)
|
||||
at_list = at_startup_list_remove (at_list, "gok");
|
||||
}
|
||||
if (at_startup_state_recent.flags != startup_state->flags) {
|
||||
at_startup_state_recent.flags = startup_state->flags;
|
||||
gconf_client_set_list (client, AT_STARTUP_KEY, GCONF_VALUE_STRING, at_list, &error);
|
||||
}
|
||||
g_object_unref (client);
|
||||
g_slist_free (at_list);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
#include <glib.h>
|
||||
|
||||
typedef union {
|
||||
guint flags;
|
||||
struct {
|
||||
guint support:1;
|
||||
guint osk:1;
|
||||
guint magnifier:1;
|
||||
guint screenreader:1;
|
||||
guint osk_installed:1;
|
||||
guint magnifier_installed:1;
|
||||
guint screenreader_installed:1;
|
||||
} enabled;
|
||||
} AtStartupState;
|
||||
|
||||
void at_startup_state_init (AtStartupState *startup_state);
|
||||
|
||||
void at_startup_state_update (AtStartupState *startup_state);
|
||||
|
Before Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 2.9 KiB |
@@ -1,296 +0,0 @@
|
||||
#include <config.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <gconf/gconf-client.h>
|
||||
#include <glade/glade.h>
|
||||
|
||||
#include "capplet-util.h"
|
||||
#include "gconf-property-editor.h"
|
||||
#include "activate-settings-daemon.h"
|
||||
#include "at-startup-session.h"
|
||||
|
||||
#define ACCESSIBILITY_KEY "/desktop/gnome/interface/accessibility"
|
||||
#define ACCESSIBILITY_KEY_DIR "/desktop/gnome/interface"
|
||||
#define AT_STARTUP_DIR "/desktop/gnome/accessibility/startup"
|
||||
#define AT_STARTUP_KEY "/desktop/gnome/accessibility/startup/exec_ats"
|
||||
#define SR_PREFS_DIR "/apps/gnopernicus/srcore"
|
||||
|
||||
static AtStartupState at_startup_state, at_startup_state_initial;
|
||||
|
||||
static void
|
||||
init_startup_state (GladeXML *dialog)
|
||||
{
|
||||
GConfClient *client = gconf_client_get_default ();
|
||||
|
||||
at_startup_state.flags = (gconf_client_get_bool (client,
|
||||
ACCESSIBILITY_KEY,
|
||||
NULL)) ? 1 : 0;
|
||||
|
||||
at_startup_state_init (&at_startup_state);
|
||||
|
||||
at_startup_state_initial.flags = at_startup_state.flags;
|
||||
g_object_unref (client);
|
||||
|
||||
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (WID ("at_keyboard_toggle")),
|
||||
at_startup_state.enabled.osk);
|
||||
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (WID ("at_screenreader_toggle")),
|
||||
at_startup_state.enabled.screenreader);
|
||||
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (WID ("at_magnifier_toggle")),
|
||||
at_startup_state.enabled.magnifier);
|
||||
|
||||
gtk_widget_set_sensitive (WID ("at_keyboard_toggle"),
|
||||
at_startup_state.enabled.osk_installed);
|
||||
gtk_widget_set_sensitive (WID ("at_screenreader_toggle"),
|
||||
at_startup_state.enabled.screenreader_installed);
|
||||
gtk_widget_set_sensitive (WID ("at_magnifier_toggle"),
|
||||
at_startup_state.enabled.magnifier_installed);
|
||||
|
||||
if (at_startup_state.enabled.osk_installed &&
|
||||
at_startup_state.enabled.screenreader_installed &&
|
||||
at_startup_state.enabled.magnifier_installed) {
|
||||
gtk_widget_hide (WID ("at_applications_warning_label"));
|
||||
gtk_widget_hide (WID ("at_applications_hseparator"));
|
||||
} else {
|
||||
gchar *warning_label;
|
||||
|
||||
gtk_widget_show (WID ("at_applications_warning_label"));
|
||||
gtk_widget_show (WID ("at_applications_hseparator"));
|
||||
if (!at_startup_state.enabled.osk_installed &&
|
||||
!(at_startup_state.enabled.screenreader_installed ||
|
||||
at_startup_state.enabled.magnifier_installed)) {
|
||||
warning_label = g_strdup_printf ("<i>%s</i>", _("No Assistive Technology is available on your system. The 'gok' package must be installed in order to get on-screen keyboard support, and the 'gnopernicus' package must be installed for screenreading and magnifying capabilities."));
|
||||
} else if (!at_startup_state.enabled.osk_installed) {
|
||||
warning_label = g_strdup_printf ("<i>%s</i>", _("Not all available assistive technologies are installed on your system. The 'gok' package must be installed in order to get on-screen keyboard support."));
|
||||
} else {
|
||||
warning_label = g_strdup_printf ("<i>%s</i>", _("Not all available assistive technologies are installed on your system. The 'gnopernicus' package must be installed for screenreading and magnifying capabilities."));
|
||||
}
|
||||
gtk_label_set_markup (GTK_LABEL (WID ("at_applications_warning_label")), warning_label);
|
||||
g_free (warning_label);
|
||||
}
|
||||
}
|
||||
|
||||
static GladeXML *
|
||||
create_dialog (void)
|
||||
{
|
||||
GladeXML *dialog;
|
||||
|
||||
dialog = glade_xml_new (GLADEDIR "/at-enable-dialog.glade", "at_properties_dialog", NULL);
|
||||
|
||||
gtk_image_set_from_stock (GTK_IMAGE (WID ("at_close_and_logout_image")),
|
||||
GTK_STOCK_QUIT, GTK_ICON_SIZE_BUTTON);
|
||||
|
||||
gtk_image_set_from_file (GTK_IMAGE (WID ("at_enable_image")),
|
||||
PIXMAPDIR "/at-support.png");
|
||||
|
||||
gtk_image_set_from_file (GTK_IMAGE (WID ("at_applications_image")),
|
||||
PIXMAPDIR "/at-startup.png");
|
||||
|
||||
return dialog;
|
||||
}
|
||||
|
||||
static void
|
||||
cb_dialog_response (GtkDialog *dialog, gint response_id)
|
||||
{
|
||||
GnomeClient *client;
|
||||
if (response_id == GTK_RESPONSE_HELP)
|
||||
capplet_help (GTK_WINDOW (dialog),
|
||||
"user-guide.xml",
|
||||
"goscustaccess-11");
|
||||
else if (response_id == GTK_RESPONSE_CLOSE || response_id == GTK_RESPONSE_DELETE_EVENT)
|
||||
gtk_main_quit ();
|
||||
else {
|
||||
g_message ("CLOSE AND LOGOUT!");
|
||||
if (!(client = gnome_master_client ())) {
|
||||
|
||||
gtk_main_quit ();
|
||||
}
|
||||
gnome_client_request_save (client, GNOME_SAVE_GLOBAL, TRUE,
|
||||
GNOME_INTERACT_ANY, FALSE, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
close_logout_update (GladeXML *dialog)
|
||||
{
|
||||
GConfClient *client = gconf_client_get_default ();
|
||||
gboolean has_changed =
|
||||
(at_startup_state.flags != at_startup_state_initial.flags) &&
|
||||
gconf_client_get_bool (client, ACCESSIBILITY_KEY, NULL);
|
||||
|
||||
gtk_widget_set_sensitive (WID ("at_close_logout_button"), has_changed);
|
||||
g_object_unref (client);
|
||||
}
|
||||
|
||||
static void
|
||||
at_startup_toggled (GtkToggleButton *toggle_button,
|
||||
GladeXML *dialog)
|
||||
{
|
||||
if (toggle_button == GTK_TOGGLE_BUTTON (WID ("at_keyboard_toggle"))) {
|
||||
at_startup_state.enabled.osk = gtk_toggle_button_get_active (toggle_button);
|
||||
}
|
||||
else if (toggle_button == GTK_TOGGLE_BUTTON (WID ("at_magnifier_toggle"))) {
|
||||
at_startup_state.enabled.magnifier = gtk_toggle_button_get_active (toggle_button);
|
||||
}
|
||||
else if (toggle_button == GTK_TOGGLE_BUTTON (WID ("at_screenreader_toggle"))) {
|
||||
at_startup_state.enabled.screenreader = gtk_toggle_button_get_active (toggle_button);
|
||||
}
|
||||
|
||||
at_startup_state_update (&at_startup_state);
|
||||
close_logout_update (dialog);
|
||||
}
|
||||
|
||||
static void
|
||||
at_enable_toggled (GtkToggleButton *toggle_button,
|
||||
GladeXML *dialog)
|
||||
{
|
||||
GConfClient *client = gconf_client_get_default ();
|
||||
gboolean is_enabled = gtk_toggle_button_get_active (toggle_button);
|
||||
|
||||
gconf_client_set_bool (client, ACCESSIBILITY_KEY,
|
||||
is_enabled,
|
||||
NULL);
|
||||
at_startup_state.enabled.support = is_enabled;
|
||||
g_object_unref (client);
|
||||
}
|
||||
|
||||
static void
|
||||
at_startup_update_ui (GConfClient *client,
|
||||
GladeXML *dialog)
|
||||
{
|
||||
at_startup_state_init (&at_startup_state);
|
||||
|
||||
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (WID ("at_keyboard_toggle")),
|
||||
at_startup_state.enabled.osk);
|
||||
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (WID ("at_screenreader_toggle")),
|
||||
at_startup_state.enabled.screenreader);
|
||||
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (WID ("at_magnifier_toggle")),
|
||||
at_startup_state.enabled.magnifier);
|
||||
}
|
||||
|
||||
static void
|
||||
at_enable_update (GConfClient *client,
|
||||
GladeXML *dialog)
|
||||
{
|
||||
gboolean is_enabled = gconf_client_get_bool (client, ACCESSIBILITY_KEY, NULL);
|
||||
|
||||
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (WID ("at_enable_toggle")),
|
||||
is_enabled);
|
||||
|
||||
gtk_widget_set_sensitive (WID ("at_applications_frame"), is_enabled);
|
||||
}
|
||||
|
||||
static void
|
||||
at_startup_changed (GConfClient *client,
|
||||
guint cnxn_id,
|
||||
GConfEntry *entry,
|
||||
gpointer user_data)
|
||||
{
|
||||
at_startup_state_init (&at_startup_state);
|
||||
at_startup_update_ui (client, user_data);
|
||||
close_logout_update (user_data);
|
||||
}
|
||||
|
||||
static void
|
||||
at_enable_changed (GConfClient *client,
|
||||
guint cnxn_id,
|
||||
GConfEntry *entry,
|
||||
gpointer user_data)
|
||||
{
|
||||
at_enable_update (client, user_data);
|
||||
close_logout_update (user_data);
|
||||
}
|
||||
|
||||
static void
|
||||
setup_dialog (GladeXML *dialog)
|
||||
{
|
||||
GConfClient *client;
|
||||
GtkWidget *widget;
|
||||
GObject *peditor;
|
||||
|
||||
client = gconf_client_get_default ();
|
||||
|
||||
gconf_client_add_dir (client, ACCESSIBILITY_KEY_DIR,
|
||||
GCONF_CLIENT_PRELOAD_ONELEVEL, NULL);
|
||||
|
||||
widget = WID ("at_enable_toggle");
|
||||
g_signal_connect (widget, "toggled",
|
||||
G_CALLBACK (at_enable_toggled),
|
||||
dialog);
|
||||
|
||||
peditor = gconf_peditor_new_boolean (NULL, ACCESSIBILITY_KEY,
|
||||
widget,
|
||||
NULL);
|
||||
|
||||
at_enable_update (client, dialog);
|
||||
|
||||
gconf_client_notify_add (client, ACCESSIBILITY_KEY_DIR,
|
||||
at_enable_changed,
|
||||
dialog, NULL, NULL);
|
||||
|
||||
gconf_client_add_dir (client, AT_STARTUP_DIR,
|
||||
GCONF_CLIENT_PRELOAD_ONELEVEL, NULL);
|
||||
|
||||
gconf_client_add_dir (client, SR_PREFS_DIR,
|
||||
GCONF_CLIENT_PRELOAD_ONELEVEL, NULL);
|
||||
|
||||
gconf_client_notify_add (client, AT_STARTUP_DIR,
|
||||
at_startup_changed,
|
||||
dialog, NULL, NULL);
|
||||
|
||||
gconf_client_notify_add (client, SR_PREFS_DIR,
|
||||
at_startup_changed,
|
||||
dialog, NULL, NULL);
|
||||
|
||||
widget = WID ("at_keyboard_toggle");
|
||||
|
||||
g_signal_connect (widget, "toggled",
|
||||
G_CALLBACK (at_startup_toggled),
|
||||
dialog);
|
||||
|
||||
widget = WID ("at_magnifier_toggle");
|
||||
g_signal_connect (widget, "toggled",
|
||||
G_CALLBACK (at_startup_toggled),
|
||||
dialog);
|
||||
|
||||
widget = WID ("at_screenreader_toggle");
|
||||
g_signal_connect (widget, "toggled",
|
||||
G_CALLBACK (at_startup_toggled),
|
||||
dialog);
|
||||
|
||||
widget = WID ("at_properties_dialog");
|
||||
capplet_set_icon (widget, "gnome-settings-accessibility-technologies");
|
||||
|
||||
g_signal_connect (G_OBJECT (widget),
|
||||
"response",
|
||||
G_CALLBACK (cb_dialog_response), NULL);
|
||||
|
||||
gtk_widget_show (widget);
|
||||
|
||||
g_object_unref (client);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
GladeXML *dialog;
|
||||
|
||||
bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
|
||||
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
|
||||
textdomain (GETTEXT_PACKAGE);
|
||||
|
||||
gnome_program_init ("gnome-at-properties", VERSION,
|
||||
LIBGNOMEUI_MODULE, argc, argv,
|
||||
GNOME_PARAM_APP_DATADIR, GNOMECC_DATA_DIR,
|
||||
NULL);
|
||||
|
||||
activate_settings_daemon ();
|
||||
|
||||
dialog = create_dialog ();
|
||||
|
||||
init_startup_state (dialog);
|
||||
|
||||
setup_dialog (dialog);
|
||||
|
||||
gtk_main ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
Makefile
|
||||
Makefile.in
|
||||
.deps
|
||||
.libs
|
||||
*.o
|
||||
*.lo
|
||||
*.la
|
||||
*.gladep
|
||||
*.glade.bak
|
||||
gnome-accessibility-keyboard-properties
|
||||
accessibility-keyboard.desktop
|
||||
accessibility-keyboard.desktop.in
|
||||
@@ -1,388 +0,0 @@
|
||||
2005-01-05 Sebastien Bacher <seb128@debian.org>
|
||||
|
||||
* gnome-accessibility-keyboard-properties.glade: fixed a typo in the
|
||||
label-for for the "pixels/second" label (Part of #162368).
|
||||
|
||||
2004-11-09 Mark McLoughlin <mark@skynet.ie>
|
||||
|
||||
* Makefile.am: install .desktop file in $(datadir)/applications.
|
||||
|
||||
* accessibility-keyboard.desktop.in: add OnlyShowIn=GNOME;
|
||||
|
||||
2004-10-14 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* Release 2.8.1
|
||||
|
||||
2004-08-20 Frederic Crozat <fcrozat@mandrakesoft.com>
|
||||
|
||||
* gnome-accessibility-keyboard-properties.c: (main):
|
||||
Use themed icon for window hint.
|
||||
|
||||
2004-07-06 Padraig O'Briain <padraig.obriain@sun.com>
|
||||
|
||||
* gnome-accessibility-keyboard-properties.glade: Add label-for/
|
||||
labelled-by relations. Fixes bug #144174.
|
||||
|
||||
2004-04-15 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* Release 2.6.1
|
||||
|
||||
2004-04-01 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* Release 2.6.0.3
|
||||
|
||||
2004-03-30 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* Release 2.6.0.1
|
||||
|
||||
2004-03-23 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* Release 2.6.0
|
||||
|
||||
2004-03-11 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* Release 2.5.4
|
||||
|
||||
2004-02-16 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* accessibility-keyboard.c (cb_load_CDE_file) : Add a kludge to set
|
||||
the vertical size based on the monitor size until the filesel can do
|
||||
a better job of doing it itself.
|
||||
|
||||
2003-12-07 Jan Arne Petersen <jpetersen@uni-bonn.de>
|
||||
|
||||
* accessibility-keyboard.c: (load_CDE_file),
|
||||
(fchooser_handle_response), (cb_load_CDE_file): replace
|
||||
GtkFileSelection with GtkFileChooser.
|
||||
|
||||
2004-02-13 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* Release 2.5.3
|
||||
|
||||
2004-02-12 Mark McLoughlin <mark@skynet.ie>
|
||||
|
||||
* gnome-accessibility-keyboard-properties.c: (dialog_response): Update
|
||||
help link to point to user-guide.xml
|
||||
|
||||
2004-01-14 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* Release 2.5.2
|
||||
|
||||
2003-12-30 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* Release 2.5.1.1
|
||||
|
||||
2003-12-30 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* Release 2.5.1
|
||||
|
||||
2003-11-18 Padraig O'Briain <padraig.obriain@sun.com>
|
||||
|
||||
* gnome-accessibility-keyboard-properties.glade: Add atk relations.
|
||||
Fixes bug #126718
|
||||
|
||||
2003-11-03 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
http://bugzilla.gnome.org/show_bug.cgi?id=120842
|
||||
* gnome-accessibility-keyboard-properties.c : older xservers require
|
||||
X11/Xlib.h too, its not sun specific.
|
||||
|
||||
2003-10-28 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* Release 2.5.0
|
||||
|
||||
2003-10-28 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
http://bugzilla.gnome.org/show_bug.cgi?id=120842
|
||||
* gnome-accessibility-keyboard-properties.glade : Remove bone headed
|
||||
spitting of checkbox and label.
|
||||
* accessibility-keyboard.c (setup_toggles) : It was probably done so
|
||||
that the headers could be made bold.
|
||||
|
||||
Mon Aug 11 11:55:49 2003 Jonathan Blandford <jrb@redhat.com>
|
||||
|
||||
* gnome-accessibility-keyboard-properties.glade: Patch from Elijah
|
||||
Newren <newren@math.utah.edu> to bring the possible repeat range
|
||||
in sync with the keyboard capplet.
|
||||
|
||||
2003-08-01 Dennis Cranston <dennis_cranston at yahoo com>
|
||||
|
||||
* gnome-accessibility-keyboard-properties.glade: Patch to add
|
||||
two more pixels of spacing between action area and vbox of
|
||||
preferences dialog.
|
||||
|
||||
2003-07-24 Pasupathi Duraisamy <pasupathi.duraisamy@wipro.com>
|
||||
|
||||
* gnome-accessibility-keyboard-properties.glade:
|
||||
Allow only numeric values in spinbutton.
|
||||
Fixes bugzilla bug# 118175
|
||||
|
||||
2003-07-17 Dennis Cranston <dennis_cranston at yahoo com>
|
||||
|
||||
* gnome-accessibility-keyboard-properties.glade,
|
||||
accessibility-keyboard.c: HIG fixes for ui-review bug
|
||||
report #98915.
|
||||
|
||||
2003-07-16 Dennis Cranston <dennis_cranston at yahoo com>
|
||||
|
||||
* gnome-accessibility-keyboard-properties.glade: Adjust widget
|
||||
padding to make dialog a little more HIG compliant.
|
||||
|
||||
2003-07-07 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* Release 2.3.4
|
||||
|
||||
2003-06-24 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* Release 2.3.3
|
||||
|
||||
2003-05-07 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* Release 2.3.1
|
||||
|
||||
2003-05-05 Kjartan Maraas <kmaraas@gnome.org>
|
||||
|
||||
* gnome-accessibility-keyboard-properties.c: Merge fix
|
||||
for bug #110266.
|
||||
|
||||
2003-04-30 Alex Duggan <aldug@astrolinux.com>
|
||||
|
||||
* gnome-accessibility-keyboard-properties.c: use appropriate
|
||||
window border icon.
|
||||
|
||||
2003-04-30 Kjartan Maraas <kmaraas@gnome.org>
|
||||
|
||||
* gnome-accessibility-keyboard-properties.c: Fix build
|
||||
on Solaris. Fixes bug #106196.
|
||||
|
||||
2003-02-21 Calum Benson <calum.benson@sun.com>
|
||||
|
||||
* gnome-accessibility-keyboard-properties.glade:
|
||||
HIG-ified frames and labels.
|
||||
|
||||
Tue Feb 4 17:09:18 2003 Jonathan Blandford <jrb@redhat.com>
|
||||
|
||||
* Release 2.2.0.1
|
||||
|
||||
Tue Jan 21 01:15:14 2003 Jonathan Blandford <jrb@gnome.org>
|
||||
|
||||
* Release 2.2.0
|
||||
|
||||
Thu Jan 16 02:41:09 2003 Jonathan Blandford <jrb@gnome.org>
|
||||
|
||||
* Release 2.1.7
|
||||
|
||||
2003-01-10 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* Release 2.1.6
|
||||
|
||||
2003-01-08 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
http://bugzilla.gnome.org/show_bug.cgi?id=96483
|
||||
* accessibility-keyboard.c : sigh. The defaults apparently need to be
|
||||
0 too.
|
||||
|
||||
2003-01-08 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
http://bugzilla.gnome.org/show_bug.cgi?id=96484
|
||||
* accessibility-keyboard.c : make 0 min for slow and bounce
|
||||
|
||||
2003-01-07 Abel Cheung <maddog@linux.org.hk>
|
||||
|
||||
* gnome-accessibility-keyboard-properties.c (xkb_enabled): Fix typo
|
||||
in error msg dialog.
|
||||
|
||||
2002-12-18 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* Release 2.1.5
|
||||
|
||||
2002-11-23 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* Release 2.1.3
|
||||
|
||||
2002-11-13 Pasupathi Duraisamy <pasupathi.duraisamy@wipro.com>
|
||||
|
||||
* accessibility-keyboard.c : Tweaked the incremental values
|
||||
of spin button to 10. Fixes #95511
|
||||
|
||||
2002-11-02 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* Release 2.1.2
|
||||
|
||||
2002-11-02 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* accessibility-keyboard.c : Merge in Calum's new layout
|
||||
* gnome-accessibility-keyboard-properties.glade : ditto.
|
||||
|
||||
2002-10-21 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* Release 2.1.1
|
||||
|
||||
2002-10-11 Balamurali Viswanathan <balamurali.viswanathan@wipro.com>
|
||||
|
||||
* gnome-accessibility-keyboard-properties.c (xkb_enabled): Dismiss
|
||||
the XKB extensions warning dialog. Fixes #95069
|
||||
|
||||
2002-10-01 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* Release 2.1.0.1
|
||||
|
||||
2002-09-26 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* gnome-accessibility-keyboard-properties.glade : add ellipsis for CDE
|
||||
import and Repeat key buttons.
|
||||
|
||||
2002-09-25 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* gnome-accessibility-keyboard-properties.glade : remove spaces before
|
||||
colons and fix the title.
|
||||
|
||||
2002-09-24 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* accessibility-keyboard.c (load_CDE_file) : blah the
|
||||
XrmGetFileDatabase is implementation specific in its handling of
|
||||
invalid files. Add a hack that if the imported file did not contain
|
||||
any resources it was invalid.
|
||||
|
||||
* gnome-accessibility-keyboard-properties.glade : add mnemonic_widget
|
||||
for mousekeys_init_delay_title. Remove the atkrelations for things
|
||||
with mnemonic_widget.
|
||||
|
||||
2002-09-11 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* gnome-accessibility-keyboard-properties.glade : Fix conflicting
|
||||
accelerators.
|
||||
|
||||
* accessibility-keyboard.c (setup_dialog) : connect the simple items
|
||||
before the master.
|
||||
(cb_master_enable_toggle) : desensitize the subfeature content if the
|
||||
master switch is disabled.
|
||||
|
||||
2002-09-09 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* gnome-accessibility-keyboard-properties.c (main) : add a warning if
|
||||
xkb is not available.
|
||||
|
||||
2002-09-09 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* accessibility-keyboard.c : on 2nd thought lets disable the 'beep on
|
||||
feature change' if the master switch is off.
|
||||
|
||||
http://bugzilla.gnome.org/show_bug.cgi?id=92488
|
||||
* gnome-accessibility-keyboard-properties.glade : tweak accelerators
|
||||
|
||||
2002-09-09 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
http://bugzilla.gnome.org/show_bug.cgi?id=90936
|
||||
* gnome-accessibility-keyboard-properties.glade : Add mnemonic_widget
|
||||
assignments and fix a typo.
|
||||
|
||||
2002-08-28 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
http://bugzilla.gnome.org/show_bug.cgi?id=91854
|
||||
* accessibility-keyboard.c : the max slow key delay is 500ms.
|
||||
We clamp that in the settings daemon. Fix the ui to reflect that.
|
||||
|
||||
2002-08-21 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* Release 2.1.0
|
||||
|
||||
2002-08-19 Ross Burton <ross@burtonini.com>
|
||||
|
||||
* accessibility-keyboard.desktop.in: Fix the desktop file so that
|
||||
it validates.
|
||||
|
||||
2002-08-05 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* gnome-accessibility-keyboard-properties.glade : Restore the master
|
||||
toggle.
|
||||
|
||||
* accessibility-keyboard.c (setup_dialog) : support the master toggle.
|
||||
(cb_master_enable_toggle) : new.
|
||||
|
||||
2002-08-01 jacob berkman <jacob@ximian.com>
|
||||
|
||||
* accessibility-keyboard.c (setup_accessX_dialog): fix widget name
|
||||
for the keyboard capplet button
|
||||
|
||||
* gnome-accessibility-keyboard-properties.c (dialog_response):
|
||||
don't quit when the import accessx button is clicked (#89358)
|
||||
|
||||
2002-06-21 Satyajit Kanungo <satyajit.kanungo@wipro.com>
|
||||
|
||||
* gnome-accessibility-keyboard-properties.c :
|
||||
Changed the help link to point to the correct document (#85895)
|
||||
|
||||
2002-06-10 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* accessibility-keyboard.c : tweak the layout as requested and adjust
|
||||
the max slowkey delay to 500 to avoid losing the keyboard due to some
|
||||
sort of an X problem.
|
||||
|
||||
2002-06-17 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* Release 2.0.0
|
||||
|
||||
Sun May 26 11:44:41 2002 Jonathan Blandford <jrb@gnome.org>
|
||||
|
||||
* gnome-accessibility-keyboard-properties.c (main): use APPID
|
||||
instead of argv[0]
|
||||
|
||||
2002-05-08 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* gnome-accessibility-keyboard-properties.c (dialog_response) : fix
|
||||
path to help.
|
||||
|
||||
2002-04-24 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* accessibility-keyboard.c : adjust the defaults.
|
||||
|
||||
2002-04-18 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* accessibility-keyboard.c (setup_accessX_dialog) : Use 'clicked'
|
||||
rather than 'activated' for the file sel.
|
||||
|
||||
2002-04-10 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* gnome-accessibility-keyboard-properties.glade2 (</) : slim down the
|
||||
tooltips.
|
||||
|
||||
Wed Apr 10 18:02:29 2002 Jonathan Blandford <jrb@gnome.org>
|
||||
|
||||
* accessibility-keyboard.desktop.in (Exec): s/gnome2/gnome
|
||||
|
||||
2002-03-30 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* gnome-accessibility-keyboard-properties.glade2 : rename Sample -> Text
|
||||
because that makes more sense.
|
||||
|
||||
http://bugzilla.gnome.org/show_bug.cgi?id=76315
|
||||
* accessibility-keyboard.desktop.in : rename from AccessX -> Keyboard
|
||||
|
||||
2002-03-29 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* accessibility-keyboard.c (setup_dialog) : spelling error.
|
||||
(CONFIG_ROOT) : fix spelling error in the schema.
|
||||
|
||||
2002-03-29 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* accessibility-keyboard.c : tweak the mouse key slider ranges
|
||||
max_speed : 100 pixels every 10 msec is plenty fast Limit things to
|
||||
1..100 default 10 step 5
|
||||
accel_time : 10..5000 default 300 step 100
|
||||
init_delay : 10..5000 default 300 step 100
|
||||
|
||||
2002-03-28 jacob berkman <jacob@ximian.com>
|
||||
|
||||
* accessibility-keyboard.c: on solaris Xresource.h sez /* You must
|
||||
include <X11/Xlib.h> before including this file */
|
||||
|
||||
2002-03-25 Jody Goldberg <jody@gnome.org>
|
||||
|
||||
* accessibility-keyboard.c (setup_accessX_dialog) : Only load the
|
||||
necessary toplevel widget in the non-dialog case.
|
||||
(setup_dialog) : pass as_dialog to the sub-init routines.
|
||||
(setup_images) : only load widgets appropriate for the current state.
|
||||
(setup_ranges) : ditto, and be more vocal about invalid glade.
|
||||
(setup_simple_toggles) : ditto.
|
||||
(setup_toggles) : ditto.
|
||||
@@ -1,36 +0,0 @@
|
||||
noinst_LIBRARIES = libaccessibility-keyboard.a
|
||||
|
||||
libaccessibility_keyboard_a_SOURCES = \
|
||||
accessibility-keyboard.c \
|
||||
accessibility-keyboard.h
|
||||
|
||||
# in case we need to forward port the sun accessX extension
|
||||
# AccessXcomm.c
|
||||
|
||||
bin_PROGRAMS = gnome-accessibility-keyboard-properties
|
||||
|
||||
gnome_accessibility_keyboard_properties_SOURCES = gnome-accessibility-keyboard-properties.c
|
||||
gnome_accessibility_keyboard_properties_LDADD = \
|
||||
libaccessibility-keyboard.a $(GNOMECC_CAPPLETS_LIBS)
|
||||
|
||||
@INTLTOOL_DESKTOP_RULE@
|
||||
|
||||
pixmapdir = $(GNOMECC_PIXMAPS_DIR)
|
||||
pixmap_DATA = \
|
||||
accessibility-keyboard-togglekey.png \
|
||||
accessibility-keyboard-mousekey.png \
|
||||
accessibility-keyboard-slowkey.png \
|
||||
accessibility-keyboard-stickykey.png \
|
||||
accessibility-keyboard-bouncekey.png
|
||||
|
||||
Gladedir = $(GNOMECC_GLADE_DIR)
|
||||
Glade_DATA = gnome-accessibility-keyboard-properties.glade
|
||||
|
||||
desktopdir = $(datadir)/applications
|
||||
Desktop_in_files = accessibility-keyboard.desktop.in
|
||||
desktop_DATA = $(Desktop_in_files:.desktop.in=.desktop)
|
||||
|
||||
INCLUDES = $(GNOMECC_CAPPLETS_CFLAGS)
|
||||
CLEANFILES = $(GNOMECC_CAPPLETS_CLEANFILES) $(Desktop_in_files) $(desktop_DATA)
|
||||
EXTRA_DIST = $(Glade_DATA) $(pixmap_DATA)
|
||||
|
||||
|
Before Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 3.1 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 3.2 KiB |
@@ -1,477 +0,0 @@
|
||||
/* -*- mode: c; style: linux -*- */
|
||||
|
||||
/* accessibility-keyboard.c
|
||||
* Copyright (C) 2002 Ximian, Inc.
|
||||
*
|
||||
* Written by: Jody Goldberg <jody@gnome.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <gnome.h>
|
||||
#include <gconf/gconf-client.h>
|
||||
#include <glade/glade.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xresource.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "capplet-util.h"
|
||||
#include "capplet-stock-icons.h"
|
||||
#include "gconf-property-editor.h"
|
||||
#include "activate-settings-daemon.h"
|
||||
|
||||
#define CONFIG_ROOT "/desktop/gnome/accessibility/keyboard"
|
||||
|
||||
static struct {
|
||||
char const * const checkbox;
|
||||
char const * const image;
|
||||
char const * const image_file;
|
||||
char const * const gconf_key;
|
||||
char const * const content [3];
|
||||
gboolean always_enabled;
|
||||
} const features [] = {
|
||||
{ "repeatkeys_enable", "repeatkeys_image", KEYBOARD_REPEAT,
|
||||
"/desktop/gnome/peripherals/keyboard/repeat",
|
||||
{ "repeatkeys_table", NULL, NULL }, TRUE },
|
||||
{ "bouncekeys_enable", "bouncekeys_image", ACCESSX_KEYBOARD_BOUNCE,
|
||||
CONFIG_ROOT "/bouncekeys_enable",
|
||||
{ "bouncekey_table", NULL, NULL }, FALSE },
|
||||
{ "slowkeys_enable", "slowkeys_image", ACCESSX_KEYBOARD_SLOW,
|
||||
CONFIG_ROOT "/slowkeys_enable",
|
||||
{ "slowkeys_table", NULL, NULL }, FALSE },
|
||||
{ "mousekeys_enable", "mousekeys_image", ACCESSX_KEYBOARD_MOUSE,
|
||||
CONFIG_ROOT "/mousekeys_enable",
|
||||
{ "mousekeys_table", NULL, NULL }, FALSE },
|
||||
{ "stickykeys_enable", "stickykeys_image", ACCESSX_KEYBOARD_STICK,
|
||||
CONFIG_ROOT "/stickykeys_enable",
|
||||
{ "stickeykeys_table", NULL, NULL }, FALSE },
|
||||
{ "togglekeys_enable", "togglekeys_image", ACCESSX_KEYBOARD_TOGGLE,
|
||||
CONFIG_ROOT "/togglekeys_enable",
|
||||
{ NULL, NULL, NULL }, FALSE },
|
||||
{ "timeout_enable", NULL, NULL,
|
||||
CONFIG_ROOT "/timeout_enable",
|
||||
{ "timeout_slide", "timeout_spin", "timeout_label" }, FALSE },
|
||||
{ "feature_state_change_beep", NULL, NULL,
|
||||
CONFIG_ROOT "/feature_state_change_beep",
|
||||
{ NULL, NULL, NULL }, FALSE }
|
||||
};
|
||||
|
||||
static struct {
|
||||
char const * const slide;
|
||||
char const * const spin;
|
||||
int default_val;
|
||||
int min_val;
|
||||
int max_val;
|
||||
int step_size;
|
||||
char const * const gconf_key;
|
||||
} const ranges [] = {
|
||||
{ "repeatkeys_delay_slide", "repeatkeys_delay_spin", 500, 100, 1500, 10,
|
||||
"/desktop/gnome/peripherals/keyboard/delay" },
|
||||
{ "repeatkeys_rate_slide", "repeatkeys_rate_spin", 90, 10, 110, 10,
|
||||
"/desktop/gnome/peripherals/keyboard/rate" },
|
||||
{ "bouncekeys_delay_slide", "bouncekeys_delay_spin", 0, 0, 900, 10,
|
||||
CONFIG_ROOT "/bouncekeys_delay" },
|
||||
{ "slowkeys_delay_slide", "slowkeys_delay_spin", 0, 0, 500, 10,
|
||||
CONFIG_ROOT "/slowkeys_delay" },
|
||||
/* WARNING anything larger than approx 512 seems to loose all keyboard input */
|
||||
{ "mousekeys_max_speed_slide", "mousekeys_max_speed_spin", 300, 10, 500, 10,
|
||||
CONFIG_ROOT "/mousekeys_max_speed" },
|
||||
{ "mousekeys_accel_time_slide", "mousekeys_accel_time_spin", 300, 10, 3000, 10,
|
||||
CONFIG_ROOT "/mousekeys_accel_time" },
|
||||
{ "mousekeys_init_delay_slide", "mousekeys_init_delay_spin", 300, 10, 5000, 10,
|
||||
CONFIG_ROOT "/mousekeys_init_delay" },
|
||||
{ "timeout_slide", "timeout_spin", 200, 10, 500, 10,
|
||||
CONFIG_ROOT "/timeout" },
|
||||
};
|
||||
|
||||
static void
|
||||
set_sensitive (GladeXML *dialog, char const *name, gboolean state)
|
||||
{
|
||||
if (name != NULL)
|
||||
gtk_widget_set_sensitive (WID (name), state);
|
||||
}
|
||||
|
||||
/**
|
||||
* cb_feature_toggled :
|
||||
*
|
||||
* NOTE : for this to work the toggle MUST be initialized to active in the
|
||||
* glade file. That way if the gconf setting is FALSE the toggle will fire.
|
||||
*/
|
||||
static void
|
||||
cb_feature_toggled (GtkToggleButton *btn, gpointer feature_index)
|
||||
{
|
||||
gboolean const state =
|
||||
(GTK_WIDGET_STATE (btn) != GTK_STATE_INSENSITIVE) &&
|
||||
gtk_toggle_button_get_active (btn);
|
||||
GladeXML *dialog = g_object_get_data (G_OBJECT (btn), "dialog");
|
||||
int feature, i;
|
||||
|
||||
g_return_if_fail (dialog != NULL);
|
||||
|
||||
feature = GPOINTER_TO_INT (feature_index);
|
||||
|
||||
if (features [feature].image != NULL)
|
||||
set_sensitive (dialog, features [feature].image, state);
|
||||
for (i = G_N_ELEMENTS (features [feature].content) ; i-- > 0 ; )
|
||||
set_sensitive (dialog, features [feature].content [i], state);
|
||||
}
|
||||
|
||||
static void
|
||||
setup_toggles (GladeXML *dialog, GConfChangeSet *changeset)
|
||||
{
|
||||
GObject *peditor;
|
||||
GtkWidget *checkbox;
|
||||
GtkWidget *checkbox_label;
|
||||
int i = G_N_ELEMENTS (features);
|
||||
|
||||
while (i-- > 0) {
|
||||
checkbox = WID (features [i].checkbox);
|
||||
|
||||
g_return_if_fail (checkbox != NULL);
|
||||
|
||||
/* you can't do this from glade */
|
||||
checkbox_label = gtk_bin_get_child (GTK_BIN (checkbox));
|
||||
g_object_set (G_OBJECT (checkbox_label), "use_markup", TRUE, NULL);
|
||||
|
||||
g_object_set_data (G_OBJECT (checkbox), "dialog", dialog);
|
||||
g_signal_connect (G_OBJECT (checkbox),
|
||||
"toggled",
|
||||
G_CALLBACK (cb_feature_toggled), GINT_TO_POINTER (i));
|
||||
peditor = gconf_peditor_new_boolean (changeset,
|
||||
(gchar *)features [i].gconf_key, checkbox, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
setup_simple_toggles (GladeXML *dialog, GConfChangeSet *changeset)
|
||||
{
|
||||
static struct {
|
||||
char const *gconf_key;
|
||||
char const *checkbox;
|
||||
} const simple_toggles [] = {
|
||||
{ CONFIG_ROOT "/bouncekeys_beep_reject", "bouncekeys_beep_reject" },
|
||||
|
||||
{ CONFIG_ROOT "/slowkeys_beep_press", "slowkeys_beep_press" },
|
||||
{ CONFIG_ROOT "/slowkeys_beep_accept", "slowkeys_beep_accept" },
|
||||
{ CONFIG_ROOT "/slowkeys_beep_reject", "slowkeys_beep_reject" },
|
||||
|
||||
{ CONFIG_ROOT "/stickykeys_two_key_off", "stickykeys_two_key_off" },
|
||||
{ CONFIG_ROOT "/stickykeys_modifier_beep", "stickykeys_modifier_beep" },
|
||||
};
|
||||
int i = G_N_ELEMENTS (simple_toggles);
|
||||
while (i-- > 0) {
|
||||
GtkWidget *w = WID (simple_toggles [i].checkbox);
|
||||
|
||||
g_return_if_fail (w != NULL);
|
||||
|
||||
gconf_peditor_new_boolean (changeset,
|
||||
(gchar *) simple_toggles [i].gconf_key,
|
||||
w, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
setup_ranges (GladeXML *dialog, GConfChangeSet *changeset)
|
||||
{
|
||||
GObject *peditor;
|
||||
GtkWidget *slide, *spin;
|
||||
GtkAdjustment *adjustment;
|
||||
int i = G_N_ELEMENTS (ranges);
|
||||
|
||||
while (i-- > 0) {
|
||||
slide = WID (ranges [i].slide);
|
||||
spin = WID (ranges [i].spin);
|
||||
g_return_if_fail (slide != NULL);
|
||||
g_return_if_fail (spin != NULL);
|
||||
|
||||
adjustment = gtk_range_get_adjustment (GTK_RANGE (slide));
|
||||
|
||||
g_return_if_fail (adjustment != NULL);
|
||||
|
||||
adjustment->value = ranges [i].default_val;
|
||||
adjustment->lower = ranges [i].min_val;
|
||||
adjustment->upper = ranges [i].max_val + ranges [i].step_size;
|
||||
adjustment->step_increment = ranges [i].step_size;
|
||||
adjustment->page_increment = ranges [i].step_size;
|
||||
adjustment->page_size = ranges [i].step_size;
|
||||
|
||||
gtk_adjustment_changed (adjustment);
|
||||
gtk_spin_button_configure (GTK_SPIN_BUTTON (spin), adjustment,
|
||||
ranges [i].step_size, 0);
|
||||
peditor = gconf_peditor_new_numeric_range (changeset,
|
||||
(gchar *)ranges [i].gconf_key, slide,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
setup_images (GladeXML *dialog)
|
||||
{
|
||||
int i = G_N_ELEMENTS (features);
|
||||
while (i-- > 0)
|
||||
if (features [i].image != NULL)
|
||||
gtk_image_set_from_stock (GTK_IMAGE (WID (features [i].image)),
|
||||
features [i].image_file,
|
||||
keyboard_capplet_icon_get_size ());
|
||||
}
|
||||
|
||||
static void
|
||||
cb_launch_mouse_capplet (GtkButton *button, GtkWidget *dialog)
|
||||
{
|
||||
GError *err = NULL;
|
||||
if (!g_spawn_command_line_async ("gnome-mouse-properties", &err))
|
||||
capplet_error_dialog (GTK_WINDOW (gtk_widget_get_toplevel (dialog)),
|
||||
_("There was an error launching the mouse preferences dialog: %s"),
|
||||
err);
|
||||
}
|
||||
|
||||
static void
|
||||
cb_master_enable_toggle (GtkToggleButton *btn, GladeXML *dialog)
|
||||
{
|
||||
int i = G_N_ELEMENTS (features);
|
||||
gboolean flag = gtk_toggle_button_get_active (btn);
|
||||
GtkWidget *w;
|
||||
|
||||
while (i-- > 0) {
|
||||
if (!features [i].always_enabled) {
|
||||
w = WID (features [i].checkbox);
|
||||
gtk_widget_set_sensitive (w, flag);
|
||||
cb_feature_toggled (GTK_TOGGLE_BUTTON (w), GINT_TO_POINTER (i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
setup_dialog (GladeXML *dialog, GConfChangeSet *changeset)
|
||||
{
|
||||
GtkWidget *master_enable = WID ("master_enable");
|
||||
|
||||
capplet_init_stock_icons ();
|
||||
setup_images (dialog);
|
||||
setup_ranges (dialog, changeset);
|
||||
setup_toggles (dialog, changeset);
|
||||
setup_simple_toggles (dialog, changeset);
|
||||
|
||||
g_signal_connect (master_enable,
|
||||
"toggled",
|
||||
G_CALLBACK (cb_master_enable_toggle), dialog);
|
||||
gconf_peditor_new_boolean (changeset,
|
||||
CONFIG_ROOT "/enable",
|
||||
GTK_WIDGET (master_enable), NULL);
|
||||
}
|
||||
|
||||
/*******************************************************************************/
|
||||
|
||||
static gboolean
|
||||
xrm_get_bool (GConfClient *client, XrmDatabase *db, char const *gconf_key,
|
||||
char const *res_str, char const *class_str)
|
||||
{
|
||||
XrmValue resourceValue;
|
||||
char *res;
|
||||
|
||||
if (!XrmGetResource (*db, res_str, class_str, &res, &resourceValue))
|
||||
return FALSE;
|
||||
gconf_client_set_bool (client, gconf_key,
|
||||
!g_ascii_strcasecmp (resourceValue.addr, "True"), NULL);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
xrm_get_int (GConfClient *client, XrmDatabase *db, char const *gconf_key,
|
||||
char const *res_str, char const *class_str, float scale)
|
||||
{
|
||||
XrmValue resourceValue;
|
||||
char *res;
|
||||
int value, log_scale;
|
||||
char resource [256];
|
||||
|
||||
snprintf (resource, sizeof (resource), "%s.value", res_str);
|
||||
if (!XrmGetResource (*db, resource, class_str, &res, &resourceValue))
|
||||
return FALSE;
|
||||
value = atoi (resourceValue.addr);
|
||||
|
||||
snprintf (resource, sizeof (resource), "%s.decimalPoints", res_str);
|
||||
if (!XrmGetResource (*db, resource, class_str, &res, &resourceValue))
|
||||
return FALSE;
|
||||
log_scale = atoi (resourceValue.addr);
|
||||
|
||||
while (log_scale-- > 0)
|
||||
scale /= 10.;
|
||||
|
||||
gconf_client_set_int (client, gconf_key, value, NULL);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* This loads the current users XKB settings from their file */
|
||||
static gboolean
|
||||
load_CDE_file (GtkFileChooser *fchooser)
|
||||
{
|
||||
char *file = gtk_file_chooser_get_filename (fchooser);
|
||||
GConfClient *client;
|
||||
XrmDatabase db;
|
||||
gboolean found = FALSE;
|
||||
|
||||
if (!(db = XrmGetFileDatabase (file))) {
|
||||
GtkWidget *warn = gtk_message_dialog_new (
|
||||
gtk_window_get_transient_for (GTK_WINDOW (fchooser)),
|
||||
GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
|
||||
_("Unable to import AccessX settings from file '%s'"),
|
||||
file);
|
||||
g_signal_connect (warn,
|
||||
"response",
|
||||
G_CALLBACK (gtk_widget_destroy), NULL);
|
||||
gtk_widget_show (warn);
|
||||
g_free (file);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
client = gconf_client_get_default ();
|
||||
gconf_client_set_bool (client, CONFIG_ROOT "/enable", TRUE, NULL);
|
||||
|
||||
found |= xrm_get_bool (client, &db, CONFIG_ROOT "/feature_state_change_beep",
|
||||
"*SoundOnOffToggle.set", "AccessX*ToggleButtonGadget.XmCSet");
|
||||
found |= xrm_get_bool (client, &db, CONFIG_ROOT "/timeout_enable",
|
||||
"*TimeOutToggle.set", "AccessX*ToggleButtonGadget.XmCSet");
|
||||
found |= xrm_get_bool (client, &db, CONFIG_ROOT "/stickykeys_enable",
|
||||
"*StickyKeysToggle.set", "AccessX*ToggleButtonGadget.XmCSet");
|
||||
found |= xrm_get_bool (client, &db, CONFIG_ROOT "/mousekeys_enable",
|
||||
"*MouseKeysToggle.set", "AccessX*ToggleButtonGadget.XmCSet");
|
||||
found |= xrm_get_bool (client, &db, CONFIG_ROOT "/togglekeys_enable",
|
||||
"*ToggleKeysToggle.set", "AccessX*ToggleButtonGadget.XmCSet");
|
||||
found |= xrm_get_bool (client, &db, CONFIG_ROOT "/slowkeys_enable",
|
||||
"*SlowKeysToggle.set", "AccessX*ToggleButtonGadget.XmCSet");
|
||||
found |= xrm_get_bool (client, &db, CONFIG_ROOT "/bouncekeys_enable",
|
||||
"*BounceKeysToggle.set", "AccessX*ToggleButtonGadget.XmCSet");
|
||||
found |= xrm_get_bool (client, &db, CONFIG_ROOT "/stickykeys_modifier_beep",
|
||||
"*StickyModSoundToggle.set", "AccessX*ToggleButtonGadget.XmCSet");
|
||||
found |= xrm_get_bool (client, &db, CONFIG_ROOT "/stickykeys_two_key_off",
|
||||
"*StickyTwoKeysToggle.set", "AccessX*ToggleButtonGadget.XmCSet");
|
||||
found |= xrm_get_bool (client, &db, CONFIG_ROOT "/slowkeys_beep_press",
|
||||
"*SlowKeysOnPressToggle.set", "AccessX*ToggleButtonGadget.XmCSet");
|
||||
found |= xrm_get_bool (client, &db, CONFIG_ROOT "/slowkeys_beep_accept",
|
||||
"*SlowKeysOnAcceptToggle.set", "AccessX*ToggleButtonGadget.XmCSet");
|
||||
found |= xrm_get_int (client, &db, CONFIG_ROOT "/timeout",
|
||||
"*TimeOutScale", "AccessX*XmScale", 60);
|
||||
found |= xrm_get_int (client, &db, CONFIG_ROOT "/mousekeys_max_speed",
|
||||
"*MouseMaxSpeedScale", "AccessX*XmScale", 1);
|
||||
found |= xrm_get_int (client, &db, CONFIG_ROOT "/mousekeys_accel_time",
|
||||
"*MouseAccelScale", "AccessX*XmScale", 1);
|
||||
found |= xrm_get_int (client, &db, CONFIG_ROOT "/mousekeys_init_delay",
|
||||
"*MouseDelayScale", "AccessX*XmScale", 1);
|
||||
found |= xrm_get_int (client, &db, CONFIG_ROOT "/slowkeys_delay",
|
||||
"*KRGSlowKeysDelayScale", "AccessX*XmScale", 1000);
|
||||
found |= xrm_get_int (client, &db, CONFIG_ROOT "/bouncekeys_delay",
|
||||
"*KRGDebounceScale", "AccessX*XmScale", 1000);
|
||||
|
||||
/* Set the master enable flag last */
|
||||
found |= xrm_get_bool (client, &db, CONFIG_ROOT "/enable",
|
||||
"*EnableAccessXToggle.set", "AccessX*ToggleButtonGadget.XmCSet");
|
||||
|
||||
g_object_unref (client);
|
||||
|
||||
if (!found) {
|
||||
/* it would be nice to have a better message bu that would
|
||||
* break string freeze
|
||||
*/
|
||||
GtkWidget *warn = gtk_message_dialog_new (
|
||||
gtk_window_get_transient_for (GTK_WINDOW (fchooser)),
|
||||
GTK_DIALOG_MODAL, GTK_MESSAGE_ERROR, GTK_BUTTONS_OK,
|
||||
_("Unable to import AccessX settings from file '%s'"),
|
||||
file);
|
||||
g_signal_connect (warn,
|
||||
"response",
|
||||
G_CALLBACK (gtk_widget_destroy), NULL);
|
||||
gtk_widget_show (warn);
|
||||
g_free (file);
|
||||
return FALSE;
|
||||
}
|
||||
g_free(file);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
fchooser_handle_response (GtkFileChooser *fchooser, gint response, gpointer data)
|
||||
{
|
||||
char *file_name;
|
||||
|
||||
if (response == GTK_RESPONSE_OK) {
|
||||
file_name = gtk_file_chooser_get_filename (fchooser);
|
||||
|
||||
/* Change into directory if that's what user selected */
|
||||
if (g_file_test (file_name, G_FILE_TEST_IS_DIR))
|
||||
gtk_file_chooser_set_current_folder (fchooser, file_name);
|
||||
else if (load_CDE_file (fchooser))
|
||||
gtk_widget_destroy (GTK_WIDGET (fchooser));
|
||||
|
||||
g_free (file_name);
|
||||
} else {
|
||||
gtk_widget_destroy (GTK_WIDGET (fchooser));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cb_load_CDE_file (GtkButton *button, GtkWidget *dialog)
|
||||
{
|
||||
GtkFileChooser *fchooser = GTK_FILE_CHOOSER (
|
||||
gtk_file_chooser_dialog_new (_("Import Feature Settings File"),
|
||||
GTK_WINDOW (gtk_widget_get_toplevel (dialog)),
|
||||
GTK_FILE_CHOOSER_ACTION_OPEN,
|
||||
GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
|
||||
_("_Import"), GTK_RESPONSE_OK,
|
||||
NULL));
|
||||
|
||||
gtk_window_set_position (GTK_WINDOW (fchooser), GTK_WIN_POS_MOUSE);
|
||||
gtk_window_set_modal (GTK_WINDOW (fchooser), TRUE);
|
||||
g_signal_connect (G_OBJECT (fchooser),
|
||||
"response",
|
||||
G_CALLBACK (fchooser_handle_response), NULL);
|
||||
|
||||
gtk_widget_show (GTK_WIDGET (fchooser));
|
||||
}
|
||||
|
||||
/*******************************************************************************/
|
||||
|
||||
GtkWidget *
|
||||
setup_accessX_dialog (GConfChangeSet *changeset)
|
||||
{
|
||||
GConfClient *client;
|
||||
char const *toplevel_name = "accessX_dialog";
|
||||
GladeXML *dialog = glade_xml_new (GNOMECC_DATA_DIR
|
||||
"/interfaces/gnome-accessibility-keyboard-properties.glade",
|
||||
toplevel_name, NULL);
|
||||
GtkWidget *toplevel = WID (toplevel_name);
|
||||
|
||||
client = gconf_client_get_default ();
|
||||
gconf_client_add_dir (client, CONFIG_ROOT, GCONF_CLIENT_PRELOAD_ONELEVEL, NULL);
|
||||
g_object_unref (client);
|
||||
|
||||
setup_dialog (dialog, changeset);
|
||||
|
||||
g_signal_connect (G_OBJECT (WID ("load_CDE_file")),
|
||||
"clicked",
|
||||
G_CALLBACK (cb_load_CDE_file), toplevel);
|
||||
g_signal_connect (G_OBJECT (WID ("launch_mouse_capplet")),
|
||||
"clicked",
|
||||
G_CALLBACK (cb_launch_mouse_capplet), toplevel);
|
||||
|
||||
return toplevel;
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
[Desktop Entry]
|
||||
Encoding=UTF-8
|
||||
_Name=Keyboard
|
||||
_Comment=Set your keyboard accessibility preferences
|
||||
Exec=gnome-accessibility-keyboard-properties
|
||||
Icon=gnome-settings-accessibility-keyboard
|
||||
Terminal=false
|
||||
Type=Application
|
||||
StartupNotify=true
|
||||
Categories=GNOME;Application;Settings;Accessibility;
|
||||
OnlyShowIn=GNOME;
|
||||
X-GNOME-Bugzilla-Bugzilla=GNOME
|
||||
X-GNOME-Bugzilla-Product=control-center
|
||||
X-GNOME-Bugzilla-Component=Keyboard Accessibility
|
||||
X-GNOME-Bugzilla-Version=@VERSION@
|
||||
@@ -1,32 +0,0 @@
|
||||
/* -*- mode: c; style: linux -*- */
|
||||
|
||||
/* accessibility-keyboard.c
|
||||
* Copyright (C) 2002 Ximian, Inc.
|
||||
*
|
||||
* Written by: Jody Goldberg <jody@gnome.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef GNOME_ACCESSIBILITY_KEYBOARD_H
|
||||
#define GNOME_ACCESSIBILITY_KEYBOARD_H
|
||||
|
||||
#include <gconf/gconf-changeset.h>
|
||||
#include <gtk/gtkwidget.h>
|
||||
|
||||
GtkWidget *setup_accessX_dialog (GConfChangeSet *changeset);
|
||||
|
||||
#endif /* GNOME_ACCESSIBILITY_KEYBOARD_H */
|
||||
@@ -1,116 +0,0 @@
|
||||
/* -*- mode: c; style: linux -*- */
|
||||
|
||||
/* gnome-accessibility-keyboard-properties.c
|
||||
* Copyright (C) 2002 Ximian, Inc.
|
||||
*
|
||||
* Written by: Jody Goldberg <jody@gnome.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <gnome.h>
|
||||
#include <gconf/gconf-client.h>
|
||||
|
||||
#include <capplet-util.h>
|
||||
#include <activate-settings-daemon.h>
|
||||
#include "accessibility-keyboard.h"
|
||||
|
||||
#ifdef HAVE_X11_EXTENSIONS_XKB_H
|
||||
# include <X11/X.h>
|
||||
# include <X11/Xlib.h>
|
||||
# include <X11/XKBlib.h>
|
||||
# include <X11/extensions/XKBstr.h>
|
||||
# include <gdk/gdk.h>
|
||||
# include <gdk/gdkx.h>
|
||||
|
||||
static void
|
||||
xkb_enabled (void)
|
||||
{
|
||||
gboolean have_xkb = FALSE;
|
||||
int opcode, errorBase, major, minor, xkbEventBase;
|
||||
|
||||
gdk_error_trap_push ();
|
||||
have_xkb = XkbQueryExtension (GDK_DISPLAY (),
|
||||
&opcode, &xkbEventBase, &errorBase, &major, &minor)
|
||||
&& XkbUseExtension (GDK_DISPLAY (), &major, &minor);
|
||||
XSync (GDK_DISPLAY (), FALSE);
|
||||
gdk_error_trap_pop ();
|
||||
|
||||
if (!have_xkb) {
|
||||
GtkWidget *warn = gtk_message_dialog_new (NULL, 0,
|
||||
GTK_MESSAGE_WARNING, GTK_BUTTONS_CLOSE,
|
||||
_("This system does not seem to have the XKB extension. The keyboard accessibility features will not operate without it."));
|
||||
gtk_dialog_run (GTK_DIALOG (warn));
|
||||
gtk_widget_destroy (warn);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
dialog_response (GtkWidget *widget,
|
||||
gint response_id,
|
||||
GConfChangeSet *changeset)
|
||||
{
|
||||
switch (response_id) {
|
||||
case GTK_RESPONSE_HELP:
|
||||
capplet_help (GTK_WINDOW (widget),
|
||||
"user-guide.xml",
|
||||
"goscustaccess-6");
|
||||
break;
|
||||
case GTK_RESPONSE_DELETE_EVENT:
|
||||
case GTK_RESPONSE_CLOSE:
|
||||
gtk_main_quit ();
|
||||
break;
|
||||
default:
|
||||
/* Import CDE AccessX File */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char **argv)
|
||||
{
|
||||
GtkWidget *dialog;
|
||||
GConfChangeSet *changeset;
|
||||
bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
|
||||
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
|
||||
textdomain (GETTEXT_PACKAGE);
|
||||
|
||||
gnome_program_init ("gnome-accessibility-keyboard-properties", VERSION,
|
||||
LIBGNOMEUI_MODULE, argc, argv,
|
||||
GNOME_PARAM_APP_DATADIR, GNOMECC_DATA_DIR,
|
||||
NULL);
|
||||
activate_settings_daemon ();
|
||||
|
||||
#ifdef HAVE_X11_EXTENSIONS_XKB_H
|
||||
xkb_enabled ();
|
||||
#endif
|
||||
|
||||
changeset = NULL;
|
||||
dialog = setup_accessX_dialog (changeset);
|
||||
g_signal_connect (G_OBJECT (dialog),
|
||||
"response",
|
||||
G_CALLBACK (dialog_response), changeset);
|
||||
capplet_set_icon (dialog, "gnome-settings-accessibility-keyboard");
|
||||
gtk_widget_show_all (dialog);
|
||||
gtk_main ();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
Makefile
|
||||
Makefile.in
|
||||
.deps
|
||||
.libs
|
||||
*.o
|
||||
*.lo
|
||||
*.la
|
||||
background.desktop
|
||||
background.desktop.in
|
||||
gnome-background-properties
|
||||
gnome-wallpaper-properties
|
||||
*.oaf
|
||||
*.server
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
WALLPAPER_DATADIR = $(datadir)/gnome-background-properties
|
||||
|
||||
INCLUDES = \
|
||||
$(GNOMECC_CAPPLETS_CFLAGS) \
|
||||
-DWALLPAPER_DATADIR=\""$(WALLPAPER_DATADIR)"\"
|
||||
|
||||
bin_PROGRAMS = gnome-background-properties
|
||||
|
||||
noinst_LTLIBRARIES = libgnomewp.la
|
||||
|
||||
gnome_background_properties_LDADD = \
|
||||
$(GNOMECC_CAPPLETS_LIBS) \
|
||||
libgnomewp.la
|
||||
|
||||
gnome_background_properties_SOURCES = \
|
||||
gnome-wp-capplet.c gnome-wp-capplet.h \
|
||||
gnome-wp-info.c gnome-wp-info.h
|
||||
|
||||
libgnomewp_la_SOURCES = \
|
||||
gnome-wp-item.c gnome-wp-item.h \
|
||||
gnome-wp-utils.c gnome-wp-utils.h \
|
||||
gnome-wp-xml.c gnome-wp-xml.h
|
||||
|
||||
libgnomewp_la_LIBADD = \
|
||||
$(GNOMECC_CAPPLETS_LIBS)
|
||||
|
||||
desktopdir = $(datadir)/applications
|
||||
desktop_in_files = background.desktop.in
|
||||
desktop_DATA = $(desktop_in_files:.desktop.in=.desktop)
|
||||
|
||||
@INTLTOOL_DESKTOP_RULE@
|
||||
|
||||
gladedir = $(GNOMECC_GLADE_DIR)
|
||||
glade_DATA = gnome-background-properties.glade
|
||||
|
||||
install-data-local:
|
||||
$(mkinstalldirs) $(DESTDIR)$(WALLPAPER_DATADIR)
|
||||
|
||||
EXTRA_DIST = \
|
||||
background.desktop.in.in \
|
||||
$(glade_DATA)
|
||||
|
||||
CLEANFILES = \
|
||||
$(desktop_in_files) $(desktop_DATA)
|
||||
|
||||
MAINTAINERCLEANFILES = \
|
||||
Makefile.in
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
[Desktop Entry]
|
||||
Encoding=UTF-8
|
||||
_Name=Desktop Background
|
||||
_Comment=Change your Desktop Background settings
|
||||
Exec=gnome-background-properties %F
|
||||
Icon=gnome-settings-background
|
||||
Terminal=false
|
||||
Type=Application
|
||||
StartupNotify=true
|
||||
Categories=GNOME;Settings;Appearance;
|
||||
OnlyShowIn=GNOME;
|
||||
X-GNOME-Bugzilla-Bugzilla=GNOME
|
||||
X-GNOME-Bugzilla-Product=control-center
|
||||
X-GNOME-Bugzilla-Component=background
|
||||
X-GNOME-Bugzilla-Version=@VERSION@
|
||||
@@ -1,483 +0,0 @@
|
||||
<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
|
||||
<!DOCTYPE glade-interface SYSTEM "http://glade.gnome.org/glade-2.0.dtd">
|
||||
|
||||
<glade-interface>
|
||||
<requires lib="gnome"/>
|
||||
|
||||
<widget class="GtkDialog" id="gnome_wp_properties">
|
||||
<property name="visible">True</property>
|
||||
<property name="title" translatable="yes">Desktop Background Preferences</property>
|
||||
<property name="type">GTK_WINDOW_TOPLEVEL</property>
|
||||
<property name="window_position">GTK_WIN_POS_CENTER</property>
|
||||
<property name="modal">False</property>
|
||||
<property name="default_width">360</property>
|
||||
<property name="default_height">418</property>
|
||||
<property name="resizable">True</property>
|
||||
<property name="destroy_with_parent">False</property>
|
||||
<property name="has_separator">False</property>
|
||||
|
||||
<child internal-child="vbox">
|
||||
<widget class="GtkVBox" id="dialog-vbox1">
|
||||
<property name="visible">True</property>
|
||||
<property name="homogeneous">False</property>
|
||||
<property name="spacing">6</property>
|
||||
|
||||
<child internal-child="action_area">
|
||||
<widget class="GtkHButtonBox" id="dialog-action_area1">
|
||||
<property name="visible">True</property>
|
||||
<property name="layout_style">GTK_BUTTONBOX_END</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkButton" id="helpbutton1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_default">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="label">gtk-help</property>
|
||||
<property name="use_stock">True</property>
|
||||
<property name="relief">GTK_RELIEF_NORMAL</property>
|
||||
<property name="response_id">-11</property>
|
||||
</widget>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkButton" id="closebutton1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_default">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="label">gtk-close</property>
|
||||
<property name="use_stock">True</property>
|
||||
<property name="relief">GTK_RELIEF_NORMAL</property>
|
||||
<property name="response_id">-7</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="pack_type">GTK_PACK_END</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkVBox" id="vbox1">
|
||||
<property name="border_width">12</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="homogeneous">False</property>
|
||||
<property name="spacing">6</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label1">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes"><b>Desktop _Wallpaper</b></property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">GTK_JUSTIFY_LEFT</property>
|
||||
<property name="wrap">False</property>
|
||||
<property name="selectable">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
<property name="mnemonic_widget">wp_tree</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox1">
|
||||
<property name="visible">True</property>
|
||||
<property name="homogeneous">False</property>
|
||||
<property name="spacing">6</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label2">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes"></property>
|
||||
<property name="use_underline">False</property>
|
||||
<property name="use_markup">False</property>
|
||||
<property name="justify">GTK_JUSTIFY_LEFT</property>
|
||||
<property name="wrap">False</property>
|
||||
<property name="selectable">False</property>
|
||||
<property name="xalign">0.5</property>
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label3">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes"></property>
|
||||
<property name="use_underline">False</property>
|
||||
<property name="use_markup">False</property>
|
||||
<property name="justify">GTK_JUSTIFY_LEFT</property>
|
||||
<property name="wrap">False</property>
|
||||
<property name="selectable">False</property>
|
||||
<property name="xalign">0.5</property>
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkVBox" id="vbox3">
|
||||
<property name="visible">True</property>
|
||||
<property name="homogeneous">False</property>
|
||||
<property name="spacing">6</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkHBox" id="wp_hbox">
|
||||
<property name="visible">True</property>
|
||||
<property name="homogeneous">False</property>
|
||||
<property name="spacing">6</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkScrolledWindow" id="scrolledwindow1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
|
||||
<property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
|
||||
<property name="shadow_type">GTK_SHADOW_IN</property>
|
||||
<property name="window_placement">GTK_CORNER_TOP_LEFT</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkTreeView" id="wp_tree">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="headers_visible">False</property>
|
||||
<property name="rules_hint">False</property>
|
||||
<property name="reorderable">False</property>
|
||||
<property name="enable_search">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox4">
|
||||
<property name="visible">True</property>
|
||||
<property name="homogeneous">False</property>
|
||||
<property name="spacing">6</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label5">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">_Style:</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_markup">False</property>
|
||||
<property name="justify">GTK_JUSTIFY_LEFT</property>
|
||||
<property name="wrap">False</property>
|
||||
<property name="selectable">False</property>
|
||||
<property name="xalign">0.5</property>
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
<property name="mnemonic_widget">style_menu</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkOptionMenu" id="style_menu">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="history">-1</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkButton" id="rem_button">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="label">gtk-remove</property>
|
||||
<property name="use_stock">True</property>
|
||||
<property name="relief">GTK_RELIEF_NORMAL</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="pack_type">GTK_PACK_END</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkButton" id="add_button">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="relief">GTK_RELIEF_NORMAL</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkAlignment" id="alignment1">
|
||||
<property name="visible">True</property>
|
||||
<property name="xalign">0.5</property>
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xscale">0</property>
|
||||
<property name="yscale">0</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox2">
|
||||
<property name="visible">True</property>
|
||||
<property name="homogeneous">False</property>
|
||||
<property name="spacing">2</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkImage" id="image1">
|
||||
<property name="visible">True</property>
|
||||
<property name="stock">gtk-add</property>
|
||||
<property name="icon_size">4</property>
|
||||
<property name="xalign">0.5</property>
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label4">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">_Add Wallpaper</property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_markup">False</property>
|
||||
<property name="justify">GTK_JUSTIFY_LEFT</property>
|
||||
<property name="wrap">False</property>
|
||||
<property name="selectable">False</property>
|
||||
<property name="xalign">0.5</property>
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
<property name="pack_type">GTK_PACK_END</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label7">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes"></property>
|
||||
<property name="use_underline">False</property>
|
||||
<property name="use_markup">False</property>
|
||||
<property name="justify">GTK_JUSTIFY_LEFT</property>
|
||||
<property name="wrap">False</property>
|
||||
<property name="selectable">False</property>
|
||||
<property name="xalign">0.5</property>
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label6">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes"><b>_Desktop Colors</b></property>
|
||||
<property name="use_underline">True</property>
|
||||
<property name="use_markup">True</property>
|
||||
<property name="justify">GTK_JUSTIFY_LEFT</property>
|
||||
<property name="wrap">False</property>
|
||||
<property name="selectable">False</property>
|
||||
<property name="xalign">0</property>
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
<property name="mnemonic_widget">color_menu</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkHBox" id="hbox5">
|
||||
<property name="visible">True</property>
|
||||
<property name="homogeneous">False</property>
|
||||
<property name="spacing">6</property>
|
||||
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label8">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes"></property>
|
||||
<property name="use_underline">False</property>
|
||||
<property name="use_markup">False</property>
|
||||
<property name="justify">GTK_JUSTIFY_LEFT</property>
|
||||
<property name="wrap">False</property>
|
||||
<property name="selectable">False</property>
|
||||
<property name="xalign">0.5</property>
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkLabel" id="label9">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes"></property>
|
||||
<property name="use_underline">False</property>
|
||||
<property name="use_markup">False</property>
|
||||
<property name="justify">GTK_JUSTIFY_LEFT</property>
|
||||
<property name="wrap">False</property>
|
||||
<property name="selectable">False</property>
|
||||
<property name="xalign">0.5</property>
|
||||
<property name="yalign">0.5</property>
|
||||
<property name="xpad">0</property>
|
||||
<property name="ypad">0</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GtkOptionMenu" id="color_menu">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="history">-1</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GnomeColorPicker" id="pcpicker">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="dither">True</property>
|
||||
<property name="use_alpha">False</property>
|
||||
<property name="title" translatable="yes">Pick a color</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
|
||||
<child>
|
||||
<widget class="GnomeColorPicker" id="scpicker">
|
||||
<property name="can_focus">True</property>
|
||||
<property name="dither">True</property>
|
||||
<property name="use_alpha">False</property>
|
||||
<property name="title" translatable="yes">Pick a color</property>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
<packing>
|
||||
<property name="padding">0</property>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
|
||||
</glade-interface>
|
||||
@@ -1,109 +0,0 @@
|
||||
/*
|
||||
* Authors: Rodney Dawes <dobey@ximian.com>
|
||||
*
|
||||
* Copyright 2003-2005 Novell, Inc. (www.novell.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License
|
||||
* as published by the Free Software Foundation
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _GNOME_WP_CAPPLET_H_
|
||||
#define _GNOME_WP_CAPPLET_H_
|
||||
|
||||
#include <config.h>
|
||||
#include <gnome.h>
|
||||
#include <glib.h>
|
||||
#include <libgnomevfs/gnome-vfs.h>
|
||||
#include <libgnomevfs/gnome-vfs-mime-handlers.h>
|
||||
#include <libgnomevfs/gnome-vfs-mime-utils.h>
|
||||
#include <libgnomeui/gnome-thumbnail.h>
|
||||
#include <gconf/gconf-client.h>
|
||||
#include <libxml/parser.h>
|
||||
#include <glade/glade.h>
|
||||
|
||||
typedef struct _GnomeWPCapplet GnomeWPCapplet;
|
||||
|
||||
#include "gnome-wp-info.h"
|
||||
#include "gnome-wp-item.h"
|
||||
#include "gnome-wp-utils.h"
|
||||
#include "gnome-wp-xml.h"
|
||||
|
||||
struct _GnomeWPCapplet {
|
||||
GtkWidget * window;
|
||||
|
||||
/* List of files passed to command line */
|
||||
GSList * uri_list;
|
||||
|
||||
/* The Tree View */
|
||||
GtkWidget * treeview;
|
||||
GtkTreeModel * model;
|
||||
|
||||
/* Option Menu for Scaling Options */
|
||||
GtkWidget * wp_opts;
|
||||
GtkWidget * rm_button;
|
||||
|
||||
/* Menu Items for Fill/Scale/Center/Tile Options */
|
||||
GtkWidget * fitem;
|
||||
GtkWidget * sitem;
|
||||
GtkWidget * citem;
|
||||
GtkWidget * witem;
|
||||
|
||||
/* Widgets for Color Options */
|
||||
GtkWidget * color_opt;
|
||||
GtkWidget * pc_picker;
|
||||
GtkWidget * sc_picker;
|
||||
|
||||
/* Menu Items for Color Style Options */
|
||||
GtkWidget * smenuitem;
|
||||
GtkWidget * hmenuitem;
|
||||
GtkWidget * vmenuitem;
|
||||
|
||||
/* GConf Client */
|
||||
GConfClient * client;
|
||||
|
||||
/* Thumbnailing and Icon Theme stuff */
|
||||
GnomeThumbnailFactory * thumbs;
|
||||
GnomeIconTheme * theme;
|
||||
|
||||
/* Hash Table of Wallpapers */
|
||||
GHashTable * wphash;
|
||||
|
||||
/* Keyboard Delay */
|
||||
gint delay;
|
||||
|
||||
/* The Timeout ID for Setting the Wallpaper */
|
||||
gint idleid;
|
||||
|
||||
/* File Chooser Dialog */
|
||||
GtkWidget * filesel;
|
||||
GtkWidget * image;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
GNOME_WP_SHADE_TYPE_SOLID,
|
||||
GNOME_WP_SHADE_TYPE_HORIZ,
|
||||
GNOME_WP_SHADE_TYPE_VERT
|
||||
} GnomeWPShadeType;
|
||||
|
||||
typedef enum {
|
||||
GNOME_WP_SCALE_TYPE_CENTERED,
|
||||
GNOME_WP_SCALE_TYPE_STRETCHED,
|
||||
GNOME_WP_SCALE_TYPE_SCALED,
|
||||
GNOME_WP_SCALE_TYPE_TILED
|
||||
} GnomeWPScaleType;
|
||||
|
||||
void gnome_wp_main_quit (GnomeWPCapplet * capplet);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,114 +0,0 @@
|
||||
/*
|
||||
* Authors: Rodney Dawes <dobey@ximian.com>
|
||||
*
|
||||
* Copyright 2003-2005 Novell, Inc. (www.novell.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License
|
||||
* as published by the Free Software Foundation
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <gnome.h>
|
||||
#include "gnome-wp-info.h"
|
||||
|
||||
GnomeWPInfo * gnome_wp_info_new (const gchar * uri,
|
||||
GnomeThumbnailFactory * thumbs) {
|
||||
GnomeWPInfo * new;
|
||||
GnomeVFSFileInfo * info;
|
||||
GnomeVFSResult result;
|
||||
|
||||
gchar *escaped_uri = gnome_vfs_escape_path_string (uri);
|
||||
|
||||
info = gnome_vfs_file_info_new ();
|
||||
result = gnome_vfs_get_file_info (escaped_uri, info,
|
||||
GNOME_VFS_FILE_INFO_DEFAULT |
|
||||
GNOME_VFS_FILE_INFO_GET_MIME_TYPE |
|
||||
GNOME_VFS_FILE_INFO_FOLLOW_LINKS);
|
||||
g_free (escaped_uri);
|
||||
|
||||
if (info == NULL || info->mime_type == NULL || result != GNOME_VFS_OK) {
|
||||
if (!strcmp (uri, "(none)")) {
|
||||
new = g_new0 (GnomeWPInfo, 1);
|
||||
|
||||
new->mime_type = g_strdup ("image/x-no-data");
|
||||
new->uri = g_strdup (uri);
|
||||
|
||||
new->thumburi = g_strconcat (g_get_home_dir (),
|
||||
"/.thumbnails/normal/",
|
||||
gnome_thumbnail_md5 (gnome_vfs_escape_path_string (uri)),
|
||||
".png",
|
||||
NULL);
|
||||
|
||||
new->name = g_strdup (_("No Wallpaper"));
|
||||
|
||||
new->size = 0;
|
||||
} else {
|
||||
new = NULL;
|
||||
}
|
||||
} else {
|
||||
new = g_new0 (GnomeWPInfo, 1);
|
||||
|
||||
new->uri = g_strdup (uri);
|
||||
|
||||
new->thumburi = gnome_thumbnail_factory_lookup (thumbs,
|
||||
gnome_vfs_escape_path_string (new->uri),
|
||||
info->mtime);
|
||||
if (new->thumburi == NULL) {
|
||||
new->thumburi = g_strconcat (g_get_home_dir (),
|
||||
"/.thumbnails/normal/",
|
||||
gnome_thumbnail_md5 (gnome_vfs_escape_path_string (uri)),
|
||||
".png",
|
||||
NULL);
|
||||
}
|
||||
new->name = g_strdup (info->name);
|
||||
new->mime_type = g_strdup (info->mime_type);
|
||||
|
||||
new->size = info->size;
|
||||
new->mtime = info->mtime;
|
||||
}
|
||||
gnome_vfs_file_info_unref (info);
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
GnomeWPInfo * gnome_wp_info_dup (const GnomeWPInfo * info) {
|
||||
GnomeWPInfo * new;
|
||||
|
||||
new = g_new0 (GnomeWPInfo, 1);
|
||||
|
||||
new->uri = g_strdup (info->uri);
|
||||
new->thumburi = g_strdup (info->uri);
|
||||
|
||||
new->name = g_strdup (info->name);
|
||||
new->mime_type = g_strdup (info->mime_type);
|
||||
|
||||
new->size = info->size;
|
||||
new->mtime = info->mtime;
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
void gnome_wp_info_free (GnomeWPInfo * info) {
|
||||
if (info == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
g_free (info->uri);
|
||||
g_free (info->thumburi);
|
||||
g_free (info->name);
|
||||
g_free (info->mime_type);
|
||||
|
||||
info = NULL;
|
||||
}
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
* Authors: Rodney Dawes <dobey@ximian.com>
|
||||
*
|
||||
* Copyright 2003-2005 Novell, Inc. (www.novell.com)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of version 2 of the GNU General Public License
|
||||
* as published by the Free Software Foundation
|
||||
*
|
||||
* This program 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _GNOME_WP_INFO_H_
|
||||
#define _GNOME_WP_INFO_H_
|
||||
|
||||
#include <glib.h>
|
||||
#include <libgnomevfs/gnome-vfs.h>
|
||||
#include <libgnomeui/gnome-thumbnail.h>
|
||||
|
||||
typedef struct _GnomeWPInfo GnomeWPInfo;
|
||||
|
||||
struct _GnomeWPInfo {
|
||||
gchar * uri;
|
||||
gchar * thumburi;
|
||||
gchar * name;
|
||||
gchar * mime_type;
|
||||
|
||||
GnomeVFSFileSize size;
|
||||
|
||||
time_t mtime;
|
||||
};
|
||||
|
||||
GnomeWPInfo * gnome_wp_info_new (const gchar * uri,
|
||||
GnomeThumbnailFactory * thumbs);
|
||||
GnomeWPInfo * gnome_wp_info_dup (const GnomeWPInfo * info);
|
||||
void gnome_wp_info_free (GnomeWPInfo * info);
|
||||
|
||||
#endif
|
||||
|
||||