LINUX.ORG.RU

Вы уже догадались, опять Qt5

 , , , ,


1

2

У меня уже начинает подгорать.

Нужно сделать возможность запуска и в кли и в гуй режиме.

Смотрим: http://doc.qt.io/qt-5/qapplication.html мотаем до «Detailed Description», читаем, есть пример. Ок. Чё? фор аргв? Мухаха!!! Ну ладно, бывает, в одном месте можно и по старинке.

А если у меня много опций и для гуя и для кли? Оу, ну конечно. http://doc.qt.io/qt-5/qcommandlineparser.html#process читаем, смотрим пример. Ок.

Пробуем запустить... Парсер просит инстанс аппликейшна ДО своего запуска. Что, простите? А, ну да, один раз фор фор для но-гуй опции, дебильный иф с кастами.. Эммм.. А как насчет неизвестной опции но-гуй когда запустим процесс парсинга? В парсер тоже добавлять ради чтобы его заткнуть? Иначе он ДЕЛАЕТ ЭКСИТ(1) СРАЗУ после неуспешного парсинга. Ок.

О! парсер можно попросить только спарсить! http://doc.qt.io/qt-5/qcommandlineparser.html#process Используй parse() вместо process(), проверь успех и.. Вроде все работает.. Но, я же как честный и правильный делал parser.addHelpOption() надо проверить parser.showHelp() .. Чё? Опять требует инстанс аппликейшна и достает из штанов большой и толстый СЕГФОЛТ!!!

Т.е. я без самого главной опции хелп остаюсь? Отлично!!!

А теперь серьезно. Вопрос: как правильно разрулить гуй-негуй, создав правильный инстанс апликейшна + пропарсить опшны парсером + показать хелп?

Пока вы отвечаете, я ушел переделывать на «фор аргв + иф с дебильным кастом», по идее после этого showHelp() должно заработать.

★★★★★

Последнее исправление: deep-purple (всего исправлений: 2)

Да, взлетело. С комментариями почему именно так:

// нульцевый заранее
QCoreApplication *app = 0;
// поищем ногуй опцию
for (int a = 0; a < argc; a += 1) {
    // поищем очень хорошо
    if (!qstrcmp(argv[a], "--no-gui") || !qstrcmp(argv[a], "-n")) {
        app = new QCoreApplication(argc, argv);
        break;
    }
}
// нет, это не ногуй, это рукуй
if (!app) {
    app = new QApplication(argc, argv);
}
// теперь можно и парсер, он требует инстанс аппликейшна
QCommandLineParser parser;
// всякие опции
QCommandLineOption option1(...);
QCommandLineOption option2(...);
QCommandLineOption optionN(...);
// не забудь добавить опцию ногуй, иначе парсер скажет что ошибка, неизвестная опция
QCommandLineOption optionNoGui(QStringList() << "n" << "no-gui", QObject::tr("CLI mode"));
// все опции объявили? теперь добавляем
QCommandLineOption optionHelp = parser.addHelpOption(); // хелп
parser.addOption(option1);
parser.addOption(option2);
parser.addOption(optionN);
parser.addOption(optionNoGui);
// запускаем парсер
parser.parse(app->arguments()); // возвращает буль, успех парсинга, можно обработать
// теперь опцию хелп можно показать только так как кастомные.
if (parser.isSet(optionHelp)) {
    parser.showHelp(); // тут эта скотина делает уже exit(0), КАК ЗАСТАВИТЬ ЕЁ НЕ ДЕЛАТЬ ЭКСИТ?
}

return app->exec();

deep-purple ★★★★★
() автор топика
Ответ на: комментарий от deep-purple

Все еще остался не решенным вопрос:

Как отключить эксит у showHelp()?

Я хочу: если парсинг завершился с успехом, то, если просили показать хелп, тогда показать хелп и сделать exit(0), а если парсинг не успешен, то показать ошибку, показать хелп и сделать exit(1).

Как?

deep-purple ★★★★★
() автор топика
Ответ на: комментарий от deep-purple

void QCommandLineParser::showHelp(int exitCode = 0)

Покатит...

deep-purple ★★★★★
() автор топика

Рад что всё получилось, хотя такой способ изложения проблемы приводит к тому, что понять затруднение оказывается сложно...

I-Love-Microsoft ★★★★★
()
Ответ на: комментарий от I-Love-Microsoft

Погоди )) Еще не все. У тебя есть под рукой сконпиленое приложение с использованием этого парсера?

Либо я нашел багу, либо дело не в бобине. Пусть "-a" требует значение, а "-b" просто буль.

запускай: ./app -a value -b

Все ОК.

теперь запускай: ./app -a -b

Тут "-b" стало значением для "-a" и пропало из установленных (вне зависимости от порядка добавления этих опций в сорцах) и парсер не ругнулся на отсутствие значения для "-a".

Подтверждаешь?

deep-purple ★★★★★
() автор топика
Последнее исправление: deep-purple (всего исправлений: 2)
Ответ на: комментарий от deep-purple

Ессно надо подставить свои имена опций, которые есть в приложении.

deep-purple ★★★★★
() автор топика

Спасибо, благодаря этой теме узнал про QCommandLineParser.

Но честно говоря, для своего проекта я отдельно сделал GUI-фронтенд и отдельно CLI-утилиту, общий код подхватывается через .pri-файл. И да, распарсил командную строку вручную. Хотя сейчас бы уже подумал...

hobbit ★★★★★
()
Ответ на: комментарий от hobbit

Ты знаешь.. Прочти парой сообщений выше. Если эта херня не решится, я уже подумываю взять нормальный парсер где-нибудь или написать свою реализацию парсера, ибо эта херня полная.

deep-purple ★★★★★
() автор топика
Ответ на: комментарий от deep-purple

во первых не нравится этот прасер, используй другой, это нормально, во вторых, по поводу “ошибки” по моему типичное поведение, не плохо было бы его ловить, конечно, но багой это не назовёшь, всё же.

LiBer ★★★
()
Последнее исправление: LiBer (всего исправлений: 1)
Ответ на: комментарий от LiBer

как это не ошибка? Он жрет булеву опцию, и при проверке самой опции, говорит что таковой не устанавливалось.

deep-purple ★★★★★
() автор топика
Ответ на: комментарий от LiBer

и hobbit

Снова решено костылём, но костылем изящным.

Сначала добавляем в парсер только булевые опции и парсим их. Сохраняем их наличие как битовые маски, если опция установлена, то добавляем маску.

И только после этого добавляем в парсер опции, которые требуют значений. Парсим еще раз.

Теперь у нас есть и булевые опции и опции со значениями. Ну и что, что некоторые значения равны объявлению булевых — всеравно это куда лучше, чем просто наглое пожирание опций.

deep-purple ★★★★★
() автор топика

Ок. Чё? фор аргв?

А вы что хотели? QCoreApplication::arguments и QCommandLineParser работают уже после создания QCoreApplication. А если вам нужно до них что-то распарсить - привет сишка.

RazrFalcon ★★★★★
()
Ответ на: комментарий от RazrFalcon

А если вам нужно до них что-то распарсить - привет сишка.

И почему бы не использовать в этом случае QString / QStringList? Они работают без создания всяких QCoreApplication / QApplication. Почему в доках уродливый qstrcmp и сишка?

EXL ★★★★★
()
Ответ на: комментарий от EXL

Эээ нее, я пробовал через стринглист — как только хочешь показать хелп — показываешь сегфолт. Т.е. апликейшн один хрен нужен для показа хелпа.

deep-purple ★★★★★
() автор топика
Последнее исправление: deep-purple (всего исправлений: 1)
Ответ на: комментарий от RazrFalcon

Я хотел чтобы там не было круговой зависимости.

deep-purple ★★★★★
() автор топика
Ответ на: комментарий от RazrFalcon

Еще немного на вентилятор:

    // OMFG!!!
    // https://forum.qt.io/topic/27646/qt-5-qapplication-linux-sporadically-segmentation-faults-clicking-windows-default-close-button
    int exitCode = app->exec();
    delete app;
    return exitCode;

deep-purple ★★★★★
() автор топика
Ответ на: комментарий от deep-purple

QCoreApplication синглтон, так что всё верно. Добро пожаловать в мир С++.

RazrFalcon ★★★★★
()
Последнее исправление: RazrFalcon (всего исправлений: 1)
Ответ на: комментарий от theNamelessOne

И как называется тот нормальный парсер в вакууме который делает искаропки так как мне нужно?

deep-purple ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.