mirror of
https://github.com/wang-bin/QtAV.git
synced 2026-10-16 20:21:20 +08:00
ce21c55b6e
no qml. examples are wip. fix #1381, #1294, #1389
379 lines
11 KiB
C++
379 lines
11 KiB
C++
/******************************************************************************
|
|
QOptions: make command line options easy. https://github.com/wang-bin/qoptions
|
|
Copyright (C) 2011-2022 Wang Bin <wbsecg1@gmail.com>
|
|
|
|
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 the 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 "qoptions.h"
|
|
#include <QtCore/QStringList>
|
|
#include <QtCore/QtDebug>
|
|
|
|
QOption::QOption()
|
|
{}
|
|
|
|
QOption::QOption(const char *name, const QVariant &defaultValue, Type type, const QString &description)
|
|
:mType(type),mDescription(description),mDefaultValue(defaultValue)
|
|
{
|
|
setName(QLatin1String(name));
|
|
}
|
|
|
|
QOption::QOption(const char *name, Type type, const QString &description)
|
|
:mType(type),mDescription(description),mDefaultValue(QVariant())
|
|
{
|
|
//if (mType==QOption::NoToken)
|
|
// mValue = false;
|
|
setName(QLatin1String(name));
|
|
}
|
|
/*
|
|
QOption::QOption(const char *name, const QVariant& value, Type type, const QString &description)
|
|
:mType(type),mDescription(description),mDefaultValue(*value),mValue(value)
|
|
{qDebug("%s %s %d", __FILE__, __FUNCTION__, __LINE__);
|
|
setName(name);
|
|
}
|
|
*/
|
|
|
|
QString QOption::shortName() const
|
|
{
|
|
return mShortName;
|
|
}
|
|
|
|
QString QOption::longName() const
|
|
{
|
|
return mLongName;
|
|
}
|
|
|
|
QString QOption::formatName() const
|
|
{
|
|
if (mLongName.isEmpty())
|
|
return QLatin1String("-") + mShortName;
|
|
if (mShortName.isEmpty())
|
|
return QLatin1String("--") + mLongName;
|
|
return QString::fromLatin1("-%1 [--%2]").arg(mShortName).arg(mLongName);
|
|
}
|
|
|
|
QString QOption::description() const
|
|
{
|
|
return mDescription;
|
|
}
|
|
|
|
QVariant QOption::value() const
|
|
{
|
|
if (mValue.isValid())
|
|
return mValue;
|
|
return mDefaultValue;
|
|
}
|
|
|
|
void QOption::setValue(const QVariant &value)
|
|
{
|
|
mValue = value;
|
|
}
|
|
|
|
bool QOption::isSet() const
|
|
{
|
|
return mValue.isValid();
|
|
}
|
|
|
|
bool QOption::isValid() const
|
|
{
|
|
return !shortName().isEmpty() || !longName().isEmpty();
|
|
}
|
|
|
|
void QOption::setType(QOption::Type type)
|
|
{
|
|
mType = type;
|
|
if (mType==NoToken)
|
|
mValue = false;
|
|
}
|
|
|
|
QOption::Type QOption::type() const
|
|
{
|
|
return mType;
|
|
}
|
|
|
|
QString QOption::help() const
|
|
{
|
|
QString message = formatName();
|
|
if (type()==QOption::SingleToken)
|
|
message.append(QLatin1String(" value"));
|
|
else if (type()==QOption::MultiToken)
|
|
message.append(QLatin1String(" value1 ... valueN"));
|
|
|
|
message = QString::fromLatin1("%1").arg(message, -33);
|
|
message.append(mDescription);
|
|
if (mDefaultValue.isValid() && !mDefaultValue.toString().isEmpty())
|
|
message.append(QLatin1String(" (default: ") + mDefaultValue.toString() + QLatin1String(")"));
|
|
return message;
|
|
}
|
|
|
|
bool QOption::operator <(const QOption& o) const
|
|
{
|
|
return mType < o.type() || mShortName < o.shortName() || mLongName < o.longName() || mDescription < o.description();
|
|
}
|
|
|
|
static QString get_short(const QString& name)
|
|
{
|
|
if (name.startsWith(QLatin1String("--")))
|
|
return QString();
|
|
if (name.startsWith(QLatin1String("-")))
|
|
return name.mid(1);
|
|
return name;
|
|
}
|
|
|
|
static QString get_long(const QString& name)
|
|
{
|
|
if (name.startsWith(QLatin1String("--")))
|
|
return name.mid(2);
|
|
if (name.startsWith(QLatin1String("-")))
|
|
return QString();
|
|
return name;
|
|
}
|
|
|
|
void QOption::setName(const QString &name)
|
|
{
|
|
int comma = name.indexOf(QLatin1Char(','));
|
|
if (comma>0) {
|
|
QString name1 = name.left(comma);
|
|
QString name2 = name.mid(comma+1);
|
|
if (name1.startsWith(QLatin1String("--"))) {
|
|
mLongName = name1.mid(2);
|
|
mShortName = get_short(name2);
|
|
} else if (name1.startsWith(QLatin1String("-"))) {
|
|
mShortName = name1.mid(1);
|
|
mLongName = get_long(name2);
|
|
} else {
|
|
if (name2.startsWith(QLatin1String("--"))) {
|
|
mLongName = name2.mid(2);
|
|
mShortName = name1;
|
|
} else if (name2.startsWith(QLatin1String("-"))) {
|
|
mShortName = name2.mid(1);
|
|
mLongName = name1;
|
|
} else {
|
|
mShortName = name2;
|
|
mLongName = name1;
|
|
}
|
|
}
|
|
} else {
|
|
if (name.startsWith(QLatin1String("--")))
|
|
mLongName = name.mid(2);
|
|
else if (name.startsWith(QLatin1String("-")))
|
|
mShortName = name.mid(1);
|
|
else
|
|
mShortName = name;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
QOptions::QOptions()
|
|
{
|
|
}
|
|
|
|
QOptions::~QOptions()
|
|
{
|
|
mOptionGroupMap.clear();
|
|
mOptions.clear();
|
|
}
|
|
|
|
bool QOptions::parse(int argc, const char *const*argv)
|
|
{
|
|
if (mOptionGroupMap.isEmpty())
|
|
return false;
|
|
|
|
if (argc==1)
|
|
return true;
|
|
|
|
bool result = true;
|
|
QStringList args;
|
|
for (int i=1;i<argc;++i) {
|
|
args.append(QString::fromLocal8Bit(argv[i]));
|
|
}
|
|
|
|
QStringList::Iterator it = args.begin();
|
|
QList<QOption>::Iterator it_list;
|
|
mOptions = mOptionGroupMap.keys();
|
|
|
|
while (it != args.end()) {
|
|
if (it->startsWith(QLatin1String("--"))) {
|
|
int e = it->indexOf(QLatin1Char('='));
|
|
for (it_list = mOptions.begin(); it_list != mOptions.end(); ++it_list) {
|
|
if (it_list->longName() == it->mid(2,e-2)) {
|
|
if (it_list->type()==QOption::NoToken) {
|
|
it_list->setValue(true);
|
|
//qDebug("%d %s", __LINE__, qPrintable(it_list->value().toString()));
|
|
it = args.erase(it);
|
|
break;
|
|
}
|
|
if (e>0) { //
|
|
it_list->setValue(it->mid(e+1));
|
|
//qDebug("%d %s", __LINE__, qPrintable(it_list->value().toString()));
|
|
} else {
|
|
it = args.erase(it);
|
|
if (it == args.end())
|
|
break;
|
|
it_list->setValue(*it);
|
|
//qDebug("%d %s", __LINE__, qPrintable(it_list->value().toString()));
|
|
}
|
|
it = args.erase(it);
|
|
break;
|
|
}
|
|
}
|
|
if (it_list == mOptions.end()) {
|
|
qWarning() << "unknown option: " << *it;
|
|
result = false;
|
|
++it;
|
|
}
|
|
//handle unknown option
|
|
} else if (it->startsWith(QLatin1Char('-'))) {
|
|
for (it_list = mOptions.begin(); it_list != mOptions.end(); ++it_list) {
|
|
QString sname = it_list->shortName();
|
|
int sname_len = sname.length(); //usally is 1
|
|
//TODO: startsWith(-height,-h) Not endsWith, -oabco
|
|
if (it->mid(1).compare(sname) == 0) {
|
|
if (it_list->type() == QOption::NoToken) {
|
|
it_list->setValue(true);
|
|
it = args.erase(it);
|
|
break;
|
|
}
|
|
if (it->length() == sname_len+1) {//-o abco
|
|
it = args.erase(it);
|
|
if (it == args.end())
|
|
break;
|
|
it_list->setValue(*it);
|
|
//qDebug("%d %s", __LINE__, qPrintable(it_list->value().toString()));
|
|
} else {
|
|
it_list->setValue(it->mid(sname_len+1));
|
|
//qDebug("%d %s", __LINE__, qPrintable(it_list->value().toString()));
|
|
}
|
|
it = args.erase(it);
|
|
break;
|
|
}
|
|
}
|
|
if (it_list==mOptions.end()) {
|
|
qWarning() << "unknown option: " << *it;
|
|
result = false;
|
|
++it;
|
|
}
|
|
//handle unknown option
|
|
} else {
|
|
qWarning() << "unknown option: " << *it;
|
|
++it;
|
|
}
|
|
}
|
|
if (!result) {
|
|
print();
|
|
}
|
|
return result;
|
|
}
|
|
|
|
QOptions& QOptions::add(const QString &group_description)
|
|
{
|
|
mCurrentDescription = group_description;
|
|
return *this;
|
|
}
|
|
|
|
QOptions& QOptions::addDescription(const QString &description)
|
|
{
|
|
mDescription = description;
|
|
return *this;
|
|
}
|
|
|
|
QOptions& QOptions::operator ()(const char* name, const QString& description)
|
|
{
|
|
QOption op(name, QOption::NoToken, description);
|
|
mOptions.append(op);
|
|
mOptionGroupMap.insert(op, mCurrentDescription);
|
|
return *this;
|
|
}
|
|
|
|
QOptions& QOptions::operator ()(const char* name, QOption::Type type, const QString& description)
|
|
{
|
|
QOption op(name, type, description);
|
|
mOptions.append(op);
|
|
mOptionGroupMap.insert(op, mCurrentDescription);
|
|
return *this;
|
|
}
|
|
|
|
QOptions& QOptions::operator ()(const char* name, const QVariant& defaultValue, const QString& description)
|
|
{
|
|
QOption op(name, defaultValue, QOption::SingleToken, description);
|
|
mOptions.append(op);
|
|
mOptionGroupMap.insert(op, mCurrentDescription);
|
|
return *this;
|
|
}
|
|
|
|
QOptions& QOptions::operator ()(const char* name, const QVariant& defaultValue, QOption::Type type, const QString& description)
|
|
{
|
|
QOption op(name, defaultValue, type, description);
|
|
mOptions.append(op);
|
|
mOptionGroupMap.insert(op, mCurrentDescription);
|
|
return *this;
|
|
}
|
|
/*
|
|
|
|
QOptions& QOptions::operator ()(const char* name, const QVariant& value, QOption::Type type, const QString& description)
|
|
{
|
|
QOption op(name, value, type, description);
|
|
mOptions.append(op);
|
|
mOptionGroupMap.insert(op, mCurrentDescription);
|
|
return *this;
|
|
}
|
|
*/
|
|
|
|
QOption QOptions::option(const QString &name) const
|
|
{
|
|
if (mOptions.isEmpty())
|
|
return QOption();
|
|
QList<QOption>::ConstIterator it_list;
|
|
for (it_list=mOptions.constBegin(); it_list!=mOptions.constEnd(); ++it_list) {
|
|
if (it_list->shortName()==name || it_list->longName()==name) {
|
|
return *it_list;
|
|
}
|
|
}
|
|
return QOption();
|
|
}
|
|
|
|
QVariant QOptions::value(const QString& name) const
|
|
{
|
|
return option(name).value();
|
|
}
|
|
|
|
QVariant QOptions::operator [](const QString& name) const
|
|
{
|
|
return value(name);
|
|
}
|
|
|
|
QString QOptions::help() const
|
|
{
|
|
QString message = mDescription;
|
|
QStringList groups = mOptionGroupMap.values();
|
|
groups.removeDuplicates();
|
|
QList<QString>::ConstIterator it;
|
|
|
|
QList<QOption>::ConstIterator it_op;
|
|
for (it=groups.constBegin(); it!=groups.constEnd(); ++it) {
|
|
message.append(QLatin1String("\n")).append(*it);
|
|
QList<QOption> options = mOptionGroupMap.keys(*it);
|
|
for (it_op=options.constBegin();it_op!=options.constEnd();++it_op)
|
|
message.append(QLatin1String("\n ")).append(it_op->help());
|
|
}
|
|
return message;
|
|
}
|
|
|
|
void QOptions::print() const
|
|
{
|
|
qDebug("%s", help().toUtf8().constData());
|
|
}
|