summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--AUTHORS1
-rw-r--r--CMakeLists.txt82
-rw-r--r--COPYING340
-rw-r--r--ChangeLog198
-rw-r--r--README124
-rw-r--r--TODO1
-rw-r--r--cmake/FindMsgfmt.cmake86
-rw-r--r--common/common.h237
-rw-r--r--common/connect.h311
-rw-r--r--config.h.cmake11
-rw-r--r--debian/cdbs/buildvars.mk86
-rw-r--r--debian/cdbs/debian-qt-kde.mk109
-rw-r--r--debian/cdbs/kde.mk97
-rw-r--r--debian/cdbs/team-members16
-rw-r--r--debian/cdbs/uploaders.mk29
-rw-r--r--debian/cdbs/versions.pl19
-rw-r--r--debian/changelog11
-rw-r--r--debian/compat1
-rw-r--r--debian/control19
-rw-r--r--debian/copyright37
-rwxr-xr-xdebian/rules30
-rwxr-xr-xdebian/rules.bkp9
-rw-r--r--gtk2/CMakeLists.txt22
-rwxr-xr-xgtk2/kgtk2-wrapper.cmake33
-rw-r--r--gtk2/kgtk2.c2005
-rwxr-xr-xkdialogd-wrapper27
-rw-r--r--kdialogd3/CMakeLists.txt17
-rw-r--r--kdialogd3/kdialogd.cpp721
-rw-r--r--kdialogd3/kdialogd.h145
-rw-r--r--kdialogd3/po/CMakeLists.txt41
-rw-r--r--kdialogd3/po/cs.po63
-rw-r--r--kdialogd3/po/de.po62
-rw-r--r--kdialogd3/po/en_GB.po60
-rw-r--r--kdialogd3/po/es.po57
-rw-r--r--kdialogd3/po/fr.po60
-rw-r--r--kdialogd3/po/kdialogd3.pot58
-rw-r--r--kdialogd3/po/pt_BR.po60
-rw-r--r--kdialogd3/po/ru.po62
-rw-r--r--kdialogd3/po/zh_CN.po60
-rw-r--r--kdialogd4/CMakeLists.txt16
-rw-r--r--kdialogd4/kdialogd.cpp759
-rw-r--r--kdialogd4/kdialogd.h146
-rw-r--r--kdialogd4/po/CMakeLists.txt41
-rw-r--r--kdialogd4/po/cs.po61
-rw-r--r--kdialogd4/po/de.po62
-rw-r--r--kdialogd4/po/en_GB.po60
-rw-r--r--kdialogd4/po/es.po56
-rw-r--r--kdialogd4/po/fr.po60
-rw-r--r--kdialogd4/po/kdialogd4.pot58
-rw-r--r--kdialogd4/po/pt_BR.po60
-rw-r--r--kdialogd4/po/ru.po62
-rw-r--r--kdialogd4/po/zh_CN.po60
-rwxr-xr-xkgtk-wrapper103
-rwxr-xr-xmangled.sh23
-rw-r--r--qt3/CMakeLists.txt24
-rwxr-xr-xqt3/kqt3-wrapper.cmake29
-rw-r--r--qt3/kqt3.cpp671
-rw-r--r--qt4/CMakeLists.txt22
-rwxr-xr-xqt4/kqt4-wrapper.cmake29
-rw-r--r--qt4/kqt4.cpp599
60 files changed, 8408 insertions, 0 deletions
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..2925c35
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1 @@
+Craig Drummond <[email protected]>
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..0593586
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,82 @@
+project(KGtk)
+cmake_minimum_required(VERSION 2.4.0)
+
+set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README")
+set(CPACK_GENERATOR "TBZ2")
+set(CPACK_SOURCE_GENERATOR "TBZ2")
+set(CPACK_PACKAGE_VERSION_MAJOR "0")
+set(CPACK_PACKAGE_VERSION_MINOR "10")
+set(CPACK_PACKAGE_VERSION_PATCH "1")
+set(KGTK_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}")
+set(KGTK_VERSION_FULL "${KGTK_VERSION}.${CPACK_PACKAGE_VERSION_PATCH}")
+set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}-${KGTK_VERSION_FULL}")
+include(CPack)
+
+set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
+include(CheckFunctionExists)
+check_function_exists(getpeereid HAVE_GETPEEREID)
+
+# Cant compile Qt3/KDE3 at the same time as Qt4/KDE4...
+if ("${KGTK_KDE4}" MATCHES "true" OR "${KGTK_QT4}" MATCHES "true")
+ if (NOT "${KGTK_KDE3}" MATCHES "false" OR NOT "${KGTK_QT3}" MATCHES "false")
+ set(KGTK_KDE3 "false")
+ set(KGTK_QT3 "false")
+ message("** INFORMATION: Compiling Qt4/KDE4, Qt3/KDE3 disabled")
+ endif (NOT "${KGTK_KDE3}" MATCHES "false" OR NOT "${KGTK_QT3}" MATCHES "false")
+endif ("${KGTK_KDE4}" MATCHES "true" OR "${KGTK_QT4}" MATCHES "true")
+
+if (NOT "${KGTK_KDE3}" MATCHES "false")
+ add_subdirectory(kdialogd3)
+endif (NOT "${KGTK_KDE3}" MATCHES "false")
+
+if ("${KGTK_KDE4}" MATCHES "true")
+ add_subdirectory(kdialogd4)
+ # For some reason kdialogd4 does not install unless you cd into the kdialogd4 folder?
+ # ...hacky fix for this...
+ install(PROGRAMS ${CMAKE_BINARY_DIR}/kdialogd4/kdialogd4 DESTINATION bin)
+endif ("${KGTK_KDE4}" MATCHES "true")
+
+if (NOT "${KGTK_GTK2}" MATCHES "false")
+ # Check if we have dlvsym...
+ find_library(LIBDLVSYM_LIBRARY
+ NAMES dl
+ PATHS /lib /usr/lib /usr/X11R6/lib /usr/local/lib)
+
+ if(LIBDLVSYM_LIBRARY)
+ set(HAVE_DLVSYM 1)
+ # Determine version of dlsym...
+ find_library(LIBDL_LIBRARY
+ NAMES dl
+ PATHS /lib /usr/lib /usr/X11R6/lib /usr/local/lib)
+
+ if(LIBDL_LIBRARY)
+ execute_process(COMMAND objdump --dynamic-syms ${LIBDL_LIBRARY}
+ COMMAND grep dlsym
+ OUTPUT_VARIABLE DLSYM_DATA)
+ separate_arguments(DLSYM_DATA)
+ if (${CMAKE_MAJOR_VERSION} GREATER 2 OR ${CMAKE_MINOR_VERSION} GREATER 4)
+ cmake_policy(SET CMP0007 OLD)
+ endif (${CMAKE_MAJOR_VERSION} GREATER 2 OR ${CMAKE_MINOR_VERSION} GREATER 4)
+ list(GET DLSYM_DATA 4 KGTK_DLSYM_VERSION)
+ endif(LIBDL_LIBRARY)
+ else(LIBDLVSYM_LIBRARY)
+ message("** INFORMATION: You're libdl does not contain dlvsym - SWT apps will not be supported")
+ endif(LIBDLVSYM_LIBRARY)
+
+ add_subdirectory(gtk2)
+endif (NOT "${KGTK_GTK2}" MATCHES "false")
+
+if (NOT "${KGTK_QT3}" MATCHES "false")
+ add_subdirectory(qt3)
+endif (NOT "${KGTK_QT3}" MATCHES "false")
+
+if ("${KGTK_QT4}" MATCHES "true")
+ add_subdirectory(qt4)
+endif ("${KGTK_QT4}" MATCHES "true")
+
+
+install(PROGRAMS ${CMAKE_SOURCE_DIR}/kdialogd-wrapper DESTINATION bin)
+install(PROGRAMS ${CMAKE_SOURCE_DIR}/kgtk-wrapper DESTINATION bin)
+
+message("** INFORMATION: Using installation prefix: ${CMAKE_INSTALL_PREFIX}")
+configure_file (config.h.cmake ${CMAKE_BINARY_DIR}/config.h)
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..5b6e7c6
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,340 @@
+ 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.
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..46ae342
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,198 @@
+0.10.1
+------
+1. Fix 'kgtk-wrapper ./app' case.
+2. Set filename for KdialogD4's save as filedialog.
+3. Hacky fix for Firefox crashing when trying to save to a file that
+ already exists -> delete it first!
+4. When launching KDialogD, try todetermin which version is installed.
+5. Add some compile fixes from kde-apps
+
+0.10
+----
+1. Fix CMake bug at double definition of destantion dir for gmo.
+ - thanks to Yar Odin.
+2. When KDialogD is started, write its PID to a file. When each app
+ attempts to connect to KDialogD, it checks if the PID in the file
+ is still active - if not it starts KDialogD.
+3. KIO::NetAccess::mostLocalUrl fails if a file does not exist. If so,
+ then check if parent folder exists - and if so, append filename to
+ that.
+
+0.9.6
+-----
+1. Fix russion translation files - thanks to Yar Odin
+2. Fix some CMake 2.6 issues.
+
+0.9.5
+-----
+1. Fix detection of firefox. Treat xulrunner as Firefox.
+2. Quick hack for kino - always save as .kino
+3. Prevent dummy gtk window from appearing in KDE4's 'present windows'
+ window selector.
+4. Translations:
+ Brazillian Portuguese (pt_BR) Márcio Moraes
+ Russion (ru) Yar Odin
+5. Fix kdialogd4's file widget.
+6. Fix kgtk-wrapper script for relative paths - thanks to Ingo Müller.
+7. set G_BROKEN_FILENAMES=1 for non UTF8 locales.
+
+0.9.4
+-----
+1. Translations:
+ Spanish (es) Marco Antonio Blanco <[email protected]>
+2. When saving with opera, show the suggested filename.
+
+0.9.3
+-----
+1. Translations:
+ German (de) [email protected]
+ Czech (cs) Marián Kyral <[email protected]>
+2. Fix firefox crash when overwriting an existing file.
+
+0.9.2
+-----
+1. Remove 'which gimp' from kgtk-wrapper - oops!
+2. In kgtk-wrapper, set opera to use qt3
+3. Fix opera crash.
+4. Use GLib's convert function to convert to/from utf8, and
+ to/from URIs
+5. Walk through Qt3's QFileDialog's children to locate combobox
+ containing filetypes, as opposed to using a copy of QFileDialogPrivate
+6. Translations:
+ Simplified Chinese (zh_CN) Liang Qi <[email protected]>
+ French (fr) Paul Thomas <[email protected]>
+ British English (en_GB) Me!
+7. Implement over-riding of non statically called Qt4 QFileDialogs
+
+0.9.1
+-----
+1. Use cmake as build system.
+2. Fix recognition of gimp 2.4
+3. Fix translation of standard kde strings.
+4. Fix case where kgtk-wrapper is called via a symlink.
+
+0.9
+---
+1. Fix dialog parenting issues with Gtk folder picker combo/menu.
+2. Fix compilation issue for KDE < 3.4
+3. Treat Iceweasel and Swiftfox the same as firefox.
+4. Improve operation under beryl.
+5. Add KDE4 and Qt4 support.
+6. Reduce heavy CPU usage of kqt
+7. Fix some i18n issues.
+8. Place wrapper scripts into prefix/bin, and libraries into prefix/lib/kgtk
+9. kgtk-wrapper can now be called for Gtk2, Qt3, nd Qt4 apps. The app is checked
+ to determin which toolkit it is using. If this check fails, you may edit
+ ~/.kde/share/config/kgtkrc and add lines such as
+
+ [Apps]
+ eclipse=gtk2
+ scribus=qt3
+ abiword=x
+
+ Setting "abiword=x" disables kgtk for abiword (as it doesnt work!)
+
+0.8
+---
+1. Install scripts into $prefix/bin as opposed to hard-coding
+ /usr/local/bin
+2. Debug messages are disabled by default, to enable reconfigure
+ with --enable-debug-messages
+3. Work correctly for autopackage'd apps - e.g. Inkscape 0.44
+4. Fix inkscape 0.44's export bitmap file dialog appearing underneath
+ export dialog.
+5. Convert kdialogd to a KDE app. This app is started by Gtk/Qt apps,
+ and will self terminate 30 seconds after the last connected app
+ has disconnected. This timeout can be changed by editing kdialogdrc
+ and changing
+
+ [General]
+ Timeout=10
+
+6. Libraries installed to $KDEPREFIX/share/apps/kgtk
+7. Remove .sh extension from scripts
+8. When starting kdialogd, create the socket folder if it does not
+ already exist.
+
+**NOTE** You *MUST* remove any previous version of KGtk before using this
+version. i.e. you must delete the kded_kdialgd.la, kded_kdialgd.so, and the
+kdialogd.desktop files. KDE also must be restarted - to remove the KDED
+module.
+
+0.7
+---
+1. Bug fix in wrapper scripts, use "$@" and not $* - thanks to
+ Victor Fernandez Martinez
+2. Fix sending of UTF-8 characters from KDED module to app.
+
+0.6
+-----
+1. Check for existance $KDETMP, or $TMPDIR when creating socket.
+2. Use UTF-8 when talking to KDED module.
+
+0.5.1
+-----
+1. Compile fixes - 64bit, Gtk<2.6
+
+0.5
+---
+1. Make the KDED module a load-on-demand module, as opposed to always being
+ loaded. Module can be unloaded with:
+
+ dcop kded kded unloadModule kdialogd
+
+2. Filters should now work for inkscape save - at least in inkscape 0.43
+3. Add ./configure check to ensure Gtk >= 2.4
+4. Added a ./configure check for dlvsym within libdl, if not found then
+ dlsym is not overriden - and SWT aps wont work :-(
+5. In ./configure try to determine version of dlsym.
+6. Try to load gtk_file_chooser_set/get_do_overwrite_confirmation's
+ from libgtk - if found then use, otherwise assume Gtk app will
+ do overwrite detection.
+7. Correctly handle empty selection in single-file open mode.
+8. Fix initial dir of non-statically called QFileDialogs
+9. Modify Scribus's save file filters to have a "Compressed Documents" entry
+ -- will break localisation of scribus :-(
+
+0.4
+---
+1. Support non-statically called QFileDialogs
+2. Fix compilation under KDE <3.5
+3. Save/restore PATH in wrapper scripts.
+4. Now works with eclipse 3.1 (and all SWT apps? Seems to also work with
+ Azureus)
+5. At start up Gtk app passes its name to KDialogD so that dialog settings
+ can be saved per-app.
+6. Remove patterns from filter combo strings - more KDE like.
+
+** NOTE: After installing v0.4, KDE (or at least kded) *must* be restarted -
+ due to changes in the communication off apps -> kdialogd.
+
+0.3
+---
+1. Don't show Gtk file-overwrite dialogs, handle the file exists case within
+ KDE portion.
+2. Fix retrieval/display of file filters.
+3. Check for accessing of non-local URLs before dialog is closed.
+
+0.2.2
+-----
+1. Remove kgtk-wrapper.sh and kqt-wrapper.sh shell scripts from archive -
+ these should've been generated at make time. Hopefully they will now.
+
+0.2.1
+-----
+1. Fix qt compile issues.
+
+0.2
+---
+1. Convert kdialogd into a kded module.
+2. Make gtk library a LD_PRELOAD library
+3. Add a Qt library
+4. Try to convert KURL's into local files
+5. When performing a save as, etc, correctly set the current filename and path.
+6. Remove font and colour dialog support
+
+0.1
+---
+1. Initial version.
diff --git a/README b/README
new file mode 100644
index 0000000..b7337f9
--- /dev/null
+++ b/README
@@ -0,0 +1,124 @@
+Introduction
+------------
+
+KGtk is a quick-n-dirty hack to allow some Gtk2, Qt3, and Qt4
+applications to use KDE3 or KDE4 file dialogs.
+
+KGtk is composed of the following pieces:
+
+1. An application called kdialogd. In this archive there are
+ two varieties of this - a KDE3 version, and a KDE4 version.
+2. LD_PRELOAD libraries that are used to override the Gtk2, Qt3,
+ and Qt4 file dialogs.
+
+If you start an application using the following command:
+ kgtk-wrapper gimp
+
+...the the following occurs:
+
+1. kgtk-wrapper determines whether the application is a Gtk2, Qt3,
+ or Qt4 application. It then sets the LD_PRELOAD environment
+ variable to point to the approriate KGtk library.
+2. When the application now starts, it checks for the
+ KDE_SESSION_VERSION environment variable. If this is not set,
+ or is less than 4, then the KDE3 version of kdialogd is started,
+ else the KDE4 version is started.
+3. When 'gimp' now tries to open a file dialog, the KGtk library
+ intercepts this, and asks kdialogd to open a file dialog instead.
+
+There will only ever be one instance of kdialogd, and all apps communicate with the same
+instance - and it termiantes itself 30 seconds after the last Gtk/Qt app has
+disconnected. This timeout can be changed by editing kdialogdrc and setting/changing
+
+ [General]
+ Timeout=10
+
+
+Installation
+------------
+As of v0.9.1, kgtk uses CMake in place of autotools.
+
+Because KGtk includes code for Qt3/KDE3 and Qt4/KDE4, you need
+to specify when building which variants you would like to build.
+This is accomplished as follows:
+
+1. mkdir build
+2. cd build
+3. cmake .. -DCMAKE_INSTALL_PREFIX=/usr
+4. make
+5. sudo make install
+
+* -DKGTK_KDE3=true instructs CMake to create makefiles for the KDE3
+ version of KDialogD. Defaults to "true", use -DKGTK_KDE3=false
+ to turn off. Turning this on, sets -DKGTK_KDE4=false and
+ -DKGTK_QT4=false
+
+* -DKGTK_KDE4=true would instruct CMake to create makefiles for
+ the KDE4 version of KDialogD. Defaults to "false".
+
+* -DKGTK_GTK2=true instructs CMake to create makefiles for the Gtk2
+ version of the LD_PRELOAD library. Defaults to "true", use
+ -DKGTK_GTK2=false to turn off.
+
+* -DKGTK_QT3=true instructs CMake to create makefiles for the Qt3
+ version of the LD_PRELOAD library. Defaults to "true", use
+ -DKGTK_QT3=false to turn off. Turning this on, sets
+ -DKGTK_KDE4=false and -DKGTK_QT4=false
+
+* -DKGTK_QT4=true instructs CMake to create makefiles for the Qt4
+ version of the LD_PRELOAD library. Defaults to "false".
+
+* For 64 bit systems, also append -DLIB_SUFFIX=64
+
+Mixing '-DKGTK_KDE3=true' and '-DKGTK_KDE4=true' wont work, so compile the Qt3/KDE3,
+and Qt4/KDE4 variants separately. Also, the 'build' folder *must* be cleaned before
+switching to/from Qt3/KDE3 from/to Qt4/KDE4
+
+
+So, to compile everything I suggest the following:
+
+ 1. mkdir build3
+ 2. cd build3
+ 3. cmake .. -DCMAKE_INSTALL_PREFIX=/usr
+ [ This will build KDialogD for KDE3, and create the LD_PRELOAD libraries for
+ Qt3 and Gtk2 ]
+ 4. make
+ 5. sudo make install
+
+ 6. set up Qt4/KDE4 env variables
+ 7. clean build folder
+
+ 8. mkdir build4
+ 9. cd build4
+10. cmake .. -DCMAKE_INSTALL_PREFIX=/usr -DKGTK_KDE4=true -DKGTK_QT4=true -DKGTK_GTK2=false
+11. make
+12. sudo make install
+
+NOTE: If you have both KDE3 and KDE4 installed, when calling cmake for KDE3, set KDEDIR to be empty.
+ e.g.
+ KDEDIR= cmake -DCMAKE_INSTALL_PREFIX=/usr -DKGTK_KDE4=false -DKGTK_QT4=false
+
+Notes
+-----
+
+The library has been tested with the following applications:
+
+Reported to work:
+
+ 1. Firefox (1.5.x only, not 1.0.x)
+ 2. Inkscape
+ 3. GIMP
+ 4. Kino
+ 5. Eclipse
+ 6. Azureus
+ 7. Galde-2
+ 8. Streamtuner
+ 9. Avidemux2
+ 10. Scribus
+ 11. QComcBook
+ 12. Planner 0.14: works, but asks twice for open file
+
+Reported *not* working:
+
+ 1. AbiWord
+
diff --git a/TODO b/TODO
new file mode 100644
index 0000000..1117687
--- /dev/null
+++ b/TODO
@@ -0,0 +1 @@
+KDE4: File dialog history
diff --git a/cmake/FindMsgfmt.cmake b/cmake/FindMsgfmt.cmake
new file mode 100644
index 0000000..60e33ee
--- /dev/null
+++ b/cmake/FindMsgfmt.cmake
@@ -0,0 +1,86 @@
+#
+# - Try to find the msgfmt executeable
+#
+# It will set the following variables:
+#
+# MSGFMT_FOUND
+# MSGFMT_EXECUTABLE
+#
+###################################################################
+#
+# Copyright (c) 2006, Andreas Schneider <[email protected]>
+#
+# 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., 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301, USA.
+#
+###################################################################
+#
+# Copyright (c) 2006 Andreas Schneider <[email protected]>
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+#
+# * Neither the name of the cmake-modules nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+
+IF (MSGFMT_EXECUTABLE)
+ # in cache alread?
+ SET(MSGFMT_FOUND TRUE)
+ELSE (MSGFMT_EXECUTABLE)
+ IF (UNIX)
+ FIND_PROGRAM(MSGFMT_EXECUTABLE
+ NAMES
+ msgfmt
+ PATHS
+ /usr/bin
+ /usr/local/bin
+ )
+
+ IF(MSGFMT_EXECUTABLE)
+ SET(MSGFMT_FOUND TRUE)
+ ELSE(MSGFMT_EXECUTABLE)
+ MESSAGE(FATAL_ERROR "msgfmt not found - po files can't be processed")
+ ENDIF(MSGFMT_EXECUTABLE)
+
+ MARK_AS_ADVANCED(MSGFMT_EXECUTABLE)
+ ENDIF(UNIX)
+ENDIF (MSGFMT_EXECUTABLE)
+
+# vim:et ts=2 sw=2 comments=\:\#
diff --git a/common/common.h b/common/common.h
new file mode 100644
index 0000000..ca246b9
--- /dev/null
+++ b/common/common.h
@@ -0,0 +1,237 @@
+#ifndef __COMMON_H__
+#define __COMMON_H__
+
+#define KDIALOGD_APP
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <time.h>
+#include "config.h"
+
+#ifdef __KDIALOGD_H__
+#include <kstandarddirs.h>
+#endif
+
+typedef enum
+{
+ OP_NULL = 0,
+ OP_FILE_OPEN = 1,
+ OP_FILE_OPEN_MULTIPLE = 2,
+ OP_FILE_SAVE = 3,
+ OP_FOLDER = 4
+} Operation;
+
+#define PID_DIR "kde-"
+#define PID_NAME "kdialogd.pid"
+
+static const char * getPidFileName()
+{
+ static char *pidfile=NULL;
+
+ if(!pidfile)
+ {
+ char *user=getenv("USER");
+
+ if(!user)
+ user=getenv("LOGNAME");
+
+ if(user)
+ {
+ char *tmp=getenv("KDETMP");
+
+ if(!tmp || !tmp[0])
+ tmp=getenv("TMPDIR");
+
+ if(!tmp || !tmp[0])
+ tmp=(char *)"/tmp";
+
+ pidfile=(char *)malloc(strlen(tmp)+strlen(PID_DIR)+strlen(user)+strlen(PID_NAME)+1);
+ pidfile=(char *)malloc(strlen(tmp)+strlen("/")+strlen(PID_DIR)+strlen(user)+strlen("/")+strlen(PID_NAME)+1);
+
+#ifdef __KDIALOGD_H__
+ // We are kdialogd - so create socket folder if it does not exist...
+ sprintf(pidfile, "%s/%s%s", tmp, PID_DIR, user);
+ KStandardDirs::makeDir(QString::fromAscii(pidfile));
+#endif
+
+ /* CPD: TODO get dispaly number! */
+ sprintf(pidfile, "%s/%s%s/%s", tmp, PID_DIR, user, PID_NAME);
+ }
+ }
+
+ return pidfile;
+}
+
+#define SOCK_DIR "ksocket-"
+#define SOCK_NAME "kdialogd"
+
+static const char * getSockName()
+{
+ static char *sock=NULL;
+
+ if(!sock)
+ {
+ char *user=getenv("USER");
+
+ if(!user)
+ user=getenv("LOGNAME");
+
+ if(user)
+ {
+ char *tmp=getenv("KDETMP");
+
+ if(!tmp || !tmp[0])
+ tmp=getenv("TMPDIR");
+
+ if(!tmp || !tmp[0])
+ tmp=(char *)"/tmp";
+
+ sock=(char *)malloc(strlen(tmp)+strlen("/")+strlen(SOCK_DIR)+strlen(user)+strlen("/")+strlen(SOCK_NAME)+strlen("18446744073709551616")+1);
+
+#ifdef __KDIALOGD_H__
+ // We are kdialogd - so create socket folder if it does not exist...
+ sprintf(sock, "%s/%s%s", tmp, SOCK_DIR, user);
+ KStandardDirs::makeDir(QString::fromAscii(sock));
+#endif
+
+ /* CPD: TODO get dispaly number! */
+ sprintf(sock, "%s/%s%s/%s-%d", tmp, SOCK_DIR, user, SOCK_NAME, 1);
+ }
+ }
+
+ return sock;
+}
+
+static int readBlock(int fd, char* pData, int size)
+{
+ int bytesToRead=size;
+
+ do
+ {
+ fd_set fdSet;
+
+ FD_ZERO(&fdSet);
+ FD_SET(fd, &fdSet);
+
+ if(select(fd + 1, &fdSet, NULL, NULL, NULL)<0)
+ return 0;
+
+ if(FD_ISSET(fd, &fdSet))
+ {
+ int bytesRead=read(fd, &pData[size-bytesToRead], bytesToRead);
+
+ if (bytesRead>0)
+ bytesToRead-=bytesRead;
+ else
+ return 0;
+ }
+ }
+ while(bytesToRead>0);
+
+ return 1;
+}
+
+static int writeBlock(int fd, const char *pData, int size)
+{
+ int bytesToWrite=size;
+
+ do
+ {
+ fd_set fdSet;
+
+ FD_ZERO(&fdSet);
+ FD_SET(fd, &fdSet);
+
+ if(select(fd + 1, NULL, &fdSet, NULL, NULL)<0)
+ return 0;
+
+ if(FD_ISSET(fd, &fdSet))
+ {
+ int bytesWritten=write(fd, (char *)&pData[size-bytesToWrite], bytesToWrite);
+
+ if (bytesWritten>0)
+ bytesToWrite-=bytesWritten;
+ else
+ return 0;
+ }
+ }
+ while(bytesToWrite>0);
+
+ return 1;
+}
+
+#ifdef KDIALOGD_APP
+/*
+ So that kdailogd can terminate when the last app exits, need a way of synchronising the Gtk/Qt
+ apps that may wish to connect, and the removal of the socket.
+
+ To this en, a lockfile is created,and used to guard around the critical sections
+*/
+static int lockFd=-1;
+
+#define LOCK_EXT ".lock"
+
+const char * getLockName()
+{
+ static char *lockName=NULL;
+
+ if(!lockName)
+ {
+ const char *sock=getSockName();
+
+ if(sock)
+ {
+ lockName=(char *)malloc(strlen(sock)+strlen(LOCK_EXT)+1);
+ sprintf(lockName, "%s%s", sock, LOCK_EXT);
+ }
+ }
+
+ return lockName;
+}
+
+/* Lock is stale if it does not exist or is older than 2 seconds */
+static int isStale(const char *fname)
+{
+ struct stat stat_buf;
+
+ return 0!=stat(fname, &stat_buf) ||
+ abs(stat_buf.st_mtime-time(NULL))>2;
+}
+
+static int grabLock(int tries)
+{
+ do
+ {
+ lockFd=open(getLockName(), O_WRONLY | O_CREAT | O_EXCL, 0777);
+ if (lockFd<0 && errno==EEXIST)
+ {
+ /* Hmm, lock file already exists. Is it stale? */
+ if(isStale(getLockName()))
+ {
+ tries++; /* Increment tries so that we try again... */
+ unlink(getLockName());
+ }
+ else if(tries)
+ usleep(100000);
+ }
+ }
+ while(lockFd<0 && --tries);
+
+ return lockFd;
+}
+
+static void releaseLock()
+{
+ if(lockFd>0)
+ {
+ close(lockFd);
+ unlink(getLockName());
+ }
+}
+#endif
+
+#endif
diff --git a/common/connect.h b/common/connect.h
new file mode 100644
index 0000000..2499054
--- /dev/null
+++ b/common/connect.h
@@ -0,0 +1,311 @@
+#ifndef __CONNECT_H__
+#define __CONNECT_H__
+
+#include <string.h>
+#include <errno.h>
+#include <signal.h>
+#include <sys/wait.h>
+#include "config.h"
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/stat.h>
+
+#ifndef SUN_LEN
+#define SUN_LEN(ptr) ((socklen_t) (((struct sockaddr_un *) 0)->sun_path) \
+ + strlen ((ptr)->sun_path))
+#endif
+
+#include "common.h"
+#include "config.h"
+
+#ifdef __cplusplus
+typedef bool kgtk_bool;
+#define KGTK_TRUE true
+#define KGTK_FALSE false
+#else
+typedef gboolean kgtk_bool;
+#define KGTK_TRUE TRUE
+#define KGTK_FALSE FALSE
+#endif
+
+
+static int kdialogdSocket=-1;
+
+/* From kdelibs/kdesu */
+#ifdef KDIALOGD_APP
+static int createSocketConnectionReal()
+#else
+static int createSocketConnection()
+#endif
+{
+#ifdef KGTK_DEBUG
+ printf("KGTK::createSocketConnection A\n");
+#endif
+ int sockfd=-1;
+ const char *sock=getSockName();
+ struct sockaddr_un addr;
+
+ if (access(sock, R_OK|W_OK))
+ {
+#ifdef KGTK_DEBUG
+ printf("KGTK::createSocketConnection - Could not access socket, %s\n", sock);
+#endif
+ return -1;
+ }
+
+ sockfd = socket(PF_UNIX, SOCK_STREAM, 0);
+ if (sockfd < 0)
+ {
+#ifdef KGTK_DEBUG
+ printf("KGTK::createSocketConnection - Could not create socket, %d\n", errno);
+#endif
+ return -1;
+ }
+ addr.sun_family = AF_UNIX;
+ strcpy(addr.sun_path, sock);
+
+ if (connect(sockfd, (struct sockaddr *) &addr, SUN_LEN(&addr)) < 0)
+ {
+#ifdef KGTK_DEBUG
+ printf("KGTK::createSocketConnection - Could not connect socket, %d\n", errno);
+#endif
+ close(sockfd);
+ return -1;
+ }
+
+#if !defined(SO_PEERCRED) || !defined(HAVE_STRUCT_UCRED)
+# if defined(HAVE_GETPEEREID)
+ {
+ uid_t euid;
+ gid_t egid;
+ /* Security: if socket exists, we must own it */
+ if (getpeereid(sockfd, &euid, &egid) == 0)
+ {
+ if (euid != getuid())
+ {
+#ifdef KGTK_DEBUG
+ printf("KGTK::createSocketConnection - socket not owned by me! socket uid %d\n", euid);
+#endif
+ close(sockfd);
+ return -1;
+ }
+ }
+ }
+# else
+# ifdef __GNUC__
+# warning "Using sloppy security checks"
+# endif
+ /* We check the owner of the socket after we have connected.
+ If the socket was somehow not ours an attacker will be able
+ to delete it after we connect but shouldn't be able to
+ create a socket that is owned by us. */
+ {
+ struct stat s;
+ if (lstat(sock, &s)!=0)
+ {
+#ifdef KGTK_DEBUG
+ printf("KGTK::createSocketConnection - stat failed %s\n", sock);
+#endif
+ close(sockfd);
+ return -1;
+ }
+ if (s.st_uid != getuid())
+ {
+#ifdef KGTK_DEBUG
+ printf("KGTK::createSocketConnection - socket not owned by me! socket uid %d\n", s.st_uid);
+#endif
+ close(sockfd);
+ return -1;
+ }
+ if (!S_ISSOCK(s.st_mode))
+ {
+#ifdef KGTK_DEBUG
+ printf("KGTK::createSocketConnection - socket is not a socket %s\n", sock);
+#endif
+ close(sockfd);
+ return -1;
+ }
+ }
+# endif
+#else
+ {
+ struct ucred cred;
+ socklen_t siz = sizeof(cred);
+
+ /* Security: if socket exists, we must own it */
+ if (getsockopt(sockfd, SOL_SOCKET, SO_PEERCRED, &cred, &siz) == 0)
+ {
+ if (cred.uid != getuid())
+ {
+#ifdef KGTK_DEBUG
+ printf("KGTK::createSocketConnection - socket not owned by me! socket uid %d\n", cred.uid);
+#endif
+ close(sockfd);
+ return -1;
+ }
+ }
+ }
+#endif
+
+#ifdef KGTK_DEBUG
+ printf("KGTK::createSocketConnection - sockfd:%d\n", sockfd);
+#endif
+ return sockfd;
+}
+
+#ifdef KDIALOGD_APP
+static int createSocketConnection()
+{
+ int rv=-1,
+ tries=0;
+
+ do
+ {
+ if(-1==(rv=createSocketConnectionReal()))
+ usleep(10000);
+ }
+ while(-1==rv && ++tries<50);
+
+ if(-1==rv)
+ fprintf(stderr, "ERROR: Could not talk to KDialogD!!!\n");
+ return rv;
+}
+#endif
+
+static int kdialogdPid=-1;
+
+static kgtk_bool processIsRunning()
+{
+#ifdef KGTK_DEBUG
+ printf("KGTK::processIsRunning\n");
+#endif
+
+ if(-1!=kdialogdPid && 0==kill(kdialogdPid, 0))
+ {
+#ifdef KGTK_DEBUG
+ printf("KGTK::processIsRunning (%d) YES\n", kdialogdPid);
+#endif
+ return KGTK_TRUE;
+ }
+ else
+ {
+ FILE *f=fopen(getPidFileName(), "r");
+
+ if(f)
+ {
+ int pid=0;
+
+ if(1==fscanf(f, "%d", &pid))
+ {
+ fclose(f);
+
+ if(-1!=kdialogdPid && kdialogdPid!=pid)
+ {
+#ifdef KGTK_DEBUG
+ printf("KGTK::processIsRunning pid has changed from:%d to %d - need to reconnect\n", kdialogdPid, pid);
+#endif
+ kdialogdPid=pid;
+ return KGTK_FALSE;
+ }
+#ifdef KGTK_DEBUG
+ printf("KGTK::processIsRunning file has pid:%d\n", pid);
+#endif
+ if(0==kill(pid, 0))
+ {
+#ifdef KGTK_DEBUG
+ printf("KGTK::processIsRunning (file:%d) YES\n", pid);
+#endif
+ kdialogdPid=pid;
+ return KGTK_TRUE;
+ }
+
+ kdialogdPid=-1; /* Process is not running! */
+ }
+ }
+ }
+#ifdef KGTK_DEBUG
+ printf("KGTK::processIsRunning NO\n");
+#endif
+ return KGTK_FALSE;
+}
+
+static void closeConnection()
+{
+#ifdef KGTK_DEBUG
+ printf("KGTK::closeConnection\n");
+#endif
+ close(kdialogdSocket);
+ kdialogdSocket=-1;
+}
+
+/* Note: Calling 'fork' seems to mess things up with eclipse! */
+#define KGTK_USE_SYSTEM_CALL
+
+static kgtk_bool connectToKDialogD(const char *appName)
+{
+#ifdef KGTK_DEBUG
+ printf("KGTK::connectToKDialogD %s\n", appName ? appName : "<null>");
+#endif
+ if(!processIsRunning())
+ closeConnection();
+
+ if(-1!=kdialogdSocket)
+ return KGTK_TRUE;
+ else
+ {
+ unsigned int slen=strlen(appName);
+ kgtk_bool rv=KGTK_TRUE;
+
+ if(slen)
+ slen++;
+
+#ifdef KGTK_DEBUG
+ printf("KGTK::connectToKDialogD - start wrapper\n");
+#endif
+
+#ifdef KDIALOGD_APP
+ grabLock(5);
+#ifdef KGTK_USE_SYSTEM_CALL
+ system("kdialogd-wrapper &");
+#else
+ switch(fork())
+ {
+ case -1:
+ rv=KGTK_FALSE;
+ printf("ERROR: Could not start fork :-(\n");
+ break;
+ case 0:
+ execl(KDIALOGD_LOCATION"/kdialogd-wrapper", "kdialogd-wrapper", (char *)NULL);
+ break;
+ default:
+ {
+ int status=0;
+ wait(&status);
+ }
+ }
+#endif
+ releaseLock();
+#endif
+
+ if(!rv)
+ return rv;
+
+ rv=
+#ifdef KDIALOGD_APP
+ grabLock(3)>0 &&
+#else
+ 0==system("dcop kded kded loadModule kdialogd") &&
+#endif
+ -1!=(kdialogdSocket=createSocketConnection()) &&
+ writeBlock(kdialogdSocket, (char *)&slen, 4) &&
+ (0==slen || writeBlock(kdialogdSocket, appName, slen));
+#ifdef KDIALOGD_APP
+ releaseLock();
+#endif
+ return rv;
+ }
+}
+
+#endif
diff --git a/config.h.cmake b/config.h.cmake
new file mode 100644
index 0000000..7395b46
--- /dev/null
+++ b/config.h.cmake
@@ -0,0 +1,11 @@
+/* Define to 1 if you have the `getpeereid' function. */
+#cmakedefine HAVE_GETPEEREID 1
+
+/* Define if you have the struct ucred */
+#cmakedefine HAVE_STRUCT_UCRED 1
+#cmakedefine HAVE_DLVSYM 1
+
+#define VERSION "@KGTK_VERSION_FULL@"
+
+#define KGTK_DLSYM_VERSION "@KGTK_DLSYM_VERSION@"
+
diff --git a/debian/cdbs/buildvars.mk b/debian/cdbs/buildvars.mk
new file mode 100644
index 0000000..23d4709
--- /dev/null
+++ b/debian/cdbs/buildvars.mk
@@ -0,0 +1,86 @@
+# -*- mode: makefile; coding: utf-8 -*-
+# Copyright © 2002,2003 Colin Walters <[email protected]>
+# Description: Defines some useful variables, but no rules
+#
+# 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.
+
+_cdbs_scripts_path ?= /usr/lib/cdbs
+_cdbs_rules_path ?= /usr/share/cdbs/1/rules
+_cdbs_class_path ?= /usr/share/cdbs/1/class
+
+ifndef _cdbs_rules_buildvars
+_cdbs_rules_buildvars = 1
+
+CDBS_VERSION = something
+
+# Common useful variables
+DEB_SOURCE_PACKAGE := $(strip $(shell egrep '^Source: ' debian/control | cut -f 2 -d ':'))
+DEB_VERSION := $(shell dpkg-parsechangelog | egrep '^Version:' | cut -f 2 -d ' ')
+DEB_NOEPOCH_VERSION := $(shell echo $(DEB_VERSION) | cut -d: -f2-)
+DEB_UPSTREAM_VERSION := $(shell echo $(DEB_NOEPOCH_VERSION) | sed 's/-[^-]*$$//')
+DEB_ISNATIVE := $(shell dpkg-parsechangelog | egrep '^Version:' | perl -ne 'print if not /^Version:\s*.*-/;')
+
+# Split into arch/indep packages
+ifneq ($(DEB_INDEP_PACKAGES),cdbs)
+DEB_INDEP_PACKAGES := $(filter-out $(DONT_BUILD), $(strip $(shell $(_cdbs_scripts_path)/list-packages indep)))
+DEB_ARCH_PACKAGES := $(filter-out $(DONT_BUILD), $(filter-out $(DEB_INDEP_PACKAGES),$(strip $(shell $(_cdbs_scripts_path)/list-packages same))))
+endif
+# Split into normal and udeb packages
+ifeq ($(DEB_UDEB_PACKAGES),)
+DEB_PACKAGES = $(filter-out $(DONT_BUILD), $(filter-out %-udeb, $(DEB_ARCH_PACKAGES) $(DEB_INDEP_PACKAGES)))
+DEB_UDEB_PACKAGES = $(filter-out $(DONT_BUILD),$(filter %-udeb, $(DEB_ARCH_PACKAGES) $(DEB_INDEP_PACKAGES)))
+else
+DEB_PACKAGES = $(filter-out $(DONT_BUILD), $(filter-out $(DEB_UDEB_PACKAGES), $(DEB_ARCH_PACKAGES) $(DEB_INDEP_PACKAGES)))
+endif
+# Too much bother for now. If someone complains we'll fix it.
+#DEB_ARCH_UDEB_PACKAGES = $(filter %-udeb, $(DEB_ARCH_PACKAGES))
+#DEB_INDEP_UDEB_PACKAGES = $(filter %-udeb, $(DEB_INDEP_PACKAGES))
+# A handy list of every package, udeb or not
+DEB_ALL_PACKAGES = $(filter-out $(DONT_BUILD),$(DEB_PACKAGES) $(DEB_UDEB_PACKAGES))
+DEB_INDEP_REGULAR_PACKAGES = $(filter-out $(DONT_BUILD), $(filter-out $(DEB_UDEB_PACKAGES),$(DEB_INDEP_PACKAGES)))
+DEB_ARCH_REGULAR_PACKAGES = $(filter-out $(DONT_BUILD), $(filter-out $(DEB_UDEB_PACKAGES),$(DEB_ARCH_PACKAGES)))
+
+DEB_DBG_PACKAGES = $(filter-out $(DONT_BUILD), $(filter %-dbg, $(DEB_ARCH_PACKAGES) $(DEB_INDEP_PACKAGES)))
+
+# Some support for srcdir != builddir builds.
+# These are relative to the root of the package
+DEB_SRCDIR ?= .
+DEB_BUILDDIR ?= $(strip $(DEB_SRCDIR))
+
+# Miscellaneous bits
+DEB_ARCH = $(shell dpkg --print-architecture)
+DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE)
+DEB_HOST_GNU_SYSTEM ?= $(shell dpkg-architecture -qDEB_HOST_GNU_SYSTEM)
+DEB_HOST_GNU_CPU ?= $(shell dpkg-architecture -qDEB_HOST_GNU_CPU)
+DEB_HOST_ARCH ?= $(shell dpkg-architecture -qDEB_HOST_ARCH)
+DEB_HOST_ARCH_CPU ?= $(shell dpkg-architecture -qDEB_HOST_ARCH_CPU)
+DEB_HOST_ARCH_OS ?= $(shell dpkg-architecture -qDEB_HOST_ARCH_OS)
+DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE)
+DEB_BUILD_GNU_SYSTEM ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_SYSTEM)
+DEB_BUILD_GNU_CPU ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_CPU)
+DEB_BUILD_ARCH ?= $(shell dpkg-architecture -qDEB_BUILD_ARCH)
+DEB_BUILD_ARCH_CPU ?= $(shell dpkg-architecture -qDEB_BUILD_ARCH_CPU)
+DEB_BUILD_ARCH_OS ?= $(shell dpkg-architecture -qDEB_BUILD_ARCH_OS)
+
+ifeq ($(words $(DEB_ALL_PACKAGES)),1)
+ DEB_DESTDIR = $(CURDIR)/debian/$(strip $(DEB_ALL_PACKAGES))/
+else
+ DEB_DESTDIR = $(CURDIR)/debian/tmp/
+endif
+
+CDBS_BUILD_DEPENDS := $(CDBS_BUILD_DEPENDS), cdbs (>= 0.4.23-1.1)
+
+endif
diff --git a/debian/cdbs/debian-qt-kde.mk b/debian/cdbs/debian-qt-kde.mk
new file mode 100644
index 0000000..2be8f97
--- /dev/null
+++ b/debian/cdbs/debian-qt-kde.mk
@@ -0,0 +1,109 @@
+ifndef _cdbs_bootstrap
+_cdbs_scripts_path ?= /usr/lib/cdbs
+_cdbs_rules_path ?= /usr/share/cdbs/1/rules
+_cdbs_class_path ?= /usr/share/cdbs/1/class
+endif
+
+ifndef _cdbs_class_debian-qt-kde
+_cdbs_class_debian-qt-kde := 1
+
+# Note: This _must_ be included before autotools.mk, or it won't work.
+common-configure-arch common-configure-indep:: debian/stamp-cvs-make
+debian/stamp-cvs-make:
+ cp -Rp /usr/share/aclocal/libtool.m4 admin/libtool.m4.in
+ cp -Rp /usr/share/libtool/config/ltmain.sh admin/ltmain.sh
+ $(MAKE) -C $(DEB_SRCDIR) -f admin/Makefile.common dist;
+ touch debian/stamp-cvs-make
+
+include debian/cdbs/kde.mk$(_cdbs_makefile_suffix)
+include debian/cdbs/uploaders.mk
+
+DEB_PATCHDIRS := debian/patches/common debian/patches
+
+DEB_KDE_ENABLE_FINAL := yes
+DEB_INSTALL_DOCS_ALL :=
+
+DEB_DH_MAKESHLIBS_ARGS_ALL := -V
+DEB_SHLIBDEPS_INCLUDE = $(foreach p,$(PACKAGES_WITH_LIBS),debian/$(p)/usr/lib)
+
+ifeq (,$(findstring noopt,$(DEB_BUILD_OPTIONS)))
+ cdbs_treat_me_gently_arches := arm m68k alpha ppc64 armel armeb
+ ifeq (,$(filter $(DEB_HOST_ARCH_CPU),$(cdbs_treat_me_gently_arches)))
+ cdbs_kde_enable_final = $(if $(DEB_KDE_ENABLE_FINAL),--enable-final,)
+ else
+ cdbs_kde_enable_final =
+ endif
+endif
+
+common-build-arch:: debian/stamp-man-pages
+debian/stamp-man-pages:
+ if ! test -d debian/man/out; then mkdir -p debian/man/out; fi
+ for f in $$(find debian/man -name '*.sgml'); do \
+ docbook-to-man $$f > debian/man/out/`basename $$f .sgml`.1; \
+ done
+ for f in $$(find debian/man -name '*.man'); do \
+ soelim -I debian/man $$f \
+ > debian/man/out/`basename $$f .man`.`head -n1 $$f | awk '{print $$NF}'`; \
+ done
+ touch debian/stamp-man-pages
+
+common-binary-indep::
+ ( set -e; \
+ tmpf=`mktemp debian/versions.XXXXXX`; \
+ perl debian/cdbs/versions.pl >$$tmpf; \
+ for p in $(DEB_INDEP_PACKAGES); do \
+ cat $$tmpf >>debian/$$p.substvars; \
+ done; \
+ rm -f $$tmpf )
+
+common-binary-arch::
+ ( set -e; \
+ tmpf=`mktemp debian/versions.XXXXXX`; \
+ perl debian/cdbs/versions.pl >$$tmpf; \
+ for p in $(DEB_ARCH_PACKAGES); do \
+ cat $$tmpf >>debian/$$p.substvars; \
+ done; \
+ rm -f $$tmpf )
+
+clean::
+ rm -rf debian/man/out
+ -rmdir debian/man
+ rm -f debian/stamp-man-pages
+ rm -rf debian/shlibs-check
+
+$(patsubst %,binary-install/%,$(DEB_PACKAGES)) :: binary-install/%:
+ if test -x /usr/bin/dh_desktop; then dh_desktop -p$(cdbs_curpkg) $(DEB_DH_DESKTOP_ARGS); fi
+ if test -e debian/$(cdbs_curpkg).lintian; then \
+ install -p -D -m644 debian/$(cdbs_curpkg).lintian \
+ debian/$(cdbs_curpkg)/usr/share/lintian/overrides/$(cdbs_curpkg); \
+ fi
+ if test -e debian/$(cdbs_curpkg).presubj; then \
+ install -p -D -m644 debian/$(cdbs_curpkg).presubj \
+ debian/$(cdbs_curpkg)/usr/share/bug/$(cdbs_curpkg)/presubj; \
+ fi
+
+binary-install/$(DEB_SOURCE_PACKAGE)-doc-html::
+ set -e; \
+ for doc in `cd $(DEB_DESTDIR)/opt/kde3/share/doc/kde/HTML/en; find . -name index.docbook`; do \
+ pkg=$${doc%/index.docbook}; pkg=$${pkg#./}; \
+ echo Building $$pkg HTML docs...; \
+ mkdir -p $(CURDIR)/debian/$(DEB_SOURCE_PACKAGE)-doc-html/opt/kde3/share/doc/kde/HTML/en/$$pkg; \
+ cd $(CURDIR)/debian/$(DEB_SOURCE_PACKAGE)-doc-html/opt/kde3/share/doc/kde/HTML/en/$$pkg; \
+ /opt/kde3/bin/meinproc $(DEB_DESTDIR)/opt/kde3/share/doc/kde/HTML/en/$$pkg/index.docbook; \
+ done
+ for pkg in $(DOC_HTML_PRUNE) ; do \
+ rm -rf debian/$(DEB_SOURCE_PACKAGE)-doc-html/opt/kde3/share/doc/kde/HTML/en/$$pkg; \
+ done
+
+clean::
+ if test -n "$(DEB_KDE_CVS_MAKE)" && test -d $(DEB_SRCDIR); then \
+ cd $(DEB_SRCDIR); \
+ find . -name Makefile.in -print | \
+ xargs --no-run-if-empty rm -f; \
+ rm -f Makefile.am acinclude.m4 aclocal.m4 config.h.in \
+ configure configure.files configure.in stamp-h.in \
+ subdirs; \
+ fi
+ rm -f debian/stamp-cvs-make
+
+endif
diff --git a/debian/cdbs/kde.mk b/debian/cdbs/kde.mk
new file mode 100644
index 0000000..9e41175
--- /dev/null
+++ b/debian/cdbs/kde.mk
@@ -0,0 +1,97 @@
+# -*- mode: makefile; coding: utf-8 -*-
+# Copyright © 2003 Christopher L Cheney <[email protected]>
+# Description: A class for KDE packages; sets KDE environment variables, etc
+#
+# 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.
+
+_cdbs_scripts_path ?= /usr/lib/cdbs
+_cdbs_rules_path ?= /usr/share/cdbs/1/rules
+_cdbs_class_path ?= /usr/share/cdbs/1/class
+
+ifndef _cdbs_class_kde
+_cdbs_class_kde := 1
+
+# for dh_icons
+CDBS_BUILD_DEPENDS := $(CDBS_BUILD_DEPENDS), debhelper (>= 5.0.7ubuntu4)
+
+include $(_cdbs_rules_path)/buildcore.mk$(_cdbs_makefile_suffix)
+
+ifdef _cdbs_tarball_dir
+DEB_BUILDDIR = $(_cdbs_tarball_dir)/obj-$(DEB_BUILD_GNU_TYPE)
+else
+DEB_BUILDDIR = obj-$(DEB_BUILD_GNU_TYPE)
+endif
+
+include $(_cdbs_class_path)/autotools.mk$(_cdbs_makefile_suffix)
+
+export kde_cgidir = \$${libdir}/cgi-bin
+export kde_confdir = \$${sysconfdir}/kde3
+export kde_htmldir = \$${datadir}/doc/kde/HTML
+
+ifeq (,$(filter noopt,$(DEB_BUILD_OPTIONS)))
+ cdbs_kde_enable_final = $(if $(DEB_KDE_ENABLE_FINAL),--enable-final,)
+endif
+
+ifneq (,$(filter nostrip,$(DEB_BUILD_OPTIONS)))
+ cdbs_kde_enable_final =
+ cdbs_kde_enable_debug = --enable-debug=yes
+else
+ cdbs_kde_enable_debug = --disable-debug
+endif
+
+ifneq (,$(filter debug,$(DEB_BUILD_OPTIONS)))
+ cdbs_kde_enable_debug = --enable-debug=full
+endif
+
+cdbs_configure_flags += --with-qt-dir=/usr/share/qt3 --disable-rpath --with-xinerama $(cdbs_kde_enable_final) $(cdbs_kde_enable_debug)
+
+DEB_AC_AUX_DIR = $(DEB_SRCDIR)/admin
+DEB_CONFIGURE_INCLUDEDIR = "\$${prefix}/include/kde"
+DEB_COMPRESS_EXCLUDE = .dcl .docbook -license .tag .sty .el
+
+$(patsubst %,binary-install/%,$(DEB_PACKAGES)) :: binary-install/%:
+ if test -x /usr/bin/dh_icons; then dh_icons -p$(cdbs_curpkg) $(DEB_DH_ICONCACHE_ARGS); fi
+
+cleanbuilddir::
+ -$(if $(call cdbs_streq,$(DEB_BUILDDIR),$(DEB_SRCDIR)),,rm -rf $(DEB_BUILDDIR))
+
+common-build-arch common-build-indep:: debian/stamp-kde-apidox
+debian/stamp-kde-apidox:
+ $(if $(DEB_KDE_APIDOX),+$(DEB_MAKE_INVOKE) apidox)
+ touch $@
+
+common-install-prehook-impl::
+ mkdir -p po
+ -XGETTEXT=/usr/bin/kde-xgettext EXTRACTATTR=/opt/kde3/bin/extractattr sh $(DEB_SRCDIR)/admin/cvs.sh extract-messages
+ -for file in po/*pot; do \
+ sed "s/charset=CHARSET/charset=UTF-8/" -i $$file; \
+ done
+
+common-install-arch common-install-indep:: common-install-kde-apidox
+common-install-kde-apidox::
+ $(if $(DEB_KDE_APIDOX),+$(DEB_MAKE_INVOKE) install-apidox DESTDIR=$(DEB_DESTDIR))
+
+clean::
+ rm -f debian/stamp-kde-apidox
+ rm -rf po/*.pot
+
+# This is a convenience target for calling manually. It's not part of
+# the build process.
+buildprep: clean apply-patches
+ $(MAKE) -f admin/Makefile.common dist
+ debian/rules clean
+
+endif
diff --git a/debian/cdbs/team-members b/debian/cdbs/team-members
new file mode 100644
index 0000000..05761af
--- /dev/null
+++ b/debian/cdbs/team-members
@@ -0,0 +1,16 @@
+Sune Vuorela <[email protected]>
+Ana Beatriz Guerrero Lopez <[email protected]>
+Fathi Boudra <[email protected]>
+Modestas Vainius <[email protected]>
+Josh Metzler <[email protected]>
+Isaac Clerencia <[email protected]>
+Adeodato Simó <[email protected]>
+Adeodato Simo <[email protected]>
+Christopher Martin <[email protected]>
+Daniel Schepler <[email protected]>
+Sarah Hobbs <[email protected]>
+Nacho Barrientos Arias <[email protected]>
+Ricardo Javier Cardenes Medina <[email protected]>
+Ricardo Cardenes <[email protected]>
+Armin Berres <[email protected]>
+Francesco Pedrini <[email protected]>
diff --git a/debian/cdbs/uploaders.mk b/debian/cdbs/uploaders.mk
new file mode 100644
index 0000000..31adfe3
--- /dev/null
+++ b/debian/cdbs/uploaders.mk
@@ -0,0 +1,29 @@
+
+MAINTAINER=Debian Qt/KDE Maintainers <[email protected]>
+UPLOADERS=$(shell grep -e +++ -e "^ -- " debian/changelog | grep -v "[email protected]" | head -13 | /bin/sed 's/^\s*//;s/\s*$$//;s/^+++\? Changes by //;s/^+++\? //;s/-- //;s/:$$//;s/ <.*//' | sort -u | while read line ; do grep "$$line" debian/cdbs/team-members ; done | tr "\n" ", " | sed 's/,/, /g;s/, $$//')
+
+
+debian/control.tmp:
+ @if [ ! -e debian/control.in ] ; then \
+ echo "this package is not yet prepared for using automatic update of uploaders"; \
+ echo "Please do so."; \
+ exit 1; \
+ fi
+ @sed 's/@@@UPLOADERS@@@/$(UPLOADERS)/;s#@@@MAINTAINER@@@#$(MAINTAINER)#' debian/control.in > debian/control.tmp
+
+check-uploaders: debian/control.tmp
+ @if ! diff -q debian/control debian/control.tmp ; then \
+ echo "WARNING:: Control file differs from manually generated one" ; \
+ echo "WARNING:: Please update it manually and check it afterwards" ; \
+ echo "WARNING:: Uploaders are updated by debian/rules update-uploaders" ;\
+ echo "WARNING:: If this is a binNMU, NMU or security upload, just ignore" ;\
+ fi
+
+
+clean::
+ rm -f debian/control.tmp
+
+update-uploaders: debian/control.tmp
+ @mv -f debian/control.tmp debian/control
+
+makebuilddir:: check-uploaders
diff --git a/debian/cdbs/versions.pl b/debian/cdbs/versions.pl
new file mode 100644
index 0000000..9ce11d8
--- /dev/null
+++ b/debian/cdbs/versions.pl
@@ -0,0 +1,19 @@
+#!/usr/bin/env perl
+
+use strict;
+use warnings;
+
+my $version = `dpkg-parsechangelog | awk '/^Version/ {print \$2}'`;
+my ($version3, $version3_next);
+my ($version2, $version2_next);
+
+($version3 = $version) =~ s/-[^-]+$//;
+($version2 = $version3) =~ s/\.[^.]+$//;
+
+($version3_next = $version3) =~ s/(?<=\.)(\d+)[a-z]?$/($1+1)/e;
+($version2_next = $version2) =~ s/(?<=\.)(\d+)$/($1+1)/e;
+
+print "KDE-Version3=$version3\n";
+print "KDE-Version2=$version2\n";
+print "KDE-Next-Version3=$version3_next\n";
+print "KDE-Next-Version2=$version2_next\n";
diff --git a/debian/changelog b/debian/changelog
new file mode 100644
index 0000000..a69a5a0
--- /dev/null
+++ b/debian/changelog
@@ -0,0 +1,11 @@
+kgtk-qt3-kde3 (0.10.2-0ubuntu5) maverick; urgency=low
+
+ * Maverick build
+
+ -- Timothy Pearson <[email protected]> Mon, 05 Apr 2010 13:20:00 -0600
+
+kgtk-qt3 (0.10.1-0ubuntu1~ppa1) jaunty; urgency=low
+
+ * Initial release
+
+ -- Anthony Mercatante <[email protected]> Mon, 17 Mar 2009 01:24:08 +0100
diff --git a/debian/compat b/debian/compat
new file mode 100644
index 0000000..7f8f011
--- /dev/null
+++ b/debian/compat
@@ -0,0 +1 @@
+7
diff --git a/debian/control b/debian/control
new file mode 100644
index 0000000..226eafe
--- /dev/null
+++ b/debian/control
@@ -0,0 +1,19 @@
+Source: kgtk-qt3-kde3
+Section: kde
+Priority: optional
+Maintainer: Timothy Pearson <[email protected]>
+Build-Depends: debhelper (>= 7), cdbs, kdelibs4-kde3-dev, libgtk2.0-dev, libqt3-mt-dev, cmake
+Standards-Version: 3.8.3
+Homepage: http://kde-apps.org/content/show.php/KGtk+(Use+KDE+Dialogs+in+Gtk+Apps)?content=36077
+
+Package: kgtk-qt3-kde3
+Architecture: any
+Depends: ${shlibs:Depends}
+Description: Use KDE dialogs in Gtk apps
+ This is a quick-and-dirty LD_PRELOAD hack that allows *some* Gtk
+ applications to use KDE's file dialogs when run under KDE.
+ .
+ The Gtk file chooser functions have been overridden to communicate
+ with this KDE module/application.
+ .
+ This package includes the kqt3-wrapper
diff --git a/debian/copyright b/debian/copyright
new file mode 100644
index 0000000..0e93ef8
--- /dev/null
+++ b/debian/copyright
@@ -0,0 +1,37 @@
+This package was debianized by:
+
+ Anthony Mercatante <[email protected]>
+
+It was downloaded from:
+
+ http://kde-apps.org/content/show.php/KGtk+(Use+KDE+Dialogs+in+Gtk+Apps)?content=36077
+
+Upstream Authors:
+
+ Craig Drummond <[email protected]>
+
+Copyright:
+ Copyright (C) Craig Drummond, 2006-2007
+
+License:
+ 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.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+ On Debian systems, the complete text of the GNU General
+ Public License can be found in `/usr/share/common-licenses/GPL-2'.
+
+The Debian packaging is:
+
+ Copyright C) 2009, Anthony Mercatante <[email protected]>
+ and is licensed under the GPL-2, see above.
diff --git a/debian/rules b/debian/rules
new file mode 100755
index 0000000..a9d9faa
--- /dev/null
+++ b/debian/rules
@@ -0,0 +1,30 @@
+#!/usr/bin/make -f
+# -*- makefile -*-
+# Sample debian/rules that uses debhelper.
+# This file was originally written by Joey Hess and Craig Small.
+# As a special exception, when this file is copied by dh-make into a
+# dh-make output file, you may use that output file without restriction.
+# This special exception was added by Craig Small in version 0.37 of dh-make.
+
+include /usr/share/cdbs/1/rules/debhelper.mk
+include /usr/share/cdbs/1/rules/simple-patchsys.mk
+
+DEB_CONFIGURE_INCLUDEDIR := /opt/kde3/include/kde
+DEB_CONFIGURE_MANDIR := /opt/kde3/share/man
+DEB_CONFIGURE_PREFIX := /opt/kde3
+DEB_CONFIGURE_INFODIR := /opt/kde3/share/info
+DEB_CMAKE_CUSTOM_FLAGS := -DKGTK_KDE3=true -DKGTK_QT3=true
+
+cdbs_configure_flags := --with-qt-dir=/usr/share/qt3 --disable-rpath --with-xinerama $(cdbs_kde_enable_final) $(cdbs_kde_enable_debug)
+
+DEB_CONFIGURE_EXTRA_FLAGS := --prefix=/opt/kde3 --with-extra-libs=/opt/kde3/lib
+
+configure/kgtk-qt3-kde3::
+ env PATH=/opt/kde3/bin:$(PATH) CMAKE_LIBRARY_PATH=/opt/kde3/lib CMAKE_INCLUDE_PATH=/opt/kde3/include/kde cmake -D CMAKE_INSTALL_PREFIX=/opt/kde3 .
+
+build/kgtk-qt3-kde3::
+ env PATH=/opt/kde3/bin:$(PATH) CMAKE_LIBRARY_PATH=/opt/kde3/lib CMAKE_INCLUDE_PATH=/opt/kde3/include/kde $(MAKE)
+
+install/kgtk-qt3-kde3::
+ env PATH=/opt/kde3/bin:$(PATH) CMAKE_LIBRARY_PATH=/opt/kde3/lib CMAKE_INCLUDE_PATH=/opt/kde3/include/kde $(MAKE) install DESTDIR=$(CURDIR)/debian/kgtk-qt3-kde3
+
diff --git a/debian/rules.bkp b/debian/rules.bkp
new file mode 100755
index 0000000..6a608c7
--- /dev/null
+++ b/debian/rules.bkp
@@ -0,0 +1,9 @@
+#!/usr/bin/make -f
+
+DEB_CMAKE_CUSTOM_FLAGS := -DKGTK_KDE3=true -DKGTK_QT3=true
+
+include debian/cdbs/kde.mk
+
+binary-install/kgtk-qt3::
+ rm -f debian/kgtk-qt3/usr/bin/kdialogd-wrapper
+ rm -f debian/kgtk-qt3/usr/bin/kgtk-wrapper
diff --git a/gtk2/CMakeLists.txt b/gtk2/CMakeLists.txt
new file mode 100644
index 0000000..36b3e3f
--- /dev/null
+++ b/gtk2/CMakeLists.txt
@@ -0,0 +1,22 @@
+include(FindPkgConfig)
+
+pkg_check_modules(GTK gtk+-2.0>=2.6)
+
+if (GTK_FOUND)
+ message("** INFORMATION: Gtk2 LD_PRELOAD library will be built.")
+
+ # set(LIB_SUFFIX "" CACHE STRING "Define suffix of directory name (32/64)" )
+ set(LIB_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX} CACHE PATH "The subdirectory relative to the install prefix where libraries will be installed (default is /lib${LIB_SUFFIX})" FORCE)
+
+ include_directories (${CMAKE_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_SOURCE_DIR}/common ${CMAKE_BINARY_DIR} ${GTK_INCLUDE_DIRS})
+ set(kgtk2_SRCS kgtk2.c)
+ add_library(kgtk2 SHARED ${kgtk2_SRCS})
+ target_link_libraries(kgtk2 ${GTK_LDFLAGS} -lgthread-2.0 -lglib-2.0 -lc -ldl)
+
+ install(TARGETS kgtk2 LIBRARY DESTINATION ${LIB_INSTALL_DIR}/kgtk )
+
+ configure_file (kgtk2-wrapper.cmake ${CMAKE_CURRENT_BINARY_DIR}/kgtk2-wrapper @ONLY)
+ install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/kgtk2-wrapper DESTINATION bin)
+else (GTK_FOUND)
+ message("** ERROR : Could not locate Gtk2 headers, Gtk2 LD_PRELOAD library will not be built.")
+endif (GTK_FOUND)
diff --git a/gtk2/kgtk2-wrapper.cmake b/gtk2/kgtk2-wrapper.cmake
new file mode 100755
index 0000000..46865b7
--- /dev/null
+++ b/gtk2/kgtk2-wrapper.cmake
@@ -0,0 +1,33 @@
+#!/bin/bash
+
+#
+# This script is part of the KGtk package.
+#
+# (C) Craig Drummond, 2007
+#
+#
+# --
+# Released under the GPL v2 or later
+# --
+#
+
+if [ "`locale | grep 'LANG=' | grep -i 'utf-8' | wc -l`" = "0" ] ; then
+ export G_BROKEN_FILENAMES=1
+fi
+
+app=`basename $0`
+
+if [ "$app" = "kgtk2-wrapper" ] ; then
+ LD_PRELOAD=@CMAKE_INSTALL_PREFIX@/lib/kgtk/libkgtk2.so:$LD_PRELOAD "$@"
+else
+ dir=`dirname $0`
+ oldPath=$PATH
+ PATH=`echo $PATH | sed s:$dir::g`
+ real=`which $app`
+ PATH=$oldPath
+
+ if [ "$real" != "" ] && [ "`dirname $real`" != "$dir" ] ; then
+ LD_PRELOAD=@CMAKE_INSTALL_PREFIX@/lib@LIB_SUFFIX@/kgtk/libkgtk2.so:$LD_PRELOAD $real "$@"
+ fi
+fi
diff --git a/gtk2/kgtk2.c b/gtk2/kgtk2.c
new file mode 100644
index 0000000..d0457c5
--- /dev/null
+++ b/gtk2/kgtk2.c
@@ -0,0 +1,2005 @@
+/************************************************************************
+ *
+ * All dialogs opened are created and used modal.
+ *
+ ************************************************************************
+ * (C) Craig Drummond, 2006
+ ************************************************************************
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ ************************************************************************/
+
+/*
+ NOTES:
+
+ 1. Inkscape does not use the standard Gtk fileters to determine Save type
+ ...it uses an extra combo, which we try to locate.
+ 2. Firefox. This has two filters with the same patterns - *.htm and *.html. We
+ modify this so that one is *.htm and the other is *.html
+ 3. Glade-2 I noticed this crash a couple of times on loading - but not always.
+ Not sure if this is a Glade problem or not...
+*/
+
+/*
+TODO
+ abiword: seems to call gtk_widget_show - but just overriding this cuases the dialog to
+ appear twice, and then it still donest use result :-(
+ Overload font picker!
+ Overload normal old file selector? ie. in addtition to file chooser?
+ Message boxes: Auto set alternative button order?
+*/
+
+/*
+#define KGTK_DEBUG
+*/
+
+#define _GNU_SOURCE
+#include <dlfcn.h>
+#include <gtk/gtk.h>
+#include <glib.h>
+#include <gdk/gdkx.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <pwd.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdarg.h>
+#include "connect.h"
+#include "config.h"
+
+#ifndef KGTK_DLSYM_VERSION
+#define KGTK_DLSYM_VERSION "GLIBC_2.0"
+#endif
+
+/*
+#define KGTK_DEBUG_DLSYM
+*/
+
+/*
+ * For SWT apps (e.g. eclipse) we need to override dlsym, but we can only do this if
+ * dlvsym is present in libdl. dlvsym is needed so that we can access the real dlsym
+ * as well as our fake dlsym
+ */
+#ifdef HAVE_DLVSYM
+static void * real_dlsym (void *handle, const char *name);
+#else
+#define real_dlsym(A, B) dlsym(A, B)
+#endif
+
+typedef enum
+{
+ APP_ANY,
+ APP_GIMP,
+ APP_INKSCAPE,
+ APP_FIREFOX,
+ APP_KINO
+} Application;
+
+static const char *kgtkAppName=NULL;
+static gboolean useKde=FALSE;
+static gboolean kdialogdError=FALSE;
+static GMainLoop *kdialogdLoop=NULL;
+static gchar *kgtkFileFilter=NULL;
+static Application kgtkApp=APP_ANY;
+
+#define MAX_DATA_LEN 4096
+#define MAX_FILTER_LEN 256
+#define MAX_LINE_LEN 1024
+#define MAX_APP_NAME_LEN 32
+
+static char * kgtk_get_app_name(int pid)
+{
+ static char app_name[MAX_APP_NAME_LEN+1]="\0";
+
+ int procFile=-1;
+ char cmdline[MAX_LINE_LEN+1];
+
+ sprintf(cmdline, "/proc/%d/cmdline",pid);
+
+ if(-1!=(procFile=open(cmdline, O_RDONLY)))
+ {
+ if(read(procFile, cmdline, MAX_LINE_LEN)>2)
+ {
+ int len=strlen(cmdline),
+ pos=0;
+
+ for(pos=len-1; pos>0 && cmdline[pos] && cmdline[pos]!='/'; --pos)
+ ;
+
+ if(pos>=0 && pos<len)
+ {
+ strncpy(app_name, &cmdline[pos ? pos+1 : 0], MAX_APP_NAME_LEN);
+ app_name[MAX_APP_NAME_LEN]='\0';
+ }
+ }
+ close(procFile);
+ }
+
+ return app_name;
+}
+
+/* Try to get name of application executable - either from argv[0], or /proc */
+static const gchar *getAppName(const gchar *app)
+{
+ static const char *appName=NULL;
+
+ if(!appName)
+ {
+ /* Is there an app name set? - if not read from /proc */
+ const gchar *a=app ? app : kgtk_get_app_name(getpid());
+ gchar *slash;
+
+ /* Was the cmdline app java? if so, try to use its parent name - just in case
+ its run from a shell script, etc. - e.g. as eclipse does */
+ if(a && 0==strcmp(a, "java"))
+ a=kgtk_get_app_name(getppid());
+
+ if(a && a[0]=='\0')
+ a=NULL;
+
+ appName=a && (slash=strrchr(a, '/')) && '\0'!=slash[1]
+ ? &(slash[1])
+ : a ? a : "GtkApp";
+ }
+
+#ifdef KGTK_DEBUG
+ printf("KGTK::getAppName: %s\n", appName);
+#endif
+ return appName;
+}
+
+static gboolean writeString(const char *s)
+{
+ unsigned int slen=strlen(s)+1;
+
+ return writeBlock(kdialogdSocket, (char *)&slen, 4) &&
+ writeBlock(kdialogdSocket, s, slen);
+}
+
+static gboolean writeBool(gboolean b)
+{
+ char bv=b ? 1 : 0;
+
+ return writeBlock(kdialogdSocket, (char *)&bv, 1);
+}
+
+typedef struct
+{
+ GSList *res;
+ gchar *selFilter;
+} KGtkData;
+
+static gpointer kdialogdMain(gpointer data)
+{
+ KGtkData *d=(struct KGtkData *)data;
+ char buffer[MAX_DATA_LEN+1]={'\0'};
+ int num=0;
+
+ if(readBlock(kdialogdSocket, (char *)&num, 4))
+ {
+ int n;
+
+ for(n=0; n<num && !kdialogdError; ++n)
+ {
+ int size=0;
+
+ if(readBlock(kdialogdSocket, (char *)&size, 4))
+ {
+ if(size>0)
+ {
+ if(size<=MAX_DATA_LEN && readBlock(kdialogdSocket, buffer, size))
+ {
+ /*buffer[size-1]='\0'; */
+ if('/'==buffer[0])
+ d->res=g_slist_prepend(d->res, g_filename_from_utf8(buffer, -1, NULL, NULL, NULL));
+ else if(!(d->selFilter))
+ d->selFilter=g_strdup(buffer);
+ }
+ else
+ kdialogdError=TRUE;
+ }
+ }
+ else
+ kdialogdError=TRUE;
+ }
+ }
+ else
+ kdialogdError=TRUE;
+
+ if(g_main_loop_is_running(kdialogdLoop))
+ g_main_loop_quit(kdialogdLoop);
+
+ return 0L;
+}
+
+static gboolean sendMessage(GtkWidget *widget, Operation op, GSList **res, gchar **selFilter,
+ const char *title, const char *p1, const char *p2, gboolean overWrite)
+{
+#ifdef KGTK_DEBUG
+ printf("KGTK::sendMessage\n");
+#endif
+
+ if(connectToKDialogD(getAppName(kgtkAppName)))
+ {
+ char o=(char)op;
+ int xid=0;
+
+ if(widget)
+ {
+ if(widget->parent)
+ {
+#ifdef KGTK_DEBUG
+ printf("KGTK::Dialog has a parent!\n");
+#endif
+ xid=GDK_WINDOW_XID(gtk_widget_get_toplevel(widget->parent));
+ }
+
+ /*
+ Inkscape's 0.44 export bitmap filechooser is set to be transient for the main window, and
+ not the export dialog. This makes the KDE dialog appear underneath it! So, for inkscape
+ dont try to get the window transient for...
+
+ ...might need to remove this whole section, if it starts to affect too many apps
+ */
+ if(!xid && APP_INKSCAPE!=kgtkApp && GTK_IS_WINDOW(widget))
+ {
+ GtkWindow *win=gtk_window_get_transient_for(GTK_WINDOW(widget));
+
+#ifdef KGTK_DEBUG
+ printf("KGTK::Get window transient for...\n");
+#endif
+ if(win && win->focus_widget)
+ xid=GDK_WINDOW_XID(gtk_widget_get_toplevel(win->focus_widget)->window);
+ }
+ }
+
+ if(!xid)
+ {
+ GList *topWindows,
+ *node;
+ int prevX=0;
+
+#ifdef KGTK_DEBUG
+ printf("KGTK::No xid, need to traverse window list...\n");
+#endif
+ for(topWindows=node=gtk_window_list_toplevels(); node; node = node->next)
+ {
+ GtkWidget *w=node->data;
+
+ if(w && GTK_IS_WIDGET(w) && w->window)
+ if(gtk_window_has_toplevel_focus(GTK_WINDOW(w)) &&
+ gtk_window_is_active(GTK_WINDOW(w)))
+ {
+ /* If the currently active window is a popup - then assume it is a popup-menu,
+ * so use the previous window as the one to be transient for...*/
+ if(GTK_WINDOW_POPUP==GTK_WINDOW(w)->type && prevX)
+ xid=prevX;
+ else
+ xid=GDK_WINDOW_XID(w->window);
+ if(xid)
+ break;
+ }
+ else
+ prevX=GDK_WINDOW_XID(w->window);
+ }
+ g_list_free(topWindows);
+ }
+
+ if(writeBlock(kdialogdSocket, &o, 1) &&
+ writeBlock(kdialogdSocket, (char *)&xid, 4) &&
+ writeString(title) &&
+ (p1 ? writeString(p1) : TRUE) &&
+ (p2 ? writeString(p2) : TRUE) &&
+ (OP_FILE_SAVE==op ? writeBool(overWrite) : TRUE))
+ {
+ GtkWidget *dlg=gtk_dialog_new();
+ KGtkData d;
+
+ gtk_widget_set_name(dlg, "--kgtk-modal-dialog-hack--");
+ d.res=NULL;
+ d.selFilter=NULL;
+
+ /* Create a tmporary, hidden, dialog so that the kde dialog appears as modal */
+ g_object_ref(dlg);
+ gtk_window_set_modal(GTK_WINDOW(dlg), TRUE);
+ gtk_window_iconify(GTK_WINDOW(dlg));
+ gtk_dialog_set_has_separator(GTK_DIALOG(dlg), FALSE);
+ gtk_window_set_has_frame(GTK_WINDOW(dlg), FALSE);
+ gtk_window_set_decorated(GTK_WINDOW(dlg), FALSE);
+ gtk_window_set_keep_below(GTK_WINDOW(dlg), TRUE);
+ gtk_window_set_opacity(GTK_WINDOW(dlg), 100);
+ gtk_window_set_type_hint(GTK_WINDOW(dlg), GDK_WINDOW_TYPE_HINT_DOCK);
+ gtk_widget_show(dlg);
+ gtk_window_move(GTK_WINDOW(dlg), 32768, 32768);
+ gtk_window_set_skip_taskbar_hint(GTK_WINDOW(dlg), TRUE);
+ gtk_window_set_skip_pager_hint(GTK_WINDOW(dlg), TRUE);
+ kdialogdLoop = g_main_loop_new (NULL, FALSE);
+ kdialogdError=FALSE;
+ g_thread_create(&kdialogdMain, &d, FALSE, NULL);
+
+ GDK_THREADS_LEAVE();
+ g_main_loop_run(kdialogdLoop);
+ GDK_THREADS_ENTER();
+ g_main_loop_unref(kdialogdLoop);
+ kdialogdLoop = NULL;
+ gtk_window_set_modal(GTK_WINDOW(dlg), FALSE);
+ g_object_unref(dlg);
+ gtk_widget_destroy(dlg);
+ if(kdialogdError)
+ {
+ closeConnection();
+ return FALSE;
+ }
+ if(d.res)
+ {
+ if(res)
+ *res=d.res;
+ else
+ g_slist_free(d.res);
+ }
+ if(d.selFilter)
+ {
+ if(selFilter)
+ *selFilter=d.selFilter;
+ else
+ g_free(d.selFilter);
+ }
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+static gchar * firstEntry(GSList *files)
+{
+ gchar *file=NULL;
+
+ if(files)
+ {
+ file=(gchar *)(files->data);
+ files=g_slist_delete_link(files, files);
+ if(files)
+ {
+ g_slist_foreach(files, (GFunc)g_free, NULL);
+ g_slist_free(files);
+ files=NULL;
+ }
+ }
+
+ return file;
+}
+
+static const char * getTitle(const char *title, Operation op)
+{
+ if(title && strlen(title))
+ return title;
+
+ return ".";
+}
+
+static gboolean openKdeDialog(GtkWidget *widget, const char *title, const char *p1, const char *p2,
+ Operation op, GSList **res, gchar **selFilter, gboolean overWrite)
+{
+ gboolean rv=sendMessage(widget, op, res, selFilter, getTitle(title, op), p1, p2, overWrite);
+
+ /* If we failed to talk to, or start kdialogd, then dont keep trying - just fall back to Gtk */
+/*
+ if(!rv)
+ useKde=FALSE;
+*/
+
+ return rv;
+}
+
+static void kgtkExit()
+{
+ if(useKde)
+ closeConnection();
+}
+
+static gboolean isApp(const char *str, const char *app)
+{
+ /* Standard case... */
+ if(0==strcmp(str, app))
+ return TRUE;
+
+ /* Autopackage'd app */
+ #define AUTOPACKAGE_PROXY ".proxy."
+ #define AUTOPACKAGE_PROXY_LEN 7
+
+ if(str==strstr(str, ".proxy.") && strlen(str)>AUTOPACKAGE_PROXY_LEN &&
+ 0==strcmp(&str[AUTOPACKAGE_PROXY_LEN], app))
+ return TRUE;
+
+ /* gimp and mozilla */
+ {
+ int app_len=strlen(app);
+
+ if(strlen(str)>app_len && str==strstr(str, app) &&
+ (0==memcmp(&str[app_len], "-2", 2) ||
+ 0==memcmp(&str[app_len], "-bin", 4)))
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static gboolean isMozApp(const char *app, const char *check)
+{
+ if(0==strcmp(app, check))
+ return TRUE;
+ else if(app==strstr(app, check))
+ {
+ int app_len=strlen(app),
+ check_len=strlen(check);
+
+ if(check_len+4 == app_len && 0==strcmp(&app[check_len], "-bin"))
+ return TRUE;
+
+ /* OK check for xulrunner-1.9 */
+ {
+ double dummy;
+ if(app_len>(check_len+1) && 1==sscanf(&app[check_len+1], "%f", &dummy))
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+static gboolean kgtkInit(const char *appName)
+{
+ static gboolean initialised=FALSE;
+#ifdef KGTK_DEBUG
+ printf("KGTK::kgtkInit %s\n", appName);
+#endif
+ if(!initialised)
+ {
+#ifdef KGTK_DEBUG
+ printf("KGTK::Running under KDE? %d\n", NULL!=getenv("KDE_FULL_SESSION"));
+#endif
+
+ initialised=TRUE;
+ kgtkAppName=getAppName(appName);
+ useKde=NULL!=getenv("KDE_FULL_SESSION") && connectToKDialogD(kgtkAppName);
+ if(useKde)
+ {
+ const gchar *prg=getAppName(NULL);
+
+ if(prg)
+ {
+#ifdef KGTK_DEBUG
+ printf("KGTK::APP %s\n", prg);
+#endif
+ if(isApp(prg, "inkscape"))
+ {
+ kgtkFileFilter="*.svg|Scalable Vector Graphic";
+ kgtkApp=APP_INKSCAPE;
+#ifdef KGTK_DEBUG
+ printf("KGTK::Inkscape\n");
+#endif
+ }
+ else if(isApp(prg, "gimp"))
+ {
+ kgtkApp=APP_GIMP;
+#ifdef KGTK_DEBUG
+ printf("KGTK::GIMP\n");
+#endif
+ }
+ else if(isApp(prg, "kino"))
+ {
+ kgtkApp=APP_KINO;
+#ifdef KGTK_DEBUG
+ printf("KGTK::kino\n");
+#endif
+ }
+ else if(isMozApp(prg, "firefox") || isMozApp(prg, "swiftfox") || isMozApp(prg, "iceweasel") || isMozApp(prg, "xulrunner"))
+ {
+ kgtkApp=APP_FIREFOX;
+#ifdef KGTK_DEBUG
+ printf("KGTK::Firefox\n");
+#endif
+ }
+ }
+
+ if(!g_threads_got_initialized)
+ g_thread_init(NULL);
+ atexit(&kgtkExit);
+ }
+ }
+
+#ifdef KGTK_DEBUG
+ printf("KGTK::kgtkInit useKde:%d\n", useKde);
+#endif
+
+ return useKde;
+}
+
+/* ......................... */
+
+typedef struct _GtkFileSystem GtkFileSystem;
+typedef struct _GtkFilePath GtkFilePath;
+typedef struct _GtkFileSystemModel GtkFileSystemModel;
+struct _GtkFileFilter
+{
+ GtkObject parent_instance;
+
+ gchar *name;
+ GSList *rules;
+
+ GtkFileFilterFlags needed;
+};
+
+typedef enum {
+ FILTER_RULE_PATTERN,
+ FILTER_RULE_MIME_TYPE,
+ FILTER_RULE_PIXBUF_FORMATS,
+ FILTER_RULE_CUSTOM
+} FilterRuleType;
+
+struct _FilterRule
+{
+ FilterRuleType type;
+ GtkFileFilterFlags needed;
+
+ union {
+ gchar *pattern;
+ gchar *mime_type;
+ GSList *pixbuf_formats;
+ struct {
+ GtkFileFilterFunc func;
+ gpointer data;
+ GDestroyNotify notify;
+ } custom;
+ } u;
+};
+
+#if GTK_CHECK_VERSION(2, 6, 0)
+struct _GtkFileChooserButtonPrivate
+{
+ GtkWidget *dialog;
+ GtkWidget *button;
+ GtkWidget *image;
+ GtkWidget *label;
+ GtkWidget *combo_box;
+
+ GtkCellRenderer *icon_cell;
+ GtkCellRenderer *name_cell;
+
+ GtkTreeModel *model;
+ GtkTreeModel *filter_model;
+
+ gchar *backend;
+ GtkFileSystem *fs;
+ GtkFilePath *old_path;
+
+ gulong combo_box_changed_id;
+ gulong dialog_file_activated_id;
+ gulong dialog_folder_changed_id;
+ gulong dialog_selection_changed_id;
+ gulong fs_volumes_changed_id;
+ gulong fs_bookmarks_changed_id;
+};
+#endif
+
+/* TreeModel Columns */
+enum
+{
+ ICON_COLUMN,
+ DISPLAY_NAME_COLUMN,
+ TYPE_COLUMN,
+ DATA_COLUMN,
+ NUM_COLUMNS
+};
+
+/* TreeModel Row Types */
+typedef enum
+{
+ ROW_TYPE_SPECIAL,
+ ROW_TYPE_VOLUME,
+ ROW_TYPE_SHORTCUT,
+ ROW_TYPE_BOOKMARK_SEPARATOR,
+ ROW_TYPE_BOOKMARK,
+ ROW_TYPE_CURRENT_FOLDER_SEPARATOR,
+ ROW_TYPE_CURRENT_FOLDER,
+ ROW_TYPE_OTHER_SEPARATOR,
+ ROW_TYPE_OTHER,
+
+ ROW_TYPE_INVALID = -1
+}
+RowType;
+
+static GtkWidget *
+kgtk_file_chooser_dialog_new_valist (const gchar *title,
+ GtkWindow *parent,
+ GtkFileChooserAction action,
+ const gchar *backend,
+ const gchar *first_button_text,
+ va_list varargs)
+{
+ GtkWidget *result;
+ const char *button_text = first_button_text;
+ gint response_id;
+
+ result = g_object_new (GTK_TYPE_FILE_CHOOSER_DIALOG,
+ "title", title,
+ "action", action,
+ "file-system-backend", backend,
+ NULL);
+
+ if (parent)
+ gtk_window_set_transient_for (GTK_WINDOW (result), parent);
+
+ while (button_text)
+ {
+ response_id = va_arg (varargs, gint);
+ gtk_dialog_add_button (GTK_DIALOG (result), button_text, response_id);
+ button_text = va_arg (varargs, const gchar *);
+ }
+
+ return result;
+}
+/* ......................... */
+
+gboolean gtk_init_check(int *argc, char ***argv)
+{
+ static void * (*realFunction)() = NULL;
+
+ gboolean rv=FALSE;
+
+ if(!realFunction)
+ realFunction = (void *(*)()) real_dlsym(RTLD_NEXT, "gtk_init_check");
+
+ rv=realFunction(argc, argv);
+#ifdef KGTK_DEBUG
+ printf("KGTK::gtk_init_check\n");
+#endif
+ if(rv)
+ kgtkInit(argv && argc ? (*argv)[0] : NULL);
+ return rv;
+}
+
+void gtk_init(int *argc, char ***argv)
+{
+ static void * (*realFunction)() = NULL;
+
+ if(!realFunction)
+ realFunction = (void *(*)()) real_dlsym(RTLD_NEXT, "gtk_init");
+
+ realFunction(argc, argv);
+#ifdef KGTK_DEBUG
+ printf("KGTK::gtk_init\n");
+#endif
+ kgtkInit(argv && argc ? (*argv)[0] : NULL);
+}
+
+/* Store a hash from widget pointer to folder/file list retried from KDialogD */
+static GHashTable *fileDialogHash=NULL;
+
+typedef struct
+{
+ gchar *folder;
+ gchar *name;
+ GSList *files;
+ int ok,
+ cancel;
+ gboolean setOverWrite,
+ doOverwrite;
+} KGtkFileData;
+
+static KGtkFileData * lookupHash(void *hash, gboolean create)
+{
+ KGtkFileData *rv=NULL;
+
+#ifdef KGTK_DEBUG
+ printf("KGTK::lookupHash %X\n", (int)hash);
+#endif
+ if(!fileDialogHash)
+ fileDialogHash=g_hash_table_new(g_int_hash, g_int_equal);
+
+ rv=(KGtkFileData *)g_hash_table_lookup(fileDialogHash, hash);
+
+ if(!rv && create)
+ {
+ rv=(KGtkFileData *)malloc(sizeof(KGtkFileData));
+ rv->folder=NULL;
+ rv->files=NULL;
+ rv->name=NULL;
+ rv->ok=GTK_RESPONSE_OK;
+ rv->cancel=GTK_RESPONSE_CANCEL;
+ rv->setOverWrite=FALSE;
+ rv->doOverwrite=FALSE;
+ g_hash_table_insert(fileDialogHash, hash, rv);
+ rv=g_hash_table_lookup(fileDialogHash, hash);
+ }
+
+ return rv;
+}
+
+static void freeHash(void *hash)
+{
+ KGtkFileData *data=NULL;
+
+ if(!fileDialogHash)
+ fileDialogHash=g_hash_table_new(g_int_hash, g_int_equal);
+
+ data=(KGtkFileData *)g_hash_table_lookup(fileDialogHash, hash);
+
+ if(data)
+ {
+ if(data->folder)
+ g_free(data->folder);
+ if(data->name)
+ g_free(data->name);
+ if(data->files)
+ {
+ g_slist_foreach(data->files, (GFunc)g_free, NULL);
+ g_slist_free(data->files);
+ }
+ data->files=NULL;
+ data->folder=NULL;
+ data->name=NULL;
+ g_hash_table_remove(fileDialogHash, hash);
+ }
+}
+
+/* Some Gtk apps have filter pattern *.[Pp][Nn][Gg] - wherease Qt/KDE prefer *.png */
+#define MAX_PATTERN_LEN 64
+static gchar *modifyFilter(const char *filter)
+{
+ int i=0;
+ gboolean brackets=FALSE;
+ const char *p;
+ static char res[MAX_PATTERN_LEN+1];
+
+ for(p=filter; p && *p && i<MAX_PATTERN_LEN; ++p)
+ switch(*p)
+ {
+ case '[':
+ p++;
+ if(p)
+ res[i++]=tolower(*p);
+ brackets=TRUE;
+ break;
+ case ']':
+ brackets=FALSE;
+ break;
+ default:
+ if(!brackets)
+ res[i++]=tolower(*p);
+ }
+ res[i++]='\0';
+ return res;
+}
+
+static GtkWidget * getCombo(GtkWidget *widget)
+{
+ if(widget && GTK_IS_BOX(widget))
+ {
+ GList *child=GTK_BOX(widget)->children;
+
+ for(; child; child=child->next)
+ {
+ GtkBoxChild *boxChild=(GtkBoxChild *)child->data;
+
+ if(GTK_IS_COMBO_BOX(boxChild->widget))
+ return boxChild->widget;
+ else if(GTK_IS_BOX(boxChild->widget))
+ {
+ GtkWidget *box=getCombo(boxChild->widget);
+
+ if(box)
+ return box;
+ }
+ }
+
+ }
+
+ return NULL;
+}
+
+static GString * getFilters(GtkDialog *dialog, GtkFileChooserAction act)
+{
+ GString *filter=NULL;
+ GSList *list=gtk_file_chooser_list_filters(GTK_FILE_CHOOSER(dialog));
+
+#ifdef KGTK_DEBUG
+ printf("KGTK::Get list of filters...\n");
+#endif
+
+ if(list)
+ {
+ GSList *item;
+ int filterNum=0;
+
+ filter=g_string_new("");
+ for(item=list; item; item=g_slist_next(item), ++filterNum)
+ {
+ GtkFileFilter *f=(GtkFileFilter *)(item->data);
+
+ if(f)
+ {
+ const gchar *name=gtk_file_filter_get_name(f);
+ GSList *rule=((struct _GtkFileFilter *)f)->rules;
+ GString *pattern=g_string_new("");
+
+ for(; rule; rule=g_slist_next(rule))
+ switch(((struct _FilterRule *)rule->data)->type)
+ {
+ case FILTER_RULE_PATTERN:
+ {
+ const char *modPat=
+ modifyFilter(((struct _FilterRule *)rule->data)->u.pattern);
+
+ /*
+ Firefox has:
+ *.htm *.html | Web page complete
+ *.htm *.html | HTML only
+ *.txt *.text | Text
+
+ We modify this to have:
+ *.htm | Web page complete
+ *.html | HTML only
+ *.txt *.text | Text
+ */
+
+ if(APP_FIREFOX!=kgtkApp || (strcmp(modPat, "*.html") ? filterNum!=1
+ : filterNum))
+ {
+ if(pattern->len)
+ pattern=g_string_append(pattern, " ");
+ pattern=g_string_append(pattern, modPat);
+ }
+ break;
+ }
+ case FILTER_RULE_MIME_TYPE:
+ if(filter->len)
+ filter=g_string_append(filter, "\n");
+ filter=g_string_append(filter,
+ ((struct _FilterRule *)rule->data)->u.mime_type);
+ break;
+ default:
+ break;
+ }
+
+ if(name && pattern && pattern->len)
+ {
+ gchar *n=g_strdup(name),
+ *pat=strstr(n, " (*");
+
+ if(pat)
+ *pat='\0';
+
+ if(filter->len)
+ filter=g_string_append(filter, "\n");
+ filter=g_string_append(filter, pattern->str);
+ filter=g_string_append(filter, "|");
+ filter=g_string_append(filter, n);
+ g_free(n);
+ }
+ g_string_free(pattern, TRUE);
+ }
+ }
+ g_slist_free(list);
+ }
+
+ if(!filter)
+ {
+ /* This is mainly the case for Inkscape save - but try for other apps too... */
+ GtkWidget *combo=getCombo(gtk_file_chooser_get_extra_widget(GTK_FILE_CHOOSER(dialog)));
+
+#ifdef KGTK_DEBUG
+ printf("KGTK::No filters found, try to look for an extra combo widget...\n");
+#endif
+
+ if(combo)
+ {
+ int i;
+
+ filter=g_string_new("");
+ for(i=0; i<64; ++i)
+ {
+ gchar *text=NULL;
+
+ gtk_combo_box_set_active(GTK_COMBO_BOX(combo), i);
+ if(i!=gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
+ break;
+
+ text=gtk_combo_box_get_active_text(GTK_COMBO_BOX(combo));
+
+ if(text)
+ {
+ gchar *pat=strstr(text, " (*");
+
+ if(pat)
+ {
+ gchar *close=strstr(pat, ")");
+
+ *pat='\0';
+
+ if(close)
+ *close='\0';
+
+ pat+=2; /* Skip past " (" */
+
+ if(filter->len)
+ filter=g_string_append(filter, "\n");
+ filter=g_string_append(filter, pat);
+ filter=g_string_append(filter, "|");
+ filter=g_string_append(filter, text);
+ }
+ g_free(text);
+ }
+ }
+ }
+ }
+
+ return filter;
+}
+
+static void setFilter(const gchar *filter, GtkDialog *dialog, GtkFileChooserAction act)
+{
+ gboolean found=FALSE;
+ GSList *list=gtk_file_chooser_list_filters(GTK_FILE_CHOOSER(dialog));
+
+#ifdef KGTK_DEBUG
+ printf("KGTK::Need to locate filter:%s\n", filter ? filter : "Null");
+#endif
+
+ if(list)
+ {
+ GSList *item;
+ unsigned int flen=strlen(filter);
+ int filterNum=0;
+
+ for(item=list; item && !found; item=g_slist_next(item), filterNum++)
+ {
+ GtkFileFilter *f=(GtkFileFilter *)(item->data);
+
+ if(f)
+ {
+ GSList *rule=((struct _GtkFileFilter *)f)->rules;
+ char *start=NULL;
+
+ for(; rule && !found; rule=g_slist_next(rule))
+ if(FILTER_RULE_PATTERN==((struct _FilterRule *)rule->data)->type)
+ {
+ char *filt=modifyFilter(((struct _FilterRule *)rule->data)->u.pattern);
+
+ /*
+ Firefox has:
+ *.htm *.html | Web page complete
+ *.htm *.html | HTML only
+ *.txt *.text | Text
+
+ We modify this to have:
+ *.htm | Web page complete
+ *.html | HTML only
+ *.txt *.text | Text
+ */
+
+ if((APP_FIREFOX!=kgtkApp || (strcmp(filt, "*.html") ? filterNum!=1
+ : filterNum)) &&
+ (start=strstr(filter, filt)))
+ {
+ unsigned int slen=strlen(filt);
+
+ if(((start-filter)+slen)<=flen &&
+ (' '==start[slen] || '\t'==start[slen] ||
+ '\n'==start[slen] || '\0'==start[slen]))
+ {
+#ifdef KGTK_DEBUG
+ printf("KGTK::FOUND FILTER\n");
+#endif
+ found=TRUE;
+ gtk_file_chooser_set_filter(GTK_FILE_CHOOSER(dialog), f);
+ }
+ }
+ }
+ }
+ }
+ g_slist_free(list);
+ }
+
+ if(!found)
+ {
+ /* This is mainly the case for Inkscape save - but try for other apps too... */
+ GtkWidget *combo=getCombo(gtk_file_chooser_get_extra_widget(GTK_FILE_CHOOSER(dialog)));
+
+#ifdef KGTK_DEBUG
+ printf("KGTK::No filters found, try to look for an extra combo widget...\n");
+#endif
+ if(combo)
+ {
+ int i,
+ flen=strlen(filter);
+
+ for(i=0; i<64; ++i)
+ {
+ gchar *text=NULL;
+
+ gtk_combo_box_set_active(GTK_COMBO_BOX(combo), i);
+ if(i!=gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
+ break;
+
+ text=gtk_combo_box_get_active_text(GTK_COMBO_BOX(combo));
+
+ if(text)
+ {
+ gchar *pat=strstr(text, filter);
+
+ if(pat)
+ {
+ if(pat>text && (' '==pat[-1] || '('==pat[-1]) &&
+ (' '==pat[flen] || ')'==pat[flen]))
+ return; /* found a match, so just return - filter is set */
+ }
+ g_free(text);
+ }
+ }
+
+ /* No match :-( set to last filter... */
+ for(i=0; i<64; ++i)
+ {
+ gtk_combo_box_set_active(GTK_COMBO_BOX(combo), i);
+ if(i!=gtk_combo_box_get_active(GTK_COMBO_BOX(combo)))
+ break;
+ }
+ }
+ }
+}
+
+static GSList * addProtocols(GSList *files)
+{
+ GSList *item=files;
+
+ for(; item; item=g_slist_next(item))
+ {
+ gchar *cur=item->data;
+ item->data=g_filename_to_uri(item->data, NULL, NULL);
+ g_free(cur);
+ }
+
+ return files;
+}
+
+void gtk_window_present(GtkWindow *window)
+{
+ static void * (*realFunction)() = NULL;
+
+ if(!realFunction)
+ realFunction = (void *(*)()) real_dlsym(RTLD_NEXT, "gtk_window_present");
+
+#ifdef KGTK_DEBUG
+ printf("KGTK::gtk_window_present %s %d\n", gtk_type_name(GTK_WIDGET_TYPE(window)),
+ GTK_IS_FILE_CHOOSER(window));
+#endif
+ if(GTK_IS_FILE_CHOOSER(window)) /* || (APP_GIMP==kgtkApp &&
+ 0==strcmp(gtk_type_name(GTK_WIDGET_TYPE(window)), "GimpFileDialog")))*/
+ gtk_dialog_run(GTK_DIALOG(window));
+ else
+ realFunction(window);
+}
+
+void gtk_widget_show(GtkWidget *widget)
+{
+ static void * (*realFunction)() = NULL;
+
+ if(!realFunction)
+ realFunction = (void *(*)()) real_dlsym(RTLD_NEXT, "gtk_widget_show");
+
+ if(widget && !GTK_IS_FILE_CHOOSER_BUTTON(widget) && GTK_IS_FILE_CHOOSER(widget))
+ {
+#ifdef KGTK_DEBUG
+ printf("KGTK::gtk_widget_show %s %d\n", gtk_type_name(GTK_WIDGET_TYPE(widget)),
+ GTK_IS_FILE_CHOOSER(widget));
+#endif
+ gtk_dialog_run(GTK_DIALOG(widget));
+ GTK_OBJECT_FLAGS(widget)|=GTK_REALIZED;
+ }
+ else
+ realFunction(widget);
+}
+
+void gtk_widget_hide(GtkWidget *widget)
+{
+ static void * (*realFunction)() = NULL;
+
+ if(!realFunction)
+ realFunction = (void *(*)()) real_dlsym(RTLD_NEXT, "gtk_widget_hide");
+
+ if(widget && !GTK_IS_FILE_CHOOSER_BUTTON(widget) && GTK_IS_FILE_CHOOSER(widget))
+ {
+#ifdef KGTK_DEBUG
+ printf("KGTK::gtk_widget_hide %s %d\n", gtk_type_name(GTK_WIDGET_TYPE(widget)),
+ GTK_IS_FILE_CHOOSER(widget));
+#endif
+ if(GTK_OBJECT_FLAGS(widget)&GTK_REALIZED)
+ GTK_OBJECT_FLAGS(widget)-=GTK_REALIZED;
+ }
+ else
+ realFunction(widget);
+}
+
+gboolean gtk_file_chooser_get_do_overwrite_confirmation(GtkFileChooser *widget)
+{
+ static void * (*realFunction)() = NULL;
+
+ gboolean rv=FALSE;
+
+ if(!realFunction)
+ realFunction = (void *(*)()) real_dlsym(RTLD_NEXT, "gtk_file_chooser_get_do_overwrite_confirmation");
+
+ if(realFunction)
+ {
+ KGtkFileData *data=lookupHash(widget, FALSE);
+
+ if(data)
+ {
+ if(!data->setOverWrite)
+ {
+ data->setOverWrite=TRUE;
+ data->doOverwrite=(gboolean) realFunction(widget);
+ }
+ rv=data->doOverwrite;
+ }
+ else
+ rv=(gboolean) realFunction(widget);
+ }
+
+ return rv;
+}
+
+/* ext => called from app, not kgtk */
+void kgtkFileChooserSetDoOverwriteConfirmation(GtkFileChooser *widget, gboolean v, gboolean ext)
+{
+ static void * (*realFunction)() = NULL;
+
+ if(!realFunction)
+ realFunction = (void *(*)()) real_dlsym(RTLD_NEXT, "gtk_file_chooser_set_do_overwrite_confirmation");
+
+ if(realFunction)
+ {
+ realFunction(widget, v);
+ if(ext)
+ {
+ KGtkFileData *data=lookupHash(widget, FALSE);
+
+ if(data)
+ {
+ data->setOverWrite=TRUE;
+ data->doOverwrite=v;
+ }
+ }
+ }
+}
+
+gboolean isOnFileChooser(GtkWidget *w)
+{
+ return w
+ ? GTK_IS_FILE_CHOOSER(w)
+ ? TRUE
+ : isOnFileChooser(w->parent)
+ : FALSE;
+}
+
+int gtk_combo_box_get_active(GtkComboBox *combo)
+{
+ int rv=0;
+
+ if(APP_KINO==kgtkApp && isOnFileChooser(combo))
+ return 1;
+ else
+ {
+ static void * (*realFunction)() = NULL;
+
+ if(!realFunction)
+ realFunction = (void *(*)()) real_dlsym(RTLD_NEXT, "gtk_combo_box_get_active");
+
+ rv=(int)realFunction(combo);
+ }
+
+ return rv;
+}
+
+gint gtk_dialog_run(GtkDialog *dialog)
+{
+ static void * (*realFunction)() = NULL;
+
+ if(!realFunction)
+ realFunction = (void *(*)()) real_dlsym(RTLD_NEXT, "gtk_dialog_run");
+
+#ifdef KGTK_DEBUG
+ printf("KGTK::gtk_dialog_run %s \n", dialog ? gtk_type_name(GTK_WIDGET_TYPE(dialog)) : "<null>");
+#endif
+
+ if(kgtkInit(NULL) && GTK_IS_FILE_CHOOSER(dialog))
+ {
+ static gboolean running=FALSE;
+
+ KGtkFileData *data=lookupHash(dialog, TRUE);
+
+#ifdef KGTK_DEBUG
+ printf("KGTK::run file chooser, already running? %d\n", running);
+#endif
+ if(!running)
+ {
+ GtkFileChooserAction act=gtk_file_chooser_get_action(GTK_FILE_CHOOSER(dialog));
+ gchar *current=NULL,
+ *selFilter=NULL;
+ const gchar *title=gtk_window_get_title(GTK_WINDOW(dialog));
+ GString *filter=NULL;
+ gint resp=data->cancel;
+ gboolean origOverwrite=
+ gtk_file_chooser_get_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog));
+
+ running=TRUE;
+
+ if(GTK_FILE_CHOOSER_ACTION_OPEN==act || GTK_FILE_CHOOSER_ACTION_SAVE==act)
+ filter=getFilters(dialog, act);
+ else /* GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER==act ||
+ GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER==act */
+ if(NULL==(current=gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog))))
+ current=gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(dialog));
+
+ kgtkFileChooserSetDoOverwriteConfirmation(GTK_FILE_CHOOSER(dialog), FALSE, FALSE);
+
+ switch(act)
+ {
+ case GTK_FILE_CHOOSER_ACTION_OPEN:
+ {
+#ifdef KGTK_DEBUG
+ printf("KGTK::run file chooser GTK_FILE_CHOOSER_ACTION_OPEN\n");
+#endif
+ if(gtk_file_chooser_get_select_multiple(GTK_FILE_CHOOSER(dialog)))
+ {
+ GSList *files=NULL;
+
+ openKdeDialog(GTK_WIDGET(dialog), title ? title : "",
+ data->folder ? data->folder : "",
+ filter && filter->len
+ ? filter->str
+ : kgtkFileFilter
+ ? kgtkFileFilter
+ : "", OP_FILE_OPEN_MULTIPLE, &files,
+ &selFilter, FALSE);
+
+ if(files)
+ {
+ GSList *c;
+
+ gtk_file_chooser_unselect_all(GTK_FILE_CHOOSER(dialog));
+ for(c=files; c; c=g_slist_next(c))
+ gtk_file_chooser_select_filename(GTK_FILE_CHOOSER(dialog),
+ (gchar *)(c->data));
+ g_slist_foreach(files, (GFunc)g_free, NULL);
+ g_slist_free(files);
+
+ resp=data->ok;
+ }
+ }
+ else
+ {
+ gchar *file=NULL;
+ GSList *res=NULL;
+
+ openKdeDialog(GTK_WIDGET(dialog), title ? title : "",
+ data->folder ? data->folder : "",
+ filter && filter->len
+ ? filter->str
+ : kgtkFileFilter
+ ? kgtkFileFilter
+ : "", OP_FILE_OPEN, &res, &selFilter, FALSE);
+ file=firstEntry(res);
+
+ if(file)
+ {
+ gtk_file_chooser_unselect_all(GTK_FILE_CHOOSER(dialog));
+ gtk_file_chooser_select_filename(GTK_FILE_CHOOSER(dialog), file);
+ g_free(file);
+ resp=data->ok;
+ }
+ }
+ break;
+ }
+ case GTK_FILE_CHOOSER_ACTION_SAVE:
+ {
+ gchar *file=NULL;
+ GSList *res=NULL;
+
+#ifdef KGTK_DEBUG
+ printf("KGTK::run file chooser GTK_FILE_CHOOSER_ACTION_SAVE\n");
+#endif
+ if(data->name)
+ {
+ GString *cur=g_string_new(data->folder ? data->folder
+ : get_current_dir_name());
+
+ cur=g_string_append(cur, "/");
+ cur=g_string_append(cur, data->name);
+ current=g_string_free(cur, FALSE);
+ }
+
+ openKdeDialog(GTK_WIDGET(dialog), title ? title : "",
+ current ? current : (data->folder ? data->folder : ""),
+ filter && filter->len
+ ? filter->str
+ : kgtkFileFilter
+ ? kgtkFileFilter
+ : "", OP_FILE_SAVE, &res, &selFilter, origOverwrite);
+ file=firstEntry(res);
+
+ if(file)
+ {
+ /* Firefox crashes when we save to an existing name -> so just delete it first! */
+ if(APP_FIREFOX==kgtkApp && origOverwrite)
+ {
+ struct stat info;
+
+ if(0==lstat(file, &info))
+ unlink(file);
+ }
+ gtk_file_chooser_unselect_all(GTK_FILE_CHOOSER(dialog));
+ gtk_file_chooser_select_filename(GTK_FILE_CHOOSER(dialog), file);
+ g_free(file);
+ resp=data->ok;
+ }
+ break;
+ }
+ case GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER:
+ case GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER:
+ {
+ GSList *res=NULL;
+ gchar *folder=NULL;
+
+#ifdef KGTK_DEBUG
+ if(GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER==act)
+ printf("KGTK::run file chooser GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER\n");
+ else
+ printf("KGTK::run file chooser GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER\n");
+#endif
+ openKdeDialog(GTK_WIDGET(dialog), title ? title : "",
+ data->folder ? data->folder : "", NULL,
+ OP_FOLDER, &res, NULL, FALSE);
+ folder=firstEntry(res);
+
+ if(folder)
+ {
+ gtk_file_chooser_select_filename(GTK_FILE_CHOOSER(dialog), folder);
+ gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(dialog), folder);
+ g_free(folder);
+ resp=data->ok;
+ }
+ }
+ }
+
+ if(current)
+ g_free(current);
+
+ if(filter)
+ g_string_free(filter, TRUE);
+
+ if(selFilter)
+ {
+ setFilter(selFilter, dialog, act);
+ g_free(selFilter);
+ }
+
+#ifdef KGTK_DEBUG
+ printf("KGTK::RETURN RESP:%d\n", resp);
+#endif
+ g_signal_emit_by_name(dialog, "response", resp);
+ running=FALSE;
+ return resp;
+ }
+#ifdef KGTK_DEBUG
+ printf("KGTK::ALREADY RUNNING SO RETURN RESP:%d\n", data->cancel);
+#endif
+ g_signal_emit_by_name(dialog, "response", data->cancel);
+ return data->cancel;
+ }
+ return realFunction(dialog);
+}
+
+void gtk_widget_destroy(GtkWidget *widget)
+{
+ static void * (*realFunction)() = NULL;
+
+ if(!realFunction)
+ realFunction = (void *(*)()) real_dlsym(RTLD_NEXT, "gtk_widget_destroy");
+
+ if(fileDialogHash && GTK_IS_FILE_CHOOSER(widget))
+ freeHash(widget);
+
+ realFunction(widget);
+}
+
+gchar * gtk_file_chooser_get_filename(GtkFileChooser *chooser)
+{
+ KGtkFileData *data=lookupHash(chooser, FALSE);
+
+#ifdef KGTK_DEBUG
+ printf("KGTK::gtk_file_chooser_get_filename %d %s\n", data ? g_slist_length(data->files) : 12345,
+ data && data->files && data->files->data ? data->files->data : "<>");
+#endif
+ return data && data->files && data->files->data ? g_strdup(data->files->data) : NULL;
+}
+
+gboolean gtk_file_chooser_select_filename(GtkFileChooser *chooser, const char *filename)
+{
+ KGtkFileData *data=lookupHash(chooser, TRUE);
+ static void * (*realFunction)() = NULL;
+
+ if(!realFunction)
+ realFunction = (void *(*)()) real_dlsym(RTLD_NEXT, "gtk_file_chooser_select_filename");
+ realFunction(chooser, filename);
+
+#ifdef KGTK_DEBUG
+ printf("KGTK::gtk_file_chooser_select_filename %s, %d\n", filename,
+ data ? g_slist_length(data->files) : 12345);
+#endif
+ if(data && filename)
+ {
+ GSList *c=NULL;
+
+ for(c=data->files; c; c=g_slist_next(c))
+ if(c->data && 0==strcmp((char *)(c->data), filename))
+ break;
+
+ if(!c)
+ {
+ gchar *folder=g_path_get_dirname(filename);
+
+ data->files=g_slist_prepend(data->files, g_strdup(filename));
+
+ if(folder && !data->folder || strcmp(folder, data->folder))
+ {
+ gtk_file_chooser_set_current_folder(chooser, folder);
+ g_free(folder);
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+void gtk_file_chooser_unselect_all(GtkFileChooser *chooser)
+{
+ KGtkFileData *data=lookupHash(chooser, TRUE);
+ static void * (*realFunction)() = NULL;
+
+ if(!realFunction)
+ realFunction = (void *(*)()) real_dlsym(RTLD_NEXT, "gtk_file_chooser_unselect_all");
+ realFunction(chooser);
+
+#ifdef KGTK_DEBUG
+ printf("KGTK::gtk_file_chooser_unselect_all %d\n", data ? g_slist_length(data->files) : 12345);
+#endif
+ if(data && data->files)
+ {
+ g_slist_foreach(data->files, (GFunc)g_free, NULL);
+ g_slist_free(data->files);
+ data->files=NULL;
+ }
+}
+
+gboolean gtk_file_chooser_set_filename(GtkFileChooser *chooser, const char *filename)
+{
+ KGtkFileData *data=lookupHash(chooser, TRUE);
+ static void * (*realFunction)() = NULL;
+
+ if(!realFunction)
+ realFunction = (void *(*)()) real_dlsym(RTLD_NEXT, "gtk_file_chooser_set_filename");
+ realFunction(chooser, filename);
+
+#ifdef KGTK_DEBUG
+ printf("KGTK::gtk_file_chooser_set_filename %s %d\n", filename,
+ data ? g_slist_length(data->files) : 12345);
+#endif
+ if(data && filename)
+ {
+ gchar *folder=g_path_get_dirname(filename),
+ *name=g_path_get_basename(filename);
+
+ if(data->files)
+ {
+ g_slist_foreach(data->files, (GFunc)g_free, NULL);
+ g_slist_free(data->files);
+ data->files=NULL;
+ }
+
+ data->files=g_slist_prepend(data->files, g_strdup(filename));
+
+ if(name && (!data->name || strcmp(name, data->name)))
+ gtk_file_chooser_set_current_name(chooser, name);
+ if(name)
+ g_free(name);
+ if(folder && (!data->folder || strcmp(folder, data->folder)))
+ gtk_file_chooser_set_current_folder(chooser, folder);
+ if(folder)
+ g_free(folder);
+ }
+
+ return TRUE;
+}
+
+void gtk_file_chooser_set_current_name(GtkFileChooser *chooser, const char *filename)
+{
+ KGtkFileData *data=lookupHash(chooser, TRUE);
+ GtkFileChooserAction act=gtk_file_chooser_get_action(chooser);
+
+ if(GTK_FILE_CHOOSER_ACTION_SAVE==act || GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER==act)
+ {
+ static void * (*realFunction)() = NULL;
+
+ if(!realFunction)
+ realFunction = (void *(*)()) real_dlsym(RTLD_NEXT, "gtk_file_chooser_set_current_name");
+ realFunction(chooser, filename);
+ }
+
+#ifdef KGTK_DEBUG
+ printf("KGTK::gtk_file_chooser_set_current_name %s %d\n", filename,
+ data ? g_slist_length(data->files) : 12345);
+#endif
+ if(data && filename)
+ {
+ if(data->name)
+ g_free(data->name);
+ data->name=g_strdup(filename);
+ }
+}
+
+GSList * gtk_file_chooser_get_filenames(GtkFileChooser *chooser)
+{
+ KGtkFileData *data=lookupHash(chooser, FALSE);
+ GSList *rv=NULL;
+
+#ifdef KGTK_DEBUG
+ printf("KGTK::gtk_file_chooser_get_filenames %d\n", data ? g_slist_length(data->files) : 12345);
+#endif
+ if(data && data->files)
+ {
+ GSList *item=data->files;
+
+ for(; item; item=g_slist_next(item))
+ {
+#ifdef KGTK_DEBUG
+ printf("KGTK::FILE:%s\n", item->data);
+#endif
+ if(item->data)
+ rv=g_slist_prepend(rv, g_strdup(item->data));
+ }
+ }
+#ifdef KGTK_DEBUG
+ printf("KGTK::gtk_file_chooser_get_filenames END\n");
+#endif
+ return rv;
+}
+
+gboolean gtk_file_chooser_set_current_folder(GtkFileChooser *chooser, const gchar *folder)
+{
+ KGtkFileData *data=lookupHash(chooser, TRUE);
+ static void * (*realFunction)() = NULL;
+
+ if(!realFunction)
+ realFunction = (void *(*)()) real_dlsym(RTLD_NEXT, "gtk_file_chooser_set_current_folder");
+ realFunction(chooser, folder);
+
+#ifdef KGTK_DEBUG
+ printf("KGTK::gtk_file_chooser_set_current_folder %s %d\n", folder,
+ data ? g_slist_length(data->files) : 12345);
+#endif
+ if(data && folder)
+ {
+ if(data->folder)
+ g_free(data->folder);
+ data->folder=g_strdup(folder);
+ }
+ g_signal_emit_by_name(chooser, "current-folder-changed", 0);
+
+ return TRUE;
+}
+
+gchar * gtk_file_chooser_get_current_folder(GtkFileChooser *chooser)
+{
+ KGtkFileData *data=lookupHash(chooser, FALSE);
+
+#ifdef KGTK_DEBUG
+ printf("KGTK::gtk_file_chooser_get_current_folder %d\n",
+ data ? g_slist_length(data->files) : 12345);
+#endif
+ if(!data)
+ {
+ gtk_file_chooser_set_current_folder(chooser, get_current_dir_name());
+ data=g_hash_table_lookup(fileDialogHash, chooser);
+ }
+
+ return data && data->folder ? g_strdup(data->folder) : NULL;
+}
+
+gchar * gtk_file_chooser_get_uri(GtkFileChooser *chooser)
+{
+#ifdef KGTK_DEBUG
+ printf("KGTK::gtk_file_chooser_get_uri\n");
+#endif
+ gchar *filename=gtk_file_chooser_get_filename(chooser);
+
+ if(filename)
+ {
+ gchar *uri=g_filename_to_uri(filename, NULL, NULL);
+
+ g_free(filename);
+ return uri;
+ }
+
+ return NULL;
+}
+
+gboolean gtk_file_chooser_set_uri(GtkFileChooser *chooser, const char *uri)
+{
+#ifdef KGTK_DEBUG
+ printf("KGTK::gtk_file_chooser_set_uri\n");
+#endif
+
+ gchar *file=g_filename_from_uri(uri, NULL, NULL);
+ gboolean rv=FALSE;
+
+ if(file)
+ {
+ rv=gtk_file_chooser_set_filename(chooser, file);
+
+ g_free(file);
+ }
+ return rv;
+}
+
+GSList * gtk_file_chooser_get_uris(GtkFileChooser *chooser)
+{
+#ifdef KGTK_DEBUG
+ printf("KGTK::gtk_file_chooser_get_uris\n");
+#endif
+ return addProtocols(gtk_file_chooser_get_filenames(chooser));
+}
+
+gboolean gtk_file_chooser_set_current_folder_uri(GtkFileChooser *chooser, const gchar *uri)
+{
+#ifdef KGTK_DEBUG
+ printf("KGTK::gtk_file_chooser_set_current_folder_uri\n");
+#endif
+ gchar *folder=g_filename_from_uri(uri, NULL, NULL);
+ gboolean rv=FALSE;
+
+ if(folder)
+ {
+ rv=gtk_file_chooser_set_current_folder(chooser, folder);
+
+ g_free(folder);
+ }
+ return rv;
+}
+
+gchar * gtk_file_chooser_get_current_folder_uri(GtkFileChooser *chooser)
+{
+#ifdef KGTK_DEBUG
+ printf("KGTK::gtk_file_chooser_get_current_folder_uri\n");
+#endif
+
+ gchar *folder=gtk_file_chooser_get_current_folder(chooser);
+
+ if(folder)
+ {
+ gchar *uri=g_filename_to_uri(folder, NULL, NULL);
+
+ g_free(folder);
+ return uri;
+ }
+
+ return NULL;
+}
+
+void g_signal_stop_emission_by_name(gpointer instance, const gchar *detailed_signal)
+{
+ static void * (*realFunction)() = NULL;
+
+ if(!realFunction)
+ realFunction = (void *(*)()) real_dlsym(RTLD_NEXT, "g_signal_stop_emission_by_name");
+
+#ifdef KGTK_DEBUG
+ printf("KGTK::g_signal_stop_emission_by_name %s %s (check)\n", gtk_type_name(GTK_WIDGET_TYPE(instance)), detailed_signal);
+#endif
+
+ if(kgtkApp!=APP_GIMP || !GTK_IS_FILE_CHOOSER(instance) || strcmp(detailed_signal, "response"))
+ realFunction(instance, detailed_signal);
+#ifdef KGTK_DEBUG
+ else
+ printf("KGTK::g_signal_stop_emission_by_name %s %s\n", gtk_type_name(GTK_WIDGET_TYPE(instance)), detailed_signal);
+#endif
+}
+
+GtkWidget * gtk_file_chooser_dialog_new(const gchar *title, GtkWindow *parent,
+ GtkFileChooserAction action, const gchar *first_button_text,
+ ...)
+{
+ GtkWidget *dlg=NULL;
+ KGtkFileData *data=NULL;
+ const char *text=first_button_text;
+ gint id;
+ va_list varargs;
+
+ va_start(varargs, first_button_text);
+ dlg=kgtk_file_chooser_dialog_new_valist(title, parent, action, NULL, first_button_text, varargs);
+ va_end(varargs);
+
+#ifdef KGTK_DEBUG
+ printf("KGTK::gtk_file_chooser_dialog_new\n");
+#endif
+ data=lookupHash(dlg, TRUE);
+ va_start(varargs, first_button_text);
+ while(text)
+ {
+ id = va_arg(varargs, gint);
+
+ if(text && (0==strcmp(text, GTK_STOCK_CANCEL) || 0==strcmp(text, GTK_STOCK_CLOSE) ||
+ 0==strcmp(text, GTK_STOCK_QUIT) || 0==strcmp(text, GTK_STOCK_NO)))
+ data->cancel=id;
+ else if(text && (0==strcmp(text, GTK_STOCK_OK) || 0==strcmp(text, GTK_STOCK_OPEN) ||
+ 0==strcmp(text, GTK_STOCK_SAVE) || 0==strcmp(text, GTK_STOCK_YES)))
+ data->ok=id;
+ text=va_arg(varargs, const gchar *);
+ }
+ va_end(varargs);
+ return dlg;
+}
+
+#if GTK_CHECK_VERSION(2, 6, 0)
+static void handleGtkFileChooserButtonClicked(GtkButton *button, gpointer user_data)
+{
+#ifdef KGTK_DEBUG
+ printf("KGTK::handleGtkFileChooserButtonClicked\n");
+#endif
+ gtk_dialog_run(GTK_FILE_CHOOSER_BUTTON(user_data)->priv->dialog);
+}
+
+static void handleGtkFileChooserComboChanged(GtkComboBox *combo_box, gpointer user_data)
+{
+ static gboolean handle=TRUE;
+ GtkTreeIter iter;
+
+#ifdef KGTK_DEBUG
+ printf("KGTK::handleGtkFileChooserComboChanged (handle:%d)\n", handle);
+#endif
+ if(!handle)
+ return;
+
+ if(gtk_combo_box_get_active_iter (combo_box, &iter))
+ {
+ GtkFileChooserButtonPrivate *priv=GTK_FILE_CHOOSER_BUTTON(user_data)->priv;
+ gchar type=ROW_TYPE_INVALID;
+
+ gtk_tree_model_get(priv->filter_model, &iter, TYPE_COLUMN, &type, -1);
+
+ if(ROW_TYPE_OTHER==type)
+ gtk_dialog_run(GTK_FILE_CHOOSER_BUTTON(user_data)->priv->dialog);
+ else
+ {
+ g_signal_handler_unblock(priv->combo_box, priv->combo_box_changed_id);
+ handle=FALSE;
+ g_signal_emit_by_name(priv->combo_box, "changed");
+ handle=TRUE;
+ g_signal_handler_block(priv->combo_box, priv->combo_box_changed_id);
+ }
+ }
+}
+
+GtkWidget * gtk_file_chooser_button_new(const gchar *title, GtkFileChooserAction action)
+{
+ static void * (*realFunction)() = NULL;
+
+ GtkWidget *button=NULL;
+
+ if(!realFunction)
+ realFunction = (void *(*)()) real_dlsym(RTLD_NEXT, "gtk_file_chooser_button_new");
+
+#ifdef KGTK_DEBUG
+ printf("KGTK::gtk_file_chooser_button_new\n");
+#endif
+
+ if(kgtkInit(NULL))
+ {
+ GtkFileChooserButtonPrivate *priv=NULL;
+
+ button=realFunction(title, action);
+ priv=GTK_FILE_CHOOSER_BUTTON(button)->priv;
+
+ if(priv->button)
+ {
+ g_signal_handlers_disconnect_matched(priv->button,
+ G_SIGNAL_MATCH_DATA,0, 0, NULL, NULL, button);
+
+ g_signal_connect(priv->button, "clicked",
+ G_CALLBACK(handleGtkFileChooserButtonClicked),
+ GTK_FILE_CHOOSER_BUTTON(button));
+ }
+ if(priv->combo_box)
+ {
+ g_signal_handler_block(priv->combo_box, priv->combo_box_changed_id);
+
+ g_signal_connect(priv->combo_box, "changed",
+ G_CALLBACK(handleGtkFileChooserComboChanged),
+ GTK_FILE_CHOOSER_BUTTON(button));
+ }
+ }
+ return button;
+}
+#endif
+
+static gboolean isGtk(const char *str)
+{
+ return 'g'==str[0] && 't'==str[1] && 'k'==str[2] && '_'==str[3];
+}
+
+static void * kgtk_get_fnptr(const char *raw_name)
+{
+ if(raw_name && isGtk(raw_name) && kgtkInit(NULL))
+ {
+ if(0==strcmp(raw_name, "gtk_file_chooser_get_filename"))
+ return &gtk_file_chooser_get_filename;
+
+ else if(0==strcmp(raw_name, "gtk_file_chooser_select_filename"))
+ return &gtk_file_chooser_select_filename;
+
+ else if(0==strcmp(raw_name, "gtk_file_chooser_unselect_all"))
+ return &gtk_file_chooser_unselect_all;
+
+ else if(0==strcmp(raw_name, "gtk_file_chooser_set_filename"))
+ return &gtk_file_chooser_set_filename;
+
+ else if(0==strcmp(raw_name, "gtk_file_chooser_set_current_name"))
+ return &gtk_file_chooser_set_current_name;
+
+ else if(0==strcmp(raw_name, "gtk_file_chooser_get_filenames"))
+ return &gtk_file_chooser_get_filenames;
+
+ else if(0==strcmp(raw_name, "gtk_file_chooser_set_current_folder"))
+ return &gtk_file_chooser_set_current_folder;
+
+ else if(0==strcmp(raw_name, "gtk_file_chooser_get_current_folder"))
+ return &gtk_file_chooser_get_current_folder;
+
+ else if(0==strcmp(raw_name, "gtk_file_chooser_get_uri"))
+ return &gtk_file_chooser_get_uri;
+
+ else if(0==strcmp(raw_name, "gtk_file_chooser_set_uri"))
+ return &gtk_file_chooser_set_uri;
+
+ else if(0==strcmp(raw_name, "gtk_file_chooser_get_uris"))
+ return &gtk_file_chooser_get_uris;
+
+ else if(0==strcmp(raw_name, "gtk_file_chooser_set_current_folder_uri"))
+ return &gtk_file_chooser_set_current_folder_uri;
+
+ else if(0==strcmp(raw_name, "gtk_file_chooser_get_current_folder_uri"))
+ return &gtk_file_chooser_get_current_folder_uri;
+
+ else if(0==strcmp(raw_name, "gtk_file_chooser_dialog_new"))
+ return &gtk_file_chooser_dialog_new;
+
+ else if(0==strcmp(raw_name, "gtk_file_chooser_button_new"))
+ return &gtk_file_chooser_button_new;
+
+/*
+ else if(0==strcmp(raw_name, "gtk_init_check"))
+ return &gtk_init_check;
+*/
+ }
+
+ return NULL;
+}
+
+const gchar * kgtk_g_module_check_init(GModule *module)
+{
+ return gtk_check_version(GTK_MAJOR_VERSION, GTK_MINOR_VERSION, GTK_MICRO_VERSION - GTK_INTERFACE_AGE);
+}
+
+/* Mozilla specific */
+void * PR_FindFunctionSymbol(struct PR_LoadLibrary *lib, const char *raw_name)
+{
+ static void * (*realFunction)() = NULL;
+
+ void *rv=NULL;
+
+ if(!realFunction)
+ realFunction = (void *(*)()) real_dlsym(RTLD_NEXT, "PR_FindFunctionSymbol");
+
+#ifdef KGTK_DEBUG_DLSYM
+ printf("KGTK::PR_FindFunctionSymbol : %s\n", raw_name);
+#endif
+
+ rv=kgtk_get_fnptr(raw_name);
+
+ if(!rv)
+ {
+ if (0==strcmp(raw_name, "g_module_check_init"))
+ rv=&kgtk_g_module_check_init;
+ else if (isGtk(raw_name))
+ rv=real_dlsym(RTLD_NEXT, raw_name);
+ }
+
+ return rv ? rv : realFunction(lib, raw_name);
+}
+
+#ifdef HAVE_DLVSYM
+/* Overriding dlsym is required for SWT - which dlsym's the gtk_file_chooser functions! */
+static void * real_dlsym(void *handle, const char *name)
+{
+ static void * (*realFunction)() = NULL;
+
+#ifdef KGTK_DEBUG_DLSYM
+ printf("KGTK::real_dlsym : %s\n", name);
+#endif
+
+ if (!realFunction)
+ {
+ void *ldHandle=dlopen("libdl.so", RTLD_NOW);
+
+#ifdef KGTK_DEBUG_DLSYM
+ printf("KGTK::real_dlsym : %s\n", name);
+#endif
+
+ if(ldHandle)
+ {
+ static const char * versions[]={KGTK_DLSYM_VERSION, "GLIBC_2.3", "GLIBC_2.2.5",
+ "GLIBC_2.2", "GLIBC_2.1", "GLIBC_2.0", NULL};
+
+ int i;
+
+ for(i=0; versions[i] && !realFunction; ++i)
+ realFunction=dlvsym(ldHandle, "dlsym", versions[i]);
+ }
+ }
+
+ return realFunction(handle, name);
+}
+
+void * dlsym(void *handle, const char *name)
+{
+ void *rv=NULL;
+
+#ifdef KGTK_DEBUG_DLSYM
+ printf("KGTK::dlsym : (%04X) %s\n", (int)handle, name);
+#endif
+ rv=kgtk_get_fnptr(name);
+
+ if(!rv)
+ rv=real_dlsym(handle, name);
+
+ if(!rv && 0==strcmp(name, "g_module_check_init"))
+ rv=&kgtk_g_module_check_init;
+
+#ifdef KGTK_DEBUG_DLSYM
+ printf("KGTK::dlsym found? %d\n", rv ? 1 : 0);
+#endif
+ return rv;
+}
+#endif
diff --git a/kdialogd-wrapper b/kdialogd-wrapper
new file mode 100755
index 0000000..5941e66
--- /dev/null
+++ b/kdialogd-wrapper
@@ -0,0 +1,27 @@
+#!/bin/bash
+
+#
+# This script is part of the KGtk package.
+#
+# (C) Craig Drummond, 2007
+#
+#
+# --
+# Released under the GPL v2 or later
+# --
+#
+# Wrapper script for kdialogd that removes any LD_PRELOAD. This stops
+# KDialogD from trying to connect to itself!
+#
+
+LD_PRELOAD=
+
+for app in $prefer kdialogd4 kdialogd3 ; do
+ which $app > /dev/null
+ if [ $? -eq 0 ] ; then
+ $app
+ break;
+ fi
+done
+
diff --git a/kdialogd3/CMakeLists.txt b/kdialogd3/CMakeLists.txt
new file mode 100644
index 0000000..6e054c1
--- /dev/null
+++ b/kdialogd3/CMakeLists.txt
@@ -0,0 +1,17 @@
+set(QT_MT_REQUIRED TRUE)
+find_package(KDE3)
+find_package(Qt3)
+
+if (KDE3_INCLUDE_DIR)
+ message("** INFORMATION: KDialogD for KDE3 will be built.")
+ link_directories(${KDE3_LIB_DIR})
+ include_directories (${CMAKE_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_SOURCE_DIR}/common ${CMAKE_BINARY_DIR} ${KDE3_INCLUDE_DIR} ${QT_INCLUDE_DIR})
+ set(kdialogd3_SRCS kdialogd.cpp)
+ kde3_automoc(${kdialogd3_SRCS})
+ add_executable(kdialogd3 ${kdialogd3_SRCS})
+ target_link_libraries(kdialogd3 kdeui kio kdecore)
+ install_targets(/bin kdialogd3)
+ add_subdirectory(po)
+else (KDE3_INCLUDE_DIR)
+ message("** ERROR : Could not locate Qt3/KDE3 headers, KDialogD for KDE3 will not be built.")
+endif (KDE3_INCLUDE_DIR)
diff --git a/kdialogd3/kdialogd.cpp b/kdialogd3/kdialogd.cpp
new file mode 100644
index 0000000..8aee15e
--- /dev/null
+++ b/kdialogd3/kdialogd.cpp
@@ -0,0 +1,721 @@
+//#define USE_KWIN
+
+#include "kdialogd.h"
+#include <iostream>
+#include <kdiroperator.h>
+#include <kuniqueapplication.h>
+#include <qsocketnotifier.h>
+#include <kio/netaccess.h>
+#include <kmessagebox.h>
+#include <klocale.h>
+#include <kconfig.h>
+#include <kurlcombobox.h>
+#ifdef USE_KWIN
+#include <kwin.h>
+#else
+#include <X11/Xlib.h>
+#endif
+#include <sys/un.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/errno.h>
+#include <ksockaddr.h>
+#include <kdebug.h>
+#include <kdeversion.h>
+#include <qtimer.h>
+#ifdef KDIALOGD_APP
+#include <kcmdlineargs.h>
+#include <kaboutdata.h>
+#endif
+#include <fstream>
+
+KConfig *KDialogD::theirConfig=NULL;
+
+#define CFG_KEY_DIALOG_SIZE "KDialogDSize"
+#define CFG_TIMEOUT_GROUP "General"
+#ifdef KDIALOGD_APP
+#define CFG_TIMEOUT_KEY "Timeout"
+#define DEFAULT_TIMEOUT 30
+#endif
+
+static QString groupName(const QString &app, bool fileDialog=true)
+{
+ return QString(fileDialog ? "KFileDialog " : "KDirSelectDialog ")+app;
+}
+
+// from kdebase/kdesu
+static int createSocket()
+{
+ int sockitsFd;
+ ksocklen_t addrlen;
+ struct stat s;
+ const char *sock=getSockName();
+ int stat_err=lstat(sock, &s);
+
+ if(!stat_err && S_ISLNK(s.st_mode))
+ {
+ kdWarning() << "Someone is running a symlink attack on you" << endl;
+ if(unlink(sock))
+ {
+ kdWarning() << "Could not delete symlink" << endl;
+ return -1;
+ }
+ }
+
+ if (!access(sock, R_OK|W_OK))
+ {
+ kdWarning() << "stale socket exists" << endl;
+ if (unlink(sock))
+ {
+ kdWarning() << "Could not delete stale socket" << endl;
+ return -1;
+ }
+ }
+
+ sockitsFd = socket(PF_UNIX, SOCK_STREAM, 0);
+ if (sockitsFd < 0)
+ {
+ kdError() << "socket(): " << errno << endl;
+ return -1;
+ }
+
+ struct sockaddr_un addr;
+ addr.sun_family = AF_UNIX;
+ strncpy(addr.sun_path, sock, sizeof(addr.sun_path)-1);
+ addr.sun_path[sizeof(addr.sun_path)-1] = '\000';
+ addrlen = SUN_LEN(&addr);
+ if (bind(sockitsFd, (struct sockaddr *)&addr, addrlen) < 0)
+ {
+ kdError() << "bind(): " << errno << endl;
+ return -1;
+ }
+
+ struct linger lin;
+ lin.l_onoff = lin.l_linger = 0;
+ if (setsockopt(sockitsFd, SOL_SOCKET, SO_LINGER, (char *) &lin, sizeof(linger)) < 0)
+ {
+ kdError() << "setsockopt(SO_LINGER): " << errno << endl;
+ return -1;
+ }
+
+ int opt = 1;
+ if (setsockopt(sockitsFd, SOL_SOCKET, SO_REUSEADDR, (char *) &opt, sizeof(opt)) < 0)
+ {
+ kdError() << "setsockopt(SO_REUSEADDR): " << errno << endl;
+ return -1;
+ }
+ opt = 1;
+ if (setsockopt(sockitsFd, SOL_SOCKET, SO_KEEPALIVE, (char *) &opt, sizeof(opt)) < 0)
+ {
+ kdError() << "setsockopt(SO_KEEPALIVE): " << errno << endl;
+ return -1;
+ }
+
+ if(::listen(sockitsFd, 1)<0)
+ {
+ kdError() << "listen(1): " << errno << endl;
+ return -1;
+ }
+
+ //chmod(sock, 0600);
+ return sockitsFd;
+}
+
+static void urls2Local(KURL::List &urls, QStringList &items, QWidget *parent)
+{
+ KURL::List::Iterator it(urls.begin()),
+ end(urls.end());
+
+ for(; it!=end; ++it)
+ if((*it).isLocalFile())
+ items.append((*it).path());
+ else
+ {
+#if KDE_IS_VERSION(3, 5, 0)
+ KURL url(KIO::NetAccess::mostLocalURL(*it, parent));
+
+ if(url.isLocalFile())
+ items.append(url.path());
+ else
+ break;
+#else
+ break;
+#endif
+ }
+}
+
+KDialogD::KDialogD(QObject *parent)
+ : QObject(parent),
+#ifdef KDIALOGD_APP
+ itsTimer(NULL),
+ itsTimeoutVal(DEFAULT_TIMEOUT),
+#endif
+ itsFd(::createSocket()),
+ itsNumConnections(0)
+{
+ if(itsFd<0)
+ {
+ kdError() << "KDialogD could not create socket" << endl;
+#ifdef KDIALOGD_APP
+ kapp->exit();
+#endif
+ }
+ else
+ {
+ std::ofstream f(getPidFileName());
+
+ if(f)
+ {
+ f << getpid();
+ f.close();
+ }
+ if(!theirConfig)
+ theirConfig=new KConfig("kdialogdrc", false, false);
+
+ connect(new QSocketNotifier(itsFd, QSocketNotifier::Read, this),
+ SIGNAL(activated(int)), this, SLOT(newConnection()));
+
+#ifdef KDIALOGD_APP
+ if(theirConfig->hasGroup(CFG_TIMEOUT_GROUP))
+ {
+ theirConfig->setGroup(CFG_TIMEOUT_GROUP);
+ itsTimeoutVal=theirConfig->readNumEntry(CFG_TIMEOUT_KEY, DEFAULT_TIMEOUT);
+ if(itsTimeoutVal<0)
+ itsTimeoutVal=DEFAULT_TIMEOUT;
+ theirConfig->setGroup(QString::null);
+ }
+
+ kdDebug() << "Timeout:" << itsTimeoutVal << endl;
+ if(itsTimeoutVal)
+ connect(itsTimer=new QTimer(this), SIGNAL(timeout()), this, SLOT(timeout()));
+#endif
+ }
+}
+
+KDialogD::~KDialogD()
+{
+ if(-1!=itsFd)
+ close(itsFd);
+ if(theirConfig)
+ delete theirConfig;
+ theirConfig=NULL;
+}
+
+void KDialogD::newConnection()
+{
+ kdDebug() << "New connection" << endl;
+
+ ksocklen_t addrlen = 64;
+ struct sockaddr_un clientname;
+ int connectedFD;
+
+ if((connectedFD=::accept(itsFd, (struct sockaddr *) &clientname, &addrlen))>=0)
+ {
+ int appNameLen;
+
+ if(readBlock(connectedFD, (char *)&appNameLen, 4))
+ {
+ bool ok=true;
+ QCString appName;
+
+ if(0==appNameLen)
+ appName="Generic";
+ else
+ {
+ appName.resize(appNameLen);
+ ok=readBlock(connectedFD, appName.data(), appNameLen);
+ }
+
+ if(ok)
+ {
+ itsNumConnections++;
+#ifdef KDIALOGD_APP
+ if(itsTimer)
+ itsTimer->stop();
+#endif
+ connect(new KDialogDClient(connectedFD, appName, this),
+ SIGNAL(error(KDialogDClient *)),
+ this, SLOT(deleteConnection(KDialogDClient *)));
+ }
+ }
+ }
+}
+
+void KDialogD::deleteConnection(KDialogDClient *client)
+{
+ kdDebug() << "Delete client" << endl;
+ delete client;
+
+#ifdef KDIALOGD_APP
+ if(0==--itsNumConnections)
+ if(itsTimeoutVal)
+ itsTimer->start(itsTimeoutVal*1000, true); // Only single shot...
+ else
+ timeout();
+#endif
+}
+
+void KDialogD::timeout()
+{
+#ifdef KDIALOGD_APP
+ if(0==itsNumConnections)
+ if(grabLock(0)>0) // 0=> no wait...
+ {
+ kdDebug() << "Timeout occured, and no connections, so exit" << endl;
+ kapp->exit();
+ }
+ else //...unlock lock file...
+ {
+ kdDebug() << "Timeout occured, but unable to grab lock file - app must be connecting" << endl;
+ releaseLock();
+ }
+#endif
+}
+
+KDialogDClient::KDialogDClient(int sock, const QString &an, QObject *parent)
+ : QObject(parent),
+ itsFd(sock),
+ itsDlg(NULL),
+ itsAccepted(false),
+ itsAppName(an)
+{
+ kdDebug() << "new client..." << itsAppName << " (" << itsFd << ")" << endl;
+ connect(new QSocketNotifier(itsFd, QSocketNotifier::Read, this), SIGNAL(activated(int)), this, SLOT(read()));
+ connect(new QSocketNotifier(itsFd, QSocketNotifier::Exception, this), SIGNAL(activated(int)), this, SLOT(close()));
+}
+
+KDialogDClient::~KDialogDClient()
+{
+ kdDebug() << "Deleted client" << endl;
+ if(-1!=itsFd)
+ ::close(itsFd);
+ if(KDialogD::config())
+ KDialogD::config()->sync();
+}
+
+void KDialogDClient::close()
+{
+ kdDebug() << "close " << itsFd << endl;
+
+ ::close(itsFd);
+ itsFd=-1;
+ if(itsDlg)
+ {
+ itsDlg->close();
+ itsDlg->delayedDestruct();
+ itsDlg=NULL;
+ }
+ emit error(this);
+}
+
+void KDialogDClient::read()
+{
+ kdDebug() << "read" << endl;
+
+ if(-1==itsFd)
+ return;
+
+ char request;
+ QString caption;
+ unsigned int xid=0;
+
+ if(!itsDlg && readData(&request, 1) && request>=(char)OP_FILE_OPEN && request<=(char)OP_FOLDER &&
+ readData((char *)&xid, 4) && readString(caption))
+ {
+ if("."==caption)
+ switch((Operation)request)
+ {
+ case OP_FILE_OPEN:
+ case OP_FILE_OPEN_MULTIPLE:
+ caption=i18n("Open");
+ break;
+ case OP_FILE_SAVE:
+ caption=i18n("Save As");
+ break;
+ case OP_FOLDER:
+ caption=i18n("Select Folder");
+ break;
+ default:
+ break;
+ }
+
+ if(OP_FOLDER==(Operation)request)
+ {
+ QString intialFolder;
+
+ if(readString(intialFolder))
+ {
+ initDialog(caption, new KDialogDDirSelectDialog(itsAppName, intialFolder, true, NULL,
+ "folderdialog", false), xid);
+ return;
+ }
+ }
+ else
+ {
+ QString intialFolder,
+ filter;
+ char overW=0;
+
+ if(readString(intialFolder) && readString(filter) &&
+ (OP_FILE_SAVE!=(Operation)request || readData(&overW, 1)))
+ {
+ initDialog(caption, new KDialogDFileDialog(itsAppName, (Operation)request, intialFolder,
+ filter, overW ? true : false), xid);
+ return;
+ }
+ }
+ }
+
+ kdDebug() << "Comms error, closing connection..." << itsFd << endl;
+ // If we get here something was wrong, close connection...
+ close();
+}
+
+void KDialogDClient::finished()
+{
+ if(-1==itsFd)
+ return;
+
+ //
+ // * finished is emitted when a dialog is ok'ed/cancel'ed/closed
+ // * if the user just closes the dialog - neither ok nor cancel are emitted
+ // * the dir select dialog doesnt seem to set the QDialog result parameter
+ // when it is accepted - so for this reason if ok is clicked we store an
+ // 'accepted' value there, and check for that after the dialog is finished.
+ kdDebug() << "finished" << endl;
+ if(itsDlg && !(itsAccepted || QDialog::Accepted==itsDlg->result()))
+ cancel();
+}
+
+void KDialogDClient::ok(const QStringList &items)
+{
+ kdDebug() << "ok" << endl;
+
+ int num=items.count();
+ QStringList::ConstIterator it(items.begin()),
+ end(items.end());
+ bool error=!writeData((char *)&num, 4);
+
+ for(; !error && it!=end; ++it)
+ error=!writeString(*it);
+
+ if(error)
+ close();
+ else
+ itsAccepted=true;
+ if(itsDlg)
+ itsDlg->delayedDestruct();
+ itsDlg=NULL;
+}
+
+void KDialogDClient::cancel()
+{
+ if(itsDlg)
+ {
+ kdDebug() << "cancel" << endl;
+
+ int rv=0;
+
+ if(!writeData((char *)&rv, 4))
+ close();
+ if(itsDlg)
+ itsDlg->delayedDestruct();
+ itsDlg=NULL;
+ }
+}
+
+bool KDialogDClient::readData(QCString &buffer, int size)
+{
+ buffer.resize(size);
+ return ::readBlock(itsFd, buffer.data(), size);
+}
+
+bool KDialogDClient::readString(QString &str)
+{
+ int size;
+
+ if(!readData((char *)&size, 4))
+ return false;
+
+ QCString buffer;
+ buffer.resize(size);
+
+ if(!readData(buffer.data(), size))
+ return false;
+
+ str=QString::fromUtf8(buffer.data());
+ return true;
+}
+
+bool KDialogDClient::writeString(const QString &str)
+{
+ QCString utf8(str.utf8());
+
+ int size=utf8.length()+1;
+
+ return writeData((char *)&size, 4) && writeData(utf8.data(), size);
+}
+
+void KDialogDClient::initDialog(const QString &caption, KDialogBase *d, unsigned int xid)
+{
+ itsAccepted=false;
+ itsDlg=d;
+
+ if(!caption.isEmpty())
+ itsDlg->setPlainCaption(caption);
+
+ if(xid)
+ {
+#ifdef USE_KWIN
+ KWin::setMainWindow(itsDlg, xid);
+ KWin::setState(itsDlg->winId(), NET::Modal);
+
+ KWin::WindowInfo wi(KWin::windowInfo(xid, NET::WMGeometry, NET::WM2UserTime));
+ QRect geom(wi.geometry());
+ int rx=geom.x(),
+ ry=geom.y();
+
+ rx=(rx+(geom.width()/2))-(itsDlg->width()/2);
+ if(rx<0)
+ rx=0;
+ ry=(ry+(geom.height()/2))-(itsDlg->height()/2);
+ if(ry<0)
+ ry=0;
+ itsDlg->move(rx, ry);
+#else
+ XWindowAttributes attr;
+ int rx, ry;
+ Window junkwin;
+
+ XSetTransientForHint(qt_xdisplay(), itsDlg->winId(), xid);
+ if(XGetWindowAttributes(qt_xdisplay(), xid, &attr))
+ {
+ XTranslateCoordinates(qt_xdisplay(), xid, attr.root,
+ -attr.border_width, -16,
+ &rx, &ry, &junkwin);
+
+ rx=(rx+(attr.width/2))-(itsDlg->width()/2);
+ if(rx<0)
+ rx=0;
+ ry=(ry+(attr.height/2))-(itsDlg->height()/2);
+ if(ry<0)
+ ry=0;
+ itsDlg->move(rx, ry);
+ }
+#endif
+ }
+
+ connect(itsDlg, SIGNAL(ok(const QStringList &)), this, SLOT(ok(const QStringList &)));
+ connect(itsDlg, SIGNAL(finished()), this, SLOT(finished()));
+ itsDlg->show();
+}
+
+KDialogDFileDialog::KDialogDFileDialog(QString &an, Operation op, const QString &startDir,
+ const QString &filter, bool confirmOw)
+ : KFileDialog(startDir.isEmpty() || "~"==startDir ? QDir::homeDirPath() : startDir,
+ filter, NULL, NULL, false),
+ itsConfirmOw(confirmOw),
+ itsAppName(an)
+{
+ kdDebug() << "startDir:" << startDir << endl;
+
+ switch(op)
+ {
+ case OP_FILE_OPEN:
+ setOperationMode(KFileDialog::Opening);
+ setMode((KFile::Mode)(KFile::File | KFile::ExistingOnly));
+ break;
+ case OP_FILE_OPEN_MULTIPLE:
+ setOperationMode(KFileDialog::Opening);
+ setMode((KFile::Mode)(KFile::Files | KFile::ExistingOnly));
+ break;
+ case OP_FILE_SAVE:
+ setOperationMode(KFileDialog::Saving);
+ setMode(KFile::File);
+ break;
+ default:
+ break;
+ }
+
+ if(KDialogD::config())
+ {
+ QString oldGrp(KDialogD::config()->group()),
+ grp(groupName(itsAppName));
+ QSize defaultSize(600, 400);
+
+ readConfig(KDialogD::config(), grp);
+ KDialogD::config()->setGroup(grp);
+ resize(KDialogD::config()->readSizeEntry(CFG_KEY_DIALOG_SIZE, &defaultSize));
+ KDialogD::config()->setGroup(oldGrp);
+ }
+
+ ops->clearHistory();
+}
+
+void KDialogDFileDialog::accept()
+{
+ kdDebug() << "KDialogDFileDialog::accept" << endl;
+}
+
+void KDialogDFileDialog::slotOk()
+{
+ setResult(QDialog::Accepted);
+ KFileDialog::slotOk();
+
+ kdDebug() << "KDialogDFileDialog::slotOk" << endl;
+ KURL::List urls;
+ QStringList items;
+ bool good=true;
+
+ if(mode()&KFile::Files)
+ urls=selectedURLs();
+ else if(!locationEdit->currentText().isEmpty())
+ urls.append(selectedURL());
+
+ if(urls.count())
+ {
+ urls2Local(urls, items, this);
+
+ if(urls.count()!=items.count())
+ {
+ KMessageBox::sorry(this, i18n("You can only select local files."),
+ i18n("Remote Files Not Accepted"));
+ good=false;
+ }
+ else if(itsConfirmOw && KFileDialog::Saving==operationMode())
+ good=!KIO::NetAccess::exists(urls.first(), false, this) ||
+ KMessageBox::Continue==KMessageBox::warningContinueCancel(this,
+ i18n("File %1 exits.\nDo you want to replace it?")
+ .arg(urls.first().prettyURL()),
+ i18n("File Exists"),
+ KGuiItem(i18n("Replace"), "filesaveas"), QString::null,
+ KMessageBox::Notify|KMessageBox::PlainCaption);
+
+ if(good)
+ {
+ QString filter(currentFilter());
+
+ if(!filter.isEmpty())
+ items.append(filter);
+
+ emit ok(items);
+ hide();
+ KFileDialog::accept();
+ }
+ else
+ setResult(QDialog::Rejected);
+ }
+}
+
+KDialogDFileDialog::~KDialogDFileDialog()
+{
+ kdDebug() << "~KDialogDFileDialog" << endl;
+
+ if(KDialogD::config())
+ {
+ QString oldGrp(KDialogD::config()->group()),
+ grp(groupName(itsAppName));
+
+ writeConfig(KDialogD::config(), grp);
+ KDialogD::config()->setGroup(grp);
+ KDialogD::config()->writeEntry(CFG_KEY_DIALOG_SIZE, size());
+ KDialogD::config()->setGroup(oldGrp);
+ }
+}
+
+KDialogDDirSelectDialog::KDialogDDirSelectDialog(QString &an, const QString &startDir, bool localOnly,
+ QWidget *parent, const char *name, bool modal)
+ : KDirSelectDialog(startDir.isEmpty() || "~"==startDir
+ ? QDir::homeDirPath() : startDir,
+ localOnly, parent, name, modal),
+ itsAppName(an)
+{
+ kdDebug() << "startDir:" << startDir << endl;
+
+ if(KDialogD::config())
+ {
+ QString oldGrp(KDialogD::config()->group()),
+ grp(groupName(itsAppName, false));
+ QSize defaultSize(600, 400);
+
+ //readConfig(KDialogD::config(), grp);
+ KDialogD::config()->setGroup(grp);
+ resize(KDialogD::config()->readSizeEntry(CFG_KEY_DIALOG_SIZE, &defaultSize));
+ KDialogD::config()->setGroup(oldGrp);
+ }
+}
+
+KDialogDDirSelectDialog::~KDialogDDirSelectDialog()
+{
+ kdDebug() << "~KDialogDDirSelectDialog" << endl;
+
+ if(KDialogD::config())
+ {
+ QString oldGrp(KDialogD::config()->group()),
+ grp(groupName(itsAppName, false));
+
+ //writeConfig(KDialogD::config(), grp);
+ KDialogD::config()->setGroup(grp);
+ KDialogD::config()->writeEntry(CFG_KEY_DIALOG_SIZE, size());
+ KDialogD::config()->setGroup(oldGrp);
+ }
+}
+
+void KDialogDDirSelectDialog::slotOk()
+{
+ kdDebug() << "KDialogDDirSelectDialog::slotOk" << endl;
+
+ KURL::List urls;
+ QStringList items;
+
+ urls.append(url());
+ urls2Local(urls, items, this);
+
+ if(urls.count()!=items.count())
+ KMessageBox::sorry(this, i18n("You can only select local folders."),
+ i18n("Remote Folders Not Accepted"));
+ else
+ {
+ emit ok(items);
+ hide();
+ }
+}
+
+#ifdef KDIALOGD_APP
+static KAboutData aboutData("kdialogd3", I18N_NOOP("KDialog Daemon"), VERSION,
+ I18N_NOOP("Use KDE dialogs from non-KDE apps."),
+ KAboutData::License_GPL,
+ I18N_NOOP("(c) Craig Drummond, 2006-2007"));
+
+int main(int argc, char **argv)
+{
+ KCmdLineArgs::init(argc, argv, &aboutData);
+
+ KUniqueApplication *app=new KUniqueApplication;
+ KDialogD kdialogd;
+ int rv=app->exec();
+
+ delete app;
+
+ unlink(getSockName());
+ releaseLock();
+ return rv;
+}
+#else
+extern "C"
+{
+ KDE_EXPORT KDEDModule *create_kdialogd(const QCString &obj)
+ {
+ return new KDialogDKDED(obj);
+ }
+};
+
+KDialogDKDED::KDialogDKDED(const QCString &obj)
+ : KDEDModule(obj)
+{
+ new KDialogD(this);
+}
+#endif
+
+#include "kdialogd.moc"
+
diff --git a/kdialogd3/kdialogd.h b/kdialogd3/kdialogd.h
new file mode 100644
index 0000000..7e50580
--- /dev/null
+++ b/kdialogd3/kdialogd.h
@@ -0,0 +1,145 @@
+#ifndef __KDIALOGD_H__
+#define __KDIALOGD_H__
+
+#include <kfile.h>
+#include <kfiledialog.h>
+#include <kfiledialog.h>
+#include <kdirselectdialog.h>
+#include "common.h"
+#include "config.h"
+
+#ifdef KDIALOGD_APP
+class QTimer;
+#else
+#include <kdedmodule.h>
+#endif
+class KDialogBase;
+class KConfig;
+
+class KDialogDFileDialog : public KFileDialog
+{
+ Q_OBJECT
+
+ public:
+
+ KDialogDFileDialog(QString &an, Operation op, const QString& startDir, const QString& filter,
+ bool confirmOw);
+ virtual ~KDialogDFileDialog();
+
+ public slots:
+
+ void accept();
+ void slotOk();
+
+ signals:
+
+ void ok(const QStringList &items);
+
+ private:
+
+ bool itsConfirmOw;
+ QString &itsAppName;
+};
+
+class KDialogDDirSelectDialog : public KDirSelectDialog
+{
+ Q_OBJECT
+
+ public:
+
+ KDialogDDirSelectDialog(QString &an, const QString &startDir = QString::null,
+ bool localOnly = false,
+ QWidget *parent = 0L,
+ const char *name = 0, bool modal = false);
+ virtual ~KDialogDDirSelectDialog();
+
+ public slots:
+
+ void slotOk();
+
+ signals:
+
+ void ok(const QStringList &items);
+
+ private:
+
+ QString &itsAppName;
+};
+
+class KDialogDClient : public QObject
+{
+ Q_OBJECT
+
+ public:
+
+ KDialogDClient(int sock, const QString &an, QObject *parent);
+ virtual ~KDialogDClient();
+
+ public slots:
+
+ void read();
+ void close();
+ void ok(const QStringList &items);
+ void finished();
+
+ signals:
+
+ void error(KDialogDClient *);
+
+ private:
+
+ void cancel();
+ bool readData(QCString &buffer, int size);
+ bool readData(char *buffer, int size) { return readBlock(itsFd, buffer, size); }
+ bool writeData(const char *buffer, int size) { return writeBlock(itsFd, buffer, size); }
+ bool readString(QString &str);
+ bool writeString(const QString &str);
+ void initDialog(const QString &caption, KDialogBase *d, unsigned int xid);
+
+ private:
+
+ int itsFd;
+ KDialogBase *itsDlg;
+ bool itsAccepted;
+ QString itsAppName;
+};
+
+class KDialogD : public QObject
+{
+ Q_OBJECT
+
+ public:
+
+ KDialogD(QObject *parent=0L);
+ virtual ~KDialogD();
+
+ public slots:
+
+ void newConnection();
+ void deleteConnection(KDialogDClient *client);
+ void timeout();
+
+ static KConfig * config() { return theirConfig; }
+
+ private:
+
+#ifdef KDIALOGD_APP
+ QTimer *itsTimer;
+ int itsTimeoutVal;
+#endif
+ int itsFd,
+ itsNumConnections;
+
+ static KConfig *theirConfig;
+};
+
+#ifndef KDIALOGD_APP
+class KDialogDKDED : public KDEDModule
+{
+ public:
+
+ KDialogDKDED(const QCString &obj);
+};
+#endif
+
+#endif
diff --git a/kdialogd3/po/CMakeLists.txt b/kdialogd3/po/CMakeLists.txt
new file mode 100644
index 0000000..3f456de
--- /dev/null
+++ b/kdialogd3/po/CMakeLists.txt
@@ -0,0 +1,41 @@
+find_package(Msgfmt REQUIRED)
+
+# .po to .gmo stuff
+file(GLOB _pofiles *.po)
+
+foreach(_file ${_pofiles})
+ get_filename_component(_file_we ${_file} NAME_WE)
+ set(_out "${CMAKE_CURRENT_BINARY_DIR}/${_file_we}.gmo")
+ set(_in "${_file_we}.po")
+ add_custom_command(OUTPUT ${_out} COMMAND ${MSGFMT_EXECUTABLE} -o ${_out} ${_file} DEPENDS ${_file})
+ install(FILES ${_out} DESTINATION share/locale/${_file_we}/LC_MESSAGES/ RENAME kdialogd3.mo)
+ set(_outputs ${_outputs} ${_out})
+endforeach(_file)
+
+add_custom_target(pofiles ALL DEPENDS ${_outputs})
+
+# Stuff to generate the .pot
+set(POT_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/../kdialogd.cpp)
+set(POT_OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/kdialogd3.pot)
+
+# Find xgettext
+find_program(XGETTEXT_PATH NAMES "xgettext" PATHS "/usr/bin" "/usr/local/bin")
+if(${XGETTEXT_PATH} STREQUAL "XGETTEXT_PATH-NOTFOUND")
+ message(STATUS "xgettext not found. You will not be able to run 'make extract_messages' in the 'po' directory.")
+else(${XGETTEXT_PATH} STREQUAL "XGETTEXT_PATH-NOTFOUND")
+ message(STATUS "Found xgettext: ${XGETTEXT_PATH}")
+endif(${XGETTEXT_PATH} STREQUAL "XGETTEXT_PATH-NOTFOUND")
+
+if(EXISTS ${KDE3_INCLUDE_DIR}/kde.pot)
+ add_custom_command(
+ OUTPUT ${POT_OUTPUT}
+ COMMAND ${XGETTEXT_PATH} --foreign-user -C -ci18n -ki18n -ktr2i18n -kI18N_NOOP -kI18N_NOOP2 -kaliasLocale -x "${KDE3_INCLUDE_DIR}/kde.pot" -o ${POT_OUTPUT} ${POT_SOURCES}
+ )
+else (EXISTS ${KDE3_INCLUDE_DIR}/kde.pot)
+ add_custom_command(
+ OUTPUT ${POT_OUTPUT}
+ COMMAND ${XGETTEXT_PATH} --foreign-user -C -ci18n -ki18n -ktr2i18n -kI18N_NOOP -kI18N_NOOP2 -kaliasLocale -o ${POT_OUTPUT} ${POT_SOURCES}
+ )
+endif (EXISTS ${KDE3_INCLUDE_DIR}/kde.pot)
+
+add_custom_target(extract_messages DEPENDS ${POT_OUTPUT})
diff --git a/kdialogd3/po/cs.po b/kdialogd3/po/cs.po
new file mode 100644
index 0000000..e9dd016
--- /dev/null
+++ b/kdialogd3/po/cs.po
@@ -0,0 +1,63 @@
+# translation of cs.po to Česky
+# This file is put in the public domain.
+#
+# Marián Kyral <[email protected]>, 2007.
+msgid ""
+msgstr ""
+"Project-Id-Version: cs\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2007-09-21 14:40+0100\n"
+"PO-Revision-Date: 2007-10-16 05:26+0200\n"
+"Last-Translator: Marián Kyral <[email protected]>\n"
+"Language-Team: Česky <[email protected]>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.11.4\n"
+"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
+
+#: kdialogd.cpp:328
+msgid "Select Folder"
+msgstr "Vyberte složku"
+
+#: kdialogd.cpp:573
+msgid "You can only select local files."
+msgstr "Můžete vybrat pouze místní soubory."
+
+#: kdialogd.cpp:574
+msgid "Remote Files Not Accepted"
+msgstr "Vzdálené soubory nejsou akceptovány."
+
+#: kdialogd.cpp:580
+msgid ""
+"File %1 exits.\n"
+"Do you want to replace it?"
+msgstr ""
+"Soubor %1 existuje.\n"
+"Chcete jej přepsat?"
+
+#: kdialogd.cpp:582
+msgid "File Exists"
+msgstr "Soubor existuje."
+
+#: kdialogd.cpp:667
+msgid "You can only select local folders."
+msgstr "Můžete vybrat pouze místní složky."
+
+#: kdialogd.cpp:668
+msgid "Remote Folders Not Accepted"
+msgstr "Vzdálené složky nejsou akceptovány."
+
+#: kdialogd.cpp:677
+msgid "KDialog Daemon"
+msgstr "KDialog Daemon"
+
+#: kdialogd.cpp:678
+msgid "Use KDE dialogs from non-KDE apps."
+msgstr "KDE souborové dialogy v ne-KDE aplikacích."
+
+#: kdialogd.cpp:680
+msgid "(c) Craig Drummond, 2006-2007"
+msgstr ""
+"(c) Craig Drummond, 2006-2007\n"
+"Český překlad Marián Kyral"
diff --git a/kdialogd3/po/de.po b/kdialogd3/po/de.po
new file mode 100644
index 0000000..f21775b
--- /dev/null
+++ b/kdialogd3/po/de.po
@@ -0,0 +1,62 @@
+# translation of kdialogd3.po to Deutsch
+# This file is put in the public domain.
+#
+# Jannick Kuhr <[email protected]>, 2007.
+msgid ""
+msgstr ""
+"Project-Id-Version: kdialogd3\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2007-09-21 14:40+0100\n"
+"PO-Revision-Date: 2007-10-11 13:24+0200\n"
+"Last-Translator: Jannick Kuhr <[email protected]>\n"
+"Language-Team: Deutsch <[email protected]>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.11.4\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+
+#: kdialogd.cpp:328
+msgid "Select Folder"
+msgstr "Ordner wählen"
+
+#: kdialogd.cpp:573
+msgid "You can only select local files."
+msgstr "Sie können nur lokale Dateien auswählen."
+
+#: kdialogd.cpp:574
+msgid "Remote Files Not Accepted"
+msgstr "Dateien von Fremdrechnern werden nicht akzeptiert."
+
+#: kdialogd.cpp:580
+msgid ""
+"File %1 exits.\n"
+"Do you want to replace it?"
+msgstr ""
+"Die Datei %1 exisitiert bereits.\n"
+"Wollen Sie sie ersetzen?"
+
+#: kdialogd.cpp:582
+msgid "File Exists"
+msgstr "Datei existiert bereits"
+
+#: kdialogd.cpp:667
+msgid "You can only select local folders."
+msgstr "Sie können nur lokale Ordner auswählen."
+
+#: kdialogd.cpp:668
+msgid "Remote Folders Not Accepted"
+msgstr "Ordner von Fremdrechnern werden nicht akzeptiert."
+
+#: kdialogd.cpp:677
+msgid "KDialog Daemon"
+msgstr "KDialog-Daemon"
+
+#: kdialogd.cpp:678
+msgid "Use KDE dialogs from non-KDE apps."
+msgstr "KDE-Dialoge in Nicht-KDE-Programmen verwenden."
+
+#: kdialogd.cpp:680
+msgid "(c) Craig Drummond, 2006-2007"
+msgstr "(c) Craig Drummond, 2006-2007"
+
diff --git a/kdialogd3/po/en_GB.po b/kdialogd3/po/en_GB.po
new file mode 100644
index 0000000..18fd77b
--- /dev/null
+++ b/kdialogd3/po/en_GB.po
@@ -0,0 +1,60 @@
+# translation of kdialogd3.po to British English
+# Copyright (C) 2007 Craig Drummond <[email protected]>
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: kdialogd3\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2007-09-21 14:40+0100\n"
+"PO-Revision-Date: 2007-10-05 22:35+0200\n"
+"Last-Translator: Craig Drummond <[email protected]>\n"
+"Language-Team: Craig Drummond <[email protected]>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=iso-8859-1\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#: kdialogd.cpp:328
+msgid "Select Folder"
+msgstr "Select Folder"
+
+#: kdialogd.cpp:573
+msgid "You can only select local files."
+msgstr "You can only select local files."
+
+#: kdialogd.cpp:574
+msgid "Remote Files Not Accepted"
+msgstr "Remote Files Not Accepted"
+
+#: kdialogd.cpp:580
+msgid ""
+"File %1 exits.\n"
+"Do you want to replace it?"
+msgstr ""
+"File %1 exits.\n"
+"Do you want to replace it?"
+
+#: kdialogd.cpp:582
+msgid "File Exists"
+msgstr "File Exists"
+
+#: kdialogd.cpp:667
+msgid "You can only select local folders."
+msgstr "You can only select local folders."
+
+#: kdialogd.cpp:668
+msgid "Remote Folders Not Accepted"
+msgstr "Remote Folders Not Accepted"
+
+#: kdialogd.cpp:677
+msgid "KDialog Daemon"
+msgstr "KDialog Daemon"
+
+#: kdialogd.cpp:678
+msgid "Use KDE dialogs from non-KDE apps."
+msgstr "Use KDE dialogs from non-KDE apps."
+
+#: kdialogd.cpp:680
+msgid "(c) Craig Drummond, 2006-2007"
+msgstr "(c) Craig Drummond, 2006-2007"
diff --git a/kdialogd3/po/es.po b/kdialogd3/po/es.po
new file mode 100644
index 0000000..5cdc2f4
--- /dev/null
+++ b/kdialogd3/po/es.po
@@ -0,0 +1,57 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: kdialogd3\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2007-09-21 14:40+0100\n"
+"PO-Revision-Date: 2007-10-19 18:17+0200\n"
+"Last-Translator: Marco Antonio Blanco <[email protected]>\n"
+"Language-Team: Craig Drummond <[email protected]>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=iso-8859-1\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: Pootle 0.10.1\n"
+
+#: kdialogd.cpp:328
+msgid "Select Folder"
+msgstr "Seleccionar carpeta"
+
+#: kdialogd.cpp:573
+msgid "You can only select local files."
+msgstr "S�lo se pueden seleccionar ficheros locales."
+
+#: kdialogd.cpp:574
+msgid "Remote Files Not Accepted"
+msgstr "No se aceptan ficheros remotos"
+
+#: kdialogd.cpp:580
+msgid ""
+"File %1 exits.\n"
+"Do you want to replace it?"
+msgstr ""
+"El fichero %1 existe.\n"
+"�Quiere sustituirlo?"
+
+#: kdialogd.cpp:582
+msgid "File Exists"
+msgstr "El fichero existe"
+
+#: kdialogd.cpp:667
+msgid "You can only select local folders."
+msgstr "S�lo se pueden seleccionar carpetas locales"
+
+#: kdialogd.cpp:668
+msgid "Remote Folders Not Accepted"
+msgstr "No se aceptan carpetas remotas"
+
+#: kdialogd.cpp:677
+msgid "KDialog Daemon"
+msgstr "Demonio KDialog"
+
+#: kdialogd.cpp:678
+msgid "Use KDE dialogs from non-KDE apps."
+msgstr "Utilizar di�logos KDE en aplicaciones no KDE."
+
+#: kdialogd.cpp:680
+msgid "(c) Craig Drummond, 2006-2007"
+msgstr "(c) Craig Drummond, 2006-2007"
diff --git a/kdialogd3/po/fr.po b/kdialogd3/po/fr.po
new file mode 100644
index 0000000..6afa160
--- /dev/null
+++ b/kdialogd3/po/fr.po
@@ -0,0 +1,60 @@
+# translation of kdialogd3.po to French
+# Copyright (C) 2007 aul Thomas <[email protected]>
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: kdialogd3\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2007-09-21 14:40+0100\n"
+"PO-Revision-Date: 2007-10-06 17:54+0200\n"
+"Last-Translator: Paul Thomas <[email protected]>\n"
+"Language-Team: Paul Thomas <[email protected]>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#: kdialogd.cpp:328
+msgid "Select Folder"
+msgstr "Sélectionnez le dossier"
+
+#: kdialogd.cpp:573
+msgid "You can only select local files."
+msgstr "Vous ne pouvez sélectionner que des fichiers locaux."
+
+#: kdialogd.cpp:574
+msgid "Remote Files Not Accepted"
+msgstr "Les fichiers distants ne sont pas acceptés"
+
+#: kdialogd.cpp:580
+msgid ""
+"File %1 exits.\n"
+"Do you want to replace it?"
+msgstr ""
+"Le fichier %1 exite déjà.\n"
+"Voulez-vous le remplacer"
+
+#: kdialogd.cpp:582
+msgid "File Exists"
+msgstr "Le Fichier existe déjà"
+
+#: kdialogd.cpp:667
+msgid "You can only select local folders."
+msgstr "Vous ne pouvez sélectionner que des dossiers locaux."
+
+#: kdialogd.cpp:668
+msgid "Remote Folders Not Accepted"
+msgstr "Les dossiers distants ne sont pas acceptés"
+
+#: kdialogd.cpp:677
+msgid "KDialog Daemon"
+msgstr "KDialog Daemon"
+
+#: kdialogd.cpp:678
+msgid "Use KDE dialogs from non-KDE apps."
+msgstr "Utilisez les dialogues KDE à partir d'applications non-KDE."
+
+#: kdialogd.cpp:680
+msgid "(c) Craig Drummond, 2006-2007"
+msgstr "(c) Craig Drummond, 2006-2007"
diff --git a/kdialogd3/po/kdialogd3.pot b/kdialogd3/po/kdialogd3.pot
new file mode 100644
index 0000000..a59be5f
--- /dev/null
+++ b/kdialogd3/po/kdialogd3.pot
@@ -0,0 +1,58 @@
+# SOME DESCRIPTIVE TITLE.
+# This file is put in the public domain.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2007-09-21 14:40+0100\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <[email protected]>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: kdialogd.cpp:328
+msgid "Select Folder"
+msgstr ""
+
+#: kdialogd.cpp:573
+msgid "You can only select local files."
+msgstr ""
+
+#: kdialogd.cpp:574
+msgid "Remote Files Not Accepted"
+msgstr ""
+
+#: kdialogd.cpp:580
+msgid ""
+"File %1 exits.\n"
+"Do you want to replace it?"
+msgstr ""
+
+#: kdialogd.cpp:582
+msgid "File Exists"
+msgstr ""
+
+#: kdialogd.cpp:667
+msgid "You can only select local folders."
+msgstr ""
+
+#: kdialogd.cpp:668
+msgid "Remote Folders Not Accepted"
+msgstr ""
+
+#: kdialogd.cpp:677
+msgid "KDialog Daemon"
+msgstr ""
+
+#: kdialogd.cpp:678
+msgid "Use KDE dialogs from non-KDE apps."
+msgstr ""
+
+#: kdialogd.cpp:680
+msgid "(c) Craig Drummond, 2006-2007"
+msgstr ""
diff --git a/kdialogd3/po/pt_BR.po b/kdialogd3/po/pt_BR.po
new file mode 100644
index 0000000..ac4c524
--- /dev/null
+++ b/kdialogd3/po/pt_BR.po
@@ -0,0 +1,60 @@
+# translation of kdialogd3.po to Brazillian Portuguese
+# This file is put in the public domain.
+#
+# Márcio Moraes <[email protected]>, 2007.
+msgid ""
+msgstr ""
+"Project-Id-Version: kdialogd3\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2007-09-21 14:40+0100\n"
+"PO-Revision-Date: 2008-02-26 11:22-0300\n"
+"Last-Translator: Márcio Moraes <[email protected]>\n"
+"Language-Team: Márcio Moraes <[email protected]>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=iso-8859-1\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#: kdialogd.cpp:328
+msgid "Select Folder"
+msgstr "Selecionar Pasta"
+
+#: kdialogd.cpp:573
+msgid "You can only select local files."
+msgstr "Selecione apenas arquivos locais."
+
+#: kdialogd.cpp:574
+msgid "Remote Files Not Accepted"
+msgstr "Arquivos remotos não são aceitos"
+
+#: kdialogd.cpp:580
+msgid ""
+"File %1 exits.\n"
+"Do you want to replace it?"
+msgstr ""
+"Arquivo %1 existe.\n"
+"Você realmente deseja sobrescrever?"
+
+#: kdialogd.cpp:582
+msgid "File Exists"
+msgstr "Arquivo existe"
+
+#: kdialogd.cpp:667
+msgid "You can only select local folders."
+msgstr "Selecione apenas pastas locais."
+
+#: kdialogd.cpp:668
+msgid "Remote Folders Not Accepted"
+msgstr "Pastas remotas não são aceitas"
+
+#: kdialogd.cpp:677
+msgid "KDialog Daemon"
+msgstr "KDialog Daemon"
+
+#: kdialogd.cpp:678
+msgid "Use KDE dialogs from non-KDE apps."
+msgstr "Uso de diálogos KDE em aplicações não KDE."
+
+#: kdialogd.cpp:680
+msgid "(c) Craig Drummond, 2006-2007"
+msgstr "(c) Craig Drummond, 2006-2007"
diff --git a/kdialogd3/po/ru.po b/kdialogd3/po/ru.po
new file mode 100644
index 0000000..cf2abd0
--- /dev/null
+++ b/kdialogd3/po/ru.po
@@ -0,0 +1,62 @@
+# translation of ru.po to
+# This file is put in the public domain.
+#
+# Yarodin <[email protected]>, 2008.
+msgid ""
+msgstr ""
+"Project-Id-Version: kdialogd3\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2007-09-21 14:40+0100\n"
+"PO-Revision-Date: 2008-05-01 19:31+0600\n"
+"Last-Translator: Yarodin <[email protected]>\n"
+"Language-Team: Russian <[email protected]>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.11.4\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+
+#: kdialogd.cpp:328
+msgid "Select Folder"
+msgstr "Выбор папки"
+
+#: kdialogd.cpp:573
+msgid "You can only select local files."
+msgstr "Вы можете выбрать только локальные файлы."
+
+#: kdialogd.cpp:574
+msgid "Remote Files Not Accepted"
+msgstr "Файлы на удаленной машине недоступны"
+
+#: kdialogd.cpp:580
+msgid ""
+"File %1 exits.\n"
+"Do you want to replace it?"
+msgstr ""
+"Файл %1 уже существует.\n"
+"Хотите его перезаписать?"
+
+#: kdialogd.cpp:582
+msgid "File Exists"
+msgstr "Файл существует"
+
+#: kdialogd.cpp:667
+msgid "You can only select local folders."
+msgstr "Вы можете выбрать только локальные папки."
+
+#: kdialogd.cpp:668
+msgid "Remote Folders Not Accepted"
+msgstr "Сетевые папки недоступны."
+
+#: kdialogd.cpp:677
+msgid "KDialog Daemon"
+msgstr "KDialog-Демон"
+
+#: kdialogd.cpp:678
+msgid "Use KDE dialogs from non-KDE apps."
+msgstr "Использование KDE диалогов в Не-KDE приложениях."
+
+#: kdialogd.cpp:680
+msgid "(c) Craig Drummond, 2006-2007"
+msgstr "(c) Craig Drummond, 2006-2007"
+
diff --git a/kdialogd3/po/zh_CN.po b/kdialogd3/po/zh_CN.po
new file mode 100644
index 0000000..fab0e38
--- /dev/null
+++ b/kdialogd3/po/zh_CN.po
@@ -0,0 +1,60 @@
+# translation of kdialogd3.po to Chinese Simplified
+# Copyright (C) 2007 Free Software Foundation, Inc.
+#
+# Liang Qi <[email protected]>, 2007.
+msgid ""
+msgstr ""
+"Project-Id-Version: kdialogd3\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2007-09-21 14:40+0100\n"
+"PO-Revision-Date: 2007-10-05 13:20+0200\n"
+"Last-Translator: Liang Qi <[email protected]>\n"
+"Language-Team: zh_CN <[email protected]>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#: kdialogd.cpp:328
+msgid "Select Folder"
+msgstr "选择文件夹"
+
+#: kdialogd.cpp:573
+msgid "You can only select local files."
+msgstr "仅允许选择本地文件。"
+
+#: kdialogd.cpp:574
+msgid "Remote Files Not Accepted"
+msgstr "无法接受远程文件"
+
+#: kdialogd.cpp:580
+msgid ""
+"File %1 exits.\n"
+"Do you want to replace it?"
+msgstr ""
+"文件 %1 已经存在。\n"
+"您想替换它么?"
+
+#: kdialogd.cpp:582
+msgid "File Exists"
+msgstr "文件已存在"
+
+#: kdialogd.cpp:667
+msgid "You can only select local folders."
+msgstr "仅允许选择本地文件夹。"
+
+#: kdialogd.cpp:668
+msgid "Remote Folders Not Accepted"
+msgstr "无法接受远程文件夹"
+
+#: kdialogd.cpp:677
+msgid "KDialog Daemon"
+msgstr "KDialog 守护进程"
+
+#: kdialogd.cpp:678
+msgid "Use KDE dialogs from non-KDE apps."
+msgstr "在非 KDE 程序中使用 KDE 对话框。"
+
+#: kdialogd.cpp:680
+msgid "(c) Craig Drummond, 2006-2007"
+msgstr "(c) Craig Drummond, 2006-2007"
diff --git a/kdialogd4/CMakeLists.txt b/kdialogd4/CMakeLists.txt
new file mode 100644
index 0000000..0c0f017
--- /dev/null
+++ b/kdialogd4/CMakeLists.txt
@@ -0,0 +1,16 @@
+find_package(KDE4)
+find_package(Qt4)
+
+if (KDE4_FOUND)
+ message("** INFORMATION: KDialogD for KDE4 will be built.")
+ include (KDE4Defaults)
+ include_directories (${CMAKE_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_SOURCE_DIR}/common ${CMAKE_BINARY_DIR} ${KDE4_INCLUDE_DIR} ${QT_INCLUDE_DIR})
+ set(kdialogd4_bin_SRCS kdialogd.cpp)
+ kde4_add_executable(kdialogd4_bin ${kdialogd4_bin_SRCS})
+ set_target_properties(kdialogd4_bin PROPERTIES OUTPUT_NAME kdialogd4)
+ target_link_libraries(kdialogd4_bin ${KDE4_KDEUI_LIBS} ${KDE4_KIO_LIBS} ${KDE4_KIO_LIBS} ${KDE4_KDECORE_LIBRARY} kfile )
+ install(TARGETS kdialogd4_bin ${INSTALL_TARGETS_DEFAULT_ARGS} )
+ add_subdirectory(po)
+else (KDE4_FOUND)
+ message("** ERROR : Could not locate Qt4/KDE4 headers, KDialogD for KDE4 will not be built.")
+endif (KDE4_FOUND)
diff --git a/kdialogd4/kdialogd.cpp b/kdialogd4/kdialogd.cpp
new file mode 100644
index 0000000..ddd1142
--- /dev/null
+++ b/kdialogd4/kdialogd.cpp
@@ -0,0 +1,759 @@
+#define USE_KWIN
+
+#include "kdialogd.h"
+#include <iostream>
+#include <kdiroperator.h>
+#include <kuniqueapplication.h>
+#include <QtCore/QSocketNotifier>
+#include <QtGui/QX11Info>
+#include <kio/netaccess.h>
+#include <kmessagebox.h>
+#include <klocale.h>
+#include <kconfig.h>
+#include <kurlcombobox.h>
+#ifdef USE_KWIN
+#include <kwindowsystem.h>
+#else
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include <fixx11h.h>
+#endif
+#include <sys/un.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/errno.h>
+#include <kdebug.h>
+#include <kdeversion.h>
+#ifdef KDIALOGD_APP
+#include <QtCore/QTimer>
+#include <kcmdlineargs.h>
+#include <kaboutdata.h>
+#endif
+#include <kabstractfilewidget.h>
+#include <fstream>
+
+KConfig *KDialogD::theirConfig=NULL;
+
+#define CFG_KEY_DIALOG_SIZE "KDialogDSize"
+#define CFG_TIMEOUT_GROUP "General"
+#ifdef KDIALOGD_APP
+#define CFG_TIMEOUT_KEY "Timeout"
+#define DEFAULT_TIMEOUT 30
+#endif
+
+static QString groupName(const QString &app, bool fileDialog=true)
+{
+ return QString(fileDialog ? "KFileDialog " : "KDirSelectDialog ")+app;
+}
+
+// from kdebase/kdesu
+typedef unsigned ksocklen_t;
+
+static int createSocket()
+{
+ int socketFd;
+ ksocklen_t addrlen;
+ struct stat s;
+ const char *sock=getSockName();
+ int stat_err=lstat(sock, &s);
+
+ if(!stat_err && S_ISLNK(s.st_mode))
+ {
+ kWarning() << "Someone is running a symlink attack on you" ;
+ if(unlink(sock))
+ {
+ kWarning() << "Could not delete symlink" ;
+ return -1;
+ }
+ }
+
+ if (!access(sock, R_OK|W_OK))
+ {
+ kWarning() << "stale socket exists" ;
+ if (unlink(sock))
+ {
+ kWarning() << "Could not delete stale socket" ;
+ return -1;
+ }
+ }
+
+ socketFd = socket(PF_UNIX, SOCK_STREAM, 0);
+ if (socketFd < 0)
+ {
+ kError() << "socket(): " << strerror(errno);
+ return -1;
+ }
+
+ struct sockaddr_un addr;
+ addr.sun_family = AF_UNIX;
+ strncpy(addr.sun_path, sock, sizeof(addr.sun_path)-1);
+ addr.sun_path[sizeof(addr.sun_path)-1] = '\000';
+ addrlen = SUN_LEN(&addr);
+ if (bind(socketFd, (struct sockaddr *)&addr, addrlen) < 0)
+ {
+ kError() << "bind(): " << strerror(errno);
+ return -1;
+ }
+
+ struct linger lin;
+ lin.l_onoff = lin.l_linger = 0;
+ if (setsockopt(socketFd, SOL_SOCKET, SO_LINGER, (char *) &lin,
+ sizeof(linger)) < 0)
+ {
+ kError() << "setsockopt(SO_LINGER): " << strerror(errno);
+ return -1;
+ }
+
+ int opt = 1;
+ if (setsockopt(socketFd, SOL_SOCKET, SO_REUSEADDR, (char *) &opt,
+ sizeof(opt)) < 0)
+ {
+ kError() << "setsockopt(SO_REUSEADDR): " << strerror(errno);
+ return -1;
+ }
+ opt = 1;
+ if (setsockopt(socketFd, SOL_SOCKET, SO_KEEPALIVE, (char *) &opt,
+ sizeof(opt)) < 0)
+ {
+ kError() << "setsockopt(SO_KEEPALIVE): " << strerror(errno);
+ return -1;
+ }
+ chmod(sock, 0600);
+ if (listen(socketFd, 1) < 0)
+ {
+ kError() << "listen(): " << strerror(errno);
+ return -1;
+ }
+
+ return socketFd;
+}
+
+static void urls2Local(KUrl::List &urls, QStringList &items, QWidget *parent)
+{
+ KUrl::List::Iterator it(urls.begin()),
+ end(urls.end());
+
+ for(; it!=end; ++it)
+ {
+ kDebug() << "URL:" << *it << " local? " << (*it).isLocalFile();
+ if((*it).isLocalFile())
+ items.append((*it).path());
+ else
+ {
+ KUrl url(KIO::NetAccess::mostLocalUrl(*it, parent));
+
+ kDebug() << "mostLocal:" << url << " local? " << url.isLocalFile();
+ if(url.isLocalFile())
+ items.append(url.path());
+ else
+ break;
+ }
+ }
+}
+
+KDialogD::KDialogD(QObject *parent)
+ : QObject(parent),
+#ifdef KDIALOGD_APP
+ itsTimer(NULL),
+ itsTimeoutVal(DEFAULT_TIMEOUT),
+#endif
+ itsFd(::createSocket()),
+ itsNumConnections(0)
+{
+ if(itsFd<0)
+ {
+ kError() << "KDialogD could not create socket";
+#ifdef KDIALOGD_APP
+ kapp->exit();
+#endif
+ }
+ else
+ {
+ std::ofstream f(getPidFileName());
+
+ if(f)
+ {
+ f << getpid();
+ f.close();
+ }
+ if(!theirConfig)
+ theirConfig=new KConfig("kdialogd4rc"); // , KConfig::OnlyLocal);
+
+ connect(new QSocketNotifier(itsFd, QSocketNotifier::Read, this),
+ SIGNAL(activated(int)), this, SLOT(newConnection()));
+
+#ifdef KDIALOGD_APP
+ if(theirConfig->hasGroup(CFG_TIMEOUT_GROUP))
+ {
+ itsTimeoutVal=KConfigGroup(theirConfig, CFG_TIMEOUT_GROUP).readEntry(CFG_TIMEOUT_KEY, DEFAULT_TIMEOUT);
+ if(itsTimeoutVal<0)
+ itsTimeoutVal=DEFAULT_TIMEOUT;
+ }
+ kDebug() << "Timeout:" << itsTimeoutVal;
+ if(itsTimeoutVal)
+ {
+ connect(itsTimer=new QTimer(this), SIGNAL(timeout()), this, SLOT(timeout()));
+ itsTimer->setSingleShot(true);
+ }
+#endif
+ }
+}
+
+KDialogD::~KDialogD()
+{
+ if(-1!=itsFd)
+ close(itsFd);
+ if(theirConfig)
+ delete theirConfig;
+ theirConfig=NULL;
+}
+
+void KDialogD::newConnection()
+{
+ kDebug() << "New connection";
+
+ ksocklen_t addrlen = 64;
+ struct sockaddr_un clientname;
+ int connectedFD;
+
+ if((connectedFD=::accept(itsFd, (struct sockaddr *) &clientname, &addrlen))>=0)
+ {
+ int appNameLen;
+
+ if(readBlock(connectedFD, (char *)&appNameLen, 4))
+ {
+ bool ok=true;
+ QByteArray appName;
+
+ if(0==appNameLen)
+ appName="Generic";
+ else
+ {
+ appName.resize(appNameLen);
+ ok=readBlock(connectedFD, appName.data(), appNameLen);
+ }
+
+ if(ok)
+ {
+ itsNumConnections++;
+#ifdef KDIALOGD_APP
+ if(itsTimer)
+ itsTimer->stop();
+#endif
+ connect(new KDialogDClient(connectedFD, appName, this),
+ SIGNAL(error(KDialogDClient *)),
+ this, SLOT(deleteConnection(KDialogDClient *)));
+ }
+ }
+ }
+}
+
+void KDialogD::deleteConnection(KDialogDClient *client)
+{
+ kDebug() << "Delete client";
+ delete client;
+
+#ifdef KDIALOGD_APP
+ if(0==--itsNumConnections)
+ if(itsTimeoutVal)
+ itsTimer->start(itsTimeoutVal*1000); // Only single shot...
+ else
+ timeout();
+#endif
+}
+
+void KDialogD::timeout()
+{
+#ifdef KDIALOGD_APP
+ if(0==itsNumConnections)
+ if(grabLock(0)>0) // 0=> no wait...
+ {
+ kDebug() << "Timeout occured, and no connections, so exit";
+ kapp->exit();
+ }
+ else //...unlock lock file...
+ {
+ kDebug() << "Timeout occured, but unable to grab lock file - app must be connecting";
+ releaseLock();
+ }
+#endif
+}
+
+KDialogDClient::KDialogDClient(int sock, const QString &an, QObject *parent)
+ : QObject(parent),
+ itsFd(sock),
+ itsDlg(NULL),
+ itsXid(0),
+ itsAccepted(false),
+ itsAppName(an)
+{
+ kDebug() << "new client..." << itsAppName << " (" << itsFd << ")";
+ connect(new QSocketNotifier(itsFd, QSocketNotifier::Read, this), SIGNAL(activated(int)), this, SLOT(read()));
+ connect(new QSocketNotifier(itsFd, QSocketNotifier::Exception, this), SIGNAL(activated(int)), this, SLOT(close()));
+}
+
+KDialogDClient::~KDialogDClient()
+{
+ kDebug() << "Deleted client";
+ if(-1!=itsFd)
+ ::close(itsFd);
+ itsDlg=NULL;
+ if(KDialogD::config())
+ KDialogD::config()->sync();
+}
+
+void KDialogDClient::close()
+{
+ kDebug() << "close" << itsFd;
+
+ ::close(itsFd);
+ itsFd=-1;
+ if(itsDlg)
+ {
+ itsDlg->close();
+ itsDlg->delayedDestruct();
+ itsDlg=NULL;
+ itsXid=0;
+ }
+
+ emit error(this);
+}
+
+void KDialogDClient::read()
+{
+ kDebug() << "read" << itsFd;
+
+ if(-1==itsFd)
+ return;
+
+ char request;
+ QString caption;
+
+ if(!itsDlg && readData(&request, 1) && request>=(char)OP_FILE_OPEN && request<=(char)OP_FOLDER &&
+ readData((char *)&itsXid, 4) && readString(caption))
+ {
+ if("."==caption)
+ switch((Operation)request)
+ {
+ case OP_FILE_OPEN:
+ case OP_FILE_OPEN_MULTIPLE:
+ caption=i18n("Open");
+ break;
+ case OP_FILE_SAVE:
+ caption=i18n("Save As");
+ break;
+ case OP_FOLDER:
+ caption=i18n("Select Folder");
+ break;
+ default:
+ break;
+ }
+
+ if(OP_FOLDER==(Operation)request)
+ {
+ QString intialFolder;
+
+ if(readString(intialFolder))
+ {
+ initDialog(caption, new KDialogDDirSelectDialog(itsAppName, intialFolder, true, NULL, false));
+ return;
+ }
+ }
+ else
+ {
+ QString intialFolder,
+ filter;
+ char overW=0;
+
+ if(readString(intialFolder) && readString(filter) &&
+ (OP_FILE_SAVE!=(Operation)request || readData(&overW, 1)))
+ {
+ initDialog(caption, new KDialogDFileDialog(itsAppName, (Operation)request, intialFolder,
+ filter, overW ? true : false));
+ return;
+ }
+ }
+ }
+
+ kDebug() << "Comms error, closing connection..." << itsFd;
+ // If we get here something was wrong, close connection...
+ close();
+}
+
+void KDialogDClient::finished()
+{
+ if(-1==itsFd)
+ return;
+
+ //
+ // * finished is emitted when a dialog is ok'ed/cancel'ed/closed
+ // * if the user just closes the dialog - neither ok nor cancel are emitted
+ // * the dir select dialog doesnt seem to set the QDialog result parameter
+ // when it is accepted - so for this reason if ok is clicked we store an
+ // 'accepted' value there, and check for that after the dialog is finished.
+ kDebug() << "finished " << (void *)itsDlg << itsAccepted << (itsDlg ? QDialog::Accepted==itsDlg->result() : false);
+
+ if(itsDlg && !(itsAccepted || QDialog::Accepted==itsDlg->result()))
+ cancel();
+}
+
+void KDialogDClient::ok(const QStringList &items)
+{
+ kDebug() << "ok";
+
+ int num=items.count();
+ QStringList::ConstIterator it(items.begin()),
+ end(items.end());
+ bool error=!writeData((char *)&num, 4);
+
+ for(; !error && it!=end; ++it)
+ {
+ kDebug() << "writeString " << *it;
+ error=!writeString(*it);
+ }
+
+ if(error)
+ close();
+ else
+ itsAccepted=true;
+ if(itsDlg)
+ itsDlg->delayedDestruct();
+ itsDlg=NULL;
+}
+
+void KDialogDClient::cancel()
+{
+ kDebug() << "cancel";
+
+ if(itsDlg)
+ {
+ kDebug() << "send cancel";
+
+ int rv=0;
+
+ if(!writeData((char *)&rv, 4))
+ {
+ kDebug() << "failed to write data!";
+ close();
+ }
+ if(itsDlg)
+ itsDlg->delayedDestruct();
+ itsDlg=NULL;
+ }
+}
+
+bool KDialogDClient::readData(QByteArray &buffer, int size)
+{
+ kDebug() << "readData" << itsFd;
+ buffer.resize(size);
+ return ::readBlock(itsFd, buffer.data(), size);
+}
+
+bool KDialogDClient::readString(QString &str)
+{
+ kDebug() << "readString" << itsFd;
+
+ int size;
+
+ if(!readData((char *)&size, 4))
+ return false;
+
+ QByteArray buffer;
+ buffer.resize(size);
+
+ if(!readData(buffer.data(), size))
+ return false;
+
+ str=QString::fromUtf8(buffer.data());
+ return true;
+}
+
+bool KDialogDClient::writeString(const QString &str)
+{
+ kDebug() << "writeString" << itsFd;
+
+ QByteArray utf8(str.toUtf8());
+
+ int size=utf8.length()+1;
+
+ return writeData((char *)&size, 4) && writeData(utf8.data(), size);
+}
+
+void KDialogDClient::initDialog(const QString &caption, KDialog *d)
+{
+ kDebug() << "initDialog" << itsFd;
+
+ itsAccepted=false;
+ itsDlg=d;
+
+ if(!caption.isEmpty())
+ itsDlg->setPlainCaption(caption);
+
+ if(itsXid)
+ itsDlg->installEventFilter(this);
+
+ connect(itsDlg, SIGNAL(okClicked()), itsDlg, SLOT(slotOk()));
+ connect(itsDlg, SIGNAL(ok(const QStringList &)), this, SLOT(ok(const QStringList &)));
+ connect(itsDlg, SIGNAL(finished()), this, SLOT(finished()));
+ itsDlg->show();
+}
+
+bool KDialogDClient::eventFilter(QObject *object, QEvent *event)
+{
+ if(object==itsDlg && QEvent::ShowToParent==event->type())
+ {
+#ifdef USE_KWIN
+ KWindowSystem::setMainWindow(itsDlg, itsXid);
+ KWindowSystem::setState(itsDlg->winId(), NET::Modal|NET::SkipTaskbar|NET::SkipPager);
+
+#if 0
+ KWindowInfo wi(KWindowSystem::windowInfo(itsXid, NET::WMGeometry, NET::WM2UserTime));
+ QRect geom(wi.geometry());
+ int rx=geom.x(),
+ ry=geom.y();
+
+ rx=(rx+(geom.width()/2))-(itsDlg->width()/2);
+ if(rx<0)
+ rx=0;
+ ry=(ry+(geom.height()/2))-(itsDlg->height()/2);
+ if(ry<0)
+ ry=0;
+ itsDlg->move(rx, ry);
+#endif
+ QPixmap icon=KWindowSystem::icon(itsXid, 16, 16, true, KWindowSystem::NETWM | KWindowSystem::WMHints);
+ if(!icon.isNull())
+ itsDlg->setWindowIcon(QIcon(icon));
+#else
+ XSetTransientForHint(QX11Info::display(), itsDlg->winId(), itsXid);
+#if 0
+ XWindowAttributes attr;
+ int rx, ry;
+ Window junkwin;
+
+ if(XGetWindowAttributes(QX11Info::display(), itsXid, &attr))
+ {
+ XTranslateCoordinates(QX11Info::display(), itsXid, attr.root,
+ -attr.border_width, -16,
+ &rx, &ry, &junkwin);
+
+ rx=(rx+(attr.width/2))-(itsDlg->width()/2);
+ if(rx<0)
+ rx=0;
+ ry=(ry+(attr.height/2))-(itsDlg->height()/2);
+ if(ry<0)
+ ry=0;
+ itsDlg->move(rx, ry);
+ }
+#endif
+
+// unsigned long num;
+// unsigned long *data = NULL;
+// Atom prop = XInternAtom(QX11Info::display(), "_NET_WM_ICON", False);
+// Atom typeRet;
+// int formatRet;
+// unsigned long afterRet;
+// if(XGetWindowProperty(QX11Info::display(), itsXid, prop, 0, 0x7FFFFFFF, False, XA_CARDINAL,
+// &typeRet, &formatRet, &num, &afterRet, (unsigned char **)&data))
+// {
+// kDebug() << "GOT ICON!!!";
+// }
+// else
+// kDebug() << "FAILED TO GET ICON!!!";
+#endif
+ itsDlg->removeEventFilter(this);
+ }
+
+ return false;
+}
+
+KDialogDFileDialog::KDialogDFileDialog(QString &an, Operation op, const QString &startDir,
+ const QString &filter, bool confirmOw)
+ : KFileDialog(KUrl(startDir.isEmpty() || "~"==startDir ? QDir::homePath() : startDir),
+ filter, NULL),
+ itsConfirmOw(confirmOw),
+ itsDone(false),
+ itsAppName(an)
+{
+ setModal(false);
+ setSelection(startDir);
+ kDebug() << "startDir:" << startDir;
+
+ switch(op)
+ {
+ case OP_FILE_OPEN:
+ setOperationMode(KFileDialog::Opening);
+ setMode(KFile::File|KFile::ExistingOnly);
+ break;
+ case OP_FILE_OPEN_MULTIPLE:
+ setOperationMode(KFileDialog::Opening);
+ setMode(KFile::Files|KFile::ExistingOnly);
+ break;
+ case OP_FILE_SAVE:
+ setOperationMode(KFileDialog::Saving);
+ setMode(KFile::File);
+ break;
+ default:
+ break;
+ }
+
+ if(KDialogD::config())
+ {
+ KConfigGroup cfg(KDialogD::config(), groupName(itsAppName));
+
+ //TODO !!! readConfig(KDialogD::config(), grp);
+ resize(cfg.readEntry(CFG_KEY_DIALOG_SIZE, QSize(600, 400)));
+ }
+
+ //TODO !!! ops->clearHistory();
+}
+
+void KDialogDFileDialog::accept()
+{
+ fileWidget()->accept();
+
+ kDebug() << "KDialogDFileDialog::slotOk" << selectedUrls().count() << ' ' << mode() << ' ' << selectedUrl().prettyUrl();
+ KUrl::List urls(selectedUrls());
+ QStringList items;
+ bool good=true;
+
+ if(urls.count())
+ {
+ urls2Local(urls, items, this);
+
+ if(urls.count()!=items.count())
+ {
+ KMessageBox::sorry(this, i18n("You can only select local files."),
+ i18n("Remote Files Not Accepted"));
+ good=false;
+ }
+ else if(itsConfirmOw && KFileDialog::Saving==operationMode())
+ good=!KIO::NetAccess::exists(urls.first(), KIO::NetAccess::DestinationSide, this) ||
+ KMessageBox::Continue==KMessageBox::warningContinueCancel(this,
+ i18n("File %1 exits.\nDo you want to replace it?")
+ .arg(urls.first().prettyUrl()),
+ i18n("File Exists"),
+ KGuiItem(i18n("Replace"), "filesaveas"), KStandardGuiItem::cancel(), QString(),
+ KMessageBox::Notify|KMessageBox::PlainCaption);
+
+ if(good)
+ {
+ QString filter(currentFilter());
+
+ if(!filter.isEmpty())
+ items.append(filter);
+
+ emit ok(items);
+ hide();
+ //KFileDialog::accept();
+ }
+ else
+ setResult(QDialog::Rejected);
+ }
+}
+
+KDialogDFileDialog::~KDialogDFileDialog()
+{
+ kDebug() << "~KDialogDFileDialog";
+
+ if(KDialogD::config())
+ {
+ KConfigGroup cfg(KDialogD::config(), groupName(itsAppName));
+
+ //TODO !!! writeConfig(KDialogD::config(), grp);
+ cfg.writeEntry(CFG_KEY_DIALOG_SIZE, size());
+ }
+}
+
+KDialogDDirSelectDialog::KDialogDDirSelectDialog(QString &an, const QString &startDir, bool localOnly,
+ QWidget *parent, bool modal)
+ : KDirSelectDialog(KUrl(startDir.isEmpty() || "~"==startDir
+ ? QDir::homePath() : startDir),
+ localOnly, parent),
+ itsAppName(an)
+{
+ kDebug() << "startDir:" << startDir;
+
+ setModal(false);
+ if(KDialogD::config())
+ {
+ KConfigGroup cfg(KDialogD::config(), groupName(itsAppName, false));
+
+ //TODO !!! readConfig(KDialogD::config(), grp);
+ resize(cfg.readEntry(CFG_KEY_DIALOG_SIZE, QSize(600, 400)));
+ }
+}
+
+KDialogDDirSelectDialog::~KDialogDDirSelectDialog()
+{
+ kDebug() << "~KDialogDDirSelectDialog";
+
+ if(KDialogD::config())
+ {
+ KConfigGroup cfg(KDialogD::config(), groupName(itsAppName, false));
+
+ //TODO !!! writeConfig(KDialogD::config(), grp);
+ cfg.writeEntry(CFG_KEY_DIALOG_SIZE, size());
+ }
+}
+
+void KDialogDDirSelectDialog::slotOk()
+{
+ kDebug() << "KDialogDDirSelectDialog::slotOk";
+
+ KUrl::List urls;
+ QStringList items;
+
+ urls.append(url());
+ urls2Local(urls, items, this);
+
+ if(urls.count()!=items.count())
+ KMessageBox::sorry(this, i18n("You can only select local folders."),
+ i18n("Remote Folders Not Accepted"));
+ else
+ {
+ emit ok(items);
+ hide();
+ }
+}
+
+#ifdef KDIALOGD_APP
+static KAboutData aboutData("kdialogd4", "kdialogd4", ki18n("KDialog Daemon"), VERSION,
+ ki18n("Use KDE dialogs from non-KDE apps."),
+ KAboutData::License_GPL,
+ ki18n("(c) Craig Drummond, 2006-2007"));
+
+int main(int argc, char **argv)
+{
+ KCmdLineArgs::init(argc, argv, &aboutData);
+
+ KUniqueApplication *app=new KUniqueApplication;
+ KDialogD kdialogd;
+
+ QApplication::setQuitOnLastWindowClosed(false);
+
+ int rv=app->exec();
+
+ delete app;
+
+ unlink(getSockName());
+ releaseLock();
+ return rv;
+}
+#else
+extern "C"
+{
+ KDE_EXPORT KDEDModule *create_kdialogd()
+ {
+ return new KDialogDKDED();
+ }
+};
+
+KDialogDKDED::KDialogDKDED()
+ : KDEDModule()
+{
+ new KDialogD(this);
+}
+#endif
+
+#include "kdialogd.moc"
+
diff --git a/kdialogd4/kdialogd.h b/kdialogd4/kdialogd.h
new file mode 100644
index 0000000..c5e7e7d
--- /dev/null
+++ b/kdialogd4/kdialogd.h
@@ -0,0 +1,146 @@
+#ifndef __KDIALOGD_H__
+#define __KDIALOGD_H__
+
+#include <kfile.h>
+#include <kfiledialog.h>
+#include <kfiledialog.h>
+#include <kdirselectdialog.h>
+#include "common.h"
+#include "config.h"
+
+#ifdef KDIALOGD_APP
+class QTimer;
+#else
+#include <kdedmodule.h>
+#endif
+class KDialog;
+class KConfig;
+
+class KDialogDFileDialog : public KFileDialog
+{
+ Q_OBJECT
+
+ public:
+
+ KDialogDFileDialog(QString &an, Operation op, const QString& startDir, const QString& filter,
+ bool confirmOw);
+ virtual ~KDialogDFileDialog();
+
+ public slots:
+
+ void accept();
+
+ signals:
+
+ void ok(const QStringList &items);
+
+ private:
+
+ bool itsConfirmOw,
+ itsDone;
+ QString &itsAppName;
+};
+
+class KDialogDDirSelectDialog : public KDirSelectDialog
+{
+ Q_OBJECT
+
+ public:
+
+ KDialogDDirSelectDialog(QString &an, const QString &startDir = QString(),
+ bool localOnly = false, QWidget *parent = 0L,
+ bool modal = false);
+ virtual ~KDialogDDirSelectDialog();
+
+ public slots:
+
+ void slotOk();
+
+ signals:
+
+ void ok(const QStringList &items);
+
+ private:
+
+ QString &itsAppName;
+};
+
+class KDialogDClient : public QObject
+{
+ Q_OBJECT
+
+ public:
+
+ KDialogDClient(int sock, const QString &an, QObject *parent);
+ virtual ~KDialogDClient();
+
+ public slots:
+
+ void read();
+ void close();
+ void ok(const QStringList &items);
+ void finished();
+
+ signals:
+
+ void error(KDialogDClient *);
+
+ private:
+
+ void cancel();
+ bool readData(QByteArray &buffer, int size);
+ bool readData(char *buffer, int size) { return readBlock(itsFd, buffer, size); }
+ bool writeData(const char *buffer, int size) { return writeBlock(itsFd, buffer, size); }
+ bool readString(QString &str);
+ bool writeString(const QString &str);
+ void initDialog(const QString &caption, KDialog *d);
+ bool eventFilter(QObject *object, QEvent *event);
+
+ private:
+
+ int itsFd;
+ KDialog *itsDlg;
+ unsigned int itsXid;
+ bool itsAccepted;
+ QString itsAppName;
+};
+
+class KDialogD : public QObject
+{
+ Q_OBJECT
+
+ public:
+
+ KDialogD(QObject *parent=0L);
+ virtual ~KDialogD();
+
+ public slots:
+
+ void newConnection();
+ void deleteConnection(KDialogDClient *client);
+ void timeout();
+
+ static KConfig * config() { return theirConfig; }
+
+ private:
+
+#ifdef KDIALOGD_APP
+ QTimer *itsTimer;
+ int itsTimeoutVal;
+#endif
+ int itsFd,
+ itsNumConnections;
+
+ static KConfig *theirConfig;
+};
+
+#ifndef KDIALOGD_APP
+class KDialogDKDED : public KDEDModule
+{
+ public:
+
+ KDialogDKDED();
+};
+#endif
+
+#endif
diff --git a/kdialogd4/po/CMakeLists.txt b/kdialogd4/po/CMakeLists.txt
new file mode 100644
index 0000000..c706aff
--- /dev/null
+++ b/kdialogd4/po/CMakeLists.txt
@@ -0,0 +1,41 @@
+find_package(Msgfmt REQUIRED)
+
+# .po to .gmo stuff
+file(GLOB _pofiles *.po)
+
+foreach(_file ${_pofiles})
+ get_filename_component(_file_we ${_file} NAME_WE)
+ set(_out "${CMAKE_CURRENT_BINARY_DIR}/${_file_we}.gmo")
+ set(_in "${_file_we}.po")
+ add_custom_command(OUTPUT ${_out} COMMAND ${MSGFMT_EXECUTABLE} -o ${_out} ${_file} DEPENDS ${_file})
+ install(FILES ${_out} DESTINATION share/locale/${_file_we}/LC_MESSAGES/ RENAME kdialogd4.mo)
+ set(_outputs ${_outputs} ${_out})
+endforeach(_file)
+
+add_custom_target(pofiles ALL DEPENDS ${_outputs})
+
+# Stuff to generate the .pot
+set(POT_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/../kdialogd.cpp)
+set(POT_OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/kdialogd4.pot)
+
+# Find xgettext
+find_program(XGETTEXT_PATH NAMES "xgettext" PATHS "/usr/bin" "/usr/local/bin")
+if(${XGETTEXT_PATH} STREQUAL "XGETTEXT_PATH-NOTFOUND")
+ message(STATUS "xgettext not found. You will not be able to run 'make extract_messages' in the 'po' directory.")
+else(${XGETTEXT_PATH} STREQUAL "XGETTEXT_PATH-NOTFOUND")
+ message(STATUS "Found xgettext: ${XGETTEXT_PATH}")
+endif(${XGETTEXT_PATH} STREQUAL "XGETTEXT_PATH-NOTFOUND")
+
+if(EXISTS ${KDE4_INCLUDE_DIR}/kde.pot)
+ add_custom_command(
+ OUTPUT ${POT_OUTPUT}
+ COMMAND ${XGETTEXT_PATH} --foreign-user -C -ci18n -ki18n -ktr2i18n -kI18N_NOOP -kI18N_NOOP2 -kaliasLocale -x "${KDE4_INCLUDE_DIR}/kde.pot" -o ${POT_OUTPUT} ${POT_SOURCES}
+ )
+else (EXISTS ${KDE4_INCLUDE_DIR}/kde.pot)
+ add_custom_command(
+ OUTPUT ${POT_OUTPUT}
+ COMMAND ${XGETTEXT_PATH} --foreign-user -C -ci18n -ki18n -ktr2i18n -kI18N_NOOP -kI18N_NOOP2 -kaliasLocale -o ${POT_OUTPUT} ${POT_SOURCES}
+ )
+endif (EXISTS ${KDE4_INCLUDE_DIR}/kde.pot)
+
+add_custom_target(extract_messages DEPENDS ${POT_OUTPUT})
diff --git a/kdialogd4/po/cs.po b/kdialogd4/po/cs.po
new file mode 100644
index 0000000..9e4d454
--- /dev/null
+++ b/kdialogd4/po/cs.po
@@ -0,0 +1,61 @@
+# translation of cs.po to Česky
+# This file is put in the public domain.
+#
+# Marián Kyral <[email protected]>, 2007.
+msgid ""
+msgstr ""
+"Project-Id-Version: cs\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2007-09-21 15:08+0100\n"
+"PO-Revision-Date: 2007-10-16 05:41+0200\n"
+"Last-Translator: Marián Kyral <[email protected]>\n"
+"Language-Team: Česky <[email protected]>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.11.4\n"
+"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
+
+#: kdialogd.cpp:331
+msgid "Open"
+msgstr "Otevřít"
+
+#: kdialogd.cpp:334
+msgid "Save As"
+msgstr "Uložit jako"
+
+#: kdialogd.cpp:337
+msgid "Select Folder"
+msgstr "Vyberte složku"
+
+#: kdialogd.cpp:627
+msgid "You can only select local files."
+msgstr "Můžete vybrat pouze místní soubory."
+
+#: kdialogd.cpp:628
+msgid "Remote Files Not Accepted"
+msgstr "Vzdálené soubory nejsou akceptovány."
+
+#: kdialogd.cpp:634
+msgid ""
+"File %1 exits.\n"
+"Do you want to replace it?"
+msgstr ""
+"Soubor %1 existuje.\n"
+"Chcete jej přepsat?"
+
+#: kdialogd.cpp:636
+msgid "File Exists"
+msgstr "Soubor existuje."
+
+#: kdialogd.cpp:637
+msgid "Replace"
+msgstr "Přepiš"
+
+#: kdialogd.cpp:712
+msgid "You can only select local folders."
+msgstr "Můžete vybrat pouze místní složky."
+
+#: kdialogd.cpp:713
+msgid "Remote Folders Not Accepted"
+msgstr "Vzdálené složky nejsou akceptovány."
diff --git a/kdialogd4/po/de.po b/kdialogd4/po/de.po
new file mode 100644
index 0000000..1d36f03
--- /dev/null
+++ b/kdialogd4/po/de.po
@@ -0,0 +1,62 @@
+# translation of kdialogd4.po to Deutsch
+# This file is put in the public domain.
+#
+# Jannick Kuhr <[email protected]>, 2007.
+msgid ""
+msgstr ""
+"Project-Id-Version: kdialogd4\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2007-09-21 15:08+0100\n"
+"PO-Revision-Date: 2007-10-11 13:28+0200\n"
+"Last-Translator: Jannick Kuhr <[email protected]>\n"
+"Language-Team: Deutsch <[email protected]>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.11.4\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+
+#:kdialogd.cpp:331
+msgid "Open"
+msgstr "Öffnen"
+
+#:kdialogd.cpp:334
+msgid "Save As"
+msgstr "Speichern unter"
+
+#:kdialogd.cpp:337
+msgid "Select Folder"
+msgstr "Ordner wählen"
+
+#:kdialogd.cpp:627
+msgid "You can only select local files."
+msgstr "Sie können nur lokale Dateien auswählen."
+
+#:kdialogd.cpp:628
+msgid "Remote Files Not Accepted"
+msgstr "Dateien von Fremdrechnern werden nicht akzeptiert."
+
+#:kdialogd.cpp:634
+msgid ""
+"File %1 exits.\n"
+"Do you want to replace it?"
+msgstr ""
+"Die Datei %1 exisitiert bereits.\n"
+"Wollen Sie sie ersetzen?"
+
+#:kdialogd.cpp:636
+msgid "File Exists"
+msgstr "Datei existiert bereits"
+
+#:kdialogd.cpp:637
+msgid "Replace"
+msgstr "Ersetzen"
+
+#:kdialogd.cpp:712
+msgid "You can only select local folders."
+msgstr "Sie können nur lokale Ordner auswählen."
+
+#:kdialogd.cpp:713
+msgid "Remote Folders Not Accepted"
+msgstr "Ordner von Fremdrechnern werden nicht akzeptiert."
+
diff --git a/kdialogd4/po/en_GB.po b/kdialogd4/po/en_GB.po
new file mode 100644
index 0000000..b811497
--- /dev/null
+++ b/kdialogd4/po/en_GB.po
@@ -0,0 +1,60 @@
+# translation of kdialogd4.po to British English
+# Copyright (C) 2007 Craig Drummond <[email protected]>
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: kdialogd4\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2007-09-21 14:40+0100\n"
+"PO-Revision-Date: 2007-10-05 22:35+0200\n"
+"Last-Translator: Craig Drummond <[email protected]>\n"
+"Language-Team: Craig Drummond <[email protected]>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=iso-8859-1\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#: kdialogd.cpp:328
+msgid "Select Folder"
+msgstr "Select Folder"
+
+#: kdialogd.cpp:573
+msgid "You can only select local files."
+msgstr "You can only select local files."
+
+#: kdialogd.cpp:574
+msgid "Remote Files Not Accepted"
+msgstr "Remote Files Not Accepted"
+
+#: kdialogd.cpp:580
+msgid ""
+"File %1 exits.\n"
+"Do you want to replace it?"
+msgstr ""
+"File %1 exits.\n"
+"Do you want to replace it?"
+
+#: kdialogd.cpp:582
+msgid "File Exists"
+msgstr "File Exists"
+
+#: kdialogd.cpp:667
+msgid "You can only select local folders."
+msgstr "You can only select local folders."
+
+#: kdialogd.cpp:668
+msgid "Remote Folders Not Accepted"
+msgstr "Remote Folders Not Accepted"
+
+#: kdialogd.cpp:677
+msgid "KDialog Daemon"
+msgstr "KDialog Daemon"
+
+#: kdialogd.cpp:678
+msgid "Use KDE dialogs from non-KDE apps."
+msgstr "Use KDE dialogs from non-KDE apps."
+
+#: kdialogd.cpp:680
+msgid "(c) Craig Drummond, 2006-2007"
+msgstr "(c) Craig Drummond, 2006-2007"
diff --git a/kdialogd4/po/es.po b/kdialogd4/po/es.po
new file mode 100644
index 0000000..5de4e58
--- /dev/null
+++ b/kdialogd4/po/es.po
@@ -0,0 +1,56 @@
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2007-09-21 15:08+0100\n"
+"PO-Revision-Date: 2007-10-19 18:06+0200\n"
+"Last-Translator: Marco Antonio Blanco <[email protected]>\n"
+"Language-Team: LANGUAGE <[email protected]>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: Pootle 0.10.1\n"
+
+#: kdialogd.cpp:331
+msgid "Open"
+msgstr "Abrir"
+
+#: kdialogd.cpp:334
+msgid "Save As"
+msgstr "Guardar como"
+
+#: kdialogd.cpp:337
+msgid "Select Folder"
+msgstr "Seleccione carpeta"
+
+#: kdialogd.cpp:627
+msgid "You can only select local files."
+msgstr "Sólo se pueden seleccionar ficheros locales."
+
+#: kdialogd.cpp:628
+msgid "Remote Files Not Accepted"
+msgstr "No se aceptan ficheros remotos"
+
+#: kdialogd.cpp:634
+msgid ""
+"File %1 exits.\n"
+"Do you want to replace it?"
+msgstr ""
+"El fichero %1 existe.\n"
+"¿Quiere sustituirlo?"
+
+#: kdialogd.cpp:636
+msgid "File Exists"
+msgstr "El fichero existe"
+
+#: kdialogd.cpp:637
+msgid "Replace"
+msgstr "Sustituir"
+
+#: kdialogd.cpp:712
+msgid "You can only select local folders."
+msgstr "Sólo se pueden seleccionar carpetas locales."
+
+#: kdialogd.cpp:713
+msgid "Remote Folders Not Accepted"
+msgstr "No se aceptan carpetas remotas"
diff --git a/kdialogd4/po/fr.po b/kdialogd4/po/fr.po
new file mode 100644
index 0000000..b0c500e
--- /dev/null
+++ b/kdialogd4/po/fr.po
@@ -0,0 +1,60 @@
+# translation of kdialogd4.po to French
+# Copyright (C) 2007 aul Thomas <[email protected]>
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: kdialogd4\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2007-09-21 14:40+0100\n"
+"PO-Revision-Date: 2007-10-06 17:54+0200\n"
+"Last-Translator: Paul Thomas <[email protected]>\n"
+"Language-Team: Paul Thomas <[email protected]>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#: kdialogd.cpp:328
+msgid "Select Folder"
+msgstr "Sélectionnez le dossier"
+
+#: kdialogd.cpp:573
+msgid "You can only select local files."
+msgstr "Vous ne pouvez sélectionner que des fichiers locaux."
+
+#: kdialogd.cpp:574
+msgid "Remote Files Not Accepted"
+msgstr "Les fichiers distants ne sont pas acceptés"
+
+#: kdialogd.cpp:580
+msgid ""
+"File %1 exits.\n"
+"Do you want to replace it?"
+msgstr ""
+"Le fichier %1 exite déjà.\n"
+"Voulez-vous le remplacer"
+
+#: kdialogd.cpp:582
+msgid "File Exists"
+msgstr "Le Fichier existe déjà"
+
+#: kdialogd.cpp:667
+msgid "You can only select local folders."
+msgstr "Vous ne pouvez sélectionner que des dossiers locaux."
+
+#: kdialogd.cpp:668
+msgid "Remote Folders Not Accepted"
+msgstr "Les dossiers distants ne sont pas acceptés"
+
+#: kdialogd.cpp:677
+msgid "KDialog Daemon"
+msgstr "KDialog Daemon"
+
+#: kdialogd.cpp:678
+msgid "Use KDE dialogs from non-KDE apps."
+msgstr "Utilisez les dialogues KDE à partir d'applications non-KDE."
+
+#: kdialogd.cpp:680
+msgid "(c) Craig Drummond, 2006-2007"
+msgstr "(c) Craig Drummond, 2006-2007"
diff --git a/kdialogd4/po/kdialogd4.pot b/kdialogd4/po/kdialogd4.pot
new file mode 100644
index 0000000..abc8249
--- /dev/null
+++ b/kdialogd4/po/kdialogd4.pot
@@ -0,0 +1,58 @@
+# SOME DESCRIPTIVE TITLE.
+# This file is put in the public domain.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2007-09-21 15:08+0100\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <[email protected]>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: 8bit\n"
+
+#: kdialogd.cpp:331
+msgid "Open"
+msgstr ""
+
+#: kdialogd.cpp:334
+msgid "Save As"
+msgstr ""
+
+#: kdialogd.cpp:337
+msgid "Select Folder"
+msgstr ""
+
+#: kdialogd.cpp:627
+msgid "You can only select local files."
+msgstr ""
+
+#: kdialogd.cpp:628
+msgid "Remote Files Not Accepted"
+msgstr ""
+
+#: kdialogd.cpp:634
+msgid ""
+"File %1 exits.\n"
+"Do you want to replace it?"
+msgstr ""
+
+#: kdialogd.cpp:636
+msgid "File Exists"
+msgstr ""
+
+#: kdialogd.cpp:637
+msgid "Replace"
+msgstr ""
+
+#: kdialogd.cpp:712
+msgid "You can only select local folders."
+msgstr ""
+
+#: kdialogd.cpp:713
+msgid "Remote Folders Not Accepted"
+msgstr ""
diff --git a/kdialogd4/po/pt_BR.po b/kdialogd4/po/pt_BR.po
new file mode 100644
index 0000000..79a5463
--- /dev/null
+++ b/kdialogd4/po/pt_BR.po
@@ -0,0 +1,60 @@
+# translation of kdialogd4.po to Brazillian Portuguese
+# This file is put in the public domain.
+#
+# Márcio Moraes <[email protected]>, 2007.
+msgid ""
+msgstr ""
+"Project-Id-Version: kdialogd4\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2007-09-21 15:08+0100\n"
+"PO-Revision-Date: 2008-02-26 11:47-0300\n"
+"Last-Translator: Márcio Moraes <[email protected]>\n"
+"Language-Team: Márcio Moraes <[email protected]>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=iso-8859-1\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#: kdialogd.cpp:331
+msgid "Open"
+msgstr "Abrir"
+
+#: kdialogd.cpp:334
+msgid "Save As"
+msgstr "Salvar Como"
+
+#: kdialogd.cpp:337
+msgid "Select Folder"
+msgstr "Selecionar Pasta"
+
+#: kdialogd.cpp:627
+msgid "You can only select local files."
+msgstr "Selecione apenas arquivos locais."
+
+#: kdialogd.cpp:628
+msgid "Remote Files Not Accepted"
+msgstr "Arquivos remotos não são aceitos"
+
+#: kdialogd.cpp:634
+msgid ""
+"File %1 exits.\n"
+"Do you want to replace it?"
+msgstr ""
+"Arquivo %1 exite.\n"
+"Você realmente deseja sobrescrever?"
+
+#: kdialogd.cpp:636
+msgid "File Exists"
+msgstr "Arquivo Existe"
+
+#: kdialogd.cpp:637
+msgid "Replace"
+msgstr "Sobrescrever"
+
+#: kdialogd.cpp:712
+msgid "You can only select local folders."
+msgstr "Selecione apenas pastas locais."
+
+#: kdialogd.cpp:713
+msgid "Remote Folders Not Accepted"
+msgstr "Pastas remotas não são aceitas"
diff --git a/kdialogd4/po/ru.po b/kdialogd4/po/ru.po
new file mode 100644
index 0000000..cf2abd0
--- /dev/null
+++ b/kdialogd4/po/ru.po
@@ -0,0 +1,62 @@
+# translation of ru.po to
+# This file is put in the public domain.
+#
+# Yarodin <[email protected]>, 2008.
+msgid ""
+msgstr ""
+"Project-Id-Version: kdialogd3\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2007-09-21 14:40+0100\n"
+"PO-Revision-Date: 2008-05-01 19:31+0600\n"
+"Last-Translator: Yarodin <[email protected]>\n"
+"Language-Team: Russian <[email protected]>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.11.4\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+
+#: kdialogd.cpp:328
+msgid "Select Folder"
+msgstr "Выбор папки"
+
+#: kdialogd.cpp:573
+msgid "You can only select local files."
+msgstr "Вы можете выбрать только локальные файлы."
+
+#: kdialogd.cpp:574
+msgid "Remote Files Not Accepted"
+msgstr "Файлы на удаленной машине недоступны"
+
+#: kdialogd.cpp:580
+msgid ""
+"File %1 exits.\n"
+"Do you want to replace it?"
+msgstr ""
+"Файл %1 уже существует.\n"
+"Хотите его перезаписать?"
+
+#: kdialogd.cpp:582
+msgid "File Exists"
+msgstr "Файл существует"
+
+#: kdialogd.cpp:667
+msgid "You can only select local folders."
+msgstr "Вы можете выбрать только локальные папки."
+
+#: kdialogd.cpp:668
+msgid "Remote Folders Not Accepted"
+msgstr "Сетевые папки недоступны."
+
+#: kdialogd.cpp:677
+msgid "KDialog Daemon"
+msgstr "KDialog-Демон"
+
+#: kdialogd.cpp:678
+msgid "Use KDE dialogs from non-KDE apps."
+msgstr "Использование KDE диалогов в Не-KDE приложениях."
+
+#: kdialogd.cpp:680
+msgid "(c) Craig Drummond, 2006-2007"
+msgstr "(c) Craig Drummond, 2006-2007"
+
diff --git a/kdialogd4/po/zh_CN.po b/kdialogd4/po/zh_CN.po
new file mode 100644
index 0000000..93d83f7
--- /dev/null
+++ b/kdialogd4/po/zh_CN.po
@@ -0,0 +1,60 @@
+# translation of kdialogd4.po to Chinese Simplified
+# Copyright (C) 2007 Free Software Foundation, Inc.
+#
+# Liang Qi <[email protected]>, 2007.
+msgid ""
+msgstr ""
+"Project-Id-Version: kdialogd4\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2007-09-21 14:40+0100\n"
+"PO-Revision-Date: 2007-10-05 13:20+0200\n"
+"Last-Translator: Liang Qi <[email protected]>\n"
+"Language-Team: zh_CN <[email protected]>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=CHARSET\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#: kdialogd.cpp:328
+msgid "Select Folder"
+msgstr "选择文件夹"
+
+#: kdialogd.cpp:573
+msgid "You can only select local files."
+msgstr "仅允许选择本地文件。"
+
+#: kdialogd.cpp:574
+msgid "Remote Files Not Accepted"
+msgstr "无法接受远程文件"
+
+#: kdialogd.cpp:580
+msgid ""
+"File %1 exits.\n"
+"Do you want to replace it?"
+msgstr ""
+"文件 %1 已经存在。\n"
+"您想替换它么?"
+
+#: kdialogd.cpp:582
+msgid "File Exists"
+msgstr "文件已存在"
+
+#: kdialogd.cpp:667
+msgid "You can only select local folders."
+msgstr "仅允许选择本地文件夹。"
+
+#: kdialogd.cpp:668
+msgid "Remote Folders Not Accepted"
+msgstr "无法接受远程文件夹"
+
+#: kdialogd.cpp:677
+msgid "KDialog Daemon"
+msgstr "KDialog 守护进程"
+
+#: kdialogd.cpp:678
+msgid "Use KDE dialogs from non-KDE apps."
+msgstr "在非 KDE 程序中使用 KDE 对话框。"
+
+#: kdialogd.cpp:680
+msgid "(c) Craig Drummond, 2006-2007"
+msgstr "(c) Craig Drummond, 2006-2007"
diff --git a/kgtk-wrapper b/kgtk-wrapper
new file mode 100755
index 0000000..a46c646
--- /dev/null
+++ b/kgtk-wrapper
@@ -0,0 +1,103 @@
+#!/bin/bash
+
+#
+# This script is part of the KGtk package.
+#
+# (C) Craig Drummond, 2007
+#
+#
+# --
+# Released under the GPL v2 or later
+# --
+#
+# This script attempts to determine which KGtk library (if any) should
+# be used when launching the app
+#
+
+if [ "`locale | grep 'LANG=' | grep -i 'utf-8' | wc -l`" = "0" ] ; then
+ export G_BROKEN_FILENAMES=1
+fi
+
+app=`basename $0`
+useApp=1
+
+if [ "$app" = "kgtk-wrapper" ] ; then
+ app=`basename $1`
+ useApp=0
+fi
+
+dir=$(cd "$(dirname "$0")"; pwd)
+if [ $useApp -eq 1 ] ; then
+ oldPath=$PATH
+ PATH=`echo $PATH | sed s:$dir::g | sed "s|::*|:|g"`
+fi
+
+realApp=`which $app`
+
+if [ -z $realApp ] ; then
+ realApp=`which ./$app`
+fi
+
+if [ $useApp -eq 1 ] ; then
+ PATH=$oldPath
+fi
+
+toolkit=`kreadconfig --file kgtkrc --group 'Apps' --key "$app"`
+
+if [ "$toolkit" = "" ] ; then
+ case $app in
+ eclipse | gimp | inkscape | firefox | kino | iceweasel | swiftfox | azureus | mozilla* )
+ toolkit="gtk2" ;;
+ scribus | scribus-ng | opera | designer-qt3 )
+ toolkit="qt3" ;;
+ designer-qt4 )
+ toolkit="qt4" ;;
+ abiword) # Non-working
+ toolkit="x" ;;
+ esac
+fi
+
+if [ "$toolkit" = "" ] && [ ! -z "$realApp" ] ; then
+ libs=`ldd $realApp 2>/dev/null`
+
+ if [ ! -z "$libs" ] ; then
+
+ if [ "0" != "`echo $libs | grep libgtk-x11-2 | wc -l`" ] ; then
+ toolkit="gtk2"
+ elif [ "0" != "`echo $libs | grep libqt-mt | wc -l`" ] ; then
+ toolkit="qt3"
+ elif [ "0" != "`echo $libs | grep libQtGui | wc -l`" ] ; then
+ toolkit="qt4"
+ fi
+
+ if [ "$toolkit" = "qt3" ] || [ "$toolkit" = "qt4" ] ; then
+ if [ "0" != "`echo $libs | grep libkio | wc -l`" ] ; then
+ toolkit=""
+ fi
+ fi
+
+ if [ -z "`which k$toolkit-wrapper`" ] ; then
+ toolkit=""
+ fi
+ fi
+fi
+
+if [ "$toolkit" = "x" ] ; then
+ toolkit=""
+fi
+
+if [ $useApp -eq 1 ] ; then
+ if [ "$toolkit" = "" ] ; then
+ $realApp "$@"
+ else
+ k$toolkit-wrapper $realApp "$@"
+ fi
+else
+ if [ "$toolkit" = "" ] ; then
+ "$@"
+ else
+ k$toolkit-wrapper "$@"
+ fi
+fi
+
diff --git a/mangled.sh b/mangled.sh
new file mode 100755
index 0000000..01566ad
--- /dev/null
+++ b/mangled.sh
@@ -0,0 +1,23 @@
+#!/bin/bash
+
+# $1 == C++ compiler
+# $2 == output name
+
+echo "class QApplication { public: int exec(); }; int QApplication::exec() { return 0; } " \
+ "class QDialog { public: int exec(); }; int QDialog::exec() { return 0; }" >> "$2.cpp"
+
+$1 -c "$2.cpp" -o "$2.o"
+qdialog=`nm "$2.o" | grep QDialog | grep exec | awk '{print $3}'`
+qapplication=`nm "$2.o" | grep QApplication | grep exec | awk '{print $3}'`
+rm "$2.o" "$2.cpp"
+
+echo "#ifndef __KGTK_MANGLED_H__" > "$2"
+echo "#define __KGTK_MANGLED_H__" >> "$2"
+echo "#define KQT_QDIALOG_EXEC \"$qdialog\"" >> "$2"
+echo "#define KQT_QAPPLICATION_EXEC \"$qapplication\"" >> "$2"
+echo "#endif" >> "$2"
+
+
+
+
+
diff --git a/qt3/CMakeLists.txt b/qt3/CMakeLists.txt
new file mode 100644
index 0000000..b35b6b7
--- /dev/null
+++ b/qt3/CMakeLists.txt
@@ -0,0 +1,24 @@
+set(QT_MT_REQUIRED TRUE)
+find_package(Qt3)
+
+if (QT_INCLUDE_DIR)
+ message("** INFORMATION: Qt3 LD_PRELOAD library will be built.")
+
+ # set(LIB_SUFFIX "" CACHE STRING "Define suffix of directory name (32/64)" )
+ set(LIB_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}" CACHE PATH "The subdirectory relative to the install prefix where libraries will be installed (default is /lib${LIB_SUFFIX})" FORCE)
+
+ ADD_CUSTOM_COMMAND(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/mangled.h
+ COMMAND ${CMAKE_SOURCE_DIR}/mangled.sh ${CMAKE_CXX_COMPILER} ${CMAKE_CURRENT_BINARY_DIR}/mangled.h)
+
+ include_directories (${CMAKE_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_SOURCE_DIR}/common ${CMAKE_BINARY_DIR} ${QT_INCLUDE_DIR})
+ set(kqt3_SRCS kqt3.cpp mangled.h)
+ add_definitions(${QT_DEFINITIONS} -DQT_CLEAN_NAMESPACE -DQT_THREAD_SUPPORT)
+ add_library(kqt3 SHARED ${kqt3_SRCS})
+ target_link_libraries(kqt3 ${QT_LIBRARIES} -lc -ldl)
+ install(TARGETS kqt3 LIBRARY DESTINATION ${LIB_INSTALL_DIR}/kgtk)
+
+ configure_file (kqt3-wrapper.cmake ${CMAKE_CURRENT_BINARY_DIR}/kqt3-wrapper @ONLY)
+ install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/kqt3-wrapper DESTINATION bin)
+else (QT_INCLUDE_DIR)
+ message("** ERROR : Could not locate Qt3 headers, Qt3 LD_PRELOAD library will not be built.")
+endif (QT_INCLUDE_DIR)
diff --git a/qt3/kqt3-wrapper.cmake b/qt3/kqt3-wrapper.cmake
new file mode 100755
index 0000000..e8ba648
--- /dev/null
+++ b/qt3/kqt3-wrapper.cmake
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+#
+# This script is part of the KGtk package.
+#
+# (C) Craig Drummond, 2007
+#
+#
+# --
+# Released under the GPL v2 or later
+# --
+#
+
+app=`basename $0`
+
+if [ "$app" = "kqt3-wrapper" ] ; then
+ LD_PRELOAD=@CMAKE_INSTALL_PREFIX@/lib/kgtk/libkqt3.so:$LD_PRELOAD "$@"
+else
+ dir=`dirname $0`
+ oldPath=$PATH
+ PATH=`echo $PATH | sed s:$dir::g`
+ real=`which $app`
+ PATH=$oldPath
+
+ if [ "$real" != "" ] && [ "`dirname $real`" != "$dir" ] ; then
+ LD_PRELOAD=@CMAKE_INSTALL_PREFIX@/lib@LIB_SUFFIX@/kgtk/libkqt3.so:$LD_PRELOAD $real "$@"
+ fi
+fi
diff --git a/qt3/kqt3.cpp b/qt3/kqt3.cpp
new file mode 100644
index 0000000..833b01d
--- /dev/null
+++ b/qt3/kqt3.cpp
@@ -0,0 +1,671 @@
+/************************************************************************
+ *
+ * All dialogs opened are created and used modal.
+ *
+ ************************************************************************
+ * (C) Craig Drummond, 2006
+ ************************************************************************
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ ************************************************************************/
+
+#define KQT_OVERLOAD_NON_STATIC_FILEDIALOGS
+
+#define _GNU_SOURCE
+#include <dlfcn.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+#include <signal.h>
+#include <sys/wait.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <pwd.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <qstring.h>
+#include <qstringlist.h>
+#include <qwidget.h>
+#include <qapplication.h>
+#ifdef KQT_OVERLOAD_NON_STATIC_FILEDIALOGS
+#include <qcombobox.h>
+#include <qlineedit.h>
+#include <qobjectlist.h>
+#define private public // HACK HACK HACK!!!
+#endif
+#include <qfiledialog.h>
+#include <qthread.h>
+#include <qnamespace.h>
+#include <qeventloop.h>
+#include "connect.h"
+#include "config.h"
+#include "mangled.h"
+
+static bool useKde=false;
+
+#define MAX_LINE_LEN 1024
+#define MAX_APP_NAME_LEN 32
+
+static char * getAppNameFromPid(int pid)
+{
+ static char appName[MAX_APP_NAME_LEN+1]="\0";
+
+ int procFile=-1;
+ char cmdline[MAX_LINE_LEN+1];
+
+ sprintf(cmdline, "/proc/%d/cmdline",pid);
+
+ if(-1!=(procFile=open(cmdline, O_RDONLY)))
+ {
+ if(read(procFile, cmdline, MAX_LINE_LEN)>7)
+ {
+ int len=strlen(cmdline),
+ pos=0;
+
+ for(pos=len-1; pos>0 && cmdline[pos] && cmdline[pos]!='/'; --pos)
+ ;
+
+ if(pos>=0 && pos<len)
+ {
+ strncpy(appName, &cmdline[pos ? pos+1 : 0], MAX_APP_NAME_LEN);
+ appName[MAX_APP_NAME_LEN]='\0';
+ }
+ }
+ close(procFile);
+ }
+
+ return appName;
+}
+
+static const char * getAppName(bool useQt=true)
+{
+ static const char *appName=NULL;
+
+ if(!appName)
+ {
+ const char *a=useQt && qApp ? qApp->argv()[0] : getAppNameFromPid(getpid());
+ const char *slash;
+
+ // Was the cmdline app java? if so, try to use its parent name - just in case
+ // its run from a shell script, etc. - e.g. as eclipse does
+ if(a && 0==strcmp(a, "java"))
+ a=getAppNameFromPid(getppid());
+
+ if(a && a[0]=='\0')
+ a=NULL;
+
+ appName=a && (slash=strrchr(a, '/')) && '\0'!=slash[1]
+ ? &(slash[1])
+ : a ? a : "QtApp";
+ }
+
+ return appName;
+}
+
+int QApplication::exec()
+{
+ static bool init=false;
+
+ if(!init)
+ {
+ connectToKDialogD(getAppName(false));
+ init=true;
+ }
+
+ static int (*realFunction)(void *);
+
+ if(!realFunction)
+ realFunction = (int (*)(void *)) dlsym(RTLD_NEXT, KQT_QAPPLICATION_EXEC);
+ return (int)realFunction(this);
+};
+
+static QString qt2KdeFilter(const QString &f)
+{
+ QString filter;
+ QTextOStream str(&filter);
+ QStringList list(QStringList::split(";;", f));
+ QStringList::Iterator it(list.begin()),
+ end(list.end());
+ bool first=true;
+
+ for(; it!=end; ++it)
+ {
+ int ob=(*it).findRev('('),
+ cb=(*it).findRev(')');
+
+ if(-1!=cb && ob<cb)
+ {
+ if(first)
+ first=false;
+ else
+ str << '\n';
+ str << (*it).mid(ob+1, (cb-ob)-1) << '|' << (*it).mid(0, ob);
+ }
+ }
+
+ return filter;
+}
+
+static void kde2QtFilter(const QString &orig, QString *sel)
+{
+ if(sel)
+ {
+ QStringList list(QStringList::split(";;", orig));
+ QStringList::Iterator it(list.begin()),
+ end(list.end());
+ int pos;
+
+ for(; it!=end; ++it)
+ if(-1!=(pos=(*it).find(*sel)) && pos>0 &&
+ ('('==(*it)[pos-1] || ' '==(*it)[pos-1]) &&
+ (*it).length()>=sel->length()+pos &&
+ (')'==(*it)[pos+sel->length()] || ' '==(*it)[pos+sel->length()]))
+ {
+ *sel=*it;
+ return;
+ }
+ }
+}
+
+#ifdef KQT_OVERLOAD_NON_STATIC_FILEDIALOGS
+#ifdef KQT_USE_QFILEDIALOG_PRIVATE
+// HACK HACK HACK!!!
+
+// KGtk versions <=0.9.1 used this copied QFileDialogPrivate to access the file filters
+// newer versions walk the file dialogs children...
+class QFileDialogPrivate {
+public:
+ ~QFileDialogPrivate();
+
+ QStringList history;
+
+ bool geometryDirty;
+ QComboBox * paths;
+ QComboBox * types;
+};
+#endif
+
+static const QString getFilters(QFileDialog *dlg, bool scribusSave=false)
+{
+ QString filter;
+
+#if KQT_USE_QFILEDIALOG_PRIVATE
+ if(dlg && dlg->d && dlg->d->types)
+ {
+ QTextOStream str(&filter);
+
+ for(int i=0; i<dlg->d->types->count(); ++i)
+ {
+ if(i)
+ str << ";;";
+
+ if(scribusSave && -1!=dlg->d->types->text(i).find("(*.sla *.sla.gz *.scd *scd.gz)"))
+ str << "Compressed Documents (*.sla.gz *scd.gz);;Documents (*.sla *.scd)";
+ else
+ str << dlg->d->types->text(i);
+ }
+ }
+#else
+ if(dlg)
+ {
+ const QObjectList *children=((QObject *)dlg)->children();
+
+ if(children)
+ {
+ QObjectList::ConstIterator it(children->begin()),
+ end(children->end());
+
+ for(; it!=end; ++it)
+ if(::qt_cast<QComboBox *>(*it) && 0==qstrcmp((*it)->name(), "file types"))
+ {
+ QComboBox *types=(QComboBox *)(*it);
+ QTextOStream str(&filter);
+
+ for(int i=0; i<types->count(); ++i)
+ {
+ if(i)
+ str << ";;";
+
+ if(scribusSave && -1!=types->text(i).find("(*.sla *.sla.gz *.scd *scd.gz)"))
+ str << "Compressed Documents (*.sla.gz *scd.gz);;Documents (*.sla *.scd)";
+ else
+ str << types->text(i);
+ }
+
+ break;
+ }
+ }
+ }
+#endif
+
+ return filter;
+}
+
+static QString getCurrentFileName(QFileDialog *dlg)
+{
+ if(dlg)
+ {
+ const QObjectList *children=((QObject *)dlg)->children();
+
+ if(children)
+ {
+ QObjectList::ConstIterator it(children->begin()),
+ end(children->end());
+
+ for(; it!=end; ++it)
+ if(::qt_cast<QLineEdit *>(*it)) // && 0==qstrcmp((*it)->name(), "name/filter editor"))
+ return ((QLineEdit *)(*it))->text();
+ }
+ }
+
+ return QString();
+}
+
+static QString getDir(const QString &f)
+{
+ QString d(f);
+
+ int slashPos=d.findRev('/');
+
+ if(slashPos!=-1)
+ d.remove(slashPos+1, d.length());
+
+ return d;
+}
+#endif
+
+static bool writeString(int fd, const QString &str)
+{
+ QCString utf8(str.utf8());
+ int size=utf8.length()+1;
+
+ return writeBlock(fd, (char *)&size, 4) && writeBlock(fd, utf8.data(), size);
+}
+
+static bool writeBool(int fd, bool b)
+{
+ char bv=b ? 1 : 0;
+
+ return writeBlock(fd, (char *)&bv, 1);
+}
+
+class KQtDialog : public QDialog
+{
+ public:
+
+ KQtDialog(QWidget *parent) : QDialog(parent, "kqt", true, WStyle_NoBorder|WX11BypassWM)
+ {
+ resize(1, 1);
+ setWindowOpacity(0.0);
+ setWindowState(WState_Minimized);
+ move(32768, 32768);
+ }
+
+/* void r() { QDialog::reject(); }*/
+};
+
+class KQtThread : public QThread
+{
+ public:
+
+ KQtThread(QStringList &l, QString &s, int f, KQtDialog *dlg) : dialog(dlg), kdialogdError(false), res(l), selFilter(s), fd(f)
+ { }
+
+ bool readData(QCString &buffer, int size)
+ {
+ buffer.resize(size);
+ return ::readBlock(fd, buffer.data(), size);
+ }
+
+ bool readString(QString &str, int size)
+ {
+ QCString buffer;
+ buffer.resize(size);
+
+ if(!readBlock(fd, buffer.data(), size))
+ return false;
+
+ str=QString::fromUtf8(buffer.data());
+ return true;
+ }
+
+ void run()
+ {
+ QString buffer;
+ int num=0;
+
+ if(readBlock(fd, (char *)&num, 4))
+ {
+ int n;
+
+ for(n=0; n<num && !kdialogdError; ++n)
+ {
+ int size=0;
+
+ if(readBlock(fd, (char *)&size, 4))
+ {
+ if(size>0)
+ {
+ if(readString(buffer, size))
+ {
+ //buffer[size-1]='\0';
+ if('/'==buffer[0])
+ res.append(buffer);
+ else
+ selFilter=buffer;
+ }
+ else
+ kdialogdError=true;
+ }
+ }
+ else
+ kdialogdError=true;
+ }
+ }
+ else
+ kdialogdError=true;
+
+ QApplication::postEvent(dialog, new QCloseEvent);
+ }
+
+ KQtDialog *dialog;
+ bool kdialogdError;
+ QStringList &res;
+ QString &selFilter;
+ int fd;
+};
+
+static bool sendMessage(QWidget *parent, Operation op, QStringList &res, QString &selFilter,
+ const QString &title, const QString &p1, const QString *p2, bool ow)
+{
+ if(connectToKDialogD(getAppName()))
+ {
+ char o=(char)op;
+ int xid=parent ? parent->topLevelWidget()->winId() : qApp->activeWindow()->winId();
+
+ if(writeBlock(kdialogdSocket, &o, 1) &&
+ writeBlock(kdialogdSocket, (char *)&xid, 4) &&
+ writeString(kdialogdSocket, title) &&
+ writeString(kdialogdSocket, p1) &&
+ (p2? writeString(kdialogdSocket, *p2) : true) &&
+ (OP_FILE_SAVE==op ? writeBool(kdialogdSocket, ow) : true))
+ {
+ KQtDialog dlg(parent);
+ KQtThread thread(res, selFilter, kdialogdSocket, &dlg);
+
+ thread.start();
+ dlg.exec();
+ thread.wait();
+ if(thread.kdialogdError)
+ {
+ closeConnection();
+ return false;
+ }
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static QString getTitle(const QString &title, Operation op)
+{
+ if(!title.isEmpty())
+ return title;
+
+ return ".";
+}
+
+static bool openKdeDialog(QWidget *widget, const QString &title, const QString &p1, const QString *p2,
+ Operation op, QStringList &res, QString *selFilter, bool ow=false)
+{
+ QString filter;
+ bool rv=sendMessage(widget, op, res, filter, getTitle(title, op), p1, p2, ow);
+
+ // If we failed to talk to, or start kdialogd, then dont keep trying - just fall back to Qt
+ if(!rv)
+ /*useKde=false*/;
+ else if(selFilter)
+ *selFilter=filter;
+
+ return rv;
+}
+
+static void kqtExit()
+{
+ if(useKde)
+ closeConnection();
+}
+
+static bool kqtInit()
+{
+ static bool initialised=false;
+
+ if(!initialised)
+ {
+ initialised=true;
+ useKde=NULL!=getenv("KDE_FULL_SESSION") && connectToKDialogD(getAppName());
+ if(useKde)
+ atexit(&kqtExit);
+ }
+
+ return useKde;
+}
+
+static QString lastDir;
+
+static void storeLastDir(const QString &f)
+{
+ lastDir=f;
+
+ int slashPos(lastDir.findRev('/'));
+
+ if(slashPos!=-1)
+ lastDir.remove(slashPos+1, lastDir.length());
+}
+
+static const QString & startDir(const QString &d)
+{
+ return d.isEmpty() ? lastDir : d;
+}
+
+QString QFileDialog::getOpenFileName(const QString &initially, const QString &filter,
+ QWidget *parent, const char *name, const QString &caption,
+ QString *selectedFilter, bool resolveSymlinks)
+{
+ QStringList res;
+ QString f(qt2KdeFilter(filter));
+ kqtInit();
+
+ if(openKdeDialog(parent, caption, startDir(initially), &f, OP_FILE_OPEN, res, selectedFilter))
+ {
+ kde2QtFilter(filter, selectedFilter);
+ QString fn(res.first());
+
+ storeLastDir(fn);
+ return fn;
+ }
+ return QString::null;
+}
+
+QString QFileDialog::getSaveFileName(const QString &initially, const QString &filter, QWidget *parent,
+ const char *name, const QString &caption,
+ QString *selectedFilter, bool resolveSymlinks)
+{
+ QStringList res;
+ QString f(qt2KdeFilter(filter));
+ kqtInit();
+
+ if (openKdeDialog(parent, caption, startDir(initially), &f, OP_FILE_SAVE, res, selectedFilter))
+ {
+ kde2QtFilter(filter, selectedFilter);
+ QString fn(res.first());
+
+ storeLastDir(fn);
+ return fn;
+ }
+ return QString::null;
+}
+
+QString QFileDialog::getExistingDirectory(const QString &dir, QWidget *parent, const char *name,
+ const QString &caption, bool dirOnly, bool resolveSymlinks)
+{
+ QStringList res;
+ QString dummy;
+
+ kqtInit();
+
+ return openKdeDialog(parent, caption, dir, NULL, OP_FOLDER, res, &dummy)
+ ? res.first()
+ : QString::null;
+}
+
+QStringList QFileDialog::getOpenFileNames(const QString &filter, const QString &dir, QWidget *parent,
+ const char *name, const QString &caption,
+ QString *selectedFilter, bool resolveSymlinks)
+{
+ QStringList res;
+ QString f(qt2KdeFilter(filter));
+ kqtInit();
+
+ openKdeDialog(parent, caption, startDir(dir), &f, OP_FILE_OPEN_MULTIPLE, res, selectedFilter);
+
+ if(res.count())
+ {
+ kde2QtFilter(filter, selectedFilter);
+ storeLastDir(res.first());
+ }
+ return res;
+}
+
+#ifdef KQT_OVERLOAD_NON_STATIC_FILEDIALOGS
+static QString getFile(const QString &f)
+{
+ QString d(f);
+
+ int slashPos=d.findRev('/');
+
+ if(slashPos!=-1)
+ d.remove(0, slashPos+1);
+
+ return d;
+}
+
+int QDialog::exec()
+{
+ int res=QDialog::Rejected;
+
+ if(inherits("QFileDialog"))
+ {
+ QFileDialog *that=(QFileDialog *)this;
+
+ const QDir *dirp=that->dir();
+ QString dir,
+ selectedFilter,
+ file,
+ initialDir(dirp ? dirp->absPath() : QDir::homeDirPath());
+ QStringList files;
+
+ if(dirp)
+ delete dirp;
+
+ QApplication::eventLoop()->processEvents(QEventLoop::ExcludeUserInput, 1);
+ switch(that->mode())
+ {
+ case QFileDialog::Directory:
+ case QFileDialog::DirectoryOnly:
+ dir=QFileDialog::getExistingDirectory(initialDir, parentWidget(), NULL,
+ caption(), true, true);
+
+ if(!dir.isEmpty())
+ res=QDialog::Accepted;
+ break;
+ case QFileDialog::AnyFile:
+ {
+ QString app(getFile(qApp->argv()[0])),
+ initialFile(getCurrentFileName(that));
+
+ if(!initialFile.isEmpty())
+ initialDir=initialDir+QChar('/')+initialFile;
+
+ file=QFileDialog::getSaveFileName(initialDir,
+ getFilters(that, "scribus"==app ||
+ "scribus-ng"==app),
+ parentWidget(), NULL, caption(), &selectedFilter,
+ true);
+
+ if(!file.isEmpty())
+ res=QDialog::Accepted;
+ break;
+ }
+ case QFileDialog::ExistingFile:
+ file=QFileDialog::getOpenFileName(initialDir, getFilters(that), parentWidget(),
+ NULL, caption(), &selectedFilter, true);
+
+ if(!file.isEmpty())
+ res=QDialog::Accepted;
+ break;
+ case QFileDialog::ExistingFiles:
+ files=QFileDialog::getOpenFileNames(getFilters(that), initialDir, parentWidget(),
+ NULL, caption(), &selectedFilter, true);
+
+ if(files.count())
+ res=QDialog::Accepted;
+ break;
+ }
+
+ if(QDialog::Accepted==res)
+ {
+ if(file.isEmpty() && files.count())
+ file=files.first();
+ if(dir.isEmpty() && !file.isEmpty())
+ dir=getDir(file);
+ if(!dir.isEmpty())
+ that->setDir(dir);
+ if(!selectedFilter.isEmpty())
+ that->setSelectedFilter(selectedFilter);
+ if(!file.isEmpty())
+ that->setSelection(file);
+
+ if(files.count() && that->nameEdit)
+ {
+ QStringList::Iterator it(files.begin()),
+ end(files.end());
+ QString filesStr;
+ QTextOStream str(&filesStr);
+
+ for(; it!=end; ++it)
+ str << "\"" << (*it) << "\" ";
+ that->nameEdit->setText(filesStr);
+ }
+ QApplication::eventLoop()->processEvents(QEventLoop::ExcludeUserInput, 1);
+ }
+ }
+ else
+ {
+ static int (*realFunction)(void *);
+
+ if(!realFunction)
+ realFunction = (int (*)(void *)) dlsym(RTLD_NEXT, KQT_QDIALOG_EXEC);
+ return (int)realFunction(this);
+ }
+
+ return res;
+}
+#endif
diff --git a/qt4/CMakeLists.txt b/qt4/CMakeLists.txt
new file mode 100644
index 0000000..3f8dadb
--- /dev/null
+++ b/qt4/CMakeLists.txt
@@ -0,0 +1,22 @@
+find_package(Qt4)
+
+if (QT4_FOUND)
+ message("** INFORMATION: Qt4 LD_PRELOAD library will be built.")
+ # set(LIB_SUFFIX "" CACHE STRING "Define suffix of directory name (32/64)" )
+ set(LIB_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}" CACHE PATH "The subdirectory relative to the install prefix where libraries will be installed (default is /lib${LIB_SUFFIX})" FORCE)
+
+ ADD_CUSTOM_COMMAND(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/mangled.h
+ COMMAND ${CMAKE_SOURCE_DIR}/mangled.sh ${CMAKE_CXX_COMPILER} ${CMAKE_CURRENT_BINARY_DIR}/mangled.h)
+
+ include_directories (${CMAKE_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_SOURCE_DIR}/common ${CMAKE_BINARY_DIR} ${QT_INCLUDE_DIR})
+ set(kqt4_SRCS kqt4.cpp mangled.h)
+ add_definitions(${QT_DEFINITIONS} -DQT_CLEAN_NAMESPACE -DQT_THREAD_SUPPORT)
+ add_library(kqt4 SHARED ${kqt4_SRCS})
+ target_link_libraries(kqt4 ${QT_QTGUI_LIBRARY} ${QT_QTCORE_LIBRARY} -lc -ldl)
+ install(TARGETS kqt4 LIBRARY DESTINATION ${LIB_INSTALL_DIR}/kgtk)
+
+ configure_file (kqt4-wrapper.cmake ${CMAKE_CURRENT_BINARY_DIR}/kqt4-wrapper @ONLY)
+ install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/kqt4-wrapper DESTINATION bin)
+else (QT4_FOUND)
+ message("** ERROR : Could not locate Qt4 headers, Qt4 LD_PRELOAD library will not be built.")
+endif (QT4_FOUND)
diff --git a/qt4/kqt4-wrapper.cmake b/qt4/kqt4-wrapper.cmake
new file mode 100755
index 0000000..84205b6
--- /dev/null
+++ b/qt4/kqt4-wrapper.cmake
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+#
+# This script is part of the KGtk package.
+#
+# (C) Craig Drummond, 2007
+#
+#
+# --
+# Released under the GPL v2 or later
+# --
+#
+
+app=`basename $0`
+
+if [ "$app" = "kqt4-wrapper" ] ; then
+ LD_PRELOAD=@CMAKE_INSTALL_PREFIX@/lib/kgtk/libkqt4.so:$LD_PRELOAD "$@"
+else
+ dir=`dirname $0`
+ oldPath=$PATH
+ PATH=`echo $PATH | sed s:$dir::g`
+ real=`which $app`
+ PATH=$oldPath
+
+ if [ "$real" != "" ] && [ "`dirname $real`" != "$dir" ] ; then
+ LD_PRELOAD=@CMAKE_INSTALL_PREFIX@/lib@LIB_SUFFIX@/kgtk/libkqt4.so:$LD_PRELOAD $real "$@"
+ fi
+fi
diff --git a/qt4/kqt4.cpp b/qt4/kqt4.cpp
new file mode 100644
index 0000000..4d09f80
--- /dev/null
+++ b/qt4/kqt4.cpp
@@ -0,0 +1,599 @@
+/************************************************************************
+ *
+ * All dialogs opened are created and used modal.
+ *
+ ************************************************************************
+ * (C) Craig Drummond, 2006
+ ************************************************************************
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ ************************************************************************/
+
+#define KQT_OVERLOAD_NON_STATIC_FILEDIALOGS
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+#include <dlfcn.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+#include <signal.h>
+#include <sys/wait.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <pwd.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <QtCore/QString>
+#include <QtCore/QStringList>
+#include <QtGui/QWidget>
+#include <QtGui/QApplication>
+#include <QtCore/QTextStream>
+#include <QtGui/QCloseEvent>
+#include <QtGui/QFileDialog>
+#include <QtCore/QThread>
+#include <QtCore/Qt>
+#include <QtCore/QEventLoop>
+#include "connect.h"
+#include "config.h"
+#include "mangled.h"
+
+static bool useKde=false;
+
+#define MAX_LINE_LEN 1024
+#define MAX_APP_NAME_LEN 32
+
+static char * getAppNameFromPid(int pid)
+{
+ static char appName[MAX_APP_NAME_LEN+1]="\0";
+
+ int procFile=-1;
+ char cmdline[MAX_LINE_LEN+1];
+
+ sprintf(cmdline, "/proc/%d/cmdline",pid);
+
+ if(-1!=(procFile=open(cmdline, O_RDONLY)))
+ {
+ if(read(procFile, cmdline, MAX_LINE_LEN)>7)
+ {
+ int len=strlen(cmdline),
+ pos=0;
+
+ for(pos=len-1; pos>0 && cmdline[pos] && cmdline[pos]!='/'; --pos)
+ ;
+
+ if(pos>=0 && pos<len)
+ {
+ strncpy(appName, &cmdline[pos ? pos+1 : 0], MAX_APP_NAME_LEN);
+ appName[MAX_APP_NAME_LEN]='\0';
+ }
+ }
+ close(procFile);
+ }
+
+ return appName;
+}
+
+static const char * getAppName(bool useQt=true)
+{
+ static const char *appName=NULL;
+
+ if(!appName)
+ {
+ const char *a=useQt && QCoreApplication::arguments().count()
+ ? QCoreApplication::arguments()[0].toLatin1().constData() : getAppNameFromPid(getpid());
+ char *slash;
+
+ // Was the cmdline app java? if so, try to use its parent name - just in case
+ // its run from a shell script, etc. - e.g. as eclipse does
+ if(a && 0==strcmp(a, "java"))
+ a=getAppNameFromPid(getppid());
+
+ if(a && a[0]=='\0')
+ a=NULL;
+
+ appName=a && (slash=strrchr(a, '/')) && '\0'!=slash[1]
+ ? &(slash[1])
+ : a ? a : "Qt4App";
+ }
+
+ return appName;
+}
+
+int QApplication::exec()
+{
+ static bool init=false;
+
+ if(!init)
+ {
+ connectToKDialogD(getAppName(false));
+ init=true;
+ }
+
+ static int (*realFunction)(void);
+
+ if(!realFunction)
+ realFunction = (int (*)(void)) dlsym(RTLD_NEXT, KQT_QAPPLICATION_EXEC);
+ return (int)realFunction();
+};
+
+static QString qt2KdeFilter(const QString &f)
+{
+ QString filter;
+ QTextStream str(&filter, QIODevice::WriteOnly);
+ QStringList list(f.split(";;"));
+ QStringList::Iterator it(list.begin()),
+ end(list.end());
+ bool first=true;
+
+ for(; it!=end; ++it)
+ {
+ int ob=(*it).lastIndexOf('('),
+ cb=(*it).lastIndexOf(')');
+
+ if(-1!=cb && ob<cb)
+ {
+ if(first)
+ first=false;
+ else
+ str << '\n';
+ str << (*it).mid(ob+1, (cb-ob)-1) << '|' << (*it).mid(0, ob);
+ }
+ }
+
+ return filter;
+}
+
+static void kde2QtFilter(const QString &orig, QString *sel)
+{
+ if(sel)
+ {
+ QStringList list(orig.split(";;"));
+ QStringList::Iterator it(list.begin()),
+ end(list.end());
+ int pos;
+
+ for(; it!=end; ++it)
+ if(-1!=(pos=(*it).indexOf(*sel)) && pos>0 &&
+ ('('==(*it)[pos-1] || ' '==(*it)[pos-1]) &&
+ (*it).length()>=sel->length()+pos &&
+ (')'==(*it)[pos+sel->length()] || ' '==(*it)[pos+sel->length()]))
+ {
+ *sel=*it;
+ return;
+ }
+ }
+}
+
+#ifdef KQT_OVERLOAD_NON_STATIC_FILEDIALOGS
+static const QString getFilters(QFileDialog *dlg, bool scribusSave=false)
+{
+ QString filter;
+
+ if(dlg)
+ {
+ QStringList filters(dlg->filters());
+ QStringList::ConstIterator it(filters.begin()),
+ end(filters.end());
+ bool first(true);
+ QTextStream str(&filter, QIODevice::WriteOnly);
+
+ for(; it!=end; ++it)
+ {
+ if(!first)
+ str << ";;";
+
+ if(scribusSave && -1!=(*it).indexOf("(*.sla *.sla.gz *.scd *scd.gz)"))
+ str << "Compressed Documents (*.sla.gz *scd.gz);;Documents (*.sla *.scd)";
+ else
+ str << (*it);
+ first=false;
+ }
+ }
+
+ return filter;
+}
+
+static QString getDir(const QString &f)
+{
+ QString d(f);
+
+ int slashPos=d.lastIndexOf('/');
+
+ if(slashPos!=-1)
+ d.remove(slashPos+1, d.length());
+
+ return d;
+}
+#endif
+
+static bool writeString(int fd, const QString &str)
+{
+ QByteArray utf8(str.toUtf8());
+ int size=utf8.length()+1;
+
+ return writeBlock(fd, (char *)&size, 4) && writeBlock(fd, utf8.data(), size);
+}
+
+static bool writeBool(int fd, bool b)
+{
+ char bv=b ? 1 : 0;
+
+ return writeBlock(fd, (char *)&bv, 1);
+}
+
+class KQtDialog : public QDialog
+{
+ public:
+
+ KQtDialog(QWidget *parent) : QDialog(parent, Qt::FramelessWindowHint|Qt::X11BypassWindowManagerHint)
+ {
+ setModal(true);
+ resize(1, 1);
+ setWindowOpacity(0);
+ setWindowState(Qt::WindowMinimized);
+ move(32768, 32768);
+ }
+
+/* void r() { QDialog::reject(); }*/
+};
+
+class KQtThread : public QThread
+{
+ public:
+
+ KQtThread(QStringList &l, QString &s, int f, KQtDialog *dlg) : dialog(dlg), kdialogdError(false), res(l), selFilter(s), fd(f)
+ { }
+
+ bool readData(QByteArray &buffer, int size)
+ {
+ buffer.resize(size);
+ return ::readBlock(fd, buffer.data(), size);
+ }
+
+ bool readString(QString &str, int size)
+ {
+ QByteArray buffer;
+ buffer.resize(size);
+
+ if(!readBlock(fd, buffer.data(), size))
+ return false;
+
+ str=QString::fromUtf8(buffer.data());
+ return true;
+ }
+
+ void run()
+ {
+ QString buffer;
+ int num=0;
+
+ if(readBlock(fd, (char *)&num, 4))
+ {
+ int n;
+
+ for(n=0; n<num && !kdialogdError; ++n)
+ {
+ int size=0;
+
+ if(readBlock(fd, (char *)&size, 4))
+ {
+ if(size>0)
+ {
+ if(readString(buffer, size))
+ {
+ //buffer[size-1]='\0';
+ if('/'==buffer[0])
+ res.append(buffer);
+ else
+ selFilter=buffer;
+ }
+ else
+ kdialogdError=true;
+ }
+ }
+ else
+ kdialogdError=true;
+ }
+ }
+ else
+ kdialogdError=true;
+ QCoreApplication::postEvent(dialog, new QCloseEvent);
+ }
+
+ KQtDialog *dialog;
+ bool kdialogdError;
+ QStringList &res;
+ QString &selFilter;
+ int fd;
+};
+
+static bool sendMessage(QWidget *parent, Operation op, QStringList &res, QString &selFilter,
+ const QString &title, const QString &p1, const QString *p2, bool ow)
+{
+ if(connectToKDialogD(getAppName()))
+ {
+ char o=(char)op;
+ int xid=parent ? parent->topLevelWidget()->winId() : qApp->activeWindow()->winId();
+
+ if(writeBlock(kdialogdSocket, &o, 1) &&
+ writeBlock(kdialogdSocket, (char *)&xid, 4) &&
+ writeString(kdialogdSocket, title) &&
+ writeString(kdialogdSocket, p1) &&
+ (p2? writeString(kdialogdSocket, *p2) : true) &&
+ (OP_FILE_SAVE==op ? writeBool(kdialogdSocket, ow) : true))
+ {
+ KQtDialog dlg(parent);
+ KQtThread thread(res, selFilter, kdialogdSocket, &dlg);
+
+ thread.start();
+ dlg.exec();
+ thread.wait();
+
+ if(thread.kdialogdError)
+ {
+ closeConnection();
+ return false;
+ }
+ return true;
+ }
+ }
+
+ return false;
+}
+
+static QString getTitle(const QString &title, Operation op)
+{
+ if(!title.isEmpty())
+ return title;
+
+ return ".";
+}
+
+static bool openKdeDialog(QWidget *widget, const QString &title, const QString &p1, const QString *p2,
+ Operation op, QStringList &res, QString *selFilter, bool ow=false)
+{
+ QString filter;
+ bool rv=sendMessage(widget, op, res, filter, getTitle(title, op), p1, p2, ow);
+
+ // If we failed to talk to, or start kdialogd, then dont keep trying - just fall back to Qt
+ if(!rv)
+ /*useKde=false*/;
+ else if(selFilter)
+ *selFilter=filter;
+
+ return rv;
+}
+
+static void kqtExit()
+{
+ if(useKde)
+ closeConnection();
+}
+
+static bool kqtInit()
+{
+ static bool initialised=false;
+
+ if(!initialised)
+ {
+ initialised=true;
+ useKde=NULL!=getenv("KDE_FULL_SESSION") && connectToKDialogD(getAppName());
+ if(useKde)
+ atexit(&kqtExit);
+ }
+
+ return useKde;
+}
+
+static QString lastDir;
+
+static void storeLastDir(const QString &f)
+{
+ lastDir=f;
+
+ int slashPos(lastDir.lastIndexOf('/'));
+
+ if(slashPos!=-1)
+ lastDir.remove(slashPos+1, lastDir.length());
+}
+
+static const QString & startDir(const QString &d)
+{
+ return d.isEmpty() ? lastDir : d;
+}
+
+QString QFileDialog::getOpenFileName(QWidget *parent, const QString &caption,
+ const QString &dir, const QString &filter,
+ QString *selectedFilter, Options options)
+{
+ QStringList res;
+ QString f(qt2KdeFilter(filter));
+ kqtInit();
+
+ if(openKdeDialog(parent, caption, startDir(dir), &f, OP_FILE_OPEN, res, selectedFilter) && res.count())
+ {
+ kde2QtFilter(filter, selectedFilter);
+ QString fn(res.first());
+
+ storeLastDir(fn);
+ return fn;
+ }
+ return QString();
+}
+
+QString QFileDialog::getSaveFileName(QWidget *parent, const QString &caption,
+ const QString &dir, const QString &filter,
+ QString *selectedFilter, Options options)
+{
+ QStringList res;
+ QString f(qt2KdeFilter(filter));
+ kqtInit();
+
+ if (openKdeDialog(parent, caption, startDir(dir), &f, OP_FILE_SAVE, res, selectedFilter) && res.count())
+ {
+ kde2QtFilter(filter, selectedFilter);
+ QString fn(res.first());
+
+ storeLastDir(fn);
+ return fn;
+ }
+ return QString();
+}
+
+QString QFileDialog::getExistingDirectory(QWidget *parent, const QString &caption,
+ const QString &dir, Options options)
+{
+ QStringList res;
+ QString dummy;
+
+ kqtInit();
+
+ return openKdeDialog(parent, caption, dir, NULL, OP_FOLDER, res, &dummy) && res.count()
+ ? res.first()
+ : QString();
+}
+
+QStringList QFileDialog::getOpenFileNames(QWidget *parent, const QString &caption,
+ const QString &dir, const QString &filter,
+ QString *selectedFilter, Options options)
+{
+ QStringList res;
+ QString f(qt2KdeFilter(filter));
+ kqtInit();
+
+ openKdeDialog(parent, caption, startDir(dir), &f, OP_FILE_OPEN_MULTIPLE, res, selectedFilter);
+
+ if(res.count())
+ {
+ kde2QtFilter(filter, selectedFilter);
+ storeLastDir(res.first());
+ }
+ return res;
+}
+
+#ifdef KQT_OVERLOAD_NON_STATIC_FILEDIALOGS
+static QString getFile(const QString &f)
+{
+ QString d(f);
+
+ int slashPos=d.lastIndexOf('/');
+
+ if(slashPos!=-1)
+ d.remove(0, slashPos+1);
+
+ return d;
+}
+
+int QDialog::exec()
+{
+ int res=QDialog::Rejected;
+
+ if(inherits("QFileDialog"))
+ {
+ QFileDialog *that=(QFileDialog *)this;
+
+ QDir directory(that->directory());
+ QString dir,
+ selectedFilter,
+ file;
+ QStringList files;
+
+ QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents, 1);
+ switch(that->fileMode())
+ {
+ case QFileDialog::Directory:
+ case QFileDialog::DirectoryOnly:
+ dir=QFileDialog::getExistingDirectory(parentWidget(), windowTitle(), directory.absolutePath(), 0);
+
+ if(!dir.isEmpty())
+ res=QDialog::Accepted;
+ break;
+ case QFileDialog::AnyFile:
+ {
+ QString app(getFile(qApp->argv()[0])),
+ initial(directory.absolutePath());
+/*
+TODO!!!
+ initialFile(getCurrentFileName(that));
+
+ if(!initialFile.isEmpty())
+ initial=initial+QLatin1Char('/')+initialFile;
+*/
+
+ file=QFileDialog::getSaveFileName(parentWidget(), windowTitle(), initial,
+ getFilters(that, "scribus"==app ||
+ "scribus-ng"==app), &selectedFilter, 0);
+ if(!file.isEmpty())
+ res=QDialog::Accepted;
+ break;
+ }
+ case QFileDialog::ExistingFile:
+ file=QFileDialog::getOpenFileName(parentWidget(), windowTitle(), directory.absolutePath(),
+ getFilters(that), &selectedFilter, 0);
+
+ if(!file.isEmpty())
+ res=QDialog::Accepted;
+ break;
+ case QFileDialog::ExistingFiles:
+ files=QFileDialog::getOpenFileNames(parentWidget(), windowTitle(), directory.absolutePath(),
+ getFilters(that), &selectedFilter, 0);
+
+ if(files.count())
+ res=QDialog::Accepted;
+ break;
+ }
+
+ if(QDialog::Accepted==res)
+ {
+ if(file.isEmpty() && files.count())
+ file=files.first();
+ if(dir.isEmpty() && !file.isEmpty())
+ dir=getDir(file);
+ if(!dir.isEmpty())
+ that->setDirectory(dir);
+ if(!selectedFilter.isEmpty())
+ that->selectFilter(selectedFilter);
+ if(!file.isEmpty())
+ that->selectFile(getFile(file));
+
+ if(files.count())
+ {
+ QStringList::ConstIterator it(files.begin()),
+ end(files.end());
+
+ for(; it!=end; ++it)
+ that->selectFile(getFile(*it));
+ }
+ }
+ QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents, 1);
+ }
+ else
+ {
+ static int (*realFunction)(void *);
+
+ if(!realFunction)
+ realFunction = (int (*)(void *)) dlsym(RTLD_NEXT, KQT_QDIALOG_EXEC);
+ return (int)realFunction(this);
+ }
+
+ return res;
+}
+#endif