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 | |
62 | using 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. |
67 | class WinIdEmbedder: public QObject |
68 | { |
69 | public: |
70 | WinIdEmbedder(bool printID, WId winId): |
71 | QObject(qApp), print(printID), id(winId) |
72 | { |
73 | if (qApp) |
74 | qApp->installEventFilter(this); |
75 | } |
76 | protected: |
77 | bool eventFilter(QObject *o, QEvent *e); |
78 | private: |
79 | bool print; |
80 | WId id; |
81 | }; |
82 | |
83 | bool 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 | */ |
103 | bool 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 | |
155 | static 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 | |
170 | KGuiItem configuredYes(const QString &text) |
171 | { |
172 | return KGuiItem( text, "dialog-ok" ); |
173 | } |
174 | |
175 | KGuiItem configuredNo(const QString &text) |
176 | { |
177 | return KGuiItem( text, "process-stop" ); |
178 | } |
179 | |
180 | KGuiItem configuredCancel(const QString &text) |
181 | { |
182 | return KGuiItem( text, "dialog-cancel" ); |
183 | } |
184 | |
185 | KGuiItem configuredContinue(const QString &text) |
186 | { |
187 | return KGuiItem( text, "arrow-right" ); |
188 | } |
189 | |
190 | static 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 * = 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 | |
841 | int 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 | |