diff options
author | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-09-09 20:27:19 +0000 |
---|---|---|
committer | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-09-09 20:27:19 +0000 |
commit | c6ca83d07d95e076b09bd802f66ba72d363b0235 (patch) | |
tree | f13000febb0c9c5a5da621b4bba53ba3eace022e /qt4 | |
download | kgtk-qt3-c6ca83d07d95e076b09bd802f66ba72d363b0235.tar.gz kgtk-qt3-c6ca83d07d95e076b09bd802f66ba72d363b0235.zip |
* Added kgtk-qt3
* Slight kpowersave message cleanup
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/kgtk-qt3@1173604 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'qt4')
-rw-r--r-- | qt4/CMakeLists.txt | 22 | ||||
-rwxr-xr-x | qt4/kqt4-wrapper.cmake | 29 | ||||
-rw-r--r-- | qt4/kqt4.cpp | 599 |
3 files changed, 650 insertions, 0 deletions
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 +# +# Craig.Drummond@lycos.co.uk +# +# -- +# 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 |