4#include "abstractcommand.h"
36 #
if (QT_VERSION < QT_VERSION_CHECK(6, 2, 0))
39 &PokitDiscoveryAgent::errorOccurred,
42 qCWarning(lc).noquote() <<
tr(
"Bluetooth discovery error:") << error;
109 for (index=0; (index < siPrefixes.
length()-1) && (qAbs(value) * qPow(1000.0, (
double)index) < 1); ++index);
115 for (nonZeroPos = number.
length()-1; (nonZeroPos > decimalPos) && (number.
at(nonZeroPos) == u
'0'); --nonZeroPos);
116 number.
truncate((nonZeroPos == decimalPos) ? nonZeroPos : nonZeroPos+1);
118 return QString(u
"%1%2"_s).
arg(number, siPrefixes.
at(index));
136 return uR
"("%1")"_s.arg(QString(field).replace('"'_L1, uR
"("")"_s));
155template<
typename R>
constexpr Ratio makeRatio() {
return Ratio{ R::num, R::den }; }
173template<
typename R,
typename T>
177 {
'E'_L1, makeRatio<std::exa>() },
178 {
'P'_L1, makeRatio<std::peta>() },
179 {
'T'_L1, makeRatio<std::tera>() },
180 {
'G'_L1, makeRatio<std::giga>() },
181 {
'M'_L1, makeRatio<std::mega>() },
182 {
'K'_L1, makeRatio<std::kilo>() },
183 {
'k'_L1, makeRatio<std::kilo>() },
184 {
'h'_L1, makeRatio<std::hecto>() },
185 {
'd'_L1, makeRatio<std::deci>() },
186 {
'c'_L1, makeRatio<std::centi>() },
187 {
'm'_L1, makeRatio<std::milli>() },
188 {
'u'_L1, makeRatio<std::micro>() },
189 {
QChar(0x00B5), makeRatio<std::micro>() },
190 {
QChar(0x03BC), makeRatio<std::micro>() },
191 {
'n'_L1, makeRatio<std::nano>() },
192 {
'p'_L1, makeRatio<std::pico>() },
193 {
'f'_L1, makeRatio<std::femto>() },
194 {
'a'_L1, makeRatio<std::atto>() },
202 ratio = makeRatio<std::ratio<1>>();
207 #if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0))
210 const QChar siPrefix = number.
at(number.
size() - 1);
212 const auto iter = unitPrefixScaleMap.
constFind(siPrefix);
213 if (iter != unitPrefixScaleMap.
constEnd()) {
214 Q_ASSERT(iter->isValid());
222 if (
const qulonglong integer = locale.
toULongLong(number, &ok); (ok)) {
224 return static_cast<T
>(integer);
226 #define DOKIT_RESULT(var) (static_cast<T>(var) * ratio.num * R::den / ratio.den / R::num)
228 for (ratio = makeRatio<R>(); DOKIT_RESULT(integer) < sensibleMinimum; ratio.
num *= 1000);
230 return DOKIT_RESULT(integer);
235 if (
const double dbl = locale.
toDouble(number, &ok); (ok) && (dbl > 0.0)) {
237 return static_cast<T
>(dbl);
239 #define DOKIT_RESULT(var) (var * ratio.num * R::den / ratio.den / R::num)
241 for (ratio = makeRatio<R>(); DOKIT_RESULT(dbl) < sensibleMinimum; ratio.
num *= 1000);
243 return (std::is_integral_v<T>) ?
static_cast<T
>(std::llround(DOKIT_RESULT(dbl))) : DOKIT_RESULT(dbl);
248 return (std::numeric_limits<T>::has_quiet_NaN) ? std::numeric_limits<T>::quiet_NaN() : 0;
251#define DOKIT_INSTANTIATE_TEMPLATE_FUNCTION(Ratio, Type) template \
252Type AbstractCommand::parseNumber<Ratio>(const QString &value, const QString &unit, const Type sensibleMinimum)
253DOKIT_INSTANTIATE_TEMPLATE_FUNCTION(std::exa, quint32);
254DOKIT_INSTANTIATE_TEMPLATE_FUNCTION(std::peta, quint32);
255DOKIT_INSTANTIATE_TEMPLATE_FUNCTION(std::tera, quint32);
256DOKIT_INSTANTIATE_TEMPLATE_FUNCTION(std::giga, quint32);
257DOKIT_INSTANTIATE_TEMPLATE_FUNCTION(std::mega, quint32);
258DOKIT_INSTANTIATE_TEMPLATE_FUNCTION(std::kilo, quint32);
259DOKIT_INSTANTIATE_TEMPLATE_FUNCTION(std::hecto, quint32);
260DOKIT_INSTANTIATE_TEMPLATE_FUNCTION(std::deca, quint32);
261DOKIT_INSTANTIATE_TEMPLATE_FUNCTION(std::ratio<1>, quint32);
262DOKIT_INSTANTIATE_TEMPLATE_FUNCTION(std::ratio<1>,
float);
263DOKIT_INSTANTIATE_TEMPLATE_FUNCTION(std::deci, quint32);
264DOKIT_INSTANTIATE_TEMPLATE_FUNCTION(std::centi, quint32);
265DOKIT_INSTANTIATE_TEMPLATE_FUNCTION(std::milli, quint32);
266DOKIT_INSTANTIATE_TEMPLATE_FUNCTION(std::micro, quint32);
267DOKIT_INSTANTIATE_TEMPLATE_FUNCTION(std::nano, quint32);
268DOKIT_INSTANTIATE_TEMPLATE_FUNCTION(std::pico, quint32);
269DOKIT_INSTANTIATE_TEMPLATE_FUNCTION(std::femto, quint32);
270DOKIT_INSTANTIATE_TEMPLATE_FUNCTION(std::atto, quint32);
271#undef DOKIT_INSTANTIATE_TEMPLATE_FUNCTION
302 for (
const QString &option: suppliedOptionNames) {
303 if (!supportedOptionNames.
contains(option)) {
304 qCInfo(lc).noquote() <<
tr(
"Ignoring option: %1").
arg(option);
310 if (parser.
isSet(u
"device"_s)) {
315 if ((supportedOptionNames.
contains(u
"output"_s)) &&
316 (parser.
isSet(u
"output"_s)))
319 if (output == u
"csv"_s) {
321 }
else if (output == u
"json"_s) {
323 }
else if (output == u
"text"_s) {
326 errors.
append(
tr(
"Unknown output format: %1").arg(output));
331 if (parser.
isSet(u
"timeout"_s)) {
334 errors.
append(
tr(
"Invalid timeout: %1").arg(parser.
value(u
"timeout"_s)));
336 qCWarning(lc).noquote() <<
tr(
"Platform does not support Bluetooth scan timeout");
339 qCDebug(lc).noquote() <<
tr(
"Set scan timeout to %1").
arg(
346 for (
const QString &option: requiredOptionNames) {
347 if (!parser.
isSet(option)) {
348 errors.
append(
tr(
"Missing required option: %1").arg(option));
QString deviceToScanFor
Device (if any) that were passed to processOptions().
AbstractCommand(QObject *const parent=nullptr)
Constructs a new command with parent.
virtual QStringList supportedOptions(const QCommandLineParser &parser) const
Returns a list of CLI option names supported by this command.
static QString appendSiPrefix(const double value, int precision=6)
Returns a human-readable version of value, with up-to precision decimal digits, and SI unit prefix wh...
static T parseNumber(const QString &value, const QString &unit, const T sensibleMinimum=0)
Returns value as an integer multiple of the ratio R, as number of type T.
virtual void deviceDiscovered(const QBluetoothDeviceInfo &info)=0
Handles PokitDiscoveryAgent::pokitDeviceDiscovered signal.
PokitDiscoveryAgent * discoveryAgent
Agent for Pokit device discovery.
OutputFormat format
Selected output format.
@ Text
Plain unstructured text.
@ Csv
RFC 4180 compliant CSV text.
@ Json
RFC 8259 compliant JSON text.
virtual QStringList processOptions(const QCommandLineParser &parser)
Processes the relevant options from the command line parser.
virtual void deviceDiscoveryFinished()=0
Handles PokitDiscoveryAgent::deviceDiscoveryFinished signal.
static QString escapeCsvField(const QString &field)
Returns an RFC 4180 compliant version of field.
virtual QStringList requiredOptions(const QCommandLineParser &parser) const
Returns a list of CLI option names required by this command.
The PokitDiscoveryAgent class discovers nearby Pokit devices.
void pokitDeviceDiscovered(const QBluetoothDeviceInfo &info)
This signal is emitted when the Pokit device described by info is discovered.
Declares the PokitDevice class.
Declares the PokitDiscoveryAgent class.
QBluetoothDeviceDiscoveryAgent::Error error() const const
bool isSet(const QString &name) const const
QStringList optionNames() const const
QString value(const QString &optionName) const const
void exit(int returnCode)
QCoreApplication * instance()
void append(const T &value)
const T & at(int i) const const
double toDouble(const QString &s, bool *ok) const const
qulonglong toULongLong(const QString &s, bool *ok) const const
QMap::const_iterator constEnd() const const
QMap::const_iterator constFind(const Key &key) const const
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QObject * parent() const const
QString tr(const char *sourceText, const char *disambiguation, int n)
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
const QChar at(int position) const const
bool contains(QChar ch, Qt::CaseSensitivity cs) const const
bool endsWith(const QString &s, Qt::CaseSensitivity cs) const const
int indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const const
bool isEmpty() const const
QString number(int n, int base)
QString toLower() const const
QString trimmed() const const
void truncate(int position)
bool contains(const QString &str, Qt::CaseSensitivity cs) const const
Declares the DOKIT_USE_STRINGLITERALS macro, and related functions.
#define DOKIT_STRING_INDEX_TYPE
Internal macro for matching the index type used by QString methods.
#define DOKIT_USE_STRINGLITERALS
Internal macro for using either official Qt string literals (added in Qt 6.4), or our own equivalent ...
std::intmax_t num
Numerator.
bool isValid() const
Returns true if both num and den are non-zero.