1//
2// Copyright (C) 1998 Matthias Hoelzer <hoelzer@kde.org>
3// Copyright (C) 2002 David Faure <faure@kde.org>
4// Copyright (C) 2005 Brad Hards <bradh@frogmouth.net>
5// Copyright (C) 2008 by Dmitry Suzdalev <dimsuz@gmail.com>
6// Copyright (C) 2011 Kai Uwe Broulik <kde@privat.broulik.de>
7//
8// This program is free software; you can redistribute it and/or modify
9// it under the terms of the GNU General Public License as published by
10// the Free Software Foundation; either version 2 of the License, or
11// (at your option) any later version.
12//
13// This program is distributed in the hope that it will be useful,
14// but WITHOUT ANY WARRANTY; without even the7 implied warranty of
15// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16// GNU General Public License for more details.
17//
18// You should have received a copy of the GNU General Public License
19// along with this program; if not, write to the Free Software
20// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21//
22
23#include <QDate>
24#include <kdebug.h>
25#include "widgets.h"
26
27#include <kmessagebox.h>
28#include <kapplication.h>
29#include <kpassivepopup.h>
30#include <krecentdocument.h>
31#include <kcmdlineargs.h>
32#include <kaboutdata.h>
33#include <kfiledialog.h>
34#include <kfileitem.h>
35#include <kicondialog.h>
36#include <kdirselectdialog.h>
37#include <kcolordialog.h>
38#include <kwindowsystem.h>
39#include <kiconloader.h>
40#include <klocale.h>
41
42#include <QtCore/QTimer>
43#include <QDesktopWidget>
44
45#include <iostream>
46
47#if defined Q_WS_X11 && ! defined K_WS_QTONLY
48#include <netwm.h>
49#endif
50
51#include "../config-apps.h"
52#ifdef QT_QTDBUS_FOUND
53#include <QtDBus/QDBusConnection>
54#include <QtDBus/QDBusConnectionInterface>
55#endif
56
57#ifdef Q_WS_WIN
58#include <QFileDialog>
59#endif
60#include <unistd.h>
61
62using namespace std;
63
64// this class hooks into the eventloop and outputs the id
65// of shown dialogs or makes the dialog transient for other winids.
66// Will destroy itself on app exit.
67class WinIdEmbedder: public QObject
68{
69public:
70 WinIdEmbedder(bool printID, WId winId):
71 QObject(qApp), print(printID), id(winId)
72 {
73 if (qApp)
74 qApp->installEventFilter(this);
75 }
76protected:
77 bool eventFilter(QObject *o, QEvent *e);
78private:
79 bool print;
80 WId id;
81};
82
83bool WinIdEmbedder::eventFilter(QObject *o, QEvent *e)
84{
85 if (e->type() == QEvent::Show && o->isWidgetType()
86 && o->inherits("KDialog"))
87 {
88 QWidget *w = static_cast<QWidget*>(o);
89 if (print)
90 cout << "winId: " << w->winId() << endl;
91 if (id)
92 KWindowSystem::setMainWindow(w, id);
93 deleteLater(); // WinIdEmbedder is not needed anymore after the first dialog was shown
94 return false;
95 }
96 return QObject::eventFilter(o, e);
97}
98
99/**
100 * Display a passive notification popup using the D-Bus interface, if possible.
101 * @return true if the notification was successfully sent, false otherwise.
102 */
103bool sendVisualNotification(const QString &text, const QString &title, const QString &icon, int timeout)
104{
105#ifdef QT_QTDBUS_FOUND
106 const QString dbusServiceName = "org.freedesktop.Notifications";
107 const QString dbusInterfaceName = "org.freedesktop.Notifications";
108 const QString dbusPath = "/org/freedesktop/Notifications";
109
110 // check if service already exists on plugin instantiation
111 QDBusConnectionInterface* interface = QDBusConnection::sessionBus().interface();
112
113 if (!interface || !interface->isServiceRegistered(dbusServiceName)) {
114 //kDebug() << dbusServiceName << "D-Bus service not registered";
115 return false;
116 }
117
118 if (timeout == 0)
119 timeout = 10 * 1000;
120
121 QDBusMessage m = QDBusMessage::createMethodCall(dbusServiceName, dbusPath, dbusInterfaceName, "Notify");
122 QList<QVariant> args;
123
124 args.append("kdialog"); // app_name
125 args.append(0U); // replaces_id
126 args.append(icon); // app_icon
127 args.append(title); // summary
128 args.append(text); // body
129 args.append(QStringList()); // actions - unused for plain passive popups
130 args.append(QVariantMap()); // hints - unused atm
131 args.append(timeout); // expire timout
132
133 m.setArguments(args);
134
135 QDBusMessage replyMsg = QDBusConnection::sessionBus().call(m);
136 if(replyMsg.type() == QDBusMessage::ReplyMessage) {
137 if (!replyMsg.arguments().isEmpty()) {
138 return true;
139 }
140 // Not displaying any error messages as this is optional for kdialog
141 // and KPassivePopup is a perfectly valid fallback.
142 //else {
143 // kDebug() << "Error: received reply with no arguments.";
144 //}
145 } else if (replyMsg.type() == QDBusMessage::ErrorMessage) {
146 //kDebug() << "Error: failed to send D-Bus message";
147 //kDebug() << replyMsg;
148 } else {
149 //kDebug() << "Unexpected reply type";
150 }
151#endif
152 return false;
153}
154
155static void outputStringList(const QStringList &list, bool separateOutput)
156{
157 if ( separateOutput) {
158 for ( QStringList::ConstIterator it = list.begin(); it != list.end(); ++it ) {
159 cout << (*it).toLocal8Bit().data() << endl;
160 }
161 } else {
162 for ( QStringList::ConstIterator it = list.begin(); it != list.end(); ++it ) {
163 cout << (*it).toLocal8Bit().data() << " ";
164 }
165 cout << endl;
166 }
167}
168
169
170KGuiItem configuredYes(const QString &text)
171{
172 return KGuiItem( text, "dialog-ok" );
173}
174
175KGuiItem configuredNo(const QString &text)
176{
177 return KGuiItem( text, "process-stop" );
178}
179
180KGuiItem configuredCancel(const QString &text)
181{
182 return KGuiItem( text, "dialog-cancel" );
183}
184
185KGuiItem configuredContinue(const QString &text)
186{
187 return KGuiItem( text, "arrow-right" );
188}
189
190static int directCommand(KCmdLineArgs *args)
191{
192 QString title;
193 bool separateOutput = false;
194 bool printWId = args->isSet("print-winid");
195 QString defaultEntry;
196
197 // --title text
198 KCmdLineArgs *qtargs = KCmdLineArgs::parsedArgs("qt"); // --title is a qt option
199 if(qtargs->isSet("title")) {
200 title = qtargs->getOption("title");
201 }
202
203 // --separate-output
204 if (args->isSet("separate-output"))
205 {
206 separateOutput = true;
207 }
208
209 WId winid = 0;
210 bool attach = args->isSet("attach");
211 if(attach) {
212#ifdef Q_WS_WIN
213 winid = reinterpret_cast<WId>(args->getOption("attach").toLong(&attach, 0)); //C style parsing. If the string begins with "0x", base 16 is used; if the string begins with "0", base 8 is used; otherwise, base 10 is used.
214#else
215 winid = args->getOption("attach").toLong(&attach, 0); //C style parsing. If the string begins with "0x", base 16 is used; if the string begins with "0", base 8 is used; otherwise, base 10 is used.
216#endif
217 } else if(args->isSet("embed")) {
218 /* KDialog originally used --embed for attaching the dialog box. However this is misleading and so we changed to --attach.
219 * For consistancy, we silently map --embed to --attach */
220 attach = true;
221#ifdef Q_WS_WIN
222 winid = reinterpret_cast<WId>(args->getOption("embed").toLong(&attach, 0)); //C style parsing. If the string begins with "0x", base 16 is used; if the string begins with "0", base 8 is used; otherwise, base 10 is used.
223#else
224 winid = args->getOption("embed").toLong(&attach, 0); //C style parsing. If the string begins with "0x", base 16 is used; if the string begins with "0", base 8 is used; otherwise, base 10 is used.
225#endif
226 }
227
228 if (printWId || attach)
229 {
230 (void)new WinIdEmbedder(printWId, winid);
231 }
232
233 // button labels
234 // Initialize with default labels
235 KGuiItem yesButton = KStandardGuiItem::yes();
236 KGuiItem noButton = KStandardGuiItem::no();
237 KGuiItem cancelButton = KStandardGuiItem::cancel();
238 KGuiItem continueButton = KStandardGuiItem::cont();
239
240 // Customize the asked labels
241 if (args->isSet("yes-label")) {
242 yesButton = configuredYes( args->getOption("yes-label") );
243 }
244 if (args->isSet("no-label")) {
245 noButton = configuredNo( args->getOption("no-label") );
246 }
247 if (args->isSet("cancel-label")) {
248 cancelButton = configuredCancel( args->getOption("cancel-label") );
249 }
250 if (args->isSet("continue-label")) {
251 continueButton = configuredContinue( args->getOption("continue-label") );
252 }
253
254 // --yesno and other message boxes
255 KMessageBox::DialogType type = (KMessageBox::DialogType) 0;
256 QByteArray option;
257 if (args->isSet("yesno")) {
258 option = "yesno";
259 type = KMessageBox::QuestionYesNo;
260 }
261 else if (args->isSet("yesnocancel")) {
262 option = "yesnocancel";
263 type = KMessageBox::QuestionYesNoCancel;
264 }
265 else if (args->isSet("warningyesno")) {
266 option = "warningyesno";
267 type = KMessageBox::WarningYesNo;
268 }
269 else if (args->isSet("warningcontinuecancel")) {
270 option = "warningcontinuecancel";
271 type = KMessageBox::WarningContinueCancel;
272 }
273 else if (args->isSet("warningyesnocancel")) {
274 option = "warningyesnocancel";
275 type = KMessageBox::WarningYesNoCancel;
276 }
277 else if (args->isSet("sorry")) {
278 option = "sorry";
279 type = KMessageBox::Sorry;
280 }
281 else if (args->isSet("detailedsorry")) {
282 option = "detailedsorry";
283 }
284 else if (args->isSet("error")) {
285 option = "error";
286 type = KMessageBox::Error;
287 }
288 else if (args->isSet("detailederror")) {
289 option = "detailederror";
290 }
291 else if (args->isSet("msgbox")) {
292 option = "msgbox";
293 type = KMessageBox::Information;
294 }
295
296 if ( !option.isEmpty() )
297 {
298 KConfig* dontagaincfg = NULL;
299 // --dontagain
300 QString dontagain; // QString()
301 if (args->isSet("dontagain"))
302 {
303 QString value = args->getOption("dontagain");
304 QStringList values = value.split( ':', QString::SkipEmptyParts );
305 if( values.count() == 2 )
306 {
307 dontagaincfg = new KConfig( values[ 0 ] );
308 KMessageBox::setDontShowAskAgainConfig( dontagaincfg );
309 dontagain = values[ 1 ];
310 }
311 else
312 qDebug( "Incorrect --dontagain!" );
313 }
314 int ret = 0;
315
316 QString text = Widgets::parseString(args->getOption(option));
317
318 QString details;
319 if (args->count() == 1) {
320 details = Widgets::parseString(args->arg(0));
321 }
322
323 if ( type == KMessageBox::WarningContinueCancel ) {
324 ret = KMessageBox::messageBox( 0, type, text, title, continueButton,
325 noButton, cancelButton, dontagain );
326 } else if (option == "detailedsorry") {
327 KMessageBox::detailedSorry( 0, text, details, title );
328 } else if (option == "detailederror") {
329 KMessageBox::detailedError( 0, text, details, title );
330 } else {
331 ret = KMessageBox::messageBox( 0, type, text, title,
332 yesButton, noButton, cancelButton, dontagain );
333 }
334 delete dontagaincfg;
335 // ret is 1 for Ok, 2 for Cancel, 3 for Yes, 4 for No and 5 for Continue.
336 // We want to return 0 for ok, yes and continue, 1 for no and 2 for cancel
337 return (ret == KMessageBox::Ok || ret == KMessageBox::Yes || ret == KMessageBox::Continue) ? 0
338 : ( ret == KMessageBox::No ? 1 : 2 );
339 }
340
341 // --inputbox text [init]
342 if (args->isSet("inputbox"))
343 {
344 QString result;
345 QString init;
346
347 if (args->count() > 0)
348 init = args->arg(0);
349
350 const bool retcode = Widgets::inputBox(0, title, args->getOption("inputbox"), init, result);
351 cout << result.toLocal8Bit().data() << endl;
352 return retcode ? 0 : 1;
353 }
354
355
356 // --password text
357 if (args->isSet("password"))
358 {
359 QString result;
360 const bool retcode = Widgets::passwordBox(0, title, args->getOption("password"), result);
361 cout << qPrintable(result) << endl;
362 return retcode ? 0 : 1;
363 }
364
365 // --passivepopup
366 if (args->isSet("passivepopup"))
367 {
368 int timeout = 0;
369 if (args->count() > 0) {
370 timeout = 1000 * args->arg(0).toInt();
371 }
372
373 if (timeout < 0) {
374 timeout = -1;
375 }
376
377 // since --icon is a kde option, we need to parse the kde options here as well
378 KCmdLineArgs *kdeargs = KCmdLineArgs::parsedArgs("kde");
379
380 // Use --icon parameter for passivepopup as well
381 QString icon;
382 if (kdeargs->isSet("icon")) {
383 icon = kdeargs->getOption("icon");
384 } else {
385 icon = "dialog-information"; // Use generic (i)-icon if none specified
386 }
387
388 // try to use more stylish notifications
389 if (sendVisualNotification(Widgets::parseString(args->getOption("passivepopup")), title, icon, timeout))
390 return 0;
391
392 // ...did not work, use KPassivePopup as fallback
393
394 // parse timeout time again, so it does not auto-close the fallback (timer cannot handle -1 time)
395 if (args->count() > 0) {
396 timeout = 1000 * args->arg(0).toInt();
397 }
398 if (timeout <= 0) {
399 timeout = 10*1000; // 10 seconds should be a decent time for auto-closing (you can override this using a parameter)
400 }
401
402 QPixmap passiveicon;
403 if (kdeargs->isSet("icon")) { // Only show icon if explicitly requested
404 passiveicon = KIconLoader::global()->loadIcon(icon, KIconLoader::Dialog);
405 }
406 KPassivePopup *popup = KPassivePopup::message( KPassivePopup::Boxed, // style
407 title,
408 Widgets::parseString(args->getOption("passivepopup")),
409 passiveicon,
410 (QWidget*)0UL, // parent
411 timeout );
412 KDialog::centerOnScreen( popup );
413 QTimer *timer = new QTimer();
414 QObject::connect( timer, SIGNAL(timeout()), qApp, SLOT(quit()) );
415 QObject::connect( popup, SIGNAL(clicked()), qApp, SLOT(quit()) );
416 timer->setSingleShot( true );
417 timer->start( timeout );
418
419#ifdef Q_WS_X11
420 QString geometry;
421 KCmdLineArgs *args = KCmdLineArgs::parsedArgs("kde");
422 if (args && args->isSet("geometry"))
423 geometry = args->getOption("geometry");
424 if ( !geometry.isEmpty()) {
425 int x, y;
426 int w, h;
427 int m = XParseGeometry( geometry.toLatin1(), &x, &y, (unsigned int*)&w, (unsigned int*)&h);
428 if ( (m & XNegative) )
429 x = KApplication::desktop()->width() + x - w;
430 if ( (m & YNegative) )
431 y = KApplication::desktop()->height() + y - h;
432 popup->setAnchor( QPoint(x, y) );
433 }
434#endif
435 qApp->exec();
436 return 0;
437 }
438
439 // --textbox file [width] [height]
440 if (args->isSet("textbox"))
441 {
442 int w = 0;
443 int h = 0;
444
445 if (args->count() == 2) {
446 w = args->arg(0).toInt();
447 h = args->arg(1).toInt();
448 }
449
450 return Widgets::textBox(0, w, h, title, args->getOption("textbox"));
451 }
452
453 // --textinputbox file [width] [height]
454 if (args->isSet("textinputbox"))
455 {
456 int w = 400;
457 int h = 200;
458
459 if (args->count() >= 3) {
460 w = args->arg(1).toInt();
461 h = args->arg(2).toInt();
462 }
463
464 QString init;
465 if (args->count() >= 1) {
466 init = Widgets::parseString(args->arg(0));
467 }
468
469 QString result;
470 int ret = Widgets::textInputBox(0, w, h, title, Widgets::parseString(args->getOption("textinputbox")), init, result);
471 cout << qPrintable(result) << endl;
472 return ret;
473 }
474
475 // --combobox <text> item [item] ..."
476 if (args->isSet("combobox")) {
477 QStringList list;
478 if (args->count() >= 1) {
479 for (int i = 0; i < args->count(); i++) {
480 list.append(args->arg(i));
481 }
482 const QString text = Widgets::parseString(args->getOption("combobox"));
483 if (args->isSet("default")) {
484 defaultEntry = args->getOption("default");
485 }
486 QString result;
487 const bool retcode = Widgets::comboBox(0, title, text, list, defaultEntry, result);
488 cout << result.toLocal8Bit().data() << endl;
489 return retcode ? 0 : 1;
490 }
491 return -1;
492 }
493
494 // --menu text [tag item] [tag item] ...
495 if (args->isSet("menu")) {
496 QStringList list;
497 if (args->count() >= 2) {
498 for (int i = 0; i < args->count(); i++) {
499 list.append(args->arg(i));
500 }
501 const QString text = Widgets::parseString(args->getOption("menu"));
502 if (args->isSet("default")) {
503 defaultEntry = args->getOption("default");
504 }
505 QString result;
506 const bool retcode = Widgets::listBox(0, title, text, list, defaultEntry, result);
507 if (1 == retcode) { // OK was selected
508 cout << result.toLocal8Bit().data() << endl;
509 }
510 return retcode ? 0 : 1;
511 }
512 return -1;
513 }
514
515 // --checklist text [tag item status] [tag item status] ...
516 if (args->isSet("checklist")) {
517 QStringList list;
518 if (args->count() >= 3) {
519 for (int i = 0; i < args->count(); i++) {
520 list.append(args->arg(i));
521 }
522
523 const QString text = Widgets::parseString(args->getOption("checklist"));
524 QStringList result;
525
526 const bool retcode = Widgets::checkList(0, title, text, list, separateOutput, result);
527
528 for (int i=0; i<result.count(); i++)
529 if (!result.at(i).toLocal8Bit().isEmpty()) {
530 cout << result.at(i).toLocal8Bit().data() << endl;
531 }
532 exit( retcode ? 0 : 1 );
533 }
534 return -1;
535 }
536
537 // --radiolist text width height menuheight [tag item status]
538 if (args->isSet("radiolist")) {
539 QStringList list;
540 if (args->count() >= 3) {
541 for (int i = 0; i < args->count(); i++) {
542 list.append(args->arg(i));
543 }
544
545 const QString text = Widgets::parseString(args->getOption("radiolist"));
546 QString result;
547 const bool retcode = Widgets::radioBox(0, title, text, list, result);
548 cout << result.toLocal8Bit().data() << endl;
549 exit( retcode ? 0 : 1 );
550 }
551 return -1;
552 }
553
554 // getopenfilename [startDir] [filter]
555 if (args->isSet("getopenfilename")) {
556 QString startDir;
557 QString filter;
558 startDir = args->getOption("getopenfilename");
559 if (args->count() >= 1) {
560 filter = Widgets::parseString(args->arg(0));
561 }
562 KFileDialog dlg( startDir, filter, 0 );
563 dlg.setOperationMode( KFileDialog::Opening );
564
565 if (args->isSet("multiple")) {
566 dlg.setMode(KFile::Files | KFile::LocalOnly);
567 } else {
568 dlg.setMode(KFile::File | KFile::LocalOnly);
569 }
570 Widgets::handleXGeometry(&dlg);
571 kapp->setTopWidget( &dlg );
572 dlg.setCaption(title.isEmpty() ? i18nc("@title:window", "Open") : title);
573 dlg.exec();
574
575 if (args->isSet("multiple")) {
576 QStringList result = dlg.selectedFiles();
577 if ( !result.isEmpty() ) {
578 outputStringList( result, separateOutput );
579 return 0;
580 }
581 } else {
582 QString result = dlg.selectedFile();
583 if (!result.isEmpty()) {
584 cout << result.toLocal8Bit().data() << endl;
585 return 0;
586 }
587 }
588 return 1; // canceled
589 }
590
591
592 // getsaveurl [startDir] [filter]
593 // getsavefilename [startDir] [filter]
594 if ( (args->isSet("getsavefilename") ) || (args->isSet("getsaveurl") ) ) {
595 QString startDir;
596 QString filter;
597 if ( args->isSet("getsavefilename") ) {
598 startDir = args->getOption("getsavefilename");
599 } else {
600 startDir = args->getOption("getsaveurl");
601 }
602 if (args->count() >= 1) {
603 filter = Widgets::parseString(args->arg(0));
604 }
605 // copied from KFileDialog::getSaveFileName(), so we can add geometry
606 bool specialDir = ( startDir.at(0) == ':' );
607 if ( !specialDir ) {
608 KFileItem kfi(KFileItem::Unknown, KFileItem::Unknown, KUrl(startDir));
609 specialDir = kfi.isDir();
610 }
611 KFileDialog dlg( specialDir ? startDir : QString(), filter, 0 );
612 if ( !specialDir )
613 dlg.setSelection( startDir );
614 dlg.setOperationMode( KFileDialog::Saving );
615 Widgets::handleXGeometry(&dlg);
616 kapp->setTopWidget( &dlg );
617 dlg.setCaption(title.isEmpty() ? i18nc("@title:window", "Save As") : title);
618 dlg.exec();
619
620 if ( args->isSet("getsaveurl") ) {
621 KUrl result = dlg.selectedUrl();
622 if ( result.isValid()) {
623
624 cout << result.url().toLocal8Bit().data() << endl;
625 return 0;
626 }
627 } else { // getsavefilename
628 QString result = dlg.selectedFile();
629 if (!result.isEmpty()) {
630 KRecentDocument::add(result);
631 cout << result.toLocal8Bit().data() << endl;
632 return 0;
633 }
634 }
635 return 1; // canceled
636 }
637
638 // getexistingdirectory [startDir]
639 if (args->isSet("getexistingdirectory")) {
640 QString startDir;
641 startDir = args->getOption("getexistingdirectory");
642 QString result;
643#ifdef Q_WS_WIN
644 result = QFileDialog::getExistingDirectory( 0, title, startDir,
645 QFileDialog::DontResolveSymlinks |
646 QFileDialog::ShowDirsOnly);
647#else
648 KUrl url;
649 KDirSelectDialog myDialog( startDir, true, 0 );
650
651 kapp->setTopWidget( &myDialog );
652
653 Widgets::handleXGeometry(&myDialog);
654 if ( !title.isEmpty() )
655 myDialog.setCaption( title );
656
657 if ( myDialog.exec() == QDialog::Accepted )
658 url = myDialog.url();
659
660 if ( url.isValid() )
661 result = url.path();
662#endif
663 if (!result.isEmpty()) {
664 cout << result.toLocal8Bit().data() << endl;
665 return 0;
666 }
667 return 1; // canceled
668 }
669
670 // getopenurl [startDir] [filter]
671 if (args->isSet("getopenurl")) {
672 QString startDir;
673 QString filter;
674 startDir = args->getOption("getopenurl");
675 if (args->count() >= 1) {
676 filter = Widgets::parseString(args->arg(0));
677 }
678 KFileDialog dlg( startDir, filter, 0 );
679 dlg.setOperationMode( KFileDialog::Opening );
680
681 if (args->isSet("multiple")) {
682 dlg.setMode(KFile::Files);
683 } else {
684 dlg.setMode(KFile::File);
685 }
686 Widgets::handleXGeometry(&dlg);
687 kapp->setTopWidget( &dlg );
688 dlg.setCaption(title.isEmpty() ? i18nc("@title:window", "Open") : title);
689 dlg.exec();
690
691 if (args->isSet("multiple")) {
692 KUrl::List result = dlg.selectedUrls();
693 if ( !result.isEmpty() ) {
694 outputStringList( result.toStringList(), separateOutput );
695 return 0;
696 }
697 } else {
698 KUrl result = dlg.selectedUrl();
699 if (!result.isEmpty()) {
700 cout << result.url().toLocal8Bit().data() << endl;
701 return 0;
702 }
703 }
704 return 1; // canceled
705 }
706
707 // geticon [group] [context]
708 if (args->isSet("geticon")) {
709 QString groupStr, contextStr;
710 groupStr = args->getOption("geticon");
711 if (args->count() >= 1) {
712 contextStr = args->arg(0);
713 }
714 const KIconLoader::Group group =
715 ( groupStr == QLatin1String( "Desktop" ) ) ? KIconLoader::Desktop :
716 ( groupStr == QLatin1String( "Toolbar" ) ) ? KIconLoader::Toolbar :
717 ( groupStr == QLatin1String( "MainToolbar" ) ) ? KIconLoader::MainToolbar :
718 ( groupStr == QLatin1String( "Small" ) ) ? KIconLoader::Small :
719 ( groupStr == QLatin1String( "Panel" ) ) ? KIconLoader::Panel :
720 ( groupStr == QLatin1String( "Dialog" ) ) ? KIconLoader::Dialog :
721 ( groupStr == QLatin1String( "User" ) ) ? KIconLoader::User :
722 /* else */ KIconLoader::NoGroup;
723
724 const KIconLoader::Context context =
725 ( contextStr == QLatin1String( "Action" ) ) ? KIconLoader::Action :
726 ( contextStr == QLatin1String( "Application" ) ) ? KIconLoader::Application :
727 ( contextStr == QLatin1String( "Device" ) ) ? KIconLoader::Device :
728 ( contextStr == QLatin1String( "FileSystem" ) ) ? KIconLoader::FileSystem :
729 ( contextStr == QLatin1String( "MimeType" ) ) ? KIconLoader::MimeType :
730 ( contextStr == QLatin1String( "Animation" ) ) ? KIconLoader::Animation :
731 ( contextStr == QLatin1String( "Category" ) ) ? KIconLoader::Category :
732 ( contextStr == QLatin1String( "Emblem" ) ) ? KIconLoader::Emblem :
733 ( contextStr == QLatin1String( "Emote" ) ) ? KIconLoader::Emote :
734 ( contextStr == QLatin1String( "International" ) ) ? KIconLoader::International :
735 ( contextStr == QLatin1String( "Place" ) ) ? KIconLoader::Place :
736 ( contextStr == QLatin1String( "StatusIcon" ) ) ? KIconLoader::StatusIcon :
737 // begin: KDE3 compatibility (useful?)
738 ( contextStr == QLatin1String( "Devices" ) ) ? KIconLoader::Device :
739 ( contextStr == QLatin1String( "MimeTypes" ) ) ? KIconLoader::MimeType :
740 ( contextStr == QLatin1String( "FileSystems" ) ) ? KIconLoader::FileSystem :
741 ( contextStr == QLatin1String( "Applications" ) ) ? KIconLoader::Application :
742 ( contextStr == QLatin1String( "Actions" ) ) ? KIconLoader::Action :
743 // end: KDE3 compatibility
744 /* else */ KIconLoader::Any;
745
746 KIconDialog dlg((QWidget*)0L);
747 kapp->setTopWidget( &dlg );
748 dlg.setup( group, context);
749 dlg.setIconSize(KIconLoader::SizeHuge);
750
751 if (!title.isEmpty())
752 dlg.setCaption(title);
753
754 Widgets::handleXGeometry(&dlg);
755
756 QString result = dlg.openDialog();
757
758 if (!result.isEmpty()) {
759 cout << result.toLocal8Bit().data() << endl;
760 return 0;
761 }
762 return 1; // canceled
763 }
764
765 // --progressbar text totalsteps
766 if (args->isSet("progressbar"))
767 {
768 cout << "org.kde.kdialog-" << getpid() << " /ProgressDialog" << endl;
769 if (fork())
770 _exit(0);
771 close(1);
772
773 int totalsteps = 100;
774 const QString text = Widgets::parseString(args->getOption("progressbar"));
775
776 if (args->count() == 1)
777 totalsteps = args->arg(0).toInt();
778
779 return Widgets::progressBar(0, title, text, totalsteps) ? 1 : 0;
780 }
781
782 // --getcolor
783 if (args->isSet("getcolor")) {
784 KColorDialog dlg((QWidget*)0L, true);
785
786 if (args->isSet("default")) {
787 defaultEntry = args->getOption("default");
788 dlg.setColor(defaultEntry);
789 }
790 Widgets::handleXGeometry(&dlg);
791 kapp->setTopWidget(&dlg);
792 dlg.setCaption(title.isEmpty() ? i18nc("@title:window", "Choose Color") : title);
793
794 if (dlg.exec() == KColorDialog::Accepted) {
795 QString result;
796 if (dlg.color().isValid()) {
797 result = dlg.color().name();
798 } else {
799 result = dlg.defaultColor().name();
800 }
801 cout << result.toLocal8Bit().data() << endl;
802 return 0;
803 }
804 return 1; // cancelled
805 }
806 if (args->isSet("slider"))
807 {
808 int miniValue = 0;
809 int maxValue = 0;
810 int step = 0;
811 const QString text = Widgets::parseString(args->getOption("slider"));
812 if ( args->count() == 3 )
813 {
814 miniValue = args->arg(0).toInt();
815 maxValue = args->arg( 1 ).toInt();
816 step = args->arg( 2 ).toInt();
817 }
818 int result = 0;
819
820 const bool returnCode = Widgets::slider(0, title, text, miniValue, maxValue, step, result);
821 if ( returnCode )
822 cout << result << endl;
823 return returnCode;
824 }
825 if (args->isSet("calendar"))
826 {
827 const QString text = Widgets::parseString(args->getOption("calendar"));
828 QDate result;
829
830 const bool returnCode = Widgets::calendar(0, title, text, result);
831 if ( returnCode )
832 cout << result.toString().toLocal8Bit().data() << endl;
833 return returnCode;
834 }
835
836 KCmdLineArgs::usage();
837 return -2; // NOTREACHED
838}
839
840
841int main(int argc, char *argv[])
842{
843 KAboutData aboutData( "kdialog", 0, ki18n("KDialog"),
844 "1.0", ki18n( "KDialog can be used to show nice dialog boxes from shell scripts" ),
845 KAboutData::License_GPL,
846 ki18n("(C) 2000, Nick Thompson"));
847 aboutData.addAuthor(ki18n("David Faure"), ki18n("Current maintainer"),"faure@kde.org");
848 aboutData.addAuthor(ki18n("Brad Hards"), KLocalizedString(), "bradh@frogmouth.net");
849 aboutData.addAuthor(ki18n("Nick Thompson"),KLocalizedString(), 0/*"nickthompson@lucent.com" bounces*/);
850 aboutData.addAuthor(ki18n("Matthias Hölzer"),KLocalizedString(),"hoelzer@kde.org");
851 aboutData.addAuthor(ki18n("David Gümbel"),KLocalizedString(),"david.guembel@gmx.net");
852 aboutData.addAuthor(ki18n("Richard Moore"),KLocalizedString(),"rich@kde.org");
853 aboutData.addAuthor(ki18n("Dawit Alemayehu"),KLocalizedString(),"adawit@kde.org");
854 aboutData.addAuthor(ki18n("Kai Uwe Broulik"),KLocalizedString(),"kde@privat.broulik.de");
855 aboutData.setProgramIconName("system-run");
856
857 KCmdLineArgs::init(argc, argv, &aboutData);
858
859 KCmdLineOptions options;
860 options.add("yesno <text>", ki18n("Question message box with yes/no buttons"));
861 options.add("yesnocancel <text>", ki18n("Question message box with yes/no/cancel buttons"));
862 options.add("warningyesno <text>", ki18n("Warning message box with yes/no buttons"));
863 options.add("warningcontinuecancel <text>", ki18n("Warning message box with continue/cancel buttons"));
864 options.add("warningyesnocancel <text>", ki18n("Warning message box with yes/no/cancel buttons"));
865 options.add("yes-label <text>", ki18n("Use text as Yes button label"));
866 options.add("no-label <text>", ki18n("Use text as No button label"));
867 options.add("cancel-label <text>", ki18n("Use text as Cancel button label"));
868 options.add("continue-label <text>", ki18n("Use text as Continue button label"));
869 options.add("sorry <text>", ki18n("'Sorry' message box"));
870 options.add("detailedsorry <text> <details>", ki18n("'Sorry' message box with expandable Details field"));
871 options.add("error <text>", ki18n("'Error' message box"));
872 options.add("detailederror <text> <details>", ki18n("'Error' message box with expandable Details field"));
873 options.add("msgbox <text>", ki18n("Message Box dialog"));
874 options.add("inputbox <text> <init>", ki18n("Input Box dialog"));
875 options.add("password <text>", ki18n("Password dialog"));
876 options.add("textbox <file> [width] [height]", ki18n("Text Box dialog"));
877 options.add("textinputbox <text> <init> [width] [height]", ki18n("Text Input Box dialog"));
878 options.add("combobox <text> item [item] [item] ...", ki18n("ComboBox dialog"));
879 options.add("menu <text> [tag item] [tag item] ...", ki18n("Menu dialog"));
880 options.add("checklist <text> [tag item status] ...", ki18n("Check List dialog"));
881 options.add("radiolist <text> [tag item status] ...", ki18n("Radio List dialog"));
882 options.add("passivepopup <text> <timeout>", ki18n("Passive Popup"));
883 options.add("getopenfilename [startDir] [filter]", ki18n("File dialog to open an existing file"));
884 options.add("getsavefilename [startDir] [filter]", ki18n("File dialog to save a file"));
885 options.add("getexistingdirectory [startDir]", ki18n("File dialog to select an existing directory"));
886 options.add("getopenurl [startDir] [filter]", ki18n("File dialog to open an existing URL"));
887 options.add("getsaveurl [startDir] [filter]", ki18n("File dialog to save a URL"));
888 options.add("geticon [group] [context]", ki18n("Icon chooser dialog"));
889 options.add("progressbar <text> [totalsteps]", ki18n("Progress bar dialog, returns a D-Bus reference for communication"));
890 options.add("getcolor", ki18n("Color dialog to select a color"));
891 // TODO gauge stuff, reading values from stdin
892 options.add("title <text>", ki18n("Dialog title"));
893 options.add("default <text>", ki18n("Default entry to use for combobox, menu and color"));
894 options.add("multiple", ki18n("Allows the --getopenurl and --getopenfilename options to return multiple files"));
895 options.add("separate-output", ki18n("Return list items on separate lines (for checklist option and file open with --multiple)"));
896 options.add("print-winid", ki18n("Outputs the winId of each dialog"));
897 options.add("dontagain <file:entry>", ki18n("Config file and option name for saving the \"do-not-show/ask-again\" state"));
898 options.add( "slider <text> [minvalue] [maxvalue] [step]", ki18n( "Slider dialog box, returns selected value" ) );
899 options.add( "calendar <text>", ki18n( "Calendar dialog box, returns selected date" ) );
900 /* kdialog originally used --embed for attaching the dialog box. However this is misleading and so we changed to --attach.
901 * For backwards compatibility, we silently map --embed to --attach */
902 options.add("attach <winid>", ki18n("Makes the dialog transient for an X app specified by winid"));
903 options.add("embed <winid>");
904
905 options.add("+[arg]", ki18n("Arguments - depending on main option"));
906
907 KCmdLineArgs::addCmdLineOptions( options ); // Add our own options.
908
909 KApplication app;
910
911 KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
912
913 // execute direct kdialog command
914 return directCommand(args);
915}
916
917