diff options
Diffstat (limited to 'kdialog/kdialog.cpp')
-rw-r--r-- | kdialog/kdialog.cpp | 687 |
1 files changed, 687 insertions, 0 deletions
diff --git a/kdialog/kdialog.cpp b/kdialog/kdialog.cpp new file mode 100644 index 000000000..2dafb5789 --- /dev/null +++ b/kdialog/kdialog.cpp @@ -0,0 +1,687 @@ +// +// Copyright (C) 1998 Matthias Hoelzer <[email protected]> +// Copyright (C) 2002 David Faure <[email protected]> +// Copyright (C) 2005 Brad Hards <[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 the7 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. +// + + +#include <fcntl.h> +#include <unistd.h> +#include <stdlib.h> +#include <iostream> + +#include <qptrlist.h> +#include <qfile.h> +#include <qdatastream.h> +#include <qregexp.h> +#include <qtimer.h> +#include <kmessagebox.h> +#include <kapplication.h> +#include <kdebug.h> +//#include <ktopwidget.h> +#include <kmainwindow.h> +#include <kpassivepopup.h> +#include <krecentdocument.h> +#include <kapplication.h> + +#include "widgets.h" + +#include <klocale.h> +#include <qdialog.h> +#include <kcmdlineargs.h> +#include <kaboutdata.h> +#include <kfiledialog.h> +#include <kicondialog.h> +#include <kdirselectdialog.h> + +#if defined Q_WS_X11 && ! defined K_WS_QTONLY +#include <netwm.h> +#endif + +#include <assert.h> + +using namespace std; + +#if defined(Q_WS_X11) +extern "C" { int XSetTransientForHint( Display *, unsigned long, unsigned long ); } +#endif // Q_WS_X11 + +static KCmdLineOptions options[] = +{ + { "yesno <text>", I18N_NOOP("Question message box with yes/no buttons"), 0 }, + { "yesnocancel <text>", I18N_NOOP("Question message box with yes/no/cancel buttons"), 0 }, + { "warningyesno <text>", I18N_NOOP("Warning message box with yes/no buttons"), 0 }, + { "warningcontinuecancel <text>", I18N_NOOP("Warning message box with continue/cancel buttons"), 0 }, + { "warningyesnocancel <text>", I18N_NOOP("Warning message box with yes/no/cancel buttons"), 0 }, + { "sorry <text>", I18N_NOOP("'Sorry' message box"), 0 }, + { "error <text>", I18N_NOOP("'Error' message box"), 0 }, + { "msgbox <text>", I18N_NOOP("Message Box dialog"), 0 }, + { "inputbox <text> <init>", I18N_NOOP("Input Box dialog"), 0 }, + { "password <text>", I18N_NOOP("Password dialog"), 0 }, + { "textbox <file> [width] [height]", I18N_NOOP("Text Box dialog"), 0 }, + { "textinputbox <text> <init> [width] [height]", I18N_NOOP("Text Input Box dialog"), 0 }, + { "combobox <text> [tag item] [tag item] ...", I18N_NOOP("ComboBox dialog"), 0 }, + { "menu <text> [tag item] [tag item] ...", I18N_NOOP("Menu dialog"), 0 }, + { "checklist <text> [tag item status] ...", I18N_NOOP("Check List dialog"), 0 }, + { "radiolist <text> [tag item status] ...", I18N_NOOP("Radio List dialog"), 0 }, + { "passivepopup <text> <timeout>", I18N_NOOP("Passive Popup"), 0 }, + { "getopenfilename [startDir] [filter]", I18N_NOOP("File dialog to open an existing file"), 0 }, + { "getsavefilename [startDir] [filter]", I18N_NOOP("File dialog to save a file"), 0 }, + { "getexistingdirectory [startDir]", I18N_NOOP("File dialog to select an existing directory"), 0 }, + { "getopenurl [startDir] [filter]", I18N_NOOP("File dialog to open an existing URL"), 0 }, + { "getsaveurl [startDir] [filter]", I18N_NOOP("File dialog to save a URL"), 0 }, + { "geticon [group] [context]", I18N_NOOP("Icon chooser dialog"), 0 }, + { "progressbar <text> [totalsteps]", I18N_NOOP("Progress bar dialog, returns a DCOP reference for communication"), 0}, + + // TODO gauge stuff, reading values from stdin + + { "title <text>", I18N_NOOP("Dialog title"), 0 }, + { "default <text>", I18N_NOOP("Default entry to use for combobox and menu"), 0 }, + { "multiple", I18N_NOOP("Allows the --getopenurl and --getopenfilename options to return multiple files"), 0 }, + { "separate-output", I18N_NOOP("Return list items on separate lines (for checklist option and file open with --multiple)"), 0 }, + { "print-winid", I18N_NOOP("Outputs the winId of each dialog"), 0 }, + { "embed <winid>", I18N_NOOP("Makes the dialog transient for an X app specified by winid"), 0 }, + { "dontagain <file:entry>", I18N_NOOP("Config file and option name for saving the \"dont-show/ask-again\" state"), 0 }, + + { "+[arg]", I18N_NOOP("Arguments - depending on main option"), 0 }, + KCmdLineLastOption +}; + +// this class hooks into the eventloop and outputs the id +// of shown dialogs or makes the dialog transient for other winids. +// Will destroy itself on app exit. +class WinIdEmbedder: public QObject +{ +public: + WinIdEmbedder(bool printID, WId winId): + QObject(qApp), print(printID), id(winId) + { + if (qApp) + qApp->installEventFilter(this); + } +protected: + bool eventFilter(QObject *o, QEvent *e); +private: + bool print; + WId id; +}; + +bool WinIdEmbedder::eventFilter(QObject *o, QEvent *e) +{ + if (e->type() == QEvent::Show && o->isWidgetType() + && o->inherits("KDialog")) + { + QWidget *w = static_cast<QWidget*>(o); + if (print) + cout << "winId: " << w->winId() << endl; +#ifdef Q_WS_X11 + if (id) + XSetTransientForHint(w->x11Display(), w->winId(), id); +#endif + deleteLater(); // WinIdEmbedder is not needed anymore after the first dialog was shown + return false; + } + return QObject::eventFilter(o, e); +} + +static void outputStringList(QStringList list, bool separateOutput) +{ + if ( separateOutput) { + for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) { + cout << (*it).local8Bit().data() << endl; + } + } else { + for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) { + cout << (*it).local8Bit().data() << " "; + } + cout << endl; + } +} + +static int directCommand(KCmdLineArgs *args) +{ + QString title; + bool separateOutput = FALSE; + bool printWId = args->isSet("print-winid"); + bool embed = args->isSet("embed"); + QString defaultEntry; + + // --title text + KCmdLineArgs *qtargs = KCmdLineArgs::parsedArgs("qt"); // --title is a qt option + if(qtargs->isSet("title")) { + title = QFile::decodeName(qtargs->getOption("title")); + } + + // --separate-output + if (args->isSet("separate-output")) + { + separateOutput = TRUE; + } + if (printWId || embed) + { + WId id = 0; + if (embed) { + bool ok; + long l = args->getOption("embed").toLong(&ok); + if (ok) + id = (WId)l; + } + (void)new WinIdEmbedder(printWId, id); + } + + // --yesno and other message boxes + KMessageBox::DialogType type = (KMessageBox::DialogType) 0; + QCString option; + if (args->isSet("yesno")) { + option = "yesno"; + type = KMessageBox::QuestionYesNo; + } + else if (args->isSet("yesnocancel")) { + option = "yesnocancel"; + type = KMessageBox::QuestionYesNoCancel; + } + else if (args->isSet("warningyesno")) { + option = "warningyesno"; + type = KMessageBox::WarningYesNo; + } + else if (args->isSet("warningcontinuecancel")) { + option = "warningcontinuecancel"; + type = KMessageBox::WarningContinueCancel; + } + else if (args->isSet("warningyesnocancel")) { + option = "warningyesnocancel"; + type = KMessageBox::WarningYesNoCancel; + } + else if (args->isSet("sorry")) { + option = "sorry"; + type = KMessageBox::Sorry; + } + else if (args->isSet("error")) { + option = "error"; + type = KMessageBox::Error; + } + else if (args->isSet("msgbox")) { + option = "msgbox"; + type = KMessageBox::Information; + } + + if ( !option.isEmpty() ) + { + KConfig* dontagaincfg = NULL; + // --dontagain + QString dontagain; // QString::null + if (args->isSet("dontagain")) + { + QString value = args->getOption("dontagain"); + QStringList values = QStringList::split( ':', value ); + if( values.count() == 2 ) + { + dontagaincfg = new KConfig( values[ 0 ] ); + KMessageBox::setDontShowAskAgainConfig( dontagaincfg ); + dontagain = values[ 1 ]; + } + else + qDebug( "Incorrect --dontagain!" ); + } + int ret; + + QString text = QString::fromLocal8Bit(args->getOption( option )); + int pos; + while ((pos = text.find( QString::fromLatin1("\\n") )) >= 0) + { + text.replace(pos, 2, QString::fromLatin1("\n")); + } + + if ( type == KMessageBox::WarningContinueCancel ) { + /* TODO configurable button texts*/ + ret = KMessageBox::messageBox( 0, type, text, title, KStdGuiItem::cont(), + KStdGuiItem::no(), dontagain ); + } else { + ret = KMessageBox::messageBox( 0, type, text, title /*, TODO configurable button texts*/, + KStdGuiItem::yes(), KStdGuiItem::no(), dontagain ); + } + delete dontagaincfg; + // ret is 1 for Ok, 2 for Cancel, 3 for Yes, 4 for No and 5 for Continue. + // We want to return 0 for ok, yes and continue, 1 for no and 2 for cancel + return (ret == KMessageBox::Ok || ret == KMessageBox::Yes || ret == KMessageBox::Continue) ? 0 + : ( ret == KMessageBox::No ? 1 : 2 ); + } + + // --inputbox text [init] + if (args->isSet("inputbox")) + { + QString result; + QString init; + + if (args->count() > 0) + init = QString::fromLocal8Bit(args->arg(0)); + + bool retcode = Widgets::inputBox(0, title, QString::fromLocal8Bit(args->getOption("inputbox")), init, result); + cout << result.local8Bit().data() << endl; + return retcode ? 0 : 1; + } + + + // --password text + if (args->isSet("password")) + { + QCString result; + bool retcode = Widgets::passwordBox(0, title, QString::fromLocal8Bit(args->getOption("password")), result); + cout << result.data() << endl; + return retcode ? 0 : 1; + } + + // --passivepopup + if (args->isSet("passivepopup")) + { + int duration = 0; + if (args->count() > 0) + duration = 1000 * QString::fromLocal8Bit(args->arg(0)).toInt(); + if (duration == 0) + duration = 10000; + KPassivePopup *popup = KPassivePopup::message( KPassivePopup::Balloon, // style + title, + QString::fromLocal8Bit( args->getOption("passivepopup") ), + 0, // icon + (QWidget*)0UL, // parent + 0, // name + duration ); + QTimer *timer = new QTimer(); + QObject::connect( timer, SIGNAL( timeout() ), kapp, SLOT( quit() ) ); + QObject::connect( popup, SIGNAL( clicked() ), kapp, SLOT( quit() ) ); + timer->start( duration, TRUE ); + +#ifdef Q_WS_X11 + if ( ! kapp->geometryArgument().isEmpty()) { + int x, y; + int w, h; + int m = XParseGeometry( kapp->geometryArgument().latin1(), &x, &y, (unsigned int*)&w, (unsigned int*)&h); + if ( (m & XNegative) ) + x = KApplication::desktop()->width() + x - w; + if ( (m & YNegative) ) + y = KApplication::desktop()->height() + y - h; + popup->setAnchor( QPoint(x, y) ); + } +#endif + kapp->exec(); + return 0; + } + + // --textbox file [width] [height] + if (args->isSet("textbox")) + { + int w = 0; + int h = 0; + + if (args->count() == 2) { + w = QString::fromLocal8Bit(args->arg(0)).toInt(); + h = QString::fromLocal8Bit(args->arg(1)).toInt(); + } + + return Widgets::textBox(0, w, h, title, QString::fromLocal8Bit(args->getOption("textbox"))); + } + + // --textinputbox file [width] [height] + if (args->isSet("textinputbox")) + { + int w = 400; + int h = 200; + + if (args->count() == 4) { + w = QString::fromLocal8Bit(args->arg(2)).toInt(); + h = QString::fromLocal8Bit(args->arg(3)).toInt(); + } + + QStringList list; + list.append(QString::fromLocal8Bit(args->getOption("textinputbox"))); + + if (args->count() >= 1) { + for (int i = 0; i < args->count(); i++) + list.append(QString::fromLocal8Bit(args->arg(i))); + } + + QCString result; + int ret = Widgets::textInputBox(0, w, h, title, list, result); + cout << result.data() << endl; + return ret; + } + + // --combobox <text> [tag item] [tag item] ..." + if (args->isSet("combobox")) { + QStringList list; + if (args->count() >= 2) { + for (int i = 0; i < args->count(); i++) { + list.append(QString::fromLocal8Bit(args->arg(i))); + } + QString text = QString::fromLocal8Bit(args->getOption("combobox")); + if (args->isSet("default")) { + defaultEntry = args->getOption("default"); + } + QString result; + bool retcode = Widgets::comboBox(0, title, text, list, defaultEntry, result); + cout << result.local8Bit().data() << endl; + return retcode ? 0 : 1; + } + return -1; + } + + // --menu text [tag item] [tag item] ... + if (args->isSet("menu")) { + QStringList list; + if (args->count() >= 2) { + for (int i = 0; i < args->count(); i++) { + list.append(QString::fromLocal8Bit(args->arg(i))); + } + QString text = QString::fromLocal8Bit(args->getOption("menu")); + if (args->isSet("default")) { + defaultEntry = args->getOption("default"); + } + QString result; + bool retcode = Widgets::listBox(0, title, text, list, defaultEntry, result); + if (1 == retcode) { // OK was selected + cout << result.local8Bit().data() << endl; + } + return retcode ? 0 : 1; + } + return -1; + } + + // --checklist text [tag item status] [tag item status] ... + if (args->isSet("checklist")) { + QStringList list; + if (args->count() >= 3) { + for (int i = 0; i < args->count(); i++) { + list.append(QString::fromLocal8Bit(args->arg(i))); + } + + QString text = QString::fromLocal8Bit(args->getOption("checklist")); + QStringList result; + + bool retcode = Widgets::checkList(0, title, text, list, separateOutput, result); + + unsigned int i; + for (i=0; i<result.count(); i++) + if (!result[i].local8Bit().isEmpty()) { + cout << result[i].local8Bit().data() << endl; + } + exit( retcode ? 0 : 1 ); + } + return -1; + } + + // --radiolist text width height menuheight [tag item status] + if (args->isSet("radiolist")) { + QStringList list; + if (args->count() >= 3) { + for (int i = 0; i < args->count(); i++) { + list.append(QString::fromLocal8Bit(args->arg(i))); + } + + QString text = QString::fromLocal8Bit(args->getOption("radiolist")); + QString result; + bool retcode = Widgets::radioBox(0, title, text, list, result); + cout << result.local8Bit().data() << endl; + exit( retcode ? 0 : 1 ); + } + return -1; + } + + // getopenfilename [startDir] [filter] + if (args->isSet("getopenfilename")) { + QString startDir; + QString filter; + startDir = QString::fromLocal8Bit(args->getOption("getopenfilename")); + if (args->count() >= 1) { + filter = QString::fromLocal8Bit(args->arg(0)); + } + KFileDialog dlg(startDir, filter, 0, "filedialog", true); + dlg.setOperationMode( KFileDialog::Opening ); + + if (args->isSet("multiple")) { + dlg.setMode(KFile::Files | KFile::LocalOnly); + } else { + dlg.setMode(KFile::File | KFile::LocalOnly); + } + Widgets::handleXGeometry(&dlg); + kapp->setTopWidget( &dlg ); + dlg.setCaption(title.isNull() ? i18n("Open") : title); + dlg.exec(); + + if (args->isSet("multiple")) { + QStringList result = dlg.selectedFiles(); + if ( !result.isEmpty() ) { + outputStringList( result, separateOutput ); + return 0; + } + } else { + QString result = dlg.selectedFile(); + if (!result.isEmpty()) { + cout << result.local8Bit().data() << endl; + return 0; + } + } + return 1; // cancelled + } + + + // getsaveurl [startDir] [filter] + // getsavefilename [startDir] [filter] + if ( (args->isSet("getsavefilename") ) || (args->isSet("getsaveurl") ) ) { + QString startDir; + QString filter; + if ( args->isSet("getsavefilename") ) { + startDir = QString::fromLocal8Bit(args->getOption("getsavefilename")); + } else { + startDir = QString::fromLocal8Bit(args->getOption("getsaveurl")); + } + if (args->count() >= 1) { + filter = QString::fromLocal8Bit(args->arg(0)); + } + // copied from KFileDialog::getSaveFileName(), so we can add geometry + bool specialDir = ( startDir.at(0) == ':' ); + KFileDialog dlg( specialDir ? startDir : QString::null, filter, 0, "filedialog", true ); + if ( !specialDir ) + dlg.setSelection( startDir ); + dlg.setOperationMode( KFileDialog::Saving ); + Widgets::handleXGeometry(&dlg); + kapp->setTopWidget( &dlg ); + dlg.setCaption(title.isNull() ? i18n("Save As") : title); + dlg.exec(); + + if ( args->isSet("getsaveurl") ) { + KURL result = dlg.selectedURL(); + if ( result.isValid()) { + + cout << result.url().local8Bit().data() << endl; + return 0; + } + } else { // getsavefilename + QString result = dlg.selectedFile(); + if (!result.isEmpty()) { + KRecentDocument::add(result); + cout << result.local8Bit().data() << endl; + return 0; + } + } + return 1; // cancelled + } + + // getexistingdirectory [startDir] + if (args->isSet("getexistingdirectory")) { + QString startDir; + startDir = QString::fromLocal8Bit(args->getOption("getexistingdirectory")); + QString result; +#ifdef Q_WS_WIN + result = QFileDialog::getExistingDirectory(startDir, 0, "getExistingDirectory", + title, true, true); +#else + KURL url; + KDirSelectDialog myDialog( startDir, true, 0, + "kdirselect dialog", true ); + + kapp->setTopWidget( &myDialog ); + + Widgets::handleXGeometry(&myDialog); + if ( !title.isNull() ) + myDialog.setCaption( title ); + + if ( myDialog.exec() == QDialog::Accepted ) + url = myDialog.url(); + + if ( url.isValid() ) + result = url.path(); +#endif + if (!result.isEmpty()) { + cout << result.local8Bit().data() << endl; + return 0; + } + return 1; // cancelled + } + + // getopenurl [startDir] [filter] + if (args->isSet("getopenurl")) { + QString startDir; + QString filter; + startDir = QString::fromLocal8Bit(args->getOption("getopenurl")); + if (args->count() >= 1) { + filter = QString::fromLocal8Bit(args->arg(0)); + } + KFileDialog dlg(startDir, filter, 0, "filedialog", true); + dlg.setOperationMode( KFileDialog::Opening ); + + if (args->isSet("multiple")) { + dlg.setMode(KFile::Files); + } else { + dlg.setMode(KFile::File); + } + Widgets::handleXGeometry(&dlg); + kapp->setTopWidget( &dlg ); + dlg.setCaption(title.isNull() ? i18n("Open") : title); + dlg.exec(); + + if (args->isSet("multiple")) { + KURL::List result = dlg.selectedURLs(); + if ( !result.isEmpty() ) { + outputStringList( result.toStringList(), separateOutput ); + return 0; + } + } else { + KURL result = dlg.selectedURL(); + if (!result.isEmpty()) { + cout << result.url().local8Bit().data() << endl; + return 0; + } + } + return 1; // cancelled + } + + // geticon [group] [context] + if (args->isSet("geticon")) { + QString groupStr, contextStr; + groupStr = QString::fromLocal8Bit(args->getOption("geticon")); + if (args->count() >= 1) { + contextStr = QString::fromLocal8Bit(args->arg(0)); + } + KIcon::Group group = KIcon::NoGroup; + if ( groupStr == QString::fromLatin1( "Desktop" ) ) + group = KIcon::Desktop; + else if ( groupStr == QString::fromLatin1( "Toolbar" ) ) + group = KIcon::Toolbar; + else if ( groupStr == QString::fromLatin1( "MainToolbar" ) ) + group = KIcon::MainToolbar; + else if ( groupStr == QString::fromLatin1( "Small" ) ) + group = KIcon::Small; + else if ( groupStr == QString::fromLatin1( "Panel" ) ) + group = KIcon::Panel; + else if ( groupStr == QString::fromLatin1( "User" ) ) + group = KIcon::User; + KIcon::Context context = KIcon::Any; + // From kicontheme.cpp + if ( contextStr == QString::fromLatin1( "Devices" ) ) + context = KIcon::Device; + else if ( contextStr == QString::fromLatin1( "MimeTypes" ) ) + context = KIcon::MimeType; + else if ( contextStr == QString::fromLatin1( "FileSystems" ) ) + context = KIcon::FileSystem; + else if ( contextStr == QString::fromLatin1( "Applications" ) ) + context = KIcon::Application; + else if ( contextStr == QString::fromLatin1( "Actions" ) ) + context = KIcon::Action; + + KIconDialog dlg(0, "icon dialog"); + kapp->setTopWidget( &dlg ); + dlg.setup( group, context); + if (!title.isNull()) + dlg.setCaption(title); + Widgets::handleXGeometry(&dlg); + + QString result = dlg.openDialog(); + + if (!result.isEmpty()) { + cout << result.local8Bit().data() << endl; + return 0; + } + return 1; // cancelled + } + + // --progressbar text totalsteps + if (args->isSet("progressbar")) + { + cout << "DCOPRef(kdialog-" << getpid() << ",ProgressDialog)" << endl; + if (fork()) + exit(0); + close(1); + + int totalsteps = 100; + QString text = QString::fromLocal8Bit(args->getOption("progressbar")); + + if (args->count() == 1) + totalsteps = QString::fromLocal8Bit(args->arg(0)).toInt(); + + return Widgets::progressBar(0, title, text, totalsteps) ? 1 : 0; + } + + KCmdLineArgs::usage(); + return -2; // NOTREACHED +} + + +int main(int argc, char *argv[]) +{ + KAboutData aboutData( "kdialog", I18N_NOOP("KDialog"), + "1.0", I18N_NOOP( "KDialog can be used to show nice dialog boxes from shell scripts" ), + KAboutData::License_GPL, + "(C) 2000, Nick Thompson"); + aboutData.addAuthor("David Faure", I18N_NOOP("Current maintainer"),"[email protected]"); + aboutData.addAuthor("Brad Hards", 0, "[email protected]"); + aboutData.addAuthor("Nick Thompson",0, 0/*"[email protected]" bounces*/); + aboutData.addAuthor("Matthias Hölzer",0,"[email protected]"); + aboutData.addAuthor("David Gümbel",0,"[email protected]"); + aboutData.addAuthor("Richard Moore",0,"[email protected]"); + aboutData.addAuthor("Dawit Alemayehu",0,"[email protected]"); + + KCmdLineArgs::init(argc, argv, &aboutData); + KCmdLineArgs::addCmdLineOptions( options ); // Add our own options. + + KApplication app; + + KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); + + // execute direct kdialog command + return directCommand(args); +} + |