From feda8a7db8d1d7c5439aa8f8feef7cc0dd2b59a0 Mon Sep 17 00:00:00 2001 From: Unit 193 Date: Fri, 27 Jul 2018 23:51:12 -0400 Subject: New upstream version 3.2.1+dfsg1 --- .../coreSQLiteStudio/common/bistrhash.cpp | 1 + SQLiteStudio3/coreSQLiteStudio/common/global.h | 2 +- .../coreSQLiteStudio/common/lazytrigger.cpp | 37 ++++++++ .../coreSQLiteStudio/common/lazytrigger.h | 34 +++++++ SQLiteStudio3/coreSQLiteStudio/common/objectpool.h | 7 +- SQLiteStudio3/coreSQLiteStudio/common/sortedhash.h | 4 +- SQLiteStudio3/coreSQLiteStudio/common/utils.cpp | 102 +++++++++++++++++++-- SQLiteStudio3/coreSQLiteStudio/common/utils.h | 10 ++ .../coreSQLiteStudio/common/utils_sql.cpp | 45 ++++++--- .../coreSQLiteStudio/common/valuelocker.h | 44 +++++++++ .../coreSQLiteStudio/common/xmldeserializer.cpp | 84 +++++++++++++++++ .../coreSQLiteStudio/common/xmldeserializer.h | 31 +++++++ 12 files changed, 378 insertions(+), 23 deletions(-) create mode 100644 SQLiteStudio3/coreSQLiteStudio/common/lazytrigger.cpp create mode 100644 SQLiteStudio3/coreSQLiteStudio/common/lazytrigger.h create mode 100644 SQLiteStudio3/coreSQLiteStudio/common/valuelocker.h create mode 100644 SQLiteStudio3/coreSQLiteStudio/common/xmldeserializer.cpp create mode 100644 SQLiteStudio3/coreSQLiteStudio/common/xmldeserializer.h (limited to 'SQLiteStudio3/coreSQLiteStudio/common') diff --git a/SQLiteStudio3/coreSQLiteStudio/common/bistrhash.cpp b/SQLiteStudio3/coreSQLiteStudio/common/bistrhash.cpp index 091121c..5f40521 100644 --- a/SQLiteStudio3/coreSQLiteStudio/common/bistrhash.cpp +++ b/SQLiteStudio3/coreSQLiteStudio/common/bistrhash.cpp @@ -1,4 +1,5 @@ #include "bistrhash.h" +#include BiStrHash::BiStrHash(std::initializer_list > list) { diff --git a/SQLiteStudio3/coreSQLiteStudio/common/global.h b/SQLiteStudio3/coreSQLiteStudio/common/global.h index b1f4b01..cfd8dc0 100644 --- a/SQLiteStudio3/coreSQLiteStudio/common/global.h +++ b/SQLiteStudio3/coreSQLiteStudio/common/global.h @@ -12,7 +12,7 @@ #define DEEP_COPY_COLLECTION(T, F) \ T* _new##T; \ - foreach (T* _element, other.F) \ + for (T* _element : other.F) \ { \ _new##T = new T(*_element); \ _new##T->setParent(this); \ diff --git a/SQLiteStudio3/coreSQLiteStudio/common/lazytrigger.cpp b/SQLiteStudio3/coreSQLiteStudio/common/lazytrigger.cpp new file mode 100644 index 0000000..2c39f34 --- /dev/null +++ b/SQLiteStudio3/coreSQLiteStudio/common/lazytrigger.cpp @@ -0,0 +1,37 @@ +#include "lazytrigger.h" +#include + +LazyTrigger::LazyTrigger(int delay, QObject* parent, const char* slot) : + QObject(parent) +{ + timer = new QTimer(this); + timer->setSingleShot(true); + timer->setInterval(delay); + connect(timer, &QTimer::timeout, this, &LazyTrigger::triggered); + if (slot) + connect(timer, SIGNAL(timeout()), parent, slot); +} + +LazyTrigger::LazyTrigger(int delay, LazyTrigger::Condition condition, QObject* parent, const char* slot) : + LazyTrigger(delay, parent, slot) +{ + this->condition = condition; +} + +void LazyTrigger::setDelay(int delay) +{ + timer->setInterval(delay); +} + +void LazyTrigger::schedule() +{ + timer->stop(); + + if (!condition || condition()) + timer->start(); +} + +void LazyTrigger::cancel() +{ + timer->stop(); +} diff --git a/SQLiteStudio3/coreSQLiteStudio/common/lazytrigger.h b/SQLiteStudio3/coreSQLiteStudio/common/lazytrigger.h new file mode 100644 index 0000000..9c34395 --- /dev/null +++ b/SQLiteStudio3/coreSQLiteStudio/common/lazytrigger.h @@ -0,0 +1,34 @@ +#ifndef LAZYTRIGGER_H +#define LAZYTRIGGER_H + +#include "coreSQLiteStudio_global.h" +#include +#include + +class QTimer; + +class API_EXPORT LazyTrigger : public QObject +{ + Q_OBJECT + + public: + typedef std::function Condition; + + LazyTrigger(int delay, QObject* parent = nullptr, const char* slot = nullptr); + LazyTrigger(int delay, Condition condition, QObject* parent = nullptr, const char* slot = nullptr); + + void setDelay(int delay); + + private: + QTimer* timer = nullptr; + Condition condition = nullptr; + + public slots: + void schedule(); + void cancel(); + + signals: + void triggered(); +}; + +#endif // LAZYTRIGGER_H diff --git a/SQLiteStudio3/coreSQLiteStudio/common/objectpool.h b/SQLiteStudio3/coreSQLiteStudio/common/objectpool.h index b9f6b9f..7330efc 100644 --- a/SQLiteStudio3/coreSQLiteStudio/common/objectpool.h +++ b/SQLiteStudio3/coreSQLiteStudio/common/objectpool.h @@ -24,7 +24,7 @@ class ObjectPool }; template -ObjectPool::ObjectPool(quint32 min, quint32 max) +ObjectPool::ObjectPool(quint32 min, quint32 max) : min(min), max(max) { Q_ASSERT(min > 0); @@ -36,7 +36,8 @@ ObjectPool::ObjectPool(quint32 min, quint32 max) } } -T* ObjectPool::reserve() +template +T* ObjectPool::reserve() { mutex.lock(); @@ -73,7 +74,7 @@ T* ObjectPool::reserve() } template -void ObjectPool::release(T* obj) +void ObjectPool::release(T* obj) { mutex.lock(); pool[obj] = false; diff --git a/SQLiteStudio3/coreSQLiteStudio/common/sortedhash.h b/SQLiteStudio3/coreSQLiteStudio/common/sortedhash.h index 9ca6ade..c0d44b6 100644 --- a/SQLiteStudio3/coreSQLiteStudio/common/sortedhash.h +++ b/SQLiteStudio3/coreSQLiteStudio/common/sortedhash.h @@ -74,7 +74,7 @@ class SortedHash : public QHash QList keys(const T& value) const { QList results; - foreach (const Key& k, sortedKeys) + for (const Key& k : sortedKeys) if (value(k) == value) results << k; @@ -98,7 +98,7 @@ class SortedHash : public QHash QList values() const { QList results; - foreach (const Key& k, sortedKeys) + for (const Key& k : sortedKeys) results << value(k); return results; diff --git a/SQLiteStudio3/coreSQLiteStudio/common/utils.cpp b/SQLiteStudio3/coreSQLiteStudio/common/utils.cpp index e3d2e47..fd40355 100644 --- a/SQLiteStudio3/coreSQLiteStudio/common/utils.cpp +++ b/SQLiteStudio3/coreSQLiteStudio/common/utils.cpp @@ -311,7 +311,7 @@ QStringList tokenizeArgs(const QString& str) QStringList prefixEach(const QString& prefix, const QStringList& list) { QStringList result; - foreach (const QString& item, list) + for (const QString& item : list) result << (prefix + item); return result; @@ -385,7 +385,7 @@ QString longest(const QStringList& strList) { int max = 0; QString result; - foreach (const QString str, strList) + for (const QString str : strList) { if (str.size() > max) { @@ -400,7 +400,7 @@ QString shortest(const QStringList& strList) { int max = INT_MAX; QString result; - foreach (const QString str, strList) + for (const QString str : strList) { if (str.size() < max) { @@ -421,7 +421,7 @@ QString longestCommonPart(const QStringList& strList) for (int i = 0; i < first.length(); i++) { common += first[i]; - foreach (const QString& str, strList) + for (const QString& str : strList) { if (!str.startsWith(common)) return common.left(i); @@ -434,7 +434,7 @@ QStringList applyMargin(const QString& str, int margin) { QStringList lines; QString line; - foreach (QString word, str.split(" ")) + for (QString word : str.split(" ")) { if (((line + word).length() + 1) > margin) { @@ -694,9 +694,11 @@ QString getOsString() case QSysInfo::WV_WINDOWS8_1: os += " 8.1"; break; +#if QT_VERSION >= 0x050500 case QSysInfo::WV_WINDOWS10: os += " 10"; break; +#endif case QSysInfo::WV_32s: case QSysInfo::WV_95: case QSysInfo::WV_98: @@ -710,7 +712,9 @@ QString getOsString() case QSysInfo::WV_CE_5: case QSysInfo::WV_CE_6: case QSysInfo::WV_CE_based: +#if QT_VERSION >= 0x050500 case QSysInfo::WV_None: +#endif break; } #elif defined(Q_OS_LINUX) @@ -752,6 +756,9 @@ QString getOsString() case QSysInfo::MV_10_11: os += " 10.11 El Capitan"; break; + case QSysInfo::MV_10_12: + os += " 10.12 Sierra"; + break; case QSysInfo::MV_9: case QSysInfo::MV_10_0: case QSysInfo::MV_10_1: @@ -816,6 +823,42 @@ bool isHex(const QString& str) return ok; } +bool isHex(const QChar& c) +{ + return isHex(c.toLatin1()); +} + +bool isHex(const char c) +{ + switch (c) + { + case 'a': + case 'A': + case 'b': + case 'B': + case 'c': + case 'C': + case 'd': + case 'D': + case 'e': + case 'E': + case 'f': + case 'F': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + return true; + } + return false; +} + QString formatVersion(int version) { int majorVer = version / 10000; @@ -916,9 +959,18 @@ QStringList concat(const QList& list) return result; } + QString doubleToString(const QVariant& val) { - return val.toString(); + QString str = val.toString(); + if (str.contains("e")) + str = QString::number(val.toDouble(), 'f', 14).remove(QRegExp("0*$")); + else if (!str.contains('.')) + str += ".0"; + else if (str.mid(str.indexOf('.') + 1).length() > 14) + str = QString::number(val.toDouble(), 'f', 14).remove(QRegExp("0*$")); + + return str; } void sortWithReferenceList(QList& listToSort, const QList& referenceList, Qt::CaseSensitivity cs) @@ -941,3 +993,41 @@ void sortWithReferenceList(QList& listToSort, const QList& ref return (idx1 > idx2); }); } + +QByteArray serializeToBytes(const QVariant& value) +{ + QByteArray bytes; + QDataStream stream(&bytes, QIODevice::WriteOnly); + stream << value; + return bytes; +} + +QVariant deserializeFromBytes(const QByteArray& bytes) +{ + if (bytes.isNull()) + return QVariant(); + + QVariant deserializedValue; + QDataStream stream(bytes); + stream >> deserializedValue; + return deserializedValue; +} + +QString readFileContents(const QString& path, QString* err) +{ + QFile file(path); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) + { + if (err) + *err = QObject::tr("Could not open file '%1' for reading: %2").arg(path).arg(file.errorString()); + + return QString(); + } + + QTextStream stream(&file); + stream.setCodec("UTF-8"); + QString contents = stream.readAll(); + file.close(); + + return contents; +} diff --git a/SQLiteStudio3/coreSQLiteStudio/common/utils.h b/SQLiteStudio3/coreSQLiteStudio/common/utils.h index c56a4db..24ea150 100644 --- a/SQLiteStudio3/coreSQLiteStudio/common/utils.h +++ b/SQLiteStudio3/coreSQLiteStudio/common/utils.h @@ -9,6 +9,8 @@ #include #include #include +#include +#include class QTextCodec; @@ -236,6 +238,8 @@ API_EXPORT int sum(const QList& integers); API_EXPORT QString getOsString(); API_EXPORT bool validateEmail(const QString& email); API_EXPORT bool isHex(const QString& str); +API_EXPORT bool isHex(const QChar& c); +API_EXPORT bool isHex(const char c); API_EXPORT QString formatVersion(int version); API_EXPORT bool copyRecursively(const QString& src, const QString& dst); API_EXPORT bool renameBetweenPartitions(const QString& src, const QString& dst); @@ -289,6 +293,12 @@ void removeDuplicates(QList& list) } } +API_EXPORT QByteArray serializeToBytes(const QVariant& value); + +API_EXPORT QVariant deserializeFromBytes(const QByteArray& bytes); + +API_EXPORT QString readFileContents(const QString& path, QString* err); + Q_DECLARE_METATYPE(QList) #endif // UTILS_H diff --git a/SQLiteStudio3/coreSQLiteStudio/common/utils_sql.cpp b/SQLiteStudio3/coreSQLiteStudio/common/utils_sql.cpp index ad37ff0..b5642ec 100644 --- a/SQLiteStudio3/coreSQLiteStudio/common/utils_sql.cpp +++ b/SQLiteStudio3/coreSQLiteStudio/common/utils_sql.cpp @@ -12,7 +12,8 @@ #include QString invalidIdCharacters = "[]()\"'@*.,+-=/%&|:; \t\n<>"; -QHash > wrapperChars; +QHash> wrapperChars; +QHash> wrapperEscapedEnding; QList sqlite3Wrappers; QList sqlite2Wrappers; @@ -23,6 +24,11 @@ void initUtilsSql() wrapperChars[NameWrapper::BACK_QUOTE] = QPair('`', '`'); wrapperChars[NameWrapper::DOUBLE_QUOTE] = QPair('"', '"'); + wrapperEscapedEnding[NameWrapper::BRACKET] = QPair(']', false); + wrapperEscapedEnding[NameWrapper::QUOTE] = QPair('\'', true); + wrapperEscapedEnding[NameWrapper::BACK_QUOTE] = QPair('`', true); + wrapperEscapedEnding[NameWrapper::DOUBLE_QUOTE] = QPair('"', true); + sqlite3Wrappers << NameWrapper::DOUBLE_QUOTE << NameWrapper::BRACKET << NameWrapper::QUOTE @@ -129,7 +135,7 @@ QPair getQuoteCharacter(QString& obj, Dialect dialect, NameWrapper } QPair wrapChars; - foreach (NameWrapper wrapper, wrappers) + for (NameWrapper wrapper : wrappers) { wrapChars = wrapperChars[wrapper]; if (obj.indexOf(wrapChars.first) > -1) @@ -277,6 +283,23 @@ bool isObjWrapped(const QString& str, Dialect dialect) return getObjWrapper(str, dialect) != NameWrapper::null; } +bool doesNotContainEndingWrapperChar(const QString& str, NameWrapper wrapper) +{ + QString innerPart = str.mid(1, str.length() - 2); + const QChar& endingChar = wrapperEscapedEnding[wrapper].first; + bool escapingAllowed = wrapperEscapedEnding[wrapper].second; + int idx = -1; + int lastIdx = innerPart.length() - 1; + while ((idx = innerPart.indexOf(endingChar, idx + 1)) > -1) + { + if (idx == lastIdx || !escapingAllowed || innerPart[idx + 1] != endingChar) + return false; + + idx++; // we had occurrence, but it was escaped, so we need to skip the second (escape) char + } + return true; +} + NameWrapper getObjWrapper(const QString& str, Dialect dialect) { if (str.isEmpty()) @@ -289,10 +312,10 @@ NameWrapper getObjWrapper(const QString& str, Dialect dialect) else wrappers = sqlite3Wrappers; - foreach (NameWrapper wrapper, wrappers) + for (NameWrapper wrapper : wrappers) { QPair chars = wrapperChars[wrapper]; - if (str[0] == chars.first && str[str.length()-1] == chars.second) + if (str[0] == chars.first && str[str.length()-1] == chars.second && doesNotContainEndingWrapperChar(str, wrapper)) return wrapper; } return NameWrapper::null; @@ -306,7 +329,7 @@ bool isWrapperChar(const QChar& c, Dialect dialect) else wrappers = sqlite3Wrappers; - foreach (NameWrapper wrapper, wrappers) + for (NameWrapper wrapper : wrappers) { QPair chars = wrapperChars[wrapper]; if (c == chars.first || c == chars.second) @@ -389,7 +412,7 @@ QList splitQueries(const TokenList& tokenizedQuery, bool* complete) int createTriggerMeter = 0; bool insideTrigger = false; bool completeQuery = false; - foreach (const TokenPtr& token, tokenizedQuery) + for (const TokenPtr& token : tokenizedQuery) { value = token->value.toUpper(); if (!token->isWhitespace()) @@ -556,7 +579,7 @@ QStringList splitQueries(const QString& sql, Dialect dialect, bool keepEmptyQuer QString query; QStringList queries; - foreach (const TokenList& queryTokens, tokenizedQueries) + for (const TokenList& queryTokens : tokenizedQueries) { query = queryTokens.detokenize(); if (keepEmptyQueries || (!query.trimmed().isEmpty() && query.trimmed() != ";")) @@ -627,10 +650,10 @@ QList getQueriesWithParamNames(const QString& query, Dialec QString queryStr; QStringList paramNames; - foreach (const TokenList& tokens, queries) + for (const TokenList& tokens : queries) { paramNames.clear(); - foreach (const TokenPtr& token, tokens.filter(Token::BIND_PARAM)) + for (const TokenPtr& token : tokens.filter(Token::BIND_PARAM)) paramNames << token->value; queryStr = tokens.detokenize().trimmed(); @@ -648,7 +671,7 @@ QList getQueriesWithParamCount(const QString& query, Dialec QList queries = splitQueries(allTokens); QString queryStr; - foreach (const TokenList& tokens, queries) + for (const TokenList& tokens : queries) { queryStr = tokens.detokenize().trimmed(); if (!queryStr.isEmpty()) @@ -663,7 +686,7 @@ QueryWithParamNames getQueryWithParamNames(const QString& query, Dialect dialect TokenList allTokens = Lexer::tokenize(query, dialect); QStringList paramNames; - foreach (const TokenPtr& token, allTokens.filter(Token::BIND_PARAM)) + for (const TokenPtr& token : allTokens.filter(Token::BIND_PARAM)) paramNames << token->value; return QueryWithParamNames(query, paramNames); diff --git a/SQLiteStudio3/coreSQLiteStudio/common/valuelocker.h b/SQLiteStudio3/coreSQLiteStudio/common/valuelocker.h new file mode 100644 index 0000000..a757506 --- /dev/null +++ b/SQLiteStudio3/coreSQLiteStudio/common/valuelocker.h @@ -0,0 +1,44 @@ +#ifndef VALUELOCKER_H +#define VALUELOCKER_H + +/** + * ValueLocker is similar to QMutexLocker, but it's not intended for multithreaded locks. + * It's rather for event loop locking. + * It can be created as local scope variable with a pointer to member variable. + * It will set "unlockedValue" to that variable once the locker is destroyed (goes out of scope). + * Usually the variable used will be of boolean type, but it can be virtually any other type. + * You can also provide initial value for locked state. Otherwise you will need to set the locked + * by yourself before the lock is created. + */ +template +class ValueLocker { + public: + ValueLocker(T* valueToLock, const T& lockedValue, const T& unlockedValue); + ValueLocker(T* valueToLock, const T& unlockedValue); + ~ValueLocker(); + + private: + T* valueToLock; + T unlockedValue; +}; + +template +ValueLocker::ValueLocker(T *valueToLock, const T &lockedValue, const T &unlockedValue) : + ValueLocker(valueToLock, unlockedValue) +{ + *valueToLock = lockedValue; +} + +template +ValueLocker::ValueLocker(T *valueToLock, const T &unlockedValue) : + valueToLock(valueToLock), unlockedValue(unlockedValue) +{ +} + +template +ValueLocker::~ValueLocker() +{ + *valueToLock = unlockedValue; +} + +#endif // VALUELOCKER_H diff --git a/SQLiteStudio3/coreSQLiteStudio/common/xmldeserializer.cpp b/SQLiteStudio3/coreSQLiteStudio/common/xmldeserializer.cpp new file mode 100644 index 0000000..7c86088 --- /dev/null +++ b/SQLiteStudio3/coreSQLiteStudio/common/xmldeserializer.cpp @@ -0,0 +1,84 @@ +/*#include "xmldeserializer.h" +#include "unused.h" +#include + +XmlDeserializer::XmlDeserializer() +{ +} + +QHash XmlDeserializer::deserialize(QIODevice *input) +{ + QXmlStreamReader reader(input); + return deserialize(reader); +} + +QHash XmlDeserializer::deserialize(const QString &input) +{ + QXmlStreamReader reader(input); + return deserialize(reader); +} + +QHash XmlDeserializer::deserialize(QXmlStreamReader &reader) +{ + ctxStack.clear(); + output.clear(); + ctx = &output; + + QXmlStreamReader::TokenType tokenType; + while ((tokenType = reader.readNext()) != QXmlStreamReader::EndDocument) + handleTokenType(reader, tokenType); + + return output; +} + +void XmlDeserializer::handleTokenType(QXmlStreamReader& reader, QXmlStreamReader::TokenType tokenType) +{ + switch (tokenType) + { + case QXmlStreamReader::Comment: + case QXmlStreamReader::EndDocument: + case QXmlStreamReader::DTD: + case QXmlStreamReader::NoToken: + case QXmlStreamReader::ProcessingInstruction: + case QXmlStreamReader::StartDocument: + case QXmlStreamReader::EntityReference: + break; + case QXmlStreamReader::Invalid: + qDebug() << "Invalid token while parsing XML:" << reader.errorString(); + break; + case QXmlStreamReader::StartElement: + handleStartElement(reader); + break; + case QXmlStreamReader::Characters: + handleText(reader); + break; + case QXmlStreamReader::EndElement: + handleEndElement(reader); + break; + } +} + +void XmlDeserializer::handleStartElement(QXmlStreamReader &reader) +{ + QString key = reader.name().toString(); + QHash newCtx; + ctx->insertMulti(key, newCtx); + + for (const QXmlStreamAttribute& attr : reader.attributes()) + ctx->insertMulti(attr.name().toString(), attr.value().toString()); + + ctxStack.push(ctx); + ctx = &((*ctx)[key]); +} + +void XmlDeserializer::handleText(QXmlStreamReader &reader) +{ + ctx->insertMulti(QString(), reader.text().toString()); +} + +void XmlDeserializer::handleEndElement(QXmlStreamReader &reader) +{ + UNUSED(reader); + ctx = ctxStack.pop(); +} +*/ diff --git a/SQLiteStudio3/coreSQLiteStudio/common/xmldeserializer.h b/SQLiteStudio3/coreSQLiteStudio/common/xmldeserializer.h new file mode 100644 index 0000000..52761cf --- /dev/null +++ b/SQLiteStudio3/coreSQLiteStudio/common/xmldeserializer.h @@ -0,0 +1,31 @@ +/*#ifndef XMLDESERIALIZER_H +#define XMLDESERIALIZER_H + +#include "coreSQLiteStudio_global.h" +#include +#include +#include +#include + +class API_EXPORT XmlDeserializer +{ + public: + XmlDeserializer(); + + QHash deserialize(QIODevice* input); + QHash deserialize(const QString& input); + + private: + QHash deserialize(QXmlStreamReader& reader); + void handleTokenType(QXmlStreamReader& reader, QXmlStreamReader::TokenType tokenType); + void handleStartElement(QXmlStreamReader& reader); + void handleText(QXmlStreamReader& reader); + void handleEndElement(QXmlStreamReader& reader); + + QHash output; + QHash* ctx; + QStack*> ctxStack; +}; + +#endif // XMLDESERIALIZER_H +*/ -- cgit v1.2.3