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 /qt3/kqt3.cpp | |
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 'qt3/kqt3.cpp')
-rw-r--r-- | qt3/kqt3.cpp | 671 |
1 files changed, 671 insertions, 0 deletions
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 |