This commit is contained in:
Gangphon 2023-07-21 17:40:49 +08:00
parent 0cb71807e6
commit 2cfa0cc514
9 changed files with 644 additions and 46 deletions

2
LedOK/gutil/cu.cpp Normal file
View File

@ -0,0 +1,2 @@
//#include "cu.h"

221
LedOK/gutil/cu.h Normal file
View File

@ -0,0 +1,221 @@
#ifndef CU_H
#define CU_H
#include <chrono>
#include <memory>
#include <unordered_map>
inline long long steady_milli() {
return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now().time_since_epoch()).count();
}
inline long long system_milli() {
return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
}
inline long long steady_micro() {
return std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now().time_since_epoch()).count();
}
inline long long system_micro() {
return std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
}
template <class T>
struct SharedData {
T data;
uint64_t cnt{1};
};
template <class T>
class SharedPtr {
public:
SharedPtr(SharedData<T> *ptr = 0) : ptr{ptr} {}
SharedPtr(const SharedPtr &other) : ptr{other.ptr} {
if(ptr) ptr->cnt++;
}
~SharedPtr() {
if(ptr==0) return;
if(ptr->cnt > 1) ptr->cnt--;
else delete ptr;
}
bool isNull() {return ptr==0;}
SharedPtr &operator=(const SharedPtr &other) {
this->~SharedPtr();
new (this) SharedPtr(other);
return *this;
}
T &operator*() {
if(ptr==0) ptr = new SharedData<T>;
return ptr->data;
}
T *operator->() {
if(ptr==0) ptr = new SharedData<T>;
return &ptr->data;
}
const T &operator*() const {
return ptr->data;
}
const T *operator->() const {
return &ptr->data;
}
SharedData<T> *ptr{0};
};
template <class V>
class Vector : public SharedPtr<std::vector<V>> {
public:
using SharedPtr<std::vector<V>>::SharedPtr;
using iterator = std::_Vector_iterator<std::_Vector_val<std::_Simple_types<V>>>;
using const_iterator = std::_Vector_const_iterator<std::_Vector_val<std::_Simple_types<V>>>;
Vector(std::initializer_list<V> _Ilist) {
this->ptr = new SharedData<std::vector<V>>{_Ilist, 1};
}
bool empty() const noexcept {
return this->ptr ? this->ptr->data.empty() : true;
}
uint64_t size() const noexcept {
return this->ptr ? this->ptr->data.size() : 0;
}
Vector &append(const V &val) {
(**this).push_back(val);
return *this;
}
V &operator[](const uint64_t pos) noexcept {
return (**this)[pos];
}
const V &operator[](const uint64_t pos) const noexcept {
return this->ptr ? this->ptr->data[pos] : V();
}
const const_iterator begin() const noexcept {
return this->ptr ? this->ptr->data.begin() : const_iterator();
}
const const_iterator end() const noexcept {
return this->ptr ? this->ptr->data.end() : const_iterator();
}
};
struct NodeBase {
NodeBase *next{this};
NodeBase *prev{this};
};
template <class V>
struct _Node : NodeBase {
V value;
~_Node() {
if(next) delete (_Node<V>*) next;
}
};
template <class V>
class LinkedMapIterator {
public:
LinkedMapIterator(_Node<V> *node) : node(node) {}
bool operator==(const LinkedMapIterator& that) const {
return node == that.node;
}
bool operator!=(const LinkedMapIterator& that) const {
return node != that.node;
}
LinkedMapIterator& operator++() {
node = (_Node<V>*) node->next;
return *this;
}
LinkedMapIterator& operator--() {
node = (_Node<V>*) node->prev;
return *this;
}
V &operator*() const {
return node->value;
}
V *operator->() const {
return &node->value;
}
_Node<V> *node{0};
};
template <class K, class V>
struct LinkedMapPri : NodeBase {
std::unordered_map<K, _Node<std::pair<K, V>>*> map;
uint64_t cnt{1};
~LinkedMapPri() {
if(prev) prev->next = 0;
if(next) delete (_Node<std::pair<K, V>>*) next;
}
};
template <class K, class V>
class LinkedMap {
public:
using Node = _Node<std::pair<K, V>>;
using iterator = LinkedMapIterator<std::pair<K, V>>;
using const_iterator = LinkedMapIterator<std::pair<K, V>>;
LinkedMap() {}
LinkedMap(std::initializer_list<std::pair<K, V>> pairs) : _pri{new LinkedMapPri<K, V>} {
for(auto pair : pairs) insert(pair.first, pair.second);
}
LinkedMap(std::unordered_map<K, Node*> &&map) : _pri{new LinkedMapPri<K, V>{0, 0, map}} {
_pri->next = _pri->prev = _pri;
}
LinkedMap(const LinkedMap &other) : _pri{other._pri} {
if(_pri) _pri->cnt++;
}
~LinkedMap() {
if(_pri==0) return;
if(_pri->cnt > 1) _pri->cnt--;
else delete _pri;
}
LinkedMap &operator=(const LinkedMap &other) {
this->~LinkedMap();
new (this) LinkedMap(other);
return *this;
}
const V operator[](const K &k) const {
if(_pri==0) return V();
auto it = _pri->map.find(k);
if(it==_pri->map.end()) return V();
return it->second->value.second;
}
LinkedMap &insert(const K &k, const V &v) {
if(_pri==0) _pri = new LinkedMapPri<K, V>;
auto pair = _pri->map.emplace(k, nullptr);
if(pair.second) {
auto node = new Node{_pri, _pri->prev, {k, v}};
_pri->prev->next = node;
_pri->prev = node;
pair.first->second = node;
} else pair.first->second->value.second = v;
return *this;
}
void erase(const K& k) {
if(_pri==0) return;
auto it = _pri->map.find(k);
if(it==_pri->map.end()) return;
auto node = it->second;
_pri->map.erase(it);
node->prev->next = node->next;
node->next->prev = node->prev;
node->next = 0;
node->prev = 0;
delete node;
}
inline bool empty() const {
return _pri==0 || _pri->map.empty();
}
const_iterator begin() const {
return const_iterator((Node*) (_pri ? _pri->next : 0));
}
const_iterator end() const {
return const_iterator((Node*) _pri);
}
LinkedMapPri<K, V> *_pri{0};
};
#endif // CU_H

View File

@ -62,17 +62,13 @@ public:
inline VBox(QBoxLayout *parent) : QBoxLayout(TopToBottom) {
parent->addLayout(this);
};
inline VBox(QStackedLayout *parent) : QBoxLayout(TopToBottom) {
inline VBox(QStackedLayout *stack) : QBoxLayout(TopToBottom, new QWidget) {
stack->addWidget(parentWidget());
setContentsMargins(0,0,0,0);
auto wgt = new QWidget;
wgt->setLayout(this);
parent->addWidget(wgt);
};
inline VBox(QSplitter *parent) : QBoxLayout(TopToBottom) {
inline VBox(QSplitter *splitter) : QBoxLayout(TopToBottom, new QWidget) {
splitter->addWidget(parentWidget());
setContentsMargins(0,0,0,0);
auto wgt = new QWidget;
wgt->setLayout(this);
parent->addWidget(wgt);
};
inline QLabel *addLabel(const QString &text) {
auto lb = new QLabel(text);
@ -86,17 +82,13 @@ public:
inline HBox(QBoxLayout *parent) : QBoxLayout(LeftToRight) {
parent->addLayout(this);
};
inline HBox(QStackedLayout *parent) : QBoxLayout(LeftToRight) {
inline HBox(QStackedLayout *stack) : QBoxLayout(LeftToRight, new QWidget) {
stack->addWidget(parentWidget());
setContentsMargins(0,0,0,0);
auto wgt = new QWidget;
wgt->setLayout(this);
parent->addWidget(wgt);
};
inline HBox(QSplitter *parent) : QBoxLayout(LeftToRight) {
inline HBox(QSplitter *splitter) : QBoxLayout(LeftToRight, new QWidget) {
splitter->addWidget(parentWidget());
setContentsMargins(0,0,0,0);
auto wgt = new QWidget;
wgt->setLayout(this);
parent->addWidget(wgt);
};
inline QLabel *addLabel(const QString &text) {
auto lb = new QLabel(text);
@ -110,11 +102,17 @@ public:
inline Grid(QBoxLayout *parent) {
parent->addLayout(this);
};
inline Grid(QStackedLayout *parent) {
auto wgt = new QWidget;
wgt->setLayout(this);
parent->addWidget(wgt);
inline Grid(QStackedLayout *stack) : QGridLayout(new QWidget) {
stack->addWidget(parentWidget());
};
inline Grid(QSplitter *splitter) : QGridLayout(new QWidget) {
splitter->addWidget(parentWidget());
};
inline QLabel *addLabel(const QString &text) {
auto lb = new QLabel(text);
addWidget(lb);
return lb;
}
};
class ListWgt : public QListWidget {

183
LedOK/gutil/qjson.cpp Normal file
View File

@ -0,0 +1,183 @@
#include "qjson.h"
inline QChar readOne(QTextStream &in) {
QChar ch;
in >> ch;
return ch;
}
JValue JParser::readValue() {
if(ch=='{') {
JObj obj;
while(true) {
do skipSpace(); //ch有三种可能
while(ch==',');
if(ch=='}') return obj;
QString key;
if(ch == '"') key = readStr();
else if(ch!='n' || in.read(3)!="ull") throw QString("Unexpected char ")+ch+" (code "+ch+"): was expecting double-quote to start field name or null";
skipSpace();
if(ch != ':') throw QString("Unexpected char ")+ch+" (code "+ch+"): was expecting a colon to separate field name and value";
skipSpace();
obj.insert(key, readValue());
skipSpace(); //ch有两种可能
if(ch=='}') return obj;
if(ch!=',') throw QString("Unexpected char ")+ch+"' (code "+ch+"): was expecting } to end Object or comma to separate Object entries";
}
}
if(ch=='[') {
JArray list;
while(true) {
do skipSpace(); //ch有三种可能
while(ch==',');
if(ch==']') return list;
list->push_back(readValue());
skipSpace(); //ch有两种可能
if(ch==']') return list;
if(ch!=',') throw QString("Unexpected char ")+ch+" (code "+ch+"): was expecting ] to end Array or comma to separate Array entries";
}
}
if(ch=='"') return readStr();
if((ch>='0' && ch<='9') || ch=='-') {
QString buf;
buf += ch;
bool isInt = true;
while(0 != (ch = readOne(in))) {
if((ch>'*' && ch<':' && ch!=',' && ch!='/') || ch=='e' || ch=='E') {
buf.append(ch);
if(isInt && ch=='.') isInt = false;
} else {
bk = ch;
break;
}
}
bool ok;
if(isInt) {
auto num = buf.toLongLong(&ok);
if(! ok) throw "Illegal number: "+buf;
return num;
} else {
auto num = buf.toDouble(&ok);
if(! ok) throw "Illegal number: "+buf;
return num;
}
}
if(ch=='n') {
if(in.read(3)=="ull") return JValue();
else throw "Unexpected char n: expected null";
}
if(ch=='t') {
if(in.read(3)=="rue") return true;
else throw "Unexpected char t: expected true";
}
if(ch=='f') {
if(in.read(4)=="alse") return false;
else throw "Unexpected char f: expected false";
}
throw QString("Unexpected char ")+ch+" (code "+ch+"): expected {}, [], \"string\", number, null, true or false";
}
QString JParser::readStr() {
QString buf;
while((ch = readOne(in)) != '"') {
if(ch==0) throw "Unexpected end-of-input: was expecting closing quote for string";
if(ch=='\\') {
in>>ch;
if(ch==0) throw "Unexpected end-of-input in char escape sequence";
if(ch=='"' || ch=='\\' || ch=='/') buf.append(ch);
else if(ch=='n') buf.append('\n');
else if(ch=='r') buf.append('\r');
else if(ch=='t') buf.append('\t');
else if(ch=='f') buf.append('\f');
else if(ch=='b') buf.append('\b');
else if(ch=='u') {
auto hex = in.read(4);
if(hex.size()<4) throw "Unexpected end-of-input in char escape sequence";
bool ok;
buf.append(hex.toUShort(&ok, 16));
if(! ok) throw "Illegal hex-digits in char escape sequence: \\u"+hex;
} else throw QString("Unrecognized char-escape ")+ch+" (code "+ch+")";
} else buf.append(ch);
}
return buf;
}
void JParser::skipSpace() {
if(bk.unicode()) {
bk = QChar::Null;
if(! ch.isSpace()) return;
}
in.skipWhiteSpace();
in >> ch;
if(ch==0) throw "Unexpected end-of-input";
}
void JOut::write(const JValue &value) {
if(value.type==JValue::Null) out << "null";
else if(value.type==JValue::Str) writeStr(value.toStr());
else if(value.type==JValue::Obj) writeMap(value.toObj());
else if(value.type==JValue::Array) writeList(value.toArray());
else out << value.toStr();
out.flush();
}
void JOut::writeStr(const QString &str) {
out << '"';
QChar ch;
for(int i=0; i<str.length(); i++) {
ch = str[i];
if(ch=='"'||ch=='\\') out<<'\\'<<ch;
else if(ch < ' ') {
if(ch=='\n') out<<"\\n";
else if(ch=='\r') out<<"\\r";
else if(ch=='\t') out<<"\\t";
else if(ch=='\f') out<<"\\f";
else if(ch=='\b') out<<"\\b";
else {
out<<"\\u00";
auto aa = QString::number(ch.unicode(), 16);
if(aa.size()==1) out<<'0';
out<<aa;
}
} else out << ch;
}
out << '"';
}
void JOut::writeMap(const JObj &map) {
out << '{';
if(! map.empty()) {
if(indent.size()) {
out << '\n';
cnt++;
for(int c=0; c<cnt; c++) out << indent;
}
bool addSep = false;
for(const auto &pair : map) {
if(addSep) {
out << ',';
if(indent.size()) {
out << '\n';
for(int c=0; c<cnt; c++) out << indent;
}
}
else addSep = true;
out << '"' << pair.first << "\":";
if(indent.size()) out << ' ';
write(pair.second);
}
if(indent.size()) {
out << '\n';
cnt--;
for(int c=0; c<cnt; c++) out << indent;
}
}
out << '}';
}
void JOut::writeList(const JArray &vals) {
out << '[';
auto iter = vals.begin();
auto end = vals.end();
if(iter!=end) write(*iter++);
while(iter!=end) {
out << ',';
if(indent.size()) out << ' ';
write(*iter++);
}
out << ']';
}

177
LedOK/gutil/qjson.h Normal file
View File

@ -0,0 +1,177 @@
#ifndef QJSON_H
#define QJSON_H
#include "cu.h"
#include "QtCore/qhashfunctions.h"
#include <QTextStream>
class JValue;
using JObj = LinkedMap<QString, JValue>;
using JArray = Vector<JValue>;
class JValue {
public:
int data[2]{0};
enum Type {
Null, Bool, Int, Long, Double, Obj, Array, Str
};
Type type{Null};
JValue(Type = Null) {}
JValue(bool b) : type(Bool) {data[0] = b;}
JValue(int n) : type(Int) {data[0] = n;}
JValue(qint64 n) : type(Long) {*(qint64*) data = n;}
JValue(double d) : type(Double) {*(double*) data = d;}
JValue(const JObj &o) : type(Obj) {new (data) JObj(o);}
JValue(const JArray &a) : type(Array) {new (data) JArray(a);}
JValue(const QString &s) : type(Str) {*(SharedData<QString>**) data = new SharedData<QString>{s, 1};}
JValue(const char *s) : JValue(QString::fromUtf8(s)) {}
JValue(const JValue &other) {
type = other.type;
if(type==Obj) new (data) JObj(*(JObj*) other.data);
else if(type==Array) new (data) JArray(*(JArray*) other.data);
else {
data[0] = other.data[0];
data[1] = other.data[1];
if(type==Str) (*(SharedData<QString>**) data)->cnt++;
}
}
~JValue() {
if(type < Obj) return;
else if(type==Obj) ((JObj*) data)->~JObj();
else if(type==Array) ((JArray*) data)->~JArray();
else if(type==Str) {
auto ptr = *(SharedData<QString>**) data;
if(ptr->cnt > 1) ptr->cnt--;
else delete ptr;
}
}
JValue &operator=(const JValue &other) {
this->~JValue();
new (this) JValue(other);
return *this;
}
bool isNull() const {return type==Null;}
bool isObj() const {return type==Obj;}
bool isArray() const {return type==Array;}
bool toBool(bool def = false) const {
return type==Null ? def : data[0] || data[1];
}
int toInt(int def = 0) const {
if(type==Bool || type==Int) return data[0];
if(type==Long) return *(qint64*) data;
if(type==Double) return *(double*) data;
return def;
}
qint64 toLong(qint64 def = 0) const {
if(type==Bool || type==Int) return data[0];
if(type==Long) return *(qint64*) data;
if(type==Double) return *(double*) data;
return def;
}
double toDouble(double def = 0) const {
if(type==Bool || type==Int) return data[0];
if(type==Long) return *(qint64*) data;
if(type==Double) return *(double*) data;
return def;
}
QString toStr(const QString &def = "") const {
if(type==Bool) return data[0] ? "true" : "false";
if(type==Int) return QString::number(data[0]);
if(type==Long) return QString::number(*(qint64*) data);
if(type==Double) return QString::number(*(double*) data);
if(type==Str) return (*(SharedData<QString>**) data)->data;
return def;
}
JObj toObj() const {
if(type==Obj) return *(JObj*) data;
return JObj();
}
JArray toArray() const {
if(type==Array) return *(JArray*) data;
return JArray();
}
private:
JValue(const void *) = delete; // avoid implicit conversions from char * to bool
};
class JParser {
public:
JParser(QTextStream &in) : in(in) {}
inline JValue read() {
skipSpace();
return readValue();
}
protected:
JValue readValue();
QString readStr();
void skipSpace();
QTextStream &in;
QChar ch{0}, bk{0};
};
inline JValue JFrom(const QByteArray &json, QString *err = 0) {
QTextStream in(json);
try {
return JParser(in).read();
} catch (QString anerr) {
if(err) *err = anerr;
} catch (const char *anerr) {
if(err) *err = anerr;
} catch (...) {
if(err) *err = "unknow error";
}
return JValue();
}
inline JValue JFrom(QIODevice *device, QString *err = 0) {
QTextStream in(device);
try {
return JParser(in).read();
} catch (QString anerr) {
if(err) *err = anerr;
} catch (const char *anerr) {
if(err) *err = anerr;
} catch (...) {
if(err) *err = "unknow error";
}
return JValue();
}
class JOut {
public:
JOut(QTextStream &out, QString indent = "") : out(out), indent(indent) {}
void write(const JValue &obj);
void writeStr(const QString &str);
void writeMap(const JObj &map);
void writeList(const JArray &objs);
protected:
QTextStream &out;
QString indent;
int cnt{0};
};
inline QString JToStr(const JValue &obj, QString indent = "") {
QString json;
QTextStream out(&json);
JOut(out, indent).write(obj);
return json;
}
inline QByteArray JToBytes(const JValue &obj, QString indent = "") {
QByteArray json;
QTextStream out(&json);
JOut(out, indent).write(obj);
return json;
}
inline QTextStream::Status JWrite(const JValue &obj, QIODevice *device, QString indent = "") {
QTextStream out(device);
JOut(out, indent).write(obj);
return out.status();
}
#endif // QJSON_H

View File

@ -5,16 +5,16 @@
const char *const FormBoundary = "----GangphonQtBoundary_.oOo._";
QNetworkAccessManager &netAccess() {
QNetworkAccessManager *netAccess() {
static QNetworkAccessManager access;
return access;
return &access;
};
QString errStr(QNetworkReply *reply) {
reply->deleteLater();
auto error = reply->error();
if(error != QNetworkReply::NoError) {
if(error==QNetworkReply::OperationCanceledError) return QString(QMetaEnum::fromType<QNetworkReply::NetworkError>().valueToKey(QNetworkReply::TimeoutError))+" ("+QString::number(QNetworkReply::TimeoutError)+") "+QCoreApplication::translate("Net","Connection Timeout");
if(error==QNetworkReply::OperationCanceledError) return "TimeoutError ("+QString::number(QNetworkReply::TimeoutError)+") "+QCoreApplication::translate("Net","Connection Timeout");
auto errStr = reply->errorString();
if(error!=QNetworkReply::InternalServerError || ! errStr.endsWith("replied: Unknown")) return QString(QMetaEnum::fromType<QNetworkReply::NetworkError>().valueToKey(error))+" ("+QString::number(error)+") "+errStr;
}

View File

@ -8,19 +8,38 @@
extern const char *const FormBoundary;
QNetworkAccessManager &netAccess();
QNetworkAccessManager *netAccess();
class NetReq : public QNetworkRequest {
public:
#if(QT_VERSION_MAJOR > 5)
using QNetworkRequest::QNetworkRequest;
explicit NetReq(const QString &url) : QNetworkRequest{url} {};
explicit NetReq(QNetworkAccessManager *access) : mAccess(access) {};
#else
NetReq() {init();};
explicit NetReq(const QString &url) : QNetworkRequest{url} {init();};
explicit NetReq(QNetworkAccessManager *access) : mAccess(access) {init();};
explicit NetReq(const QUrl &url) : QNetworkRequest{url} {init();};
NetReq(const QNetworkRequest &other) : QNetworkRequest{other} {init();};
inline void init() {
#if(QT_VERSION_MAJOR < 6)
setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::NoLessSafeRedirectPolicy);
}
#endif
using QNetworkRequest::url;
inline NetReq &url(const QUrl &url) {
setUrl(url);
return *this;
}
inline NetReq &access(QNetworkAccessManager *access) {
mAccess = access;
return *this;
}
inline NetReq &header(const QByteArray &headerName, const QByteArray &value) {
setRawHeader(headerName, value);
return *this;
}
inline NetReq &header(KnownHeaders header, const QVariant &value) {
setHeader(header, value);
return *this;
}
inline NetReq &type(const QByteArray &value) {
@ -37,14 +56,16 @@ public:
}
inline QNetworkReply *get() {
return netAccess().get(*this);
if(mAccess==0) mAccess = netAccess();
return mAccess->get(*this);
}
inline QNetworkReply *post(const QByteArray &data) {
return netAccess().post(*this, data);
if(mAccess==0) mAccess = netAccess();
return mAccess->post(*this, data);
}
inline QNetworkReply *post(const QJsonDocument &json) {
setRawHeader("Content-Type", "application/json");
return netAccess().post(*this, json.toJson(QJsonDocument::Compact));
return post(json.toJson(QJsonDocument::Compact));
}
inline QNetworkReply *post(const QJsonObject &json) {
return post(QJsonDocument{json});
@ -53,13 +74,20 @@ public:
return post(QJsonDocument{json});
}
inline QNetworkReply *post(QHttpMultiPart *multiPart) {
return netAccess().post(*this, multiPart);
if(mAccess==0) mAccess = netAccess();
return mAccess->post(*this, multiPart);
}
QNetworkAccessManager *mAccess{0};
};
QString errStr(QNetworkReply *);
QString errStrWithData(QNetworkReply *, QJsonDocument * = 0);
inline int waitFinished(QNetworkReply *reply, bool excludeUser = false) {
QEventLoop loop;
QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
return excludeUser ? loop.exec(QEventLoop::ExcludeUserInputEvents) : loop.exec();
}
inline void abortSilence(QNetworkReply *reply) {
reply->blockSignals(true);
reply->abort();

View File

@ -143,7 +143,7 @@ void SendProgThread::run() {
return;
}
while(remain > 0) {
auto readed = file->read(qMin(4096LL, remain));
auto readed = file->read(qMin(4*4096LL, remain));
if(readed.isEmpty()) {
emit emErr(tr("Read file failed")+" "+file->errorString());
tcp.close();

View File

@ -124,21 +124,10 @@ QBrush Tools::getBrush(const QColor& color) {
}
int Tools::color2Int(const QColor& color) {
int res = 0;
res |= (color.red() & 0xFF) << 24;
res |= (color.green() & 0xFF) << 16;
res |= (color.blue() & 0xFF) << 8;
res |= (color.alpha() & 0xFF);
return res;
return color.red() << 24 | color.green() << 16 | color.blue() << 8 | color.alpha();
}
QColor Tools::int2Color(int value) {
QColor res;
res.setRed ((value >> 24) & 0xFF);
res.setGreen((value >> 16) & 0xFF);
res.setBlue ((value >> 8) & 0xFF);
res.setAlpha((value ) & 0xFF);
return res;
return QColor((value >> 24) & 0xff, (value >> 16) & 0xff, (value >> 8) & 0xff, value & 0xff);
}
QString Tools::selectStr(bool f, const QString &s0, const QString &s1) {