diff --git a/src/kdialog.cpp b/src/kdialog.cpp index 3e04a5c78..0463806af 100644 --- a/src/kdialog.cpp +++ b/src/kdialog.cpp @@ -1,1025 +1,1025 @@ // // Copyright (C) 1998 Matthias Hoelzer // Copyright (C) 2002, 2016 David Faure // Copyright (C) 2005 Brad Hards // Copyright (C) 2008 by Dmitry Suzdalev // Copyright (C) 2011 Kai Uwe Broulik // // 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 "config-kdialog.h" #include "widgets.h" #include "utils.h" -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include +// KF +#include +#include +#include +#include +#include +#include +#include +#include +#include #include +// Qt #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined HAVE_X11 #include #include #endif #ifdef Qt5DBus_FOUND #include #include #endif #include #include #include using namespace std; // 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) Q_DECL_OVERRIDE; private: bool print; WId id; }; bool WinIdEmbedder::eventFilter(QObject *o, QEvent *e) { if (e->type() == QEvent::Show && o->isWidgetType() && o->inherits("QDialog")) { QWidget *w = static_cast(o); if (print) cout << "winId: " << w->winId() << endl; if (id) KWindowSystem::setMainWindow(w, id); deleteLater(); // WinIdEmbedder is not needed anymore after the first dialog was shown return false; } return QObject::eventFilter(o, e); } /** * Display a passive notification popup using the D-Bus interface, if possible. * @return true if the notification was successfully sent, false otherwise. */ static bool sendVisualNotification(const QString &text, const QString &title, const QString &icon, int timeout) { #ifdef Qt5DBus_FOUND const QString dbusServiceName = QStringLiteral("org.freedesktop.Notifications"); const QString dbusInterfaceName = QStringLiteral("org.freedesktop.Notifications"); const QString dbusPath = QStringLiteral("/org/freedesktop/Notifications"); // check if service already exists on plugin instantiation QDBusConnectionInterface* interface = QDBusConnection::sessionBus().interface(); if (!interface || !interface->isServiceRegistered(dbusServiceName)) { //kDebug() << dbusServiceName << "D-Bus service not registered"; return false; } if (timeout == 0) timeout = 10 * 1000; QDBusMessage m = QDBusMessage::createMethodCall(dbusServiceName, dbusPath, dbusInterfaceName, QStringLiteral("Notify")); QList args; args.append(QStringLiteral("kdialog")); // app_name args.append(0U); // replaces_id args.append(icon); // app_icon args.append(title); // summary args.append(text); // body args.append(QStringList()); // actions - unused for plain passive popups args.append(QVariantMap()); // hints - unused atm args.append(timeout); // expire timeout m.setArguments(args); QDBusMessage replyMsg = QDBusConnection::sessionBus().call(m); if(replyMsg.type() == QDBusMessage::ReplyMessage) { if (!replyMsg.arguments().isEmpty()) { return true; } // Not displaying any error messages as this is optional for kdialog // and KPassivePopup is a perfectly valid fallback. //else { // kDebug() << "Error: received reply with no arguments."; //} } else if (replyMsg.type() == QDBusMessage::ErrorMessage) { //kDebug() << "Error: failed to send D-Bus message"; //kDebug() << replyMsg; } else { //kDebug() << "Unexpected reply type"; } #endif return false; } static void outputStringList(const QStringList &list, bool separateOutput) { if ( separateOutput) { for ( QStringList::ConstIterator it = list.constBegin(); it != list.constEnd(); ++it ) { cout << (*it).toLocal8Bit().data() << endl; } } else { for ( QStringList::ConstIterator it = list.constBegin(); it != list.constEnd(); ++it ) { cout << (*it).toLocal8Bit().data() << " "; } cout << endl; } } static void outputStringList(const QList &list, bool separateOutput) { if ( separateOutput) { for ( auto it = list.constBegin(); it != list.constEnd(); ++it ) { cout << (*it).toDisplayString().toLocal8Bit().data() << endl; } } else { for ( auto it = list.constBegin(); it != list.constEnd(); ++it ) { cout << (*it).toDisplayString().toLocal8Bit().data() << " "; } cout << endl; } } static KGuiItem configuredYes(const QString &text) { return KGuiItem( text, QStringLiteral("dialog-ok") ); } static KGuiItem configuredNo(const QString &text) { return KGuiItem( text, QStringLiteral("process-stop") ); } static KGuiItem configuredCancel(const QString &text) { return KGuiItem( text, QStringLiteral("dialog-cancel") ); } static KGuiItem configuredContinue(const QString &text) { return KGuiItem( text, QStringLiteral("arrow-right") ); } static void setFileDialogFilter(QFileDialog &dlg, const QString &filter) { if (filter.contains(QStringLiteral("*"))) { QString qtFilter = filter; dlg.setNameFilter(qtFilter.replace(QLatin1Char('|'),QLatin1Char('\n'))); } else if (!filter.isEmpty()) { dlg.setMimeTypeFilters(filter.trimmed().split(QLatin1Char(' '))); } } // taken from qfiledialog.cp static QString initialSelection(const QUrl &url) { if (url.isEmpty()) { return QString(); } if (url.isLocalFile()) { QFileInfo info(url.toLocalFile()); if (!info.isDir()) { return info.fileName(); } else { return QString(); } } // With remote URLs we can only assume. return url.fileName(); } static QUrl initialDirectory(const QUrl &url) { if (url.isLocalFile() && QFileInfo(url.toLocalFile()).isDir()) { return url; } return url.adjusted(QUrl::RemoveFilename); } int main(int argc, char *argv[]) { // Bug 373677: Qt removes various arguments it treats internally (such as title and icon) from args // and applies them to the first Qt::Window, while here we only show dialogs // so we need to store them before we even create our QApplication QStringList rawArgs; for (int i = 0; i < argc; ++i) { rawArgs << QString::fromLocal8Bit(argv[i]); } QApplication app(argc, argv); KLocalizedString::setApplicationDomain("kdialog"); // enable high dpi support app.setAttribute(Qt::AA_UseHighDpiPixmaps, true); KAboutData aboutData( QStringLiteral("kdialog"), i18n("KDialog"), QStringLiteral("2.0"), i18n( "KDialog can be used to show nice dialog boxes from shell scripts" ), KAboutLicense::GPL, i18n("(C) 2000, Nick Thompson")); aboutData.addAuthor(i18n("David Faure"), i18n("Current maintainer"),QStringLiteral("faure@kde.org")); aboutData.addAuthor(i18n("Brad Hards"), QString(), QStringLiteral("bradh@frogmouth.net")); aboutData.addAuthor(i18n("Nick Thompson"),QString(), QString()/*"nickthompson@lucent.com" bounces*/); aboutData.addAuthor(i18n("Matthias Hölzer"),QString(),QStringLiteral("hoelzer@kde.org")); aboutData.addAuthor(i18n("David Gümbel"),QString(),QStringLiteral("david.guembel@gmx.net")); aboutData.addAuthor(i18n("Richard Moore"),QString(),QStringLiteral("rich@kde.org")); aboutData.addAuthor(i18n("Dawit Alemayehu"),QString(),QStringLiteral("adawit@kde.org")); aboutData.addAuthor(i18n("Kai Uwe Broulik"),QString(),QStringLiteral("kde@privat.broulik.de")); KAboutData::setApplicationData(aboutData); QCommandLineParser parser; aboutData.setupCommandLine(&parser); parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("yesno"), i18n("Question message box with yes/no buttons"), QStringLiteral("text"))); parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("yesnocancel"), i18n("Question message box with yes/no/cancel buttons"), QStringLiteral("text"))); parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("warningyesno"), i18n("Warning message box with yes/no buttons"), QStringLiteral("text"))); parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("warningcontinuecancel"), i18n("Warning message box with continue/cancel buttons"), QStringLiteral("text"))); parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("warningyesnocancel"), i18n("Warning message box with yes/no/cancel buttons"), QStringLiteral("text"))); parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("yes-label"), i18n("Use text as Yes button label"), QStringLiteral("text"))); parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("no-label"), i18n("Use text as No button label"), QStringLiteral("text"))); parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("cancel-label"), i18n("Use text as Cancel button label"), QStringLiteral("text"))); parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("continue-label"), i18n("Use text as Continue button label"), QStringLiteral("text"))); parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("sorry"), i18n("'Sorry' message box"), QStringLiteral("text"))); parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("detailedsorry"), i18n("'Sorry' message box with expandable Details field"), QStringLiteral("text> {xX}][{+-}{+-}]"), QStringLiteral("geometry"))); parser.addPositionalArgument(QStringLiteral("[arg]"), i18n("Arguments - depending on main option")); parser.process(rawArgs); aboutData.processCommandLine(&parser); // execute kdialog command QApplication::setWindowIcon(QIcon::fromTheme(parser.value(QStringLiteral("icon")), QIcon::fromTheme(QStringLiteral("system-run")))); const QStringList args = parser.positionalArguments(); const QString title = parser.value(QStringLiteral("title")); const bool separateOutput = parser.isSet(QStringLiteral("separate-output")); const bool printWId = parser.isSet(QStringLiteral("print-winid")); QString defaultEntry; const QString geometry = parser.value(QStringLiteral("geometry")); Utils::setGeometry(geometry); WId winid = 0; bool attach = parser.isSet(QStringLiteral("attach")); if(attach) { #ifdef Q_WS_WIN winid = reinterpret_cast(parser.value(QStringLiteral("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. #else winid = parser.value(QStringLiteral("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. #endif } else if(parser.isSet(QStringLiteral("embed"))) { /* KDialog originally used --embed for attaching the dialog box. However this is misleading and so we changed to --attach. * For consistency, we silently map --embed to --attach */ attach = true; #ifdef Q_WS_WIN winid = reinterpret_cast(parser.value(QStringLiteral("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. #else winid = parser.value(QStringLiteral("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. #endif } if (printWId || attach) { (void)new WinIdEmbedder(printWId, winid); } // button labels // Initialize with default labels KGuiItem yesButton = KStandardGuiItem::yes(); KGuiItem noButton = KStandardGuiItem::no(); KGuiItem cancelButton = KStandardGuiItem::cancel(); KGuiItem continueButton = KStandardGuiItem::cont(); // Customize the asked labels if (parser.isSet(QStringLiteral("yes-label"))) { yesButton = configuredYes( parser.value(QStringLiteral("yes-label")) ); } if (parser.isSet(QStringLiteral("no-label"))) { noButton = configuredNo( parser.value(QStringLiteral("no-label")) ); } if (parser.isSet(QStringLiteral("cancel-label"))) { cancelButton = configuredCancel( parser.value(QStringLiteral("cancel-label") )); } if (parser.isSet(QStringLiteral("continue-label"))) { continueButton = configuredContinue( parser.value(QStringLiteral("continue-label")) ); } // --yesno and other message boxes KMessageBox::DialogType type = static_cast(0); QByteArray option; if (parser.isSet(QStringLiteral("yesno"))) { option = "yesno"; type = KMessageBox::QuestionYesNo; } else if (parser.isSet(QStringLiteral("yesnocancel"))) { option = "yesnocancel"; type = KMessageBox::QuestionYesNoCancel; } else if (parser.isSet(QStringLiteral("warningyesno"))) { option = "warningyesno"; type = KMessageBox::WarningYesNo; } else if (parser.isSet(QStringLiteral("warningcontinuecancel"))) { option = "warningcontinuecancel"; type = KMessageBox::WarningContinueCancel; } else if (parser.isSet(QStringLiteral("warningyesnocancel"))) { option = "warningyesnocancel"; type = KMessageBox::WarningYesNoCancel; } else if (parser.isSet(QStringLiteral("sorry"))) { option = "sorry"; type = KMessageBox::Sorry; } else if (parser.isSet(QStringLiteral("detailedsorry"))) { option = "detailedsorry"; } else if (parser.isSet(QStringLiteral("error"))) { option = "error"; type = KMessageBox::Error; } else if (parser.isSet(QStringLiteral("detailederror"))) { option = "detailederror"; } else if (parser.isSet(QStringLiteral("msgbox"))) { option = "msgbox"; type = KMessageBox::Information; } if ( !option.isEmpty() ) { KConfig* dontagaincfg = nullptr; // --dontagain QString dontagain; // QString() if (parser.isSet(QStringLiteral("dontagain"))) { QString value = parser.value(QStringLiteral("dontagain")); QStringList values = value.split( QLatin1Char(':'), QString::SkipEmptyParts ); if( values.count() == 2 ) { dontagaincfg = new KConfig( values[ 0 ] ); KMessageBox::setDontShowAgainConfig( dontagaincfg ); dontagain = values[ 1 ]; } else qDebug( "Incorrect --dontagain!" ); } int ret = 0; QString text = Utils::parseString(parser.value(QString::fromLatin1(option))); QString details; if (args.count() == 1) { details = Utils::parseString(args.at(0)); } if ( type == KMessageBox::WarningContinueCancel ) { ret = KMessageBox::messageBox( nullptr, type, text, title, continueButton, noButton, cancelButton, dontagain ); } else if (option == "detailedsorry") { KMessageBox::detailedSorry( nullptr, text, details, title ); } else if (option == "detailederror") { KMessageBox::detailedError( nullptr, text, details, title ); } else { ret = KMessageBox::messageBox( nullptr, type, text, title, yesButton, noButton, cancelButton, 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 (parser.isSet(QStringLiteral("inputbox"))) { QString result; QString init; if (args.count() > 0) { init = args.at(0); } const bool retcode = Widgets::inputBox(nullptr, title, parser.value(QStringLiteral("inputbox")), init, result); cout << result.toLocal8Bit().data() << endl; return retcode ? 0 : 1; } // --password text if (parser.isSet(QStringLiteral("password"))) { QString result; const bool retcode = Widgets::passwordBox(nullptr, title, parser.value(QStringLiteral("password")), result); cout << qPrintable(result) << endl; return retcode ? 0 : 1; } // --newpassword text if (parser.isSet(QStringLiteral("newpassword"))) { QString result; const bool retcode = Widgets::newPasswordBox(nullptr, title, parser.value(QStringLiteral("newpassword")), result); cout << qPrintable(result) << endl; return retcode ? 0 : 1; } // --passivepopup if (parser.isSet(QStringLiteral("passivepopup"))) { int timeout = 0; if (args.count() > 0) { timeout = 1000 * args.at(0).toInt(); } if (timeout < 0) { timeout = -1; } // Use --icon parameter for passivepopup as well QString icon; if (parser.isSet(QStringLiteral("icon"))) { icon = parser.value(QStringLiteral("icon")); } else { icon = QStringLiteral("dialog-information"); // Use generic (i)-icon if none specified } // try to use more stylish notifications if (sendVisualNotification(Utils::parseString(parser.value(QStringLiteral("passivepopup"))), title, icon, timeout)) return 0; // ...did not work, use KPassivePopup as fallback // parse timeout time again, so it does not auto-close the fallback (timer cannot handle -1 time) if (args.count() > 0) { timeout = 1000 * args.at(0).toInt(); } if (timeout <= 0) { timeout = 10*1000; // 10 seconds should be a decent time for auto-closing (you can override this using a parameter) } QPixmap passiveicon; if (parser.isSet(QStringLiteral("icon"))) { // Only show icon if explicitly requested passiveicon = KIconLoader::global()->loadIcon(icon, KIconLoader::Dialog); } KPassivePopup *popup = KPassivePopup::message( KPassivePopup::Boxed, // style title, Utils::parseString(parser.value(QStringLiteral("passivepopup"))), passiveicon, (QWidget*)nullptr, // parent timeout ); QTimer *timer = new QTimer(); QObject::connect( timer, SIGNAL(timeout()), qApp, SLOT(quit()) ); QObject::connect( popup, SIGNAL(clicked()), qApp, SLOT(quit()) ); timer->setSingleShot( true ); timer->start( timeout ); #ifdef HAVE_X11 if ( !geometry.isEmpty()) { int x, y; int w, h; int m = XParseGeometry( geometry.toLatin1().constData(), &x, &y, (unsigned int*)&w, (unsigned int*)&h); if ( (m & XNegative) ) x = QApplication::desktop()->width() + x - w; if ( (m & YNegative) ) y = QApplication::desktop()->height() + y - h; popup->setAnchor( QPoint(x, y) ); } #endif qApp->exec(); return 0; } // --textbox file [width] [height] if (parser.isSet(QStringLiteral("textbox"))) { int w = 0; int h = 0; if (args.count() == 2) { w = args.at(0).toInt(); h = args.at(1).toInt(); } return Widgets::textBox(nullptr, w, h, title, parser.value(QStringLiteral("textbox"))); } // --imgbox if (parser.isSet(QStringLiteral("imgbox"))) { return Widgets::imgBox(nullptr, title, parser.value(QStringLiteral("imgbox"))); } // --imginputbox [text] if (parser.isSet(QStringLiteral("imginputbox"))) { QString result; QString text; if (args.count() > 0) { text = args.at(0); } const bool retcode = Widgets::imgInputBox(nullptr, title, parser.value(QStringLiteral("imginputbox")), text, result); cout << result.toLocal8Bit().data() << endl; return retcode ? 0 : 1; } // --textinputbox file [width] [height] if (parser.isSet(QStringLiteral("textinputbox"))) { int w = 400; int h = 200; if (args.count() >= 3) { w = args.at(1).toInt(); h = args.at(2).toInt(); } QString init; if (args.count() >= 1) { init = Utils::parseString(args.at(0)); } QString result; int ret = Widgets::textInputBox(nullptr, w, h, title, Utils::parseString(parser.value(QStringLiteral("textinputbox"))), init, result); cout << qPrintable(result) << endl; return ret; } // --combobox item [item] ..." if (parser.isSet(QStringLiteral("combobox"))) { QStringList list; if (args.count() >= 1) { for (int i = 0; i < args.count(); i++) { list.append(args.at(i)); } const QString text = Utils::parseString(parser.value(QStringLiteral("combobox"))); if (parser.isSet(QStringLiteral("default"))) { defaultEntry = parser.value(QStringLiteral("default")); } QString result; const bool retcode = Widgets::comboBox(nullptr, title, text, list, defaultEntry, result); cout << result.toLocal8Bit().data() << endl; return retcode ? 0 : 1; } cerr << qPrintable(i18n("Syntax: --combobox item [item] ...")) << endl; return -1; } // --menu text [tag item] [tag item] ... if (parser.isSet(QStringLiteral("menu"))) { QStringList list; if (args.count() >= 2) { for (int i = 0; i < args.count(); i++) { list.append(args.at(i)); } const QString text = Utils::parseString(parser.value(QStringLiteral("menu"))); if (parser.isSet(QStringLiteral("default"))) { defaultEntry = parser.value(QStringLiteral("default")); } QString result; const bool retcode = Widgets::listBox(nullptr, title, text, list, defaultEntry, result); if (1 == retcode) { // OK was selected cout << result.toLocal8Bit().data() << endl; } return retcode ? 0 : 1; } cerr << qPrintable(i18n("Syntax: --menu text [tag item] [tag item] ...")) << endl; return -1; } // --checklist text [tag item status] [tag item status] ... if (parser.isSet(QStringLiteral("checklist"))) { QStringList list; if (args.count() >= 3) { for (int i = 0; i < args.count(); i++) { list.append(args.at(i)); } const QString text = Utils::parseString(parser.value(QStringLiteral("checklist"))); QStringList result; const bool retcode = Widgets::checkList(nullptr, title, text, list, separateOutput, result); for (int i=0; i= 3) { for (int i = 0; i < args.count(); i++) { list.append(args.at(i)); } const QString text = Utils::parseString(parser.value(QStringLiteral("radiolist"))); QString result; const bool retcode = Widgets::radioBox(nullptr, title, text, list, result); cout << result.toLocal8Bit().data() << endl; return retcode ? 0 : 1; } cerr << qPrintable(i18n("Syntax: --radiolist text [tag item on/off] ...")) << endl; return -1; } // getopenfilename [startDir] [filter] // getopenurl [startDir] [filter] if (parser.isSet(QStringLiteral("getopenfilename")) || parser.isSet(QStringLiteral("getopenurl"))) { QString startDir = args.count() > 0 ? args.at(0) : QString(); const QUrl startUrl = QUrl::fromUserInput(startDir); QString filter; if (args.count() > 1) { filter = Utils::parseString(args.at(1)); } const bool multiple = parser.isSet(QStringLiteral("multiple")); QFileDialog dlg; dlg.setAcceptMode(QFileDialog::AcceptOpen); dlg.setDirectoryUrl(initialDirectory(startUrl)); dlg.selectFile(initialSelection(startUrl)); if (multiple) { dlg.setFileMode(QFileDialog::ExistingFiles); } else { dlg.setFileMode(QFileDialog::ExistingFile); } const bool openUrls = parser.isSet(QStringLiteral("getopenurl")); if (!openUrls) { dlg.setSupportedSchemes({QStringLiteral("file")}); } setFileDialogFilter(dlg, filter); Utils::handleXGeometry(&dlg); dlg.setWindowTitle(title.isEmpty() ? i18nc("@title:window", "Open") : title); if (!dlg.exec()) { return 1; // canceled } if (openUrls) { const QList result = dlg.selectedUrls(); if (!result.isEmpty()) { if (multiple) { outputStringList(result, separateOutput); return 0; } else { cout << result.at(0).url().toLocal8Bit().data() << endl; return 0; } } } else { const QStringList result = dlg.selectedFiles(); if (!result.isEmpty()) { if (multiple) { outputStringList(result, separateOutput); return 0; } else { cout << result.at(0).toLocal8Bit().data() << endl; return 0; } } } return 1; } // getsaveurl [startDir] [filter] // getsavefilename [startDir] [filter] if ( (parser.isSet(QStringLiteral("getsavefilename")) ) || (parser.isSet(QStringLiteral("getsaveurl")) ) ) { QString startDir = args.count() > 0 ? args.at(0) : QString(); QString filter; const QUrl startUrl = QUrl::fromUserInput(startDir); if (args.count() > 1) { filter = Utils::parseString(args.at(1)); } QFileDialog dlg; dlg.setAcceptMode(QFileDialog::AcceptSave); dlg.setFileMode(QFileDialog::AnyFile); dlg.setDirectoryUrl(initialDirectory(startUrl)); dlg.selectFile(initialSelection(startUrl)); setFileDialogFilter(dlg, filter); const bool saveUrls = parser.isSet(QStringLiteral("getsaveurl")); if (!saveUrls) { dlg.setSupportedSchemes({QStringLiteral("file")}); } Utils::handleXGeometry(&dlg); dlg.setWindowTitle(title.isEmpty() ? i18nc("@title:window", "Save As") : title); if (!dlg.exec()) { return 1; // canceled } if (saveUrls) { const QList result = dlg.selectedUrls(); if (!result.isEmpty()) { cout << result.at(0).toString().toLocal8Bit().data() << endl; return 0; } } else { // getsavefilename const QStringList result = dlg.selectedFiles(); if (!result.isEmpty()) { const QString file = result.at(0); KRecentDocument::add(QUrl::fromLocalFile(file)); cout << file.toLocal8Bit().data() << endl; return 0; } } return 1; // canceled } // getexistingdirectory [startDir] if (parser.isSet(QStringLiteral("getexistingdirectory"))) { QString startDir = args.count() > 0 ? args.at(0) : QString(); const QUrl startUrl = QUrl::fromUserInput(startDir); QFileDialog dlg; dlg.setFileMode(QFileDialog::DirectoryOnly); dlg.setOption(QFileDialog::ShowDirsOnly, true); dlg.setDirectoryUrl(initialDirectory(startUrl)); dlg.selectFile(initialSelection(startUrl)); Utils::handleXGeometry(&dlg); dlg.setWindowTitle(title.isEmpty() ? i18nc("@title:window", "Select Directory") : title); if (!dlg.exec()) { return 1; // canceled } const QList urls = dlg.selectedUrls(); if (!urls.isEmpty()) { cout << qPrintable(urls.at(0).toDisplayString(QUrl::PreferLocalFile)) << endl; return 0; } return 1; // canceled } // geticon [group] [context] if (parser.isSet(QStringLiteral("geticon"))) { QString groupStr, contextStr; groupStr = parser.value(QStringLiteral("geticon")); if (args.count() >= 1) { contextStr = args.at(0); } const KIconLoader::Group group = ( groupStr == QLatin1String( "Desktop" ) ) ? KIconLoader::Desktop : ( groupStr == QLatin1String( "Toolbar" ) ) ? KIconLoader::Toolbar : ( groupStr == QLatin1String( "MainToolbar" ) ) ? KIconLoader::MainToolbar : ( groupStr == QLatin1String( "Small" ) ) ? KIconLoader::Small : ( groupStr == QLatin1String( "Panel" ) ) ? KIconLoader::Panel : ( groupStr == QLatin1String( "Dialog" ) ) ? KIconLoader::Dialog : ( groupStr == QLatin1String( "User" ) ) ? KIconLoader::User : /* else */ KIconLoader::NoGroup; const KIconLoader::Context context = ( contextStr == QLatin1String( "Action" ) ) ? KIconLoader::Action : ( contextStr == QLatin1String( "Application" ) ) ? KIconLoader::Application : ( contextStr == QLatin1String( "Device" ) ) ? KIconLoader::Device : ( contextStr == QLatin1String( "FileSystem" ) ) ? KIconLoader::FileSystem : ( contextStr == QLatin1String( "MimeType" ) ) ? KIconLoader::MimeType : ( contextStr == QLatin1String( "Animation" ) ) ? KIconLoader::Animation : ( contextStr == QLatin1String( "Category" ) ) ? KIconLoader::Category : ( contextStr == QLatin1String( "Emblem" ) ) ? KIconLoader::Emblem : ( contextStr == QLatin1String( "Emote" ) ) ? KIconLoader::Emote : ( contextStr == QLatin1String( "International" ) ) ? KIconLoader::International : ( contextStr == QLatin1String( "Place" ) ) ? KIconLoader::Place : ( contextStr == QLatin1String( "StatusIcon" ) ) ? KIconLoader::StatusIcon : // begin: KDE3 compatibility (useful?) ( contextStr == QLatin1String( "Devices" ) ) ? KIconLoader::Device : ( contextStr == QLatin1String( "MimeTypes" ) ) ? KIconLoader::MimeType : ( contextStr == QLatin1String( "FileSystems" ) ) ? KIconLoader::FileSystem : ( contextStr == QLatin1String( "Applications" ) ) ? KIconLoader::Application : ( contextStr == QLatin1String( "Actions" ) ) ? KIconLoader::Action : // end: KDE3 compatibility /* else */ KIconLoader::Any; KIconDialog dlg((QWidget*)Q_NULLPTR); dlg.setup( group, context); dlg.setIconSize(KIconLoader::SizeHuge); if (!title.isEmpty()) dlg.setWindowTitle(title); Utils::handleXGeometry(&dlg); const QString result = dlg.openDialog(); if (!result.isEmpty()) { cout << result.toLocal8Bit().data() << endl; return 0; } return 1; // canceled } // --progressbar text totalsteps if (parser.isSet(QStringLiteral("progressbar"))) { const QString text = Utils::parseString(parser.value(QStringLiteral("progressbar"))); QProcess process; QStringList arguments; arguments << QStringLiteral("--progressbar"); arguments << text; arguments << QStringLiteral("--title"); arguments << title; if (args.count() == 1) { arguments << args.at(0); } qint64 pid = 0; if (process.startDetached(QStringLiteral("kdialog_progress_helper"), arguments, QString(), &pid)) { QDBusConnection dbus = QDBusConnection::sessionBus(); const QString serviceName = QStringLiteral("org.kde.kdialog-") + QString::number(pid); QDBusServiceWatcher watcher(serviceName, dbus, QDBusServiceWatcher::WatchForRegistration); QObject::connect(&watcher, &QDBusServiceWatcher::serviceRegistered, [serviceName](){ std::cout << serviceName.toLatin1().constData() << " /ProgressDialog" << std::endl << std::flush; qApp->quit(); }); qApp->exec(); return 0; } qWarning() << "Error starting kdialog_progress_helper"; return 1; } // --getcolor if (parser.isSet(QStringLiteral("getcolor"))) { QColorDialog dlg; if (parser.isSet(QStringLiteral("default"))) { defaultEntry = parser.value(QStringLiteral("default")); dlg.setCurrentColor(defaultEntry); } else { QColor color = KColorMimeData::fromMimeData(QApplication::clipboard()->mimeData(QClipboard::Clipboard)); if (color.isValid()) { dlg.setCurrentColor(color); } } Utils::handleXGeometry(&dlg); dlg.setWindowTitle(title.isEmpty() ? i18nc("@title:window", "Choose Color") : title); if (dlg.exec()) { QString result; const QColor color = dlg.selectedColor(); if (color.isValid() && parser.isSet(QStringLiteral("format"))) { bool found = false; QString format = parser.value(QStringLiteral("format")); format.remove(QLatin1Char('*')); // stripped out * for safety QList pattern_pool; pattern_pool << QRegularExpression(QStringLiteral("(%#?[-+]?\\d*\\.?\\d*(?:ll|hh|l|h)?[diouxX])")) << QRegularExpression(QStringLiteral("(%#?[-+]?\\d*\\.?\\d*[l]?[efgEFG])")); for (int i = 0; i < pattern_pool.size(); i++) { QRegularExpressionMatchIterator itor = pattern_pool.at(i).globalMatch(format); QRegularExpressionMatch match; int match_count = 0; while (itor.hasNext()) { match = itor.next(); if (match.hasMatch()) { match_count++; } } // currently only handle RGB, when alpha is ready, should hit 4 if (3 == match_count) { found = true; if (match.captured(0).contains(QRegularExpression(QStringLiteral("[diouxX]")))) { result = QString::asprintf(format.toUtf8().constData(), color.red(), color.green(), color.blue()); } else { result = QString::asprintf(format.toUtf8().constData(), color.redF(), color.greenF(), color.blueF()); } break; } } if (false == found) { cout << "Invalid format pattern"; } } else { result = color.name(); } cout << result.toLocal8Bit().data() << endl; return 0; } return 1; // canceled } if (parser.isSet(QStringLiteral("slider"))) { int miniValue = 0; int maxValue = 0; int step = 0; const QString text = Utils::parseString(parser.value(QStringLiteral("slider"))); if (args.count() == 3) { miniValue = args.at(0).toInt(); maxValue = args.at( 1 ).toInt(); step = args.at( 2 ).toInt(); } int result = 0; const bool returnCode = Widgets::slider(nullptr, title, text, miniValue, maxValue, step, result); if ( returnCode ) cout << result << endl; return returnCode; } if (parser.isSet(QStringLiteral("calendar"))) { const QString text = Utils::parseString(parser.value(QStringLiteral("calendar"))); QDate result; const bool returnCode = Widgets::calendar(nullptr, title, text, result); if ( returnCode ) cout << result.toString().toLocal8Bit().data() << endl; return returnCode; } parser.showHelp(); return -2; // NOTREACHED } diff --git a/src/widgets.cpp b/src/widgets.cpp index b8eef94a6..f60a2ae42 100644 --- a/src/widgets.cpp +++ b/src/widgets.cpp @@ -1,403 +1,403 @@ // // Copyright (C) 1998 Matthias Hoelzer // Copyright (C) 2002-2005 David Faure // // 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. // // Own #include #include "widgets.h" #include "utils.h" // Qt #include #include #include #include #include #include #include #include #include #include -// KDE -#include -#include -#include -#include -#include +// KF +#include +#include +#include +#include +#include // Local #include "klistboxdialog.h" #include "progressdialog.h" static void addButtonBox(QDialog &dlg, QDialogButtonBox::StandardButtons buttons = QDialogButtonBox::Ok | QDialogButtonBox::Cancel) { QDialogButtonBox *buttonBox = new QDialogButtonBox(buttons, &dlg); dlg.layout()->addWidget(buttonBox); QObject::connect(buttonBox, &QDialogButtonBox::accepted, &dlg, &QDialog::accept); QObject::connect(buttonBox, &QDialogButtonBox::rejected, &dlg, &QDialog::reject); } bool Widgets::inputBox(QWidget *parent, const QString& title, const QString& text, const QString& init, QString &result) { bool ok; const QString str = QInputDialog::getText(parent, title, text, QLineEdit::Normal, init, &ok); if (ok) result = str; return ok; } bool Widgets::passwordBox(QWidget *parent, const QString& title, const QString& text, QString &result) { KPasswordDialog dlg( parent ); dlg.setWindowTitle(title); dlg.setPrompt(text); Utils::handleXGeometry(&dlg); bool retcode = (dlg.exec() == QDialog::Accepted); if ( retcode ) result = dlg.password(); return retcode; } bool Widgets::newPasswordBox(QWidget *parent, const QString& title, const QString& text, QString &result) { KNewPasswordDialog dlg( parent ); dlg.setWindowTitle(title); dlg.setPrompt(text); Utils::handleXGeometry(&dlg); bool retcode = (dlg.exec() == QDialog::Accepted); if ( retcode ) result = dlg.password(); return retcode; } int Widgets::textBox(QWidget *parent, int width, int height, const QString& title, const QString& file) { QDialog dlg(parent); dlg.setWindowTitle(title); QVBoxLayout *mainLayout = new QVBoxLayout(&dlg); KTextEdit *edit = new KTextEdit(&dlg); mainLayout->addWidget(edit); edit->setReadOnly(true); edit->setFocus(); addButtonBox(dlg, QDialogButtonBox::Ok); if (file == QLatin1String("-")) { QTextStream s(stdin, QIODevice::ReadOnly); while (!s.atEnd()) edit->append(s.readLine()); } else { QFile f(file); if (!f.open(QIODevice::ReadOnly)) { qWarning() << i18n("kdialog: could not open file %1", file); return -1; } QTextStream s(&f); while (!s.atEnd()) edit->append(s.readLine()); } edit->setTextCursor(QTextCursor(edit->document())); if (width > 0 && height > 0) dlg.resize(QSize(width, height)); Utils::handleXGeometry(&dlg); dlg.setWindowTitle(title); return (dlg.exec() == QDialog::Accepted) ? 0 : 1; } int Widgets::imgBox(QWidget *parent, const QString& title, const QString& file) { QDialog dlg(parent); dlg.setWindowTitle(title); QVBoxLayout *mainLayout = new QVBoxLayout(&dlg); QLabel *label = new QLabel(&dlg); mainLayout->addWidget(label); addButtonBox(dlg, QDialogButtonBox::Ok); QFile f(file); if (!f.open(QIODevice::ReadOnly)) { qWarning() << i18n("kdialog: could not open file %1", file); return -1; } label->setPixmap(QPixmap(file)); return (dlg.exec() == QDialog::Accepted) ? 0 : 1; } int Widgets::imgInputBox(QWidget *parent, const QString& title, const QString& file, const QString& text, QString &result) { QFile f(file); if (!f.open(QIODevice::ReadOnly)) { qWarning() << i18n("kdialog: could not open file %1", file); return -1; } QDialog dlg(parent); dlg.setWindowTitle(title); QVBoxLayout *mainLayout = new QVBoxLayout(&dlg); if (!text.isEmpty()) { QLabel *head = new QLabel(&dlg); head->setText(text); mainLayout->addWidget(head); } QLabel *label = new QLabel(&dlg); mainLayout->addWidget(label); label->setPixmap(QPixmap(file)); QLineEdit *edit = new QLineEdit(&dlg); mainLayout->addWidget(edit); edit->setReadOnly(false); edit->setFocus(); addButtonBox(dlg, QDialogButtonBox::Ok); bool retcode = (dlg.exec() == QDialog::Accepted); if (retcode) result = edit->text(); return retcode; } int Widgets::textInputBox(QWidget *parent, int width, int height, const QString& title, const QString& text, const QString& init, QString &result) { QDialog dlg(parent); dlg.setWindowTitle(title); QVBoxLayout *mainLayout = new QVBoxLayout(&dlg); if (!text.isEmpty()) { QLabel *label = new QLabel(&dlg); mainLayout->addWidget(label); label->setText(text); } KTextEdit *edit = new KTextEdit(&dlg); mainLayout->addWidget(edit); edit->setReadOnly(false); edit->setFocus(); edit->insertPlainText(init); addButtonBox(dlg, QDialogButtonBox::Ok); if (width > 0 && height > 0) dlg.resize(QSize(width, height)); Utils::handleXGeometry(&dlg); dlg.setWindowTitle(title); const int returnDialogCode = dlg.exec(); result = edit->toPlainText(); return (returnDialogCode == QDialog::Accepted ? 0 : 1); } bool Widgets::comboBox(QWidget *parent, const QString& title, const QString& text, const QStringList& args, const QString& defaultEntry, QString &result) { QDialog dlg(parent); dlg.setWindowTitle(title); QVBoxLayout *mainLayout = new QVBoxLayout(&dlg); QLabel *label = new QLabel(&dlg); label->setText(text); mainLayout->addWidget(label); QComboBox *combo = new QComboBox(&dlg); combo->addItems(args); combo->setCurrentIndex(combo->findText(defaultEntry)); combo->setFocus(); mainLayout->addWidget(combo); addButtonBox(dlg); Utils::handleXGeometry(&dlg); bool retcode = (dlg.exec() == QDialog::Accepted); if (retcode) result = combo->currentText(); return retcode; } bool Widgets::listBox(QWidget *parent, const QString& title, const QString& text, const QStringList& args, const QString& defaultEntry, QString &result) { KListBoxDialog box(text,parent); box.setWindowTitle(title); for (int i = 0; i+1setSelected( args[i+2] == QLatin1String("on") ); } Utils::handleXGeometry(&box); const bool retcode = (box.exec() == QDialog::Accepted); if ( retcode ) { if (separateOutput) { for (int i=0; iisSelected()) result.append(tags[i]); } else { for (int i=0; iisSelected()) rs += QLatin1String("\"") + tags[i] + QLatin1String("\" "); result.append(rs); } } return retcode; } bool Widgets::radioBox(QWidget *parent, const QString& title, const QString& text, const QStringList& args, QString &result) { QStringList entries, tags; KListBoxDialog box(text,parent); QListWidget &table = box.getTable(); box.setWindowTitle(title); for (int i=0; i+2addWidget(label); label->setText (text); QSlider *slider = new QSlider(&dlg); mainLayout->addWidget(slider); slider->setMinimum(minValue); slider->setMaximum(maxValue); slider->setSingleStep(step); slider->setTickPosition(QSlider::TicksAbove); slider->setOrientation(Qt::Horizontal); slider->setFocus(); Utils::handleXGeometry(&dlg); addButtonBox(dlg); const bool retcode = (dlg.exec() == QDialog::Accepted); if (retcode) result = slider->value(); return retcode; } bool Widgets::calendar( QWidget *parent, const QString &title, const QString &text, QDate & result ) { QDialog dlg(parent); dlg.setWindowTitle(title); QVBoxLayout *mainLayout = new QVBoxLayout(&dlg); QLabel *label = new QLabel(&dlg); mainLayout->addWidget(label); label->setText(text); KDatePicker *dateWidget = new KDatePicker(&dlg); mainLayout->addWidget(dateWidget); dateWidget->setFocus(); addButtonBox(dlg); Utils::handleXGeometry(&dlg); const bool retcode = (dlg.exec() == QDialog::Accepted); if (retcode) result = dateWidget->date(); return retcode; }