mirror of
https://bitbucket.org/librepilot/librepilot.git
synced 2024-12-01 09:24:10 +01:00
Conflicts:
ground/openpilotgcs/src/plugins/uavobjectbrowser/uavobjectbrowserconfiguration.cpp ground/openpilotgcs/src/plugins/uavobjectbrowser/uavobjectbrowserwidget.cpp ground/openpilotgcs/src/plugins/uavobjectbrowser/uavobjectbrowserwidget.h
This commit is contained in:
commit
77ebb4fe74
559
ground/openpilotgcs/src/libs/utils/mustache.cpp
Normal file
559
ground/openpilotgcs/src/libs/utils/mustache.cpp
Normal file
@ -0,0 +1,559 @@
|
||||
/*
|
||||
Copyright 2012, Robert Knight
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
*/
|
||||
|
||||
#include "mustache.h"
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QFile>
|
||||
#include <QtCore/QStringList>
|
||||
#include <QtCore/QTextStream>
|
||||
|
||||
using namespace Mustache;
|
||||
|
||||
QString Mustache::renderTemplate(const QString & templateString, const QVariantHash & args)
|
||||
{
|
||||
Mustache::QtVariantContext context(args);
|
||||
Mustache::Renderer renderer;
|
||||
|
||||
return renderer.render(templateString, &context);
|
||||
}
|
||||
|
||||
QString escapeHtml(const QString & input)
|
||||
{
|
||||
QString escaped(input);
|
||||
|
||||
for (int i = 0; i < escaped.count();) {
|
||||
const char *replacement = 0;
|
||||
ushort ch = escaped.at(i).unicode();
|
||||
if (ch == '&') {
|
||||
replacement = "&";
|
||||
} else if (ch == '<') {
|
||||
replacement = "<";
|
||||
} else if (ch == '>') {
|
||||
replacement = ">";
|
||||
} else if (ch == '"') {
|
||||
replacement = """;
|
||||
}
|
||||
if (replacement) {
|
||||
escaped.replace(i, 1, QLatin1String(replacement));
|
||||
i += strlen(replacement);
|
||||
} else {
|
||||
++i;
|
||||
}
|
||||
}
|
||||
return escaped;
|
||||
}
|
||||
|
||||
QString unescapeHtml(const QString & escaped)
|
||||
{
|
||||
QString unescaped(escaped);
|
||||
|
||||
unescaped.replace(QLatin1String("<"), QLatin1String("<"));
|
||||
unescaped.replace(QLatin1String(">"), QLatin1String(">"));
|
||||
unescaped.replace(QLatin1String("&"), QLatin1String("&"));
|
||||
unescaped.replace(QLatin1String("""), QLatin1String("\""));
|
||||
return unescaped;
|
||||
}
|
||||
|
||||
Context::Context(PartialResolver *resolver)
|
||||
: m_partialResolver(resolver)
|
||||
{}
|
||||
|
||||
PartialResolver *Context::partialResolver() const
|
||||
{
|
||||
return m_partialResolver;
|
||||
}
|
||||
|
||||
QString Context::partialValue(const QString & key) const
|
||||
{
|
||||
if (!m_partialResolver) {
|
||||
return QString();
|
||||
}
|
||||
return m_partialResolver->getPartial(key);
|
||||
}
|
||||
|
||||
bool Context::canEval(const QString &) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
QString Context::eval(const QString & key, const QString & _template, Renderer *renderer)
|
||||
{
|
||||
Q_UNUSED(key);
|
||||
Q_UNUSED(_template);
|
||||
Q_UNUSED(renderer);
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
QtVariantContext::QtVariantContext(const QVariant & root, PartialResolver *resolver)
|
||||
: Context(resolver)
|
||||
{
|
||||
m_contextStack << root;
|
||||
}
|
||||
|
||||
QVariant variantMapValue(const QVariant & value, const QString & key)
|
||||
{
|
||||
if (value.userType() == QVariant::Map) {
|
||||
return value.toMap().value(key);
|
||||
} else {
|
||||
return value.toHash().value(key);
|
||||
}
|
||||
}
|
||||
|
||||
QVariant variantMapValueForKeyPath(const QVariant & value, const QStringList keyPath)
|
||||
{
|
||||
if (keyPath.count() > 1) {
|
||||
QVariant firstValue = variantMapValue(value, keyPath.first());
|
||||
return firstValue.isNull() ? QVariant() : variantMapValueForKeyPath(firstValue, keyPath.mid(1));
|
||||
} else if (!keyPath.isEmpty()) {
|
||||
return variantMapValue(value, keyPath.first());
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QVariant QtVariantContext::value(const QString & key) const
|
||||
{
|
||||
if (key == "." && !m_contextStack.isEmpty()) {
|
||||
return m_contextStack.last();
|
||||
}
|
||||
QStringList keyPath = key.split(".");
|
||||
for (int i = m_contextStack.count() - 1; i >= 0; i--) {
|
||||
QVariant value = variantMapValueForKeyPath(m_contextStack.at(i), keyPath);
|
||||
if (!value.isNull()) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
bool QtVariantContext::isFalse(const QString & key) const
|
||||
{
|
||||
QVariant value = this->value(key);
|
||||
|
||||
switch (value.userType()) {
|
||||
case QVariant::Bool:
|
||||
return !value.toBool();
|
||||
|
||||
case QVariant::List:
|
||||
return value.toList().isEmpty();
|
||||
|
||||
case QVariant::Hash:
|
||||
return value.toHash().isEmpty();
|
||||
|
||||
case QVariant::Map:
|
||||
return value.toMap().isEmpty();
|
||||
|
||||
default:
|
||||
return value.toString().isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
QString QtVariantContext::stringValue(const QString & key) const
|
||||
{
|
||||
if (isFalse(key)) {
|
||||
return QString();
|
||||
}
|
||||
return value(key).toString();
|
||||
}
|
||||
|
||||
void QtVariantContext::push(const QString & key, int index)
|
||||
{
|
||||
QVariant mapItem = value(key);
|
||||
|
||||
if (index == -1) {
|
||||
m_contextStack << mapItem;
|
||||
} else {
|
||||
QVariantList list = mapItem.toList();
|
||||
m_contextStack << list.value(index, QVariant());
|
||||
}
|
||||
}
|
||||
|
||||
void QtVariantContext::pop()
|
||||
{
|
||||
m_contextStack.pop();
|
||||
}
|
||||
|
||||
int QtVariantContext::listCount(const QString & key) const
|
||||
{
|
||||
if (value(key).userType() == QVariant::List) {
|
||||
return value(key).toList().count();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool QtVariantContext::canEval(const QString & key) const
|
||||
{
|
||||
return value(key).canConvert<fn_t>();
|
||||
}
|
||||
|
||||
QString QtVariantContext::eval(const QString & key, const QString & _template, Renderer *renderer)
|
||||
{
|
||||
QVariant fn = value(key);
|
||||
|
||||
if (fn.isNull()) {
|
||||
return QString();
|
||||
}
|
||||
return fn.value<fn_t>() (_template, renderer, this);
|
||||
}
|
||||
|
||||
PartialMap::PartialMap(const QHash<QString, QString> & partials)
|
||||
: m_partials(partials)
|
||||
{}
|
||||
|
||||
QString PartialMap::getPartial(const QString & name)
|
||||
{
|
||||
return m_partials.value(name);
|
||||
}
|
||||
|
||||
PartialFileLoader::PartialFileLoader(const QString & basePath)
|
||||
: m_basePath(basePath)
|
||||
{}
|
||||
|
||||
QString PartialFileLoader::getPartial(const QString & name)
|
||||
{
|
||||
if (!m_cache.contains(name)) {
|
||||
QString path = m_basePath + '/' + name + ".mustache";
|
||||
QFile file(path);
|
||||
if (file.open(QIODevice::ReadOnly)) {
|
||||
QTextStream stream(&file);
|
||||
m_cache.insert(name, stream.readAll());
|
||||
}
|
||||
}
|
||||
return m_cache.value(name);
|
||||
}
|
||||
|
||||
Renderer::Renderer()
|
||||
: m_errorPos(-1)
|
||||
, m_defaultTagStartMarker("{{")
|
||||
, m_defaultTagEndMarker("}}")
|
||||
{}
|
||||
|
||||
QString Renderer::error() const
|
||||
{
|
||||
return m_error;
|
||||
}
|
||||
|
||||
int Renderer::errorPos() const
|
||||
{
|
||||
return m_errorPos;
|
||||
}
|
||||
|
||||
QString Renderer::errorPartial() const
|
||||
{
|
||||
return m_errorPartial;
|
||||
}
|
||||
|
||||
QString Renderer::render(const QString & _template, Context *context)
|
||||
{
|
||||
m_error.clear();
|
||||
m_errorPos = -1;
|
||||
m_errorPartial.clear();
|
||||
|
||||
m_tagStartMarker = m_defaultTagStartMarker;
|
||||
m_tagEndMarker = m_defaultTagEndMarker;
|
||||
|
||||
return render(_template, 0, _template.length(), context);
|
||||
}
|
||||
|
||||
QString Renderer::render(const QString & _template, int startPos, int endPos, Context *context)
|
||||
{
|
||||
QString output;
|
||||
int lastTagEnd = startPos;
|
||||
|
||||
while (m_errorPos == -1) {
|
||||
Tag tag = findTag(_template, lastTagEnd, endPos);
|
||||
if (tag.type == Tag::Null) {
|
||||
output += _template.midRef(lastTagEnd, endPos - lastTagEnd);
|
||||
break;
|
||||
}
|
||||
output += _template.midRef(lastTagEnd, tag.start - lastTagEnd);
|
||||
switch (tag.type) {
|
||||
case Tag::Value:
|
||||
{
|
||||
QString value = context->stringValue(tag.key);
|
||||
if (tag.escapeMode == Tag::Escape) {
|
||||
value = escapeHtml(value);
|
||||
} else if (tag.escapeMode == Tag::Unescape) {
|
||||
value = unescapeHtml(value);
|
||||
}
|
||||
output += value;
|
||||
lastTagEnd = tag.end;
|
||||
}
|
||||
break;
|
||||
case Tag::SectionStart:
|
||||
{
|
||||
Tag endTag = findEndTag(_template, tag, endPos);
|
||||
if (endTag.type == Tag::Null) {
|
||||
if (m_errorPos == -1) {
|
||||
setError("No matching end tag found for section", tag.start);
|
||||
}
|
||||
} else {
|
||||
int listCount = context->listCount(tag.key);
|
||||
if (listCount > 0) {
|
||||
for (int i = 0; i < listCount; i++) {
|
||||
context->push(tag.key, i);
|
||||
output += render(_template, tag.end, endTag.start, context);
|
||||
context->pop();
|
||||
}
|
||||
} else if (context->canEval(tag.key)) {
|
||||
output += context->eval(tag.key, _template.mid(tag.end, endTag.start - tag.end), this);
|
||||
} else if (!context->isFalse(tag.key)) {
|
||||
context->push(tag.key);
|
||||
output += render(_template, tag.end, endTag.start, context);
|
||||
context->pop();
|
||||
}
|
||||
lastTagEnd = endTag.end;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Tag::InvertedSectionStart:
|
||||
{
|
||||
Tag endTag = findEndTag(_template, tag, endPos);
|
||||
if (endTag.type == Tag::Null) {
|
||||
if (m_errorPos == -1) {
|
||||
setError("No matching end tag found for inverted section", tag.start);
|
||||
}
|
||||
} else {
|
||||
if (context->isFalse(tag.key)) {
|
||||
output += render(_template, tag.end, endTag.start, context);
|
||||
}
|
||||
lastTagEnd = endTag.end;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Tag::SectionEnd:
|
||||
setError("Unexpected end tag", tag.start);
|
||||
lastTagEnd = tag.end;
|
||||
break;
|
||||
case Tag::Partial:
|
||||
{
|
||||
QString tagStartMarker = m_tagStartMarker;
|
||||
QString tagEndMarker = m_tagEndMarker;
|
||||
|
||||
m_tagStartMarker = m_defaultTagStartMarker;
|
||||
m_tagEndMarker = m_defaultTagEndMarker;
|
||||
|
||||
m_partialStack.push(tag.key);
|
||||
|
||||
QString partial = context->partialValue(tag.key);
|
||||
output += render(partial, 0, partial.length(), context);
|
||||
lastTagEnd = tag.end;
|
||||
|
||||
m_partialStack.pop();
|
||||
|
||||
m_tagStartMarker = tagStartMarker;
|
||||
m_tagEndMarker = tagEndMarker;
|
||||
}
|
||||
break;
|
||||
case Tag::SetDelimiter:
|
||||
lastTagEnd = tag.end;
|
||||
break;
|
||||
case Tag::Comment:
|
||||
lastTagEnd = tag.end;
|
||||
break;
|
||||
case Tag::Null:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
void Renderer::setError(const QString & error, int pos)
|
||||
{
|
||||
Q_ASSERT(!error.isEmpty());
|
||||
Q_ASSERT(pos >= 0);
|
||||
|
||||
m_error = error;
|
||||
m_errorPos = pos;
|
||||
|
||||
if (!m_partialStack.isEmpty()) {
|
||||
m_errorPartial = m_partialStack.top();
|
||||
}
|
||||
}
|
||||
|
||||
Tag Renderer::findTag(const QString & content, int pos, int endPos)
|
||||
{
|
||||
int tagStartPos = content.indexOf(m_tagStartMarker, pos);
|
||||
|
||||
if (tagStartPos == -1 || tagStartPos >= endPos) {
|
||||
return Tag();
|
||||
}
|
||||
|
||||
int tagEndPos = content.indexOf(m_tagEndMarker, tagStartPos + m_tagStartMarker.length());
|
||||
if (tagEndPos == -1) {
|
||||
return Tag();
|
||||
}
|
||||
tagEndPos += m_tagEndMarker.length();
|
||||
|
||||
Tag tag;
|
||||
tag.type = Tag::Value;
|
||||
tag.start = tagStartPos;
|
||||
tag.end = tagEndPos;
|
||||
|
||||
pos = tagStartPos + m_tagStartMarker.length();
|
||||
endPos = tagEndPos - m_tagEndMarker.length();
|
||||
|
||||
QChar typeChar = content.at(pos);
|
||||
|
||||
if (typeChar == '#') {
|
||||
tag.type = Tag::SectionStart;
|
||||
tag.key = readTagName(content, pos + 1, endPos);
|
||||
} else if (typeChar == '^') {
|
||||
tag.type = Tag::InvertedSectionStart;
|
||||
tag.key = readTagName(content, pos + 1, endPos);
|
||||
} else if (typeChar == '/') {
|
||||
tag.type = Tag::SectionEnd;
|
||||
tag.key = readTagName(content, pos + 1, endPos);
|
||||
} else if (typeChar == '!') {
|
||||
tag.type = Tag::Comment;
|
||||
} else if (typeChar == '>') {
|
||||
tag.type = Tag::Partial;
|
||||
tag.key = readTagName(content, pos + 1, endPos);
|
||||
} else if (typeChar == '=') {
|
||||
tag.type = Tag::SetDelimiter;
|
||||
readSetDelimiter(content, pos + 1, tagEndPos - m_tagEndMarker.length());
|
||||
} else {
|
||||
if (typeChar == '&') {
|
||||
tag.escapeMode = Tag::Unescape;
|
||||
++pos;
|
||||
} else if (typeChar == '{') {
|
||||
tag.escapeMode = Tag::Raw;
|
||||
++pos;
|
||||
int endTache = content.indexOf('}', pos);
|
||||
if (endTache == tag.end - m_tagEndMarker.length()) {
|
||||
++tag.end;
|
||||
} else {
|
||||
endPos = endTache;
|
||||
}
|
||||
}
|
||||
tag.type = Tag::Value;
|
||||
tag.key = readTagName(content, pos, endPos);
|
||||
}
|
||||
|
||||
if (tag.type != Tag::Value) {
|
||||
expandTag(tag, content);
|
||||
}
|
||||
|
||||
return tag;
|
||||
}
|
||||
|
||||
QString Renderer::readTagName(const QString & content, int pos, int endPos)
|
||||
{
|
||||
QString name;
|
||||
|
||||
name.reserve(endPos - pos);
|
||||
while (content.at(pos).isSpace()) {
|
||||
++pos;
|
||||
}
|
||||
while (!content.at(pos).isSpace() && pos < endPos) {
|
||||
name += content.at(pos);
|
||||
++pos;
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
void Renderer::readSetDelimiter(const QString & content, int pos, int endPos)
|
||||
{
|
||||
QString startMarker;
|
||||
QString endMarker;
|
||||
|
||||
while (content.at(pos).isSpace() && pos < endPos) {
|
||||
++pos;
|
||||
}
|
||||
|
||||
while (!content.at(pos).isSpace() && pos < endPos) {
|
||||
if (content.at(pos) == '=') {
|
||||
setError("Custom delimiters may not contain '='.", pos);
|
||||
return;
|
||||
}
|
||||
startMarker += content.at(pos);
|
||||
++pos;
|
||||
}
|
||||
|
||||
while (content.at(pos).isSpace() && pos < endPos) {
|
||||
++pos;
|
||||
}
|
||||
|
||||
while (!content.at(pos).isSpace() && pos < endPos - 1) {
|
||||
if (content.at(pos) == '=') {
|
||||
setError("Custom delimiters may not contain '='.", pos);
|
||||
return;
|
||||
}
|
||||
endMarker += content.at(pos);
|
||||
++pos;
|
||||
}
|
||||
|
||||
m_tagStartMarker = startMarker;
|
||||
m_tagEndMarker = endMarker;
|
||||
}
|
||||
|
||||
Tag Renderer::findEndTag(const QString & content, const Tag & startTag, int endPos)
|
||||
{
|
||||
int tagDepth = 1;
|
||||
int pos = startTag.end;
|
||||
|
||||
while (true) {
|
||||
Tag nextTag = findTag(content, pos, endPos);
|
||||
if (nextTag.type == Tag::Null) {
|
||||
return nextTag;
|
||||
} else if (nextTag.type == Tag::SectionStart || nextTag.type == Tag::InvertedSectionStart) {
|
||||
++tagDepth;
|
||||
} else if (nextTag.type == Tag::SectionEnd) {
|
||||
--tagDepth;
|
||||
if (tagDepth == 0) {
|
||||
if (nextTag.key != startTag.key) {
|
||||
setError("Tag start/end key mismatch", nextTag.start);
|
||||
return Tag();
|
||||
}
|
||||
return nextTag;
|
||||
}
|
||||
}
|
||||
pos = nextTag.end;
|
||||
}
|
||||
|
||||
return Tag();
|
||||
}
|
||||
|
||||
void Renderer::setTagMarkers(const QString & startMarker, const QString & endMarker)
|
||||
{
|
||||
m_defaultTagStartMarker = startMarker;
|
||||
m_defaultTagEndMarker = endMarker;
|
||||
}
|
||||
|
||||
void Renderer::expandTag(Tag & tag, const QString & content)
|
||||
{
|
||||
int start = tag.start;
|
||||
int end = tag.end;
|
||||
|
||||
// Move start to beginning of line.
|
||||
while (start > 0 && content.at(start - 1) != QLatin1Char('\n')) {
|
||||
--start;
|
||||
if (!content.at(start).isSpace()) {
|
||||
return; // Not standalone.
|
||||
}
|
||||
}
|
||||
|
||||
// Move end to one past end of line.
|
||||
while (end <= content.size() && content.at(end - 1) != QLatin1Char('\n')) {
|
||||
if (end < content.size() && !content.at(end).isSpace()) {
|
||||
return; // Not standalone.
|
||||
}
|
||||
++end;
|
||||
}
|
||||
|
||||
tag.start = start;
|
||||
tag.end = end;
|
||||
}
|
266
ground/openpilotgcs/src/libs/utils/mustache.h
Normal file
266
ground/openpilotgcs/src/libs/utils/mustache.h
Normal file
@ -0,0 +1,266 @@
|
||||
/*
|
||||
Copyright 2012, Robert Knight
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/QStack>
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QVariant>
|
||||
|
||||
#include "utils_global.h"
|
||||
|
||||
#if __cplusplus >= 201103L
|
||||
#include <functional> /* for std::function */
|
||||
#endif
|
||||
|
||||
namespace Mustache {
|
||||
class PartialResolver;
|
||||
class Renderer;
|
||||
|
||||
/** Context is an interface that Mustache::Renderer::render() uses to
|
||||
* fetch substitutions for template tags.
|
||||
*/
|
||||
class QTCREATOR_UTILS_EXPORT Context {
|
||||
public:
|
||||
/** Create a context. @p resolver is used to fetch the expansions for any {{>partial}} tags
|
||||
* which appear in a template.
|
||||
*/
|
||||
explicit Context(PartialResolver *resolver = 0);
|
||||
virtual ~Context() {}
|
||||
|
||||
/** Returns a string representation of the value for @p key in the current context.
|
||||
* This is used to replace a Mustache value tag.
|
||||
*/
|
||||
virtual QString stringValue(const QString & key) const = 0;
|
||||
|
||||
/** Returns true if the value for @p key is 'false' or an empty list.
|
||||
* 'False' values typically include empty strings, the boolean value false etc.
|
||||
*
|
||||
* When processing a section Mustache tag, the section is not rendered if the key
|
||||
* is false, or for an inverted section tag, the section is only rendered if the key
|
||||
* is false.
|
||||
*/
|
||||
virtual bool isFalse(const QString & key) const = 0;
|
||||
|
||||
/** Returns the number of items in the list value for @p key or 0 if
|
||||
* the value for @p key is not a list.
|
||||
*/
|
||||
virtual int listCount(const QString & key) const = 0;
|
||||
|
||||
/** Set the current context to the value for @p key.
|
||||
* If index is >= 0, set the current context to the @p index'th value
|
||||
* in the list value for @p key.
|
||||
*/
|
||||
virtual void push(const QString & key, int index = -1) = 0;
|
||||
|
||||
/** Exit the current context. */
|
||||
virtual void pop() = 0;
|
||||
|
||||
/** Returns the partial template for a given @p key. */
|
||||
QString partialValue(const QString & key) const;
|
||||
|
||||
/** Returns the partial resolver passed to the constructor. */
|
||||
PartialResolver *partialResolver() const;
|
||||
|
||||
/** Returns true if eval() should be used to render section tags using @p key.
|
||||
* If canEval() returns true for a key, the renderer will pass the literal, unrendered
|
||||
* block of text for the section to eval() and replace the section with the result.
|
||||
*
|
||||
* canEval() and eval() are equivalents for callable objects (eg. lambdas) in other
|
||||
* Mustache implementations.
|
||||
*
|
||||
* The default implementation always returns false.
|
||||
*/
|
||||
virtual bool canEval(const QString & key) const;
|
||||
|
||||
/** Callback used to render a template section with the given @p key.
|
||||
* @p renderer will substitute the original section tag with the result of eval().
|
||||
*
|
||||
* The default implementation returns an empty string.
|
||||
*/
|
||||
virtual QString eval(const QString & key, const QString & _template, Renderer *renderer);
|
||||
|
||||
private:
|
||||
PartialResolver *m_partialResolver;
|
||||
};
|
||||
|
||||
/** A context implementation which wraps a QVariantHash or QVariantMap. */
|
||||
class QTCREATOR_UTILS_EXPORT QtVariantContext : public Context {
|
||||
public:
|
||||
/** Construct a QtVariantContext which wraps a dictionary in a QVariantHash
|
||||
* or a QVariantMap.
|
||||
*/
|
||||
#if __cplusplus >= 201103L
|
||||
typedef std::function<QString(const QString &, Mustache::Renderer *, Mustache::Context *)> fn_t;
|
||||
#else
|
||||
typedef QString (*fn_t)(const QString &, Mustache::Renderer *, Mustache::Context *);
|
||||
#endif
|
||||
explicit QtVariantContext(const QVariant & root, PartialResolver *resolver = 0);
|
||||
|
||||
virtual QString stringValue(const QString & key) const;
|
||||
virtual bool isFalse(const QString & key) const;
|
||||
virtual int listCount(const QString & key) const;
|
||||
virtual void push(const QString & key, int index = -1);
|
||||
virtual void pop();
|
||||
virtual bool canEval(const QString & key) const;
|
||||
virtual QString eval(const QString & key, const QString & _template, Mustache::Renderer *renderer);
|
||||
|
||||
private:
|
||||
QVariant value(const QString & key) const;
|
||||
|
||||
QStack<QVariant> m_contextStack;
|
||||
};
|
||||
|
||||
/** Interface for fetching template partials. */
|
||||
class QTCREATOR_UTILS_EXPORT PartialResolver {
|
||||
public:
|
||||
virtual ~PartialResolver() {}
|
||||
|
||||
/** Returns the partial template with a given @p name. */
|
||||
virtual QString getPartial(const QString & name) = 0;
|
||||
};
|
||||
|
||||
/** A simple partial fetcher which returns templates from a map of (partial name -> template)
|
||||
*/
|
||||
class QTCREATOR_UTILS_EXPORT PartialMap : public PartialResolver {
|
||||
public:
|
||||
explicit PartialMap(const QHash<QString, QString> & partials);
|
||||
|
||||
virtual QString getPartial(const QString & name);
|
||||
|
||||
private:
|
||||
QHash<QString, QString> m_partials;
|
||||
};
|
||||
|
||||
/** A partial fetcher when loads templates from '<name>.mustache' files
|
||||
* in a given directory.
|
||||
*
|
||||
* Once a partial has been loaded, it is cached for future use.
|
||||
*/
|
||||
class QTCREATOR_UTILS_EXPORT PartialFileLoader : public PartialResolver {
|
||||
public:
|
||||
explicit PartialFileLoader(const QString & basePath);
|
||||
|
||||
virtual QString getPartial(const QString & name);
|
||||
|
||||
private:
|
||||
QString m_basePath;
|
||||
QHash<QString, QString> m_cache;
|
||||
};
|
||||
|
||||
/** Holds properties of a tag in a mustache template. */
|
||||
struct Tag {
|
||||
enum Type {
|
||||
Null,
|
||||
Value, /// A {{key}} or {{{key}}} tag
|
||||
SectionStart, /// A {{#section}} tag
|
||||
InvertedSectionStart, /// An {{^inverted-section}} tag
|
||||
SectionEnd, /// A {{/section}} tag
|
||||
Partial, /// A {{^partial}} tag
|
||||
Comment, /// A {{! comment }} tag
|
||||
SetDelimiter /// A {{=<% %>=}} tag
|
||||
};
|
||||
|
||||
enum EscapeMode {
|
||||
Escape,
|
||||
Unescape,
|
||||
Raw
|
||||
};
|
||||
|
||||
Tag()
|
||||
: type(Null)
|
||||
, start(0)
|
||||
, end(0)
|
||||
, escapeMode(Escape)
|
||||
{}
|
||||
|
||||
Type type;
|
||||
QString key;
|
||||
int start;
|
||||
int end;
|
||||
EscapeMode escapeMode;
|
||||
};
|
||||
|
||||
/** Renders Mustache templates, replacing mustache tags with
|
||||
* values from a provided context.
|
||||
*/
|
||||
class QTCREATOR_UTILS_EXPORT Renderer {
|
||||
public:
|
||||
Renderer();
|
||||
|
||||
/** Render a Mustache template, using @p context to fetch
|
||||
* the values used to replace Mustache tags.
|
||||
*/
|
||||
QString render(const QString & _template, Context *context);
|
||||
|
||||
/** Returns a message describing the last error encountered by the previous
|
||||
* render() call.
|
||||
*/
|
||||
QString error() const;
|
||||
|
||||
/** Returns the position in the template where the last error occurred
|
||||
* when rendering the template or -1 if no error occurred.
|
||||
*
|
||||
* If the error occurred in a partial template, the returned position is the offset
|
||||
* in the partial template.
|
||||
*/
|
||||
int errorPos() const;
|
||||
|
||||
/** Returns the name of the partial where the error occurred, or an empty string
|
||||
* if the error occurred in the main template.
|
||||
*/
|
||||
QString errorPartial() const;
|
||||
|
||||
/** Sets the default tag start and end markers.
|
||||
* This can be overridden within a template.
|
||||
*/
|
||||
void setTagMarkers(const QString & startMarker, const QString & endMarker);
|
||||
|
||||
private:
|
||||
QString render(const QString & _template, int startPos, int endPos, Context *context);
|
||||
|
||||
Tag findTag(const QString & content, int pos, int endPos);
|
||||
Tag findEndTag(const QString & content, const Tag & startTag, int endPos);
|
||||
void setError(const QString & error, int pos);
|
||||
|
||||
void readSetDelimiter(const QString & content, int pos, int endPos);
|
||||
static QString readTagName(const QString & content, int pos, int endPos);
|
||||
|
||||
/** Expands @p tag to fill the line, but only if it is standalone.
|
||||
*
|
||||
* The start position is moved to the beginning of the line. The end position is
|
||||
* moved to one past the end of the line. If @p tag is not standalone, it is
|
||||
* left unmodified.
|
||||
*
|
||||
* A tag is standalone if it is the only non-whitespace token on the the line.
|
||||
*/
|
||||
static void expandTag(Tag & tag, const QString & content);
|
||||
|
||||
QStack<QString> m_partialStack;
|
||||
QString m_error;
|
||||
int m_errorPos;
|
||||
QString m_errorPartial;
|
||||
|
||||
QString m_tagStartMarker;
|
||||
QString m_tagEndMarker;
|
||||
|
||||
QString m_defaultTagStartMarker;
|
||||
QString m_defaultTagEndMarker;
|
||||
};
|
||||
|
||||
/** A convenience function which renders a template using the given data. */
|
||||
QString renderTemplate(const QString & templateString, const QVariantHash & args);
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(Mustache::QtVariantContext::fn_t)
|
@ -56,7 +56,8 @@ SOURCES += reloadpromptutils.cpp \
|
||||
svgimageprovider.cpp \
|
||||
hostosinfo.cpp \
|
||||
logfile.cpp \
|
||||
crc.cpp
|
||||
crc.cpp \
|
||||
mustache.cpp
|
||||
|
||||
SOURCES += xmlconfig.cpp
|
||||
|
||||
@ -115,7 +116,8 @@ HEADERS += utils_global.h \
|
||||
svgimageprovider.h \
|
||||
hostosinfo.h \
|
||||
logfile.h \
|
||||
crc.h
|
||||
crc.h \
|
||||
mustache.h
|
||||
|
||||
|
||||
HEADERS += xmlconfig.h
|
||||
|
@ -187,14 +187,12 @@ void ConfigStabilizationWidget::updateThrottleCurveFromObject()
|
||||
UAVObject *stabBank = getObjectManager()->getObject(QString(m_pidTabBars.at(0)->tabData(m_currentPIDBank).toString()));
|
||||
|
||||
Q_ASSERT(stabBank);
|
||||
qDebug() << "updatingCurveFromObject" << stabBank->getName();
|
||||
|
||||
UAVObjectField *field = stabBank->getField("ThrustPIDScaleCurve");
|
||||
Q_ASSERT(field);
|
||||
|
||||
QList<double> curve;
|
||||
for (quint32 i = 0; i < field->getNumElements(); i++) {
|
||||
qDebug() << field->getName() << field->getElementNames().at(i) << "=>" << field->getValue(i);
|
||||
curve.append(field->getValue(i).toDouble());
|
||||
}
|
||||
|
||||
@ -214,7 +212,6 @@ void ConfigStabilizationWidget::updateObjectFromThrottleCurve()
|
||||
UAVObject *stabBank = getObjectManager()->getObject(QString(m_pidTabBars.at(0)->tabData(m_currentPIDBank).toString()));
|
||||
|
||||
Q_ASSERT(stabBank);
|
||||
qDebug() << "updatingObjectFromCurve" << stabBank->getName();
|
||||
|
||||
UAVObjectField *field = stabBank->getField("ThrustPIDScaleCurve");
|
||||
Q_ASSERT(field);
|
||||
@ -222,7 +219,6 @@ void ConfigStabilizationWidget::updateObjectFromThrottleCurve()
|
||||
QList<double> curve = ui->thrustPIDScalingCurve->getCurve();
|
||||
for (quint32 i = 0; i < field->getNumElements(); i++) {
|
||||
field->setValue(curve.at(i), i);
|
||||
qDebug() << field->getName() << field->getElementNames().at(i) << "<=" << curve.at(i);
|
||||
}
|
||||
|
||||
field = stabBank->getField("EnableThrustPIDScaling");
|
||||
@ -351,10 +347,8 @@ void ConfigStabilizationWidget::realtimeUpdatesSlot(bool value)
|
||||
|
||||
if (value && !realtimeUpdates->isActive()) {
|
||||
realtimeUpdates->start(AUTOMATIC_UPDATE_RATE);
|
||||
qDebug() << "Instant Update timer started.";
|
||||
} else if (!value && realtimeUpdates->isActive()) {
|
||||
realtimeUpdates->stop();
|
||||
qDebug() << "Instant Update timer stopped.";
|
||||
}
|
||||
}
|
||||
|
||||
@ -451,7 +445,6 @@ void ConfigStabilizationWidget::pidBankChanged(int index)
|
||||
setWidgetBindingObjectEnabled(m_pidTabBars.at(0)->tabData(index).toString(), true);
|
||||
|
||||
m_currentPIDBank = index;
|
||||
qDebug() << "current bank:" << m_currentPIDBank;
|
||||
updateThrottleCurveFromObject();
|
||||
setDirty(dirty);
|
||||
}
|
||||
|
@ -47,8 +47,8 @@ MagicWaypointGadgetWidget::MagicWaypointGadgetWidget(QWidget *parent) : QLabel(p
|
||||
m_magicwaypoint->setupUi(this);
|
||||
|
||||
// Connect object updated event from UAVObject to also update check boxes
|
||||
connect(getPathDesired(), SIGNAL(objectUpdated(UAVObject *)), this, SLOT(positionObjectChanged(UAVObject *)));
|
||||
connect(getPositionState(), SIGNAL(objectUpdated(UAVObject *)), this, SLOT(positionObjectChanged(UAVObject *)));
|
||||
connect(getPathDesired(), SIGNAL(objectUpdated(UAVObject *)), this, SLOT(positionStateChanged(UAVObject *)));
|
||||
connect(getPositionState(), SIGNAL(objectUpdated(UAVObject *)), this, SLOT(positionStateChanged(UAVObject *)));
|
||||
|
||||
// Connect updates from the position widget to this widget
|
||||
connect(m_magicwaypoint->widgetPosition, SIGNAL(positionClicked(double, double)), this, SLOT(positionSelected(double, double)));
|
||||
|
@ -0,0 +1,62 @@
|
||||
<html>
|
||||
<head></head>
|
||||
<body style="font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;">
|
||||
<table width='100%' cellpadding="5">
|
||||
<tr bgcolor='#308BC6'>
|
||||
<td rowspan='1' colspan='4'><b>{{OBJECT_NAME_TITLE}}: </b>{{OBJECT_NAME}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan='1'><b>{{CATEGORY_TITLE}}: </b>{{CATEGORY}}</td>
|
||||
<td colspan='1'><b>{{TYPE_TITLE}}: </b>{{TYPE}}</td>
|
||||
<td colspan='1'><b>{{SIZE_TITLE}}: </b>{{SIZE}} bytes</td>
|
||||
<td colspan='1'><b>{{MULTI_INSTANCE_TITLE}}: </b>{{MULTI_INSTANCE}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan='4' rowspan='1' valign='top'><b>{{DESCRIPTION_TITLE}}: </b>{{DESCRIPTION}}</td>
|
||||
<tr bgcolor='#51A0D3'>
|
||||
<td rowspan='1' colspan='4'><b>{{FIELDS_NAME_TITLE}}</td>
|
||||
</tr>
|
||||
{{#FIELDS}}
|
||||
<tr>
|
||||
<td colspan='4'>
|
||||
<table width='100%' cellpadding="5">
|
||||
<tr bgcolor='#7DBAE2'>
|
||||
<td rowspan='1' colspan='4'><b>{{FIELD_NAME_TITLE}}: </b>{{FIELD_NAME}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan='1' colspan='1'><b>{{FIELD_TYPE_TITLE}}: </b>{{FIELD_TYPE}}</td>
|
||||
{{#FIELD_UNIT_TITLE}}
|
||||
<td rowspan='1' colspan='2'><b>{{FIELD_UNIT_TITLE}}: </b>{{FIELD_UNIT}}</td>
|
||||
{{/FIELD_UNIT_TITLE}}
|
||||
</tr>
|
||||
{{#FIELD_OPTIONS_TITLE}}
|
||||
<tr>
|
||||
<td rowspan='1' colspan='2'><b>{{FIELD_OPTIONS_TITLE}}:
|
||||
</b>{{#FIELD_OPTIONS}}{{FIELD_OPTION_DELIM}}{{FIELD_OPTION}}{{/FIELD_OPTIONS}}</td>
|
||||
</tr>
|
||||
{{/FIELD_OPTIONS_TITLE}}
|
||||
{{#FIELD_ELEMENTS_TITLE}}
|
||||
<tr>
|
||||
<td rowspan='1' colspan='2'><b>{{FIELD_ELEMENTS_TITLE}}:
|
||||
</b>{{#FIELD_ELEMENTS}}{{FIELD_ELEMENT_DELIM}}{{FIELD_ELEMENT}}{{FIELD_ELEMENT_LIMIT}}{{/FIELD_ELEMENTS}}</td>
|
||||
</tr>
|
||||
{{/FIELD_ELEMENTS_TITLE}}
|
||||
{{^FIELD_ELEMENTS_TITLE}}
|
||||
{{#FIELD_LIMIT_TITLE}}
|
||||
<tr>
|
||||
<td rowspan='1' colspan='2'><b>{{FIELD_LIMIT_TITLE}}: </b>{{FIELD_LIMIT}}</td>
|
||||
</tr>
|
||||
{{/FIELD_LIMIT_TITLE}}
|
||||
{{/FIELD_ELEMENTS_TITLE}}
|
||||
{{#FIELD_DESCRIPTION_TITLE}}
|
||||
<tr>
|
||||
<td rowspan='1' colspan='2'><b>{{FIELD_DESCRIPTION_TITLE}}: </b>{{FIELD_DESCRIPTION}}</td>
|
||||
</tr>
|
||||
{{/FIELD_DESCRIPTION_TITLE}}
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
{{/FIELDS}}
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
@ -32,7 +32,8 @@ UAVObjectBrowser::UAVObjectBrowser(QString classId, UAVObjectBrowserWidget *widg
|
||||
m_widget(widget),
|
||||
m_config(NULL)
|
||||
{
|
||||
connect(m_widget, SIGNAL(viewOptionsChanged(bool, bool, bool)), this, SLOT(viewOptionsChangedSlot(bool, bool, bool)));
|
||||
connect(m_widget, SIGNAL(viewOptionsChanged(bool, bool, bool, bool)), this, SLOT(viewOptionsChangedSlot(bool, bool, bool, bool)));
|
||||
connect(m_widget, SIGNAL(splitterChanged(QByteArray)), this, SLOT(splitterChanged(QByteArray)));
|
||||
}
|
||||
|
||||
UAVObjectBrowser::~UAVObjectBrowser()
|
||||
@ -50,14 +51,23 @@ void UAVObjectBrowser::loadConfiguration(IUAVGadgetConfiguration *config)
|
||||
m_widget->setManuallyChangedColor(m->manuallyChangedColor());
|
||||
m_widget->setRecentlyUpdatedTimeout(m->recentlyUpdatedTimeout());
|
||||
m_widget->setOnlyHilightChangedValues(m->onlyHighlightChangedValues());
|
||||
m_widget->setViewOptions(m->categorizedView(), m->scientificView(), m->showMetaData());
|
||||
m_widget->setViewOptions(m->categorizedView(), m->scientificView(), m->showMetaData(), m->showDescription());
|
||||
m_widget->setSplitterState(m->splitterState());
|
||||
}
|
||||
|
||||
void UAVObjectBrowser::viewOptionsChangedSlot(bool categorized, bool scientific, bool metadata)
|
||||
void UAVObjectBrowser::viewOptionsChangedSlot(bool categorized, bool scientific, bool metadata, bool description)
|
||||
{
|
||||
if (m_config) {
|
||||
m_config->setCategorizedView(categorized);
|
||||
m_config->setScientificView(scientific);
|
||||
m_config->setShowMetaData(metadata);
|
||||
m_config->setShowDescription(description);
|
||||
}
|
||||
}
|
||||
|
||||
void UAVObjectBrowser::splitterChanged(QByteArray state)
|
||||
{
|
||||
if (m_config) {
|
||||
m_config->setSplitterState(state);
|
||||
}
|
||||
}
|
||||
|
@ -50,8 +50,11 @@ public:
|
||||
return m_widget;
|
||||
}
|
||||
void loadConfiguration(IUAVGadgetConfiguration *config);
|
||||
|
||||
private slots:
|
||||
void viewOptionsChangedSlot(bool categorized, bool scientific, bool metadata);
|
||||
void viewOptionsChangedSlot(bool categorized, bool scientific, bool metadata, bool description);
|
||||
void splitterChanged(QByteArray state);
|
||||
|
||||
private:
|
||||
UAVObjectBrowserWidget *m_widget;
|
||||
UAVObjectBrowserConfiguration *m_config;
|
||||
|
@ -6,5 +6,6 @@
|
||||
<file>images/up_alt.png</file>
|
||||
<file>images/trash.png</file>
|
||||
<file>images/1343241276_eye.png</file>
|
||||
<file>resources/uavodescription.mustache</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
@ -7,7 +7,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>786</width>
|
||||
<height>300</height>
|
||||
<height>462</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@ -220,7 +220,63 @@
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTreeView" name="treeView"/>
|
||||
<widget class="QWidget" name="widget" native="true">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QSplitter" name="splitter">
|
||||
<property name="lineWidth">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<widget class="QTreeView" name="treeView">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QTextEdit" name="descriptionText">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>150</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
<property name="placeholderText">
|
||||
<string>This space shows a description of the selected UAVObject.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
|
@ -36,23 +36,21 @@ UAVObjectBrowserConfiguration::UAVObjectBrowserConfiguration(QString classId, QS
|
||||
m_recentlyUpdatedTimeout(500),
|
||||
m_useCategorizedView(false),
|
||||
m_useScientificView(false),
|
||||
m_showMetaData(false)
|
||||
m_showMetaData(false),
|
||||
m_showDescription(false)
|
||||
{
|
||||
// if a saved configuration exists load it
|
||||
if (qSettings != 0) {
|
||||
QColor recent = qSettings->value("recentlyUpdatedColor").value<QColor>();
|
||||
QColor manual = qSettings->value("manuallyChangedColor").value<QColor>();
|
||||
int timeout = qSettings->value("recentlyUpdatedTimeout").toInt();
|
||||
bool hilight = qSettings->value("onlyHilightChangedValues").toBool();
|
||||
|
||||
m_unknownObjectColor = qSettings->value("unknownObjectColor", QVariant(QColor(Qt::gray))).value<QColor>();
|
||||
m_useCategorizedView = qSettings->value("CategorizedView").toBool();
|
||||
m_useScientificView = qSettings->value("ScientificView").toBool();
|
||||
m_showMetaData = qSettings->value("showMetaData").toBool();
|
||||
m_recentlyUpdatedColor = recent;
|
||||
m_manuallyChangedColor = manual;
|
||||
m_recentlyUpdatedTimeout = timeout;
|
||||
m_onlyHilightChangedValues = hilight;
|
||||
m_showDescription = qSettings->value("showDescription").toBool();
|
||||
m_splitterState = qSettings->value("splitterState").toByteArray();
|
||||
m_recentlyUpdatedColor = qSettings->value("recentlyUpdatedColor").value<QColor>();
|
||||
m_manuallyChangedColor = qSettings->value("manuallyChangedColor").value<QColor>();
|
||||
m_recentlyUpdatedTimeout = qSettings->value("recentlyUpdatedTimeout").toInt();
|
||||
m_onlyHilightChangedValues = qSettings->value("onlyHilightChangedValues").toBool();
|
||||
}
|
||||
}
|
||||
|
||||
@ -66,8 +64,10 @@ IUAVGadgetConfiguration *UAVObjectBrowserConfiguration::clone()
|
||||
m->m_onlyHilightChangedValues = m_onlyHilightChangedValues;
|
||||
m->m_useCategorizedView = m_useCategorizedView;
|
||||
m->m_useScientificView = m_useScientificView;
|
||||
m->m_splitterState = m_splitterState;
|
||||
m->m_showMetaData = m_showMetaData;
|
||||
m->m_unknownObjectColor = m_unknownObjectColor;
|
||||
m->m_showDescription = m_showDescription;
|
||||
return m;
|
||||
}
|
||||
|
||||
@ -85,4 +85,6 @@ void UAVObjectBrowserConfiguration::saveConfig(QSettings *qSettings) const
|
||||
qSettings->setValue("CategorizedView", m_useCategorizedView);
|
||||
qSettings->setValue("ScientificView", m_useScientificView);
|
||||
qSettings->setValue("showMetaData", m_showMetaData);
|
||||
qSettings->setValue("showDescription", m_showDescription);
|
||||
qSettings->setValue("splitterState", m_splitterState);
|
||||
}
|
||||
|
@ -41,7 +41,9 @@ class UAVObjectBrowserConfiguration : public IUAVGadgetConfiguration {
|
||||
Q_PROPERTY(bool m_onlyHilightChangedValues READ onlyHighlightChangedValues WRITE setOnlyHighlightChangedValues)
|
||||
Q_PROPERTY(bool m_useCategorizedView READ categorizedView WRITE setCategorizedView)
|
||||
Q_PROPERTY(bool m_useScientificView READ scientificView WRITE setScientificView)
|
||||
Q_PROPERTY(bool m_showDescription READ showDescription WRITE setShowDescription)
|
||||
Q_PROPERTY(bool m_showMetaData READ showMetaData WRITE setShowMetaData)
|
||||
Q_PROPERTY(QByteArray m_splitterState READ splitterState WRITE setSplitterState)
|
||||
public:
|
||||
explicit UAVObjectBrowserConfiguration(QString classId, QSettings *qSettings = 0, QObject *parent = 0);
|
||||
|
||||
@ -80,6 +82,15 @@ public:
|
||||
{
|
||||
return m_showMetaData;
|
||||
}
|
||||
bool showDescription() const
|
||||
{
|
||||
return m_showDescription;
|
||||
}
|
||||
|
||||
QByteArray splitterState() const
|
||||
{
|
||||
return m_splitterState;
|
||||
}
|
||||
|
||||
signals:
|
||||
|
||||
@ -116,6 +127,15 @@ public slots:
|
||||
{
|
||||
m_showMetaData = value;
|
||||
}
|
||||
void setShowDescription(bool value)
|
||||
{
|
||||
m_showDescription = value;
|
||||
}
|
||||
|
||||
void setSplitterState(QByteArray arg)
|
||||
{
|
||||
m_splitterState = arg;
|
||||
}
|
||||
|
||||
private:
|
||||
QColor m_unknownObjectColor;
|
||||
@ -126,6 +146,8 @@ private:
|
||||
bool m_useCategorizedView;
|
||||
bool m_useScientificView;
|
||||
bool m_showMetaData;
|
||||
bool m_showDescription;
|
||||
QByteArray m_splitterState;
|
||||
};
|
||||
|
||||
#endif // UAVOBJECTBROWSERCONFIGURATION_H
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include <QtCore/QDebug>
|
||||
#include <QItemEditorFactory>
|
||||
#include "extensionsystem/pluginmanager.h"
|
||||
#include "utils/mustache.h"
|
||||
|
||||
UAVObjectBrowserWidget::UAVObjectBrowserWidget(QWidget *parent) : QWidget(parent)
|
||||
{
|
||||
@ -55,12 +56,14 @@ UAVObjectBrowserWidget::UAVObjectBrowserWidget(QWidget *parent) : QWidget(parent
|
||||
m_browser->treeView->setItemDelegate(m_delegate);
|
||||
m_browser->treeView->setEditTriggers(QAbstractItemView::AllEditTriggers);
|
||||
m_browser->treeView->setSelectionBehavior(QAbstractItemView::SelectItems);
|
||||
|
||||
m_mustacheTemplate = loadFileIntoString(QString(":/uavobjectbrowser/resources/uavodescription.mustache"));
|
||||
showMetaData(m_viewoptions->cbMetaData->isChecked());
|
||||
|
||||
connect(m_browser->treeView->selectionModel(), SIGNAL(currentChanged(QModelIndex, QModelIndex)), this, SLOT(currentChanged(QModelIndex, QModelIndex)), Qt::UniqueConnection);
|
||||
showDescription(m_viewoptions->cbDescription->isChecked());
|
||||
connect(m_browser->treeView->selectionModel(), SIGNAL(currentChanged(QModelIndex, QModelIndex)),
|
||||
this, SLOT(currentChanged(QModelIndex, QModelIndex)), Qt::UniqueConnection);
|
||||
connect(m_viewoptions->cbMetaData, SIGNAL(toggled(bool)), this, SLOT(showMetaData(bool)));
|
||||
connect(m_viewoptions->cbCategorized, SIGNAL(toggled(bool)), this, SLOT(categorize(bool)));
|
||||
connect(m_viewoptions->cbDescription, SIGNAL(toggled(bool)), this, SLOT(showDescription(bool)));
|
||||
connect(m_browser->saveSDButton, SIGNAL(clicked()), this, SLOT(saveObject()));
|
||||
connect(m_browser->readSDButton, SIGNAL(clicked()), this, SLOT(loadObject()));
|
||||
connect(m_browser->eraseSDButton, SIGNAL(clicked()), this, SLOT(eraseObject()));
|
||||
@ -71,7 +74,8 @@ UAVObjectBrowserWidget::UAVObjectBrowserWidget(QWidget *parent) : QWidget(parent
|
||||
connect(m_viewoptions->cbScientific, SIGNAL(toggled(bool)), this, SLOT(viewOptionsChangedSlot()));
|
||||
connect(m_viewoptions->cbMetaData, SIGNAL(toggled(bool)), this, SLOT(viewOptionsChangedSlot()));
|
||||
connect(m_viewoptions->cbCategorized, SIGNAL(toggled(bool)), this, SLOT(viewOptionsChangedSlot()));
|
||||
|
||||
connect(m_viewoptions->cbDescription, SIGNAL(toggled(bool)), this, SLOT(viewOptionsChangedSlot()));
|
||||
connect(m_browser->splitter, SIGNAL(splitterMoved(int, int)), this, SLOT(splitterMoved()));
|
||||
enableSendRequest(false);
|
||||
}
|
||||
|
||||
@ -80,11 +84,17 @@ UAVObjectBrowserWidget::~UAVObjectBrowserWidget()
|
||||
delete m_browser;
|
||||
}
|
||||
|
||||
void UAVObjectBrowserWidget::setViewOptions(bool categorized, bool scientific, bool metadata)
|
||||
void UAVObjectBrowserWidget::setViewOptions(bool categorized, bool scientific, bool metadata, bool description)
|
||||
{
|
||||
m_viewoptions->cbCategorized->setChecked(categorized);
|
||||
m_viewoptions->cbMetaData->setChecked(metadata);
|
||||
m_viewoptions->cbScientific->setChecked(scientific);
|
||||
m_viewoptions->cbDescription->setChecked(description);
|
||||
}
|
||||
|
||||
void UAVObjectBrowserWidget::setSplitterState(QByteArray state)
|
||||
{
|
||||
m_browser->splitter->restoreState(state);
|
||||
}
|
||||
|
||||
void UAVObjectBrowserWidget::showMetaData(bool show)
|
||||
@ -95,6 +105,11 @@ void UAVObjectBrowserWidget::showMetaData(bool show)
|
||||
}
|
||||
}
|
||||
|
||||
void UAVObjectBrowserWidget::showDescription(bool show)
|
||||
{
|
||||
m_browser->descriptionText->setVisible(show);
|
||||
}
|
||||
|
||||
void UAVObjectBrowserWidget::categorize(bool categorize)
|
||||
{
|
||||
UAVObjectTreeModel *tmpModel = m_model;
|
||||
@ -165,6 +180,17 @@ ObjectTreeItem *UAVObjectBrowserWidget::findCurrentObjectTreeItem()
|
||||
return objItem;
|
||||
}
|
||||
|
||||
QString UAVObjectBrowserWidget::loadFileIntoString(QString fileName)
|
||||
{
|
||||
QFile file(fileName);
|
||||
|
||||
file.open(QIODevice::ReadOnly);
|
||||
QTextStream stream(&file);
|
||||
QString line = stream.readAll();
|
||||
file.close();
|
||||
return line;
|
||||
}
|
||||
|
||||
void UAVObjectBrowserWidget::saveObject()
|
||||
{
|
||||
this->setFocus();
|
||||
@ -233,6 +259,7 @@ void UAVObjectBrowserWidget::currentChanged(const QModelIndex ¤t, const QM
|
||||
enable = false;
|
||||
}
|
||||
enableSendRequest(enable);
|
||||
updateDescription();
|
||||
}
|
||||
|
||||
void UAVObjectBrowserWidget::viewSlot()
|
||||
@ -249,7 +276,94 @@ void UAVObjectBrowserWidget::viewSlot()
|
||||
|
||||
void UAVObjectBrowserWidget::viewOptionsChangedSlot()
|
||||
{
|
||||
emit viewOptionsChanged(m_viewoptions->cbCategorized->isChecked(), m_viewoptions->cbScientific->isChecked(), m_viewoptions->cbMetaData->isChecked());
|
||||
emit viewOptionsChanged(m_viewoptions->cbCategorized->isChecked(), m_viewoptions->cbScientific->isChecked(),
|
||||
m_viewoptions->cbMetaData->isChecked(), m_viewoptions->cbDescription->isChecked());
|
||||
}
|
||||
|
||||
void UAVObjectBrowserWidget::splitterMoved()
|
||||
{
|
||||
emit splitterChanged(m_browser->splitter->saveState());
|
||||
}
|
||||
|
||||
QString UAVObjectBrowserWidget::createObjectDescription(UAVObject *object)
|
||||
{
|
||||
QString mustache(m_mustacheTemplate);
|
||||
|
||||
QVariantHash uavoHash;
|
||||
|
||||
uavoHash["OBJECT_NAME_TITLE"] = tr("Name");
|
||||
uavoHash["OBJECT_NAME"] = object->getName();
|
||||
uavoHash["CATEGORY_TITLE"] = tr("Category");
|
||||
uavoHash["CATEGORY"] = object->getCategory();
|
||||
uavoHash["TYPE_TITLE"] = tr("Type");
|
||||
uavoHash["TYPE"] = object->isMetaDataObject() ? tr("Metadata") : object->isSettingsObject() ? tr("Setting") : tr("Data");
|
||||
uavoHash["SIZE_TITLE"] = tr("Size");
|
||||
uavoHash["SIZE"] = object->getNumBytes();
|
||||
uavoHash["DESCRIPTION_TITLE"] = tr("Description");
|
||||
uavoHash["DESCRIPTION"] = object->getDescription().replace("@ref", "");
|
||||
uavoHash["MULTI_INSTANCE_TITLE"] = tr("Multi");
|
||||
uavoHash["MULTI_INSTANCE"] = object->isSingleInstance() ? tr("No") : tr("Yes");
|
||||
uavoHash["FIELDS_NAME_TITLE"] = tr("Fields");
|
||||
QVariantList fields;
|
||||
foreach(UAVObjectField * field, object->getFields()) {
|
||||
QVariantHash fieldHash;
|
||||
|
||||
fieldHash["FIELD_NAME_TITLE"] = tr("Name");
|
||||
fieldHash["FIELD_NAME"] = field->getName();
|
||||
fieldHash["FIELD_TYPE_TITLE"] = tr("Type");
|
||||
fieldHash["FIELD_TYPE"] = QString("%1%2").arg(field->getTypeAsString(),
|
||||
(field->getNumElements() > 1 ? QString("[%1]").arg(field->getNumElements()) : QString()));
|
||||
if (!field->getUnits().isEmpty()) {
|
||||
fieldHash["FIELD_UNIT_TITLE"] = tr("Unit");
|
||||
fieldHash["FIELD_UNIT"] = field->getUnits();
|
||||
}
|
||||
if (!field->getOptions().isEmpty()) {
|
||||
fieldHash["FIELD_OPTIONS_TITLE"] = tr("Options");
|
||||
QVariantList options;
|
||||
foreach(QString option, field->getOptions()) {
|
||||
QVariantHash optionHash;
|
||||
|
||||
optionHash["FIELD_OPTION"] = option;
|
||||
if (!options.isEmpty()) {
|
||||
optionHash["FIELD_OPTION_DELIM"] = ", ";
|
||||
}
|
||||
options.append(optionHash);
|
||||
}
|
||||
fieldHash["FIELD_OPTIONS"] = options;
|
||||
}
|
||||
if (field->getElementNames().count() > 1) {
|
||||
fieldHash["FIELD_ELEMENTS_TITLE"] = tr("Elements");
|
||||
QVariantList elements;
|
||||
for (int i = 0; i < field->getElementNames().count(); i++) {
|
||||
QString element = field->getElementNames().at(i);
|
||||
QVariantHash elementHash;
|
||||
elementHash["FIELD_ELEMENT"] = element;
|
||||
QString limitsString = field->getLimitsAsString(i);
|
||||
if (!limitsString.isEmpty()) {
|
||||
elementHash["FIELD_ELEMENT_LIMIT"] = limitsString.prepend(" (").append(")");
|
||||
}
|
||||
if (!elements.isEmpty()) {
|
||||
elementHash["FIELD_ELEMENT_DELIM"] = ", ";
|
||||
}
|
||||
elements.append(elementHash);
|
||||
}
|
||||
fieldHash["FIELD_ELEMENTS"] = elements;
|
||||
} else if (!field->getLimitsAsString(0).isEmpty()) {
|
||||
fieldHash["FIELD_LIMIT_TITLE"] = tr("Limits");
|
||||
fieldHash["FIELD_LIMIT"] = field->getLimitsAsString(0);
|
||||
}
|
||||
|
||||
if (!field->getDescription().isEmpty()) {
|
||||
fieldHash["FIELD_DESCRIPTION_TITLE"] = tr("Description");
|
||||
fieldHash["FIELD_DESCRIPTION"] = field->getDescription();
|
||||
}
|
||||
|
||||
fields.append(fieldHash);
|
||||
}
|
||||
uavoHash["FIELDS"] = fields;
|
||||
Mustache::QtVariantContext context(uavoHash);
|
||||
Mustache::Renderer renderer;
|
||||
return renderer.render(mustache, &context);
|
||||
}
|
||||
|
||||
void UAVObjectBrowserWidget::enableSendRequest(bool enable)
|
||||
@ -260,3 +374,17 @@ void UAVObjectBrowserWidget::enableSendRequest(bool enable)
|
||||
m_browser->readSDButton->setEnabled(enable);
|
||||
m_browser->eraseSDButton->setEnabled(enable);
|
||||
}
|
||||
|
||||
void UAVObjectBrowserWidget::updateDescription()
|
||||
{
|
||||
ObjectTreeItem *objItem = findCurrentObjectTreeItem();
|
||||
|
||||
if (objItem) {
|
||||
UAVObject *obj = objItem->object();
|
||||
if (obj) {
|
||||
m_browser->descriptionText->setText(createObjectDescription(obj));
|
||||
return;
|
||||
}
|
||||
}
|
||||
m_browser->descriptionText->setText("");
|
||||
}
|
||||
|
@ -70,9 +70,11 @@ public:
|
||||
m_onlyHilightChangedValues = hilight;
|
||||
m_model->setOnlyHilightChangedValues(hilight);
|
||||
}
|
||||
void setViewOptions(bool categorized, bool scientific, bool metadata);
|
||||
void setViewOptions(bool categorized, bool scientific, bool metadata, bool description);
|
||||
void setSplitterState(QByteArray state);
|
||||
public slots:
|
||||
void showMetaData(bool show);
|
||||
void showDescription(bool show);
|
||||
void categorize(bool categorize);
|
||||
void useScientificNotation(bool scientific);
|
||||
|
||||
@ -85,10 +87,11 @@ private slots:
|
||||
void currentChanged(const QModelIndex ¤t, const QModelIndex &previous);
|
||||
void viewSlot();
|
||||
void viewOptionsChangedSlot();
|
||||
|
||||
void splitterMoved();
|
||||
QString createObjectDescription(UAVObject *object);
|
||||
signals:
|
||||
void viewOptionsChanged(bool categorized, bool scientific, bool metadata);
|
||||
|
||||
void viewOptionsChanged(bool categorized, bool scientific, bool metadata, bool description);
|
||||
void splitterChanged(QByteArray state);
|
||||
private:
|
||||
QPushButton *m_requestUpdate;
|
||||
QPushButton *m_sendUpdate;
|
||||
@ -102,10 +105,13 @@ private:
|
||||
QColor m_recentlyUpdatedColor;
|
||||
QColor m_manuallyChangedColor;
|
||||
bool m_onlyHilightChangedValues;
|
||||
QString m_mustacheTemplate;
|
||||
|
||||
void updateObjectPersistance(ObjectPersistence::OperationOptions op, UAVObject *obj);
|
||||
void enableSendRequest(bool enable);
|
||||
void updateDescription();
|
||||
ObjectTreeItem *findCurrentObjectTreeItem();
|
||||
QString loadFileIntoString(QString fileName);
|
||||
};
|
||||
|
||||
#endif /* UAVOBJECTBROWSERWIDGET_H_ */
|
||||
|
@ -256,6 +256,7 @@ void UAVObjectTreeModel::addSingleField(int index, UAVObjectField *field, TreeIt
|
||||
Q_ASSERT(false);
|
||||
}
|
||||
item->setHighlightManager(m_highlightManager);
|
||||
item->setDescription(field->getDescription());
|
||||
connect(item, SIGNAL(updateHighlight(TreeItem *)), this, SLOT(updateHighlight(TreeItem *)));
|
||||
parent->appendChild(item);
|
||||
}
|
||||
|
@ -6,8 +6,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>169</width>
|
||||
<height>96</height>
|
||||
<width>172</width>
|
||||
<height>124</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@ -35,6 +35,13 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="cbDescription">
|
||||
<property name="text">
|
||||
<string>Show Description</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
|
@ -41,10 +41,10 @@ UAVMetaObject::UAVMetaObject(quint32 objID, const QString & name, UAVObject *par
|
||||
QStringList modesBitField;
|
||||
modesBitField << tr("FlightReadOnly") << tr("GCSReadOnly") << tr("FlightTelemetryAcked") << tr("GCSTelemetryAcked") << tr("FlightUpdatePeriodic") << tr("FlightUpdateOnChange") << tr("GCSUpdatePeriodic") << tr("GCSUpdateOnChange") << tr("LoggingUpdatePeriodic") << tr("LoggingUpdateOnChange");
|
||||
QList<UAVObjectField *> fields;
|
||||
fields.append(new UAVObjectField(tr("Modes"), tr("boolean"), UAVObjectField::BITFIELD, modesBitField, QStringList()));
|
||||
fields.append(new UAVObjectField(tr("Flight Telemetry Update Period"), tr("ms"), UAVObjectField::UINT16, 1, QStringList()));
|
||||
fields.append(new UAVObjectField(tr("GCS Telemetry Update Period"), tr("ms"), UAVObjectField::UINT16, 1, QStringList()));
|
||||
fields.append(new UAVObjectField(tr("Logging Update Period"), tr("ms"), UAVObjectField::UINT16, 1, QStringList()));
|
||||
fields.append(new UAVObjectField(tr("Modes"), tr("Metadata modes"), tr("boolean"), UAVObjectField::BITFIELD, modesBitField, QStringList()));
|
||||
fields.append(new UAVObjectField(tr("Flight Telemetry Update Period"), tr("This is how often flight side will update telemetry data"), tr("ms"), UAVObjectField::UINT16, 1, QStringList()));
|
||||
fields.append(new UAVObjectField(tr("GCS Telemetry Update Period"), tr("This is how often GCS will update telemetry data"), tr("ms"), UAVObjectField::UINT16, 1, QStringList()));
|
||||
fields.append(new UAVObjectField(tr("Logging Update Period"), tr("This is how often logging will be updated."), tr("ms"), UAVObjectField::UINT16, 1, QStringList()));
|
||||
// Initialize parent
|
||||
UAVObject::initialize(0);
|
||||
UAVObject::initializeFields(fields, (quint8 *)&parentMetadata, sizeof(Metadata));
|
||||
|
@ -30,7 +30,7 @@
|
||||
#include <QDebug>
|
||||
#include <QtWidgets>
|
||||
|
||||
UAVObjectField::UAVObjectField(const QString & name, const QString & units, FieldType type, quint32 numElements, const QStringList & options, const QString &limits)
|
||||
UAVObjectField::UAVObjectField(const QString & name, const QString & description, const QString & units, FieldType type, quint32 numElements, const QStringList & options, const QString &limits)
|
||||
{
|
||||
QStringList elementNames;
|
||||
|
||||
@ -39,18 +39,19 @@ UAVObjectField::UAVObjectField(const QString & name, const QString & units, Fiel
|
||||
elementNames.append(QString("%1").arg(n));
|
||||
}
|
||||
// Initialize
|
||||
constructorInitialize(name, units, type, elementNames, options, limits);
|
||||
constructorInitialize(name, description, units, type, elementNames, options, limits);
|
||||
}
|
||||
|
||||
UAVObjectField::UAVObjectField(const QString & name, const QString & units, FieldType type, const QStringList & elementNames, const QStringList & options, const QString &limits)
|
||||
UAVObjectField::UAVObjectField(const QString & name, const QString & description, const QString & units, FieldType type, const QStringList & elementNames, const QStringList & options, const QString &limits)
|
||||
{
|
||||
constructorInitialize(name, units, type, elementNames, options, limits);
|
||||
constructorInitialize(name, description, units, type, elementNames, options, limits);
|
||||
}
|
||||
|
||||
void UAVObjectField::constructorInitialize(const QString & name, const QString & units, FieldType type, const QStringList & elementNames, const QStringList & options, const QString &limits)
|
||||
void UAVObjectField::constructorInitialize(const QString & name, const QString & description, const QString & units, FieldType type, const QStringList & elementNames, const QStringList & options, const QString &limits)
|
||||
{
|
||||
// Copy params
|
||||
this->name = name;
|
||||
this->description = description;
|
||||
this->units = units;
|
||||
this->type = type;
|
||||
this->options = options;
|
||||
@ -458,11 +459,65 @@ bool UAVObjectField::isWithinLimits(QVariant var, quint32 index, int board)
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
QString UAVObjectField::getLimitsAsString(quint32 index, int board)
|
||||
{
|
||||
QString limitString;
|
||||
|
||||
if (elementLimits.keys().contains(index)) {
|
||||
foreach(LimitStruct struc, elementLimits.value(index)) {
|
||||
if ((struc.board != board) && board != 0 && struc.board != 0) {
|
||||
continue;
|
||||
}
|
||||
switch (struc.type) {
|
||||
case EQUAL:
|
||||
{
|
||||
limitString.append(tr("one of")).append(" [");
|
||||
bool first = true;
|
||||
foreach(QVariant var, struc.values) {
|
||||
if (!first) {
|
||||
limitString.append(", ");
|
||||
}
|
||||
limitString.append(var.toString());
|
||||
first = false;
|
||||
}
|
||||
return limitString.append("]");
|
||||
}
|
||||
case NOT_EQUAL:
|
||||
{
|
||||
limitString.append(tr("none of")).append(" [");
|
||||
bool first = true;
|
||||
foreach(QVariant var, struc.values) {
|
||||
if (!first) {
|
||||
limitString.append(", ");
|
||||
}
|
||||
limitString.append(var.toString());
|
||||
first = false;
|
||||
}
|
||||
return limitString.append("]");
|
||||
}
|
||||
case BIGGER: return limitString.append(QString("%1 %2").arg(tr("more than"), struc.values.at(0).toString()));
|
||||
|
||||
case BETWEEN: return limitString.append(QString("%1 %2 %3 %4")
|
||||
.arg(tr("between"), struc.values.at(0).toString(),
|
||||
tr(" and "), struc.values.at(1).toString()));
|
||||
|
||||
case SMALLER: return limitString.append(QString("%1 %2").arg(tr("less than"), struc.values.at(0).toString()));
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return limitString;
|
||||
}
|
||||
|
||||
QVariant UAVObjectField::getMaxLimit(quint32 index, int board)
|
||||
{
|
||||
if (!elementLimits.keys().contains(index)) {
|
||||
@ -478,20 +533,14 @@ QVariant UAVObjectField::getMaxLimit(quint32 index, int board)
|
||||
case BIGGER:
|
||||
return QVariant();
|
||||
|
||||
break;
|
||||
break;
|
||||
case BETWEEN:
|
||||
return struc.values.at(1);
|
||||
|
||||
break;
|
||||
case SMALLER:
|
||||
return struc.values.at(0);
|
||||
|
||||
break;
|
||||
default:
|
||||
return QVariant();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
return QVariant();
|
||||
@ -511,20 +560,14 @@ QVariant UAVObjectField::getMinLimit(quint32 index, int board)
|
||||
case SMALLER:
|
||||
return QVariant();
|
||||
|
||||
break;
|
||||
break;
|
||||
case BETWEEN:
|
||||
return struc.values.at(0);
|
||||
|
||||
break;
|
||||
case BIGGER:
|
||||
return struc.values.at(0);
|
||||
|
||||
break;
|
||||
default:
|
||||
return QVariant();
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
return QVariant();
|
||||
@ -609,6 +652,11 @@ QString UAVObjectField::getName()
|
||||
return name;
|
||||
}
|
||||
|
||||
QString UAVObjectField::getDescription()
|
||||
{
|
||||
return description;
|
||||
}
|
||||
|
||||
QString UAVObjectField::getUnits()
|
||||
{
|
||||
return units;
|
||||
|
@ -45,20 +45,21 @@ class UAVOBJECTS_EXPORT UAVObjectField : public QObject {
|
||||
|
||||
public:
|
||||
typedef enum { INT8 = 0, INT16, INT32, UINT8, UINT16, UINT32, FLOAT32, ENUM, BITFIELD, STRING } FieldType;
|
||||
typedef enum { EQUAL, NOT_EQUAL, BETWEEN, BIGGER, SMALLER } LimitType;
|
||||
typedef enum { EQUAL, NOT_EQUAL, BETWEEN, BIGGER, SMALLER, UNDEFINED } LimitType;
|
||||
typedef struct {
|
||||
LimitType type;
|
||||
QList<QVariant> values;
|
||||
int board;
|
||||
} LimitStruct;
|
||||
|
||||
UAVObjectField(const QString & name, const QString & units, FieldType type, quint32 numElements, const QStringList & options, const QString & limits = QString());
|
||||
UAVObjectField(const QString & name, const QString & units, FieldType type, const QStringList & elementNames, const QStringList & options, const QString & limits = QString());
|
||||
UAVObjectField(const QString & name, const QString & description, const QString & units, FieldType type, quint32 numElements, const QStringList & options, const QString & limits = QString());
|
||||
UAVObjectField(const QString & name, const QString & description, const QString & units, FieldType type, const QStringList & elementNames, const QStringList & options, const QString & limits = QString());
|
||||
void initialize(quint8 *data, quint32 dataOffset, UAVObject *obj);
|
||||
UAVObject *getObject();
|
||||
FieldType getType();
|
||||
QString getTypeAsString();
|
||||
QString getName();
|
||||
QString getDescription();
|
||||
QString getUnits();
|
||||
quint32 getNumElements();
|
||||
QStringList getElementNames();
|
||||
@ -84,6 +85,7 @@ public:
|
||||
void fromJson(const QJsonObject &jsonObject);
|
||||
|
||||
bool isWithinLimits(QVariant var, quint32 index, int board = 0);
|
||||
QString getLimitsAsString(quint32 index, int board = 0);
|
||||
QVariant getMaxLimit(quint32 index, int board = 0);
|
||||
QVariant getMinLimit(quint32 index, int board = 0);
|
||||
signals:
|
||||
@ -91,6 +93,7 @@ signals:
|
||||
|
||||
protected:
|
||||
QString name;
|
||||
QString description;
|
||||
QString units;
|
||||
FieldType type;
|
||||
QStringList elementNames;
|
||||
@ -102,7 +105,7 @@ protected:
|
||||
UAVObject *obj;
|
||||
QMap<quint32, QList<LimitStruct> > elementLimits;
|
||||
void clear();
|
||||
void constructorInitialize(const QString & name, const QString & units, FieldType type, const QStringList & elementNames, const QStringList & options, const QString &limits);
|
||||
void constructorInitialize(const QString & name, const QString & description, const QString & units, FieldType type, const QStringList & elementNames, const QStringList & options, const QString &limits);
|
||||
void limitsInitialize(const QString &limits);
|
||||
};
|
||||
|
||||
|
@ -10,8 +10,6 @@ Rectangle {
|
||||
sourceComponent: scrollDecorator.flickableItem ? scrollBar : undefined
|
||||
}
|
||||
|
||||
Component.onDestruction: scrollLoader.sourceComponent = undefined
|
||||
|
||||
Component {
|
||||
id: scrollBar
|
||||
Rectangle {
|
||||
|
@ -259,8 +259,9 @@ bool UAVObjectGeneratorGCS::process_object(ObjectInfo *info)
|
||||
.arg(varOptionName)
|
||||
.arg(options[m]));
|
||||
}
|
||||
finit.append(QString(" fields.append( new UAVObjectField(QString(\"%1\"), QString(\"%2\"), UAVObjectField::ENUM, %3, %4, QString(\"%5\")));\n")
|
||||
finit.append(QString(" fields.append( new UAVObjectField(QString(\"%1\"), tr(\"%2\"), QString(\"%3\"), UAVObjectField::ENUM, %4, %5, QString(\"%6\")));\n")
|
||||
.arg(info->fields[n]->name)
|
||||
.arg(info->fields[n]->description)
|
||||
.arg(info->fields[n]->units)
|
||||
.arg(varElemName)
|
||||
.arg(varOptionName)
|
||||
@ -268,8 +269,9 @@ bool UAVObjectGeneratorGCS::process_object(ObjectInfo *info)
|
||||
}
|
||||
// For all other types
|
||||
else {
|
||||
finit.append(QString(" fields.append( new UAVObjectField(QString(\"%1\"), QString(\"%2\"), UAVObjectField::%3, %4, QStringList(), QString(\"%5\")));\n")
|
||||
finit.append(QString(" fields.append( new UAVObjectField(QString(\"%1\"), tr(\"%2\"), QString(\"%3\"), UAVObjectField::%4, %5, QStringList(), QString(\"%6\")));\n")
|
||||
.arg(info->fields[n]->name)
|
||||
.arg(info->fields[n]->description)
|
||||
.arg(info->fields[n]->units)
|
||||
.arg(fieldTypeStrCPPClass[info->fields[n]->type])
|
||||
.arg(varElemName)
|
||||
|
@ -25,7 +25,7 @@
|
||||
*/
|
||||
|
||||
#include "uavobjectparser.h"
|
||||
|
||||
#include <QDebug>
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
@ -441,6 +441,21 @@ QString UAVObjectParser::processObjectFields(QDomNode & childNode, ObjectInfo *i
|
||||
field->name = name;
|
||||
}
|
||||
|
||||
// Get description attribute if any
|
||||
elemAttr = elemAttributes.namedItem("description");
|
||||
if (!elemAttr.isNull()) {
|
||||
field->description = elemAttr.nodeValue();
|
||||
} else {
|
||||
// Look for a child description node
|
||||
QDomNode node = childNode.firstChildElement("description");
|
||||
if (!node.isNull()) {
|
||||
QDomNode description = node.firstChild();
|
||||
if (!description.isNull()) {
|
||||
field->description = description.nodeValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get units attribute
|
||||
elemAttr = elemAttributes.namedItem("units");
|
||||
if (elemAttr.isNull()) {
|
||||
|
@ -49,6 +49,7 @@ typedef enum {
|
||||
|
||||
typedef struct {
|
||||
QString name;
|
||||
QString description;
|
||||
QString units;
|
||||
FieldType type;
|
||||
int numElements;
|
||||
|
@ -1,6 +1,6 @@
|
||||
<xml>
|
||||
<object name="CameraStabSettings" singleinstance="true" settings="true" category="Control">
|
||||
<description>Settings for the @ref CameraStab mmodule</description>
|
||||
<description>Settings for the @ref CameraStab module</description>
|
||||
<field name="Input" units="channel" type="enum" elementnames="Roll,Pitch,Yaw" options="Accessory0,Accessory1,Accessory2,Accessory3,Accessory4,Accessory5,None" defaultvalue="None"/>
|
||||
<field name="InputRange" units="deg" type="uint8" elementnames="Roll,Pitch,Yaw" defaultvalue="20"/>
|
||||
<field name="InputRate" units="deg/s" type="uint8" elementnames="Roll,Pitch,Yaw" defaultvalue="50"/>
|
||||
|
@ -1,7 +1,10 @@
|
||||
<xml>
|
||||
<object name="DebugLogSettings" singleinstance="true" settings="true" category="System">
|
||||
<description>Configure On Board Logging Facilities</description>
|
||||
<field name="LoggingEnabled" units="" type="enum" elements="1" options="Disabled,OnlyWhenArmed,Always" defaultvalue="Disabled" />
|
||||
|
||||
<field name="LoggingEnabled" units="" type="enum" elements="1" options="Disabled,OnlyWhenArmed,Always" defaultvalue="Disabled">
|
||||
<description>If set to OnlyWhenArmed logs will only be saved when craft is armed. Disabled turns logging off, and Always will always log.</description>
|
||||
</field>
|
||||
|
||||
<access gcs="readwrite" flight="readwrite"/>
|
||||
<telemetrygcs acked="true" updatemode="onchange" period="0"/>
|
||||
|
@ -1,10 +1,10 @@
|
||||
<xml>
|
||||
<object name="DebugLogStatus" singleinstance="true" settings="false" category="System">
|
||||
<description>Log Status Object, contains log partition status information</description>
|
||||
<field name="Flight" units="" type="uint16" elements="1" />
|
||||
<field name="Entry" units="" type="uint16" elements="1" />
|
||||
<field name="UsedSlots" units="" type="uint16" elements="1" />
|
||||
<field name="FreeSlots" units="" type="uint16" elements="1" />
|
||||
<field name="Flight" units="" type="uint16" elements="1" description="The current flight number (logging session)"/>
|
||||
<field name="Entry" units="" type="uint16" elements="1" description="The current log entry id"/>
|
||||
<field name="UsedSlots" units="" type="uint16" elements="1" description="Holds the total log entries saved"/>
|
||||
<field name="FreeSlots" units="" type="uint16" elements="1" description="The number of free log slots available"/>
|
||||
<access gcs="readwrite" flight="readwrite"/>
|
||||
<telemetrygcs acked="false" updatemode="manual" period="0"/>
|
||||
<telemetryflight acked="false" updatemode="periodic" period="1000"/>
|
||||
|
@ -1,6 +1,6 @@
|
||||
<xml>
|
||||
<object name="HomeLocation" singleinstance="true" settings="true" category="Navigation">
|
||||
<description>HomeLocation setting which contains the constants to tranlate from longitutde and latitude to NED reference frame. Automatically set by @ref GPSModule after acquiring a 3D lock. Used by @ref AHRSCommsModule.</description>
|
||||
<description>HomeLocation setting which contains the constants to translate from longitude and latitude to NED reference frame. Automatically set by @ref GPSModule after acquiring a 3D lock. Used by @ref AHRSCommsModule.</description>
|
||||
<field name="Set" units="" type="enum" elements="1" options="FALSE,TRUE" defaultvalue="FALSE"/>
|
||||
<field name="Latitude" units="deg * 10e6" type="int32" elements="1" defaultvalue="0"/>
|
||||
<field name="Longitude" units="deg * 10e6" type="int32" elements="1" defaultvalue="0"/>
|
||||
|
@ -1,6 +1,6 @@
|
||||
<xml>
|
||||
<object name="ManualControlCommand" singleinstance="true" settings="false" category="Control">
|
||||
<description>The output from the @ref ManualControlModule which descodes the receiver inputs. Overriden by GCS for fly-by-wire control.</description>
|
||||
<description>The output from the @ref ManualControlModule which decodes the receiver inputs. Overriden by GCS for fly-by-wire control.</description>
|
||||
<field name="Connected" units="" type="enum" elements="1" options="False,True"/>
|
||||
<field name="Throttle" units="%" type="float" elements="1"/>
|
||||
<field name="Roll" units="%" type="float" elements="1"/>
|
||||
|
Loading…
Reference in New Issue
Block a user