diff --git a/core/BackupFormatModel.cpp b/core/BackupFormatModel.cpp index c7d23e8..743cad7 100644 --- a/core/BackupFormatModel.cpp +++ b/core/BackupFormatModel.cpp @@ -36,28 +36,6 @@ BackupFormatModel::BackupFormatModel(QObject *parent) } -//QVariant BackupFormatModel::headerData(int section, Qt::Orientation orientation, int role) const -//{ -// QVariant result; - -// if (role == Qt::DisplayRole && orientation == Qt::Horizontal) { -// switch (section) { -// case Column::Short: -// result = tr("Short"); -// break; -// case Column::Long: -// result = tr("Long"); -// break; -// case Column::Description: -// result = tr("Description"); -// break; -// } -// } - -// return result; -//} - - int BackupFormatModel::rowCount(const QModelIndex &) const { int size = static_cast(g_BackupFormats.size()); diff --git a/core/BackupFormatModel.h b/core/BackupFormatModel.h index 8615b32..0bcab98 100644 --- a/core/BackupFormatModel.h +++ b/core/BackupFormatModel.h @@ -13,10 +13,6 @@ public: explicit BackupFormatModel(QObject *parent); - // Header: -// QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; - - // Basic functionality: int rowCount(const QModelIndex &parent = QModelIndex()) const override; int columnCount(const QModelIndex &parent = QModelIndex()) const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; diff --git a/core/ExplainTreeModelItem.cpp b/core/ExplainTreeModelItem.cpp index 115eacb..16c039d 100644 --- a/core/ExplainTreeModelItem.cpp +++ b/core/ExplainTreeModelItem.cpp @@ -113,23 +113,6 @@ int ExplainTreeModelItem::childCount() const return static_cast(m_childItems.size()); } -//int ExplainTreeModelItem::columnCount() const -//{ -// return 6; -//} - -//QVariant ExplainTreeModelItem::data(int column) const -//{ -// QVariant r; -// if (column == 0) { -// r = nodeType; -// } -// else if (column == 1) { - -// } -// return r; -//} - int ExplainTreeModelItem::row() const { int idx = 0; @@ -151,166 +134,6 @@ ExplainTreeModelItemPtr ExplainTreeModelItem::parent() return p; } -//void ExplainTreeModelItem::setNodeType(QString nt) -//{ -// m_nodeType = std::move(nt); -//} - -//const QString& ExplainTreeModelItem::nodeType() const -//{ -// return m_nodeType; -//} - -//void ExplainTreeModelItem::setParallelAware(bool aware) -//{ -// m_parallelAware = aware; -//} - -//bool ExplainTreeModelItem::getParallelAware() const -//{ -// return m_parallelAware; -//} - -//void ExplainTreeModelItem::setStrategy(QString strat) -//{ -// m_strategy = std::move(strat); -//} - -//const QString& ExplainTreeModelItem::strategy() const -//{ -// return m_strategy; -//} - -//void ExplainTreeModelItem::setJoinType(QString jointype) -//{ -// m_joinType = jointype; -//} - -//QString ExplainTreeModelItem::joinType() const -//{ -// return m_joinType; -//} - -//void ExplainTreeModelItem::setStartupCost(float cost) -//{ -// m_startupCost = cost; -//} - -//void ExplainTreeModelItem::setTotalCost(float cost) -//{ -// m_totalCost = cost; -//} - -//void ExplainTreeModelItem::setEstimatedRows(long long estimated) -//{ -// m_estimatedRows = estimated; -//} - -//long long ExplainTreeModelItem::estimatedRows() const -//{ -// return m_estimatedRows; -//} - -//void ExplainTreeModelItem::setPlanWidth(int width) -//{ -// m_planWidth = width; -//} - -//void ExplainTreeModelItem::setActualStartupTime(float timems) -//{ -// m_actualStartupTime = timems; -//} - -//void ExplainTreeModelItem::setActualTotalTime(float timems) -//{ -// m_actualTotalTime = timems; -//} - -//float ExplainTreeModelItem::actualTotalTime() const -//{ -// return m_actualTotalTime; -//} - -//void ExplainTreeModelItem::setActualRows(long long rowcount) -//{ -// m_actualRows = rowcount; -//} - -//long long ExplainTreeModelItem::actualRows() const -//{ -// return m_actualRows; -//} - -//void ExplainTreeModelItem::setActualLoops(int loopcount) -//{ -// m_actualLoops = loopcount; -//} - -//int ExplainTreeModelItem::actualLoops() const -//{ -// return m_actualLoops; -//} - -//void ExplainTreeModelItem::setRelationName(QString n) -//{ -// m_relationName = std::move(n); -//} - -//void ExplainTreeModelItem::setAlias(QString a) -//{ -// m_alias = std::move(a); -//} - -//void ExplainTreeModelItem::setScanDirection(QString dir) -//{ -// m_scanDirection = std::move(dir); -//} - -//void ExplainTreeModelItem::setIndexName(QString idxname) -//{ -// m_indexName = std::move(idxname); -//} - -//void ExplainTreeModelItem::setIndexCondition(QString idxcond) -//{ -// m_indexCondition = std::move(idxcond); -//} - -//void ExplainTreeModelItem::setIndexRecheck(QString idxrecheck) -//{ -// m_indexRecheck = std::move(idxrecheck); -//} - -//void ExplainTreeModelItem::setFilter(QString filter) -//{ -// m_filter = std::move(filter); -//} - -//void ExplainTreeModelItem::setHashCondition(QString condition) -//{ -// m_hashCondition = std::move(condition); -//} - -//void ExplainTreeModelItem::setSortKey(QString key) -//{ -// m_sortKey = std::move(key); -//} - -//void ExplainTreeModelItem::setSortMethod(QString method) -//{ -// m_sortMethod = std::move(method); -//} - -//void ExplainTreeModelItem::setSortSpaceUsed(int space) -//{ -// m_sortSpaceUsed = space; -//} - -//void ExplainTreeModelItem::setSortSpaceType(QString type) -//{ -// m_sortSpaceType = std::move(type); -//} - float ExplainTreeModelItem::exclusiveTime() const { float tt = inclusiveTime(); @@ -389,29 +212,3 @@ QString ExplainTreeModelItem::detailString() const return s.trimmed(); } - -//"Sort Key": ["pg_attribute.attname"], -//"Sort Method": "quicksort", -//"Sort Space Used": 1426, -//"Sort Space Type": "Memory", - - -//{ -// "Node Type": "Index Scan", -// "Parent Relationship": "Inner", -// "Scan Direction": "Forward", -// "Index Name": "pg_type_oid_index", -// "Relation Name": "pg_type", -// "Alias": "pg_type", -// "Startup Cost": 0.15, -// "Total Cost": 0.18, -// "Plan Rows": 1, -// "Plan Width": 758, -// "Actual Startup Time": 0.003, -// "Actual Total Time": 0.004, -// "Actual Rows": 1, -// "Actual Loops": 100, -// "Index Cond": "(oid = pg_attribute.atttypid)", -// "Rows Removed by Index Recheck": 0 -// "Filter": "actief" -//} diff --git a/core/ExplainTreeModelItem.h b/core/ExplainTreeModelItem.h index f78bb73..a3c1be7 100644 --- a/core/ExplainTreeModelItem.h +++ b/core/ExplainTreeModelItem.h @@ -60,54 +60,17 @@ public: ExplainTreeModelItemPtr child(int row); int childCount() const; -// int columnCount() const; -// QVariant data(int column) const; int row() const; void setParent(const ItemPtr &parent); ItemPtr parent(); -// void setNodeType(QString nt); -// const QString& nodeType() const; -// void setParallelAware(bool aware); -// bool getParallelAware() const; -// void setStrategy(QString strat); -// const QString& strategy() const; -// void setJoinType(QString jointype); -// QString joinType() const; -// void setStartupCost(float cost); -// void setTotalCost(float cost); -// void setEstimatedRows(long long estimated); -// long long estimatedRows() const; -// void setPlanWidth(int width); -// void setActualStartupTime(float timems); -// void setActualTotalTime(float timems); -// float actualTotalTime() const; -// void setActualRows(long long rowcount); -// long long actualRows() const; -// void setActualLoops(int loopcount); -// int actualLoops() const; - -// void setRelationName(QString n); -// void setAlias(QString a); -// void setScanDirection(QString dir); -// void setIndexName(QString idxname); -// void setIndexCondition(QString idxcond); -// void setIndexRecheck(QString idxrecheck); -// void setFilter(QString filter); -// void setHashCondition(QString condition); -// void setSortKey(QString key); -// void setSortMethod(QString method); -// void setSortSpaceUsed(int space); -// void setSortSpaceType(QString type); - /** ActualTotalTime minus the actual total time of it's children */ float exclusiveTime() const; float inclusiveTime() const; float estimateError() const; QString detailString() const; -//private: std::vector m_childItems; std::weak_ptr m_parentItem; @@ -143,9 +106,6 @@ public: TempBlocks tempBlocks; IoTimes ioTimes; -// "Triggers": [ -// ], - }; class ExplainRoot { diff --git a/core/PasswordManager.cpp b/core/PasswordManager.cpp index 5f67395..44b0c5f 100644 --- a/core/PasswordManager.cpp +++ b/core/PasswordManager.cpp @@ -198,14 +198,11 @@ void PasswordManager::initializeNewPskStore(QSqlDatabase &db) " salt TEXT \n" ");"); if (!create_tbl.exec()) { -// auto sql_error = create_tbl.lastError(); -// throw std::runtime_error("create table failed"); auto err = create_tbl.lastError(); throw SqlException(err); } } -// db->create_table( QSqlQuery create_tbl(db); create_tbl.prepare( "CREATE TABLE IF NOT EXISTS " + m_secretHashTableName + "( \n" diff --git a/core/PasswordManager.h b/core/PasswordManager.h index f5c7d34..895cdc4 100644 --- a/core/PasswordManager.h +++ b/core/PasswordManager.h @@ -56,7 +56,7 @@ public: std::string encrypt(const std::string &id, const std::string &passwd); std::string decrypt(const std::string &id, const std::string_view &encpwd); -// void remove(const std::string &id); + private: QString m_passwordTableName = "psk_passwd"; QString m_secretAlgoTableName = "psk_masterkey_algo"; diff --git a/core/QueuedBackgroundTask.cpp b/core/QueuedBackgroundTask.cpp deleted file mode 100644 index 57306a0..0000000 --- a/core/QueuedBackgroundTask.cpp +++ /dev/null @@ -1,64 +0,0 @@ -#include "QueuedBackgroundTask.h" -#include "ScopeGuard.h" - -//void QueuedBackgroundTask::requestPause() -//{} - -QueuedBackgroundTask::QueuedBackgroundTask(CompletionFunction on_completion) - : m_completionFunction(std::move(on_completion)) -{ - setAutoDelete(false); -} - -QueuedBackgroundTask::~QueuedBackgroundTask() -{ - cancel(); - wait(); -} - -void QueuedBackgroundTask::cancel() -{ - QMutexLocker lock(&stateMutex); - if (!m_finished) - m_canceled = true; -} - -void QueuedBackgroundTask::wait() -{ - QMutexLocker lock(&stateMutex); - if (!m_finished) - finished.wait(&stateMutex); -} - -bool QueuedBackgroundTask::hasException() const -{ - return doRunException != nullptr; -} - -void QueuedBackgroundTask::rethrow() -{ - std::rethrow_exception(doRunException); -} - -void QueuedBackgroundTask::run() -{ - SCOPE_EXIT { - m_finished = true; - QMutexLocker lock(&stateMutex); - finished.notify_all(); - }; - QMutexLocker lock(&stateMutex); - m_started = true; - if (!m_canceled) { - lock.unlock(); - try { - doRun(); - } - catch (...) { - doRunException = std::current_exception(); - } - - if (!m_canceled && m_completionFunction) - m_completionFunction(this); - } -} diff --git a/core/QueuedBackgroundTask.h b/core/QueuedBackgroundTask.h deleted file mode 100644 index 49fa2d5..0000000 --- a/core/QueuedBackgroundTask.h +++ /dev/null @@ -1,81 +0,0 @@ -#pragma once - -#include -#include -//#include -#include -#include - -/** Base class for an object that can be queued for execution in the background. - * - * It is meaned for long running processes the end user might want to abort, - * pause and check progress on. - */ -class QueuedBackgroundTask: public QRunnable { -public: - using CompletionFunction = std::function; - - explicit QueuedBackgroundTask(CompletionFunction on_completion); - virtual ~QueuedBackgroundTask(); - - void cancel(); - void wait(); - bool hasException() const; - void rethrow(); - -protected: - - bool m_canceled = false; - bool m_started = false; - bool m_finished = false; - std::exception_ptr doRunException = nullptr; - CompletionFunction m_completionFunction = nullptr; - - QMutex stateMutex; - QWaitCondition finished; - - virtual void run() override; - - virtual void doRun() = 0; - -// /** Task should exit it's run method but remember it's state, it might be resumed later. -// */ -// void requestPause(); - -// /** Request to stop running and forget progress -// */ -// void requestAbort(); - -// QString getProgressInfo(); -}; - -//class BackgroundTaskInfo { -//public: -//}; - -///** Manages objects of type QueuedBackgroundTask -// * -// * The basic operation of this queue is hand everything directly of to the default -// * threadpool and that will decide when to run each task. But extra functions are -// * provided to control tasks to allow the program to have a UI for controlling the tasks -// */ -//class BackgroundTaskQueue { - -//public: - -// /** Returns a list of tasks in the queue and their progress. -// * -// * When building a UI to show realtime activity then make sure to first register the update events -// * then get the snapshot. After that you can use the events to update the contents of the UI. -// */ -// QVector getTaskInfoSnapshort(); - -// void pauseTask( ); - -// /** Resume a paused task -// */ -// void resumeTask( ); - -// void abortTask( ); - -//}; diff --git a/core/SqlAstExpression.cpp b/core/SqlAstExpression.cpp deleted file mode 100644 index 93bbc88..0000000 --- a/core/SqlAstExpression.cpp +++ /dev/null @@ -1,13 +0,0 @@ -#include "SqlAstExpression.h" - -using namespace SqlAst; - - -std::shared_ptr parseExpression(SqlParser &parser) -{ - // get token, what is it? - // number - // symbol - // left parenthesis - return nullptr; -} diff --git a/core/SqlAstExpression.h b/core/SqlAstExpression.h deleted file mode 100644 index 6990fd5..0000000 --- a/core/SqlAstExpression.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef SQLASTEXPRESSION_H -#define SQLASTEXPRESSION_H - -#include "SqlAstNode.h" - -class SqlParser; - -namespace SqlAst { - -/// Base class for parts of expressions like calculations, comparisons, function calls etc... -class Expression: public Node { - -}; - -std::shared_ptr parseExpression(SqlParser &parser); - -} - -#endif // SQLASTEXPRESSION_H diff --git a/core/SqlAstNode.cpp b/core/SqlAstNode.cpp deleted file mode 100644 index a6a1c5d..0000000 --- a/core/SqlAstNode.cpp +++ /dev/null @@ -1,5 +0,0 @@ -#include "SqlAstNode.h" - -using namespace SqlAst; - -Node::Node() = default; diff --git a/core/SqlAstNode.h b/core/SqlAstNode.h deleted file mode 100644 index 3c40f41..0000000 --- a/core/SqlAstNode.h +++ /dev/null @@ -1,58 +0,0 @@ -#ifndef SQLASTNODE_H -#define SQLASTNODE_H - -#include -#include - -namespace SqlAst { - -class Node { -public: - Node(); - //virtual Node* Clone() const = 0; -}; - -class DDLNode: public Node { - -}; - -class CreateTable: public Node { - -}; - - -// Is there a benefit for having a common base for crud operations??? -class CrudNode: public Node { - -}; - - -class Insert: public CrudNode { - -}; - -/** Class for representing an identifier. - * - * This can still be multiple things like: - * - name of alias, schema, table and or column - * - name of function - * - predefined symbol like LOCAL_TIME - * - * During parsing this cannot always be determined as an alias might be involved that hasn't been parsed yet - * so we put a Identifier in the AST a follow up pass could determine what it actually as and act appropriatly - * - * An identifier can consist of following fields - * - [[schema.]table.]column - * - [alias.]column - * - [schema.]table.function (for function taking a row of type table) - * - alias.function (for function taking a row of type table) - * - schema.function - * - sql symbol like CURRENT_DATE - */ -class Identifier: public Node { - -}; - -} - -#endif // SQLASTNODE_H diff --git a/core/SqlAstSelect.cpp b/core/SqlAstSelect.cpp deleted file mode 100644 index 001bedd..0000000 --- a/core/SqlAstSelect.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "SqlAstSelect.h" -#include "SqlAstSelectList.h" -#include "SqlParser.h" - -namespace SqlAst { - - -std::shared_ptr parseSelect(SqlParser &parser) -{ - auto ast_select = std::make_shared(); - // parse select list of expression + aliasses, required -// auto select_list = parseSelectList(parser); -// ast_select->setSelectList(select_list); - - // parse optional from list - - return ast_select; -} - -} diff --git a/core/SqlAstSelect.h b/core/SqlAstSelect.h deleted file mode 100644 index d2b7232..0000000 --- a/core/SqlAstSelect.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef SQLASTSELECT_H -#define SQLASTSELECT_H - -#include "SqlAstNode.h" -//#include "SqlAstSelectList.h" -#include - -class SqlParser; - -namespace SqlAst { - -class SelectList; -class From; -class Where; -class GroupBy; -class Having; -class OrderBy; - -class Select: public CrudNode { -public: - - void setSelectList(std::shared_ptr list) { select = list; } - auto getSelectList() const { return select; } - void setFrom(std::shared_ptr f) { from = f; } - -private: - std::shared_ptr select; - std::shared_ptr from; - std::shared_ptr where; - std::shared_ptr groupBy; - std::shared_ptr having; - std::shared_ptr orderBy; -}; - -std::shared_ptr parseSelect(SqlParser &parser); - -} - -#endif // SQLASTSELECT_H diff --git a/core/SqlAstSelectList.cpp b/core/SqlAstSelectList.cpp deleted file mode 100644 index 65fec73..0000000 --- a/core/SqlAstSelectList.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#include "SqlAstSelectList.h" -#include "SqlAstSelectListEntry.h" -#include "SqlParser.h" - -using namespace SqlAst; - -std::shared_ptr parseSelectList(SqlParser &parser) -{ - // parse select element - // whats next? - // comma -> parse an element - // something else return and let caller figure it out - auto ast_select_list = std::make_shared(); - while (1) { - auto ast_select_elem = parseSelectListEntry(parser); - if (ast_select_elem) { - ast_select_list->add(ast_select_elem); - } - else { - // todo error - } - if (!parser.expectToken(BasicTokenType::Comma)) { - break; - } - } - return ast_select_list; -} diff --git a/core/SqlAstSelectList.h b/core/SqlAstSelectList.h deleted file mode 100644 index 4f092e0..0000000 --- a/core/SqlAstSelectList.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef SQLASTSELECTLIST_H -#define SQLASTSELECTLIST_H - -#include "SqlAstNode.h" -#include -#include - -class SqlParser; - -namespace SqlAst { - -class SelectListEntry; - -class SelectList: public Node { -public: - using EntrySPtr = std::shared_ptr; - - void add(EntrySPtr entry) - { - entryList.push_back(entry); - } - -private: - using EntryList = std::vector; - - EntryList entryList; -}; - -std::shared_ptr parseSelectList(SqlParser &parser); - -} - -#endif // SQLASTSELECTLIST_H diff --git a/core/SqlAstSelectListEntry.cpp b/core/SqlAstSelectListEntry.cpp deleted file mode 100644 index dcf74a9..0000000 --- a/core/SqlAstSelectListEntry.cpp +++ /dev/null @@ -1,34 +0,0 @@ -#include "SqlAstSelectListEntry.h" -#include "SqlAstExpression.h" -#include "SqlParser.h" - -using namespace SqlAst; - -std::shared_ptr parseSelectListEntry(SqlParser &parser) -{ - - // parse expression - auto ast_expr = parseExpression(parser); - - if (parser.consumeOptionalKeyword(Keyword::As)) { - // alias required! - auto token = parser.expectSymbol(); - - - } - else { - - // optional alias - - } - // can come three groups of things: - // - AS keyword, alias should follow, followed by comma - // - a symbol ie an alias followed by comma - // - something else ie comma, FROM or INTO or... is something one of the callers should figure out as long as we have valid - // selectElem we are happy - - - auto ast = std::make_shared(); - - return ast; -} diff --git a/core/SqlAstSelectListEntry.h b/core/SqlAstSelectListEntry.h deleted file mode 100644 index 9ad7476..0000000 --- a/core/SqlAstSelectListEntry.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef SQLASTSELECTLISTENTRY_H -#define SQLASTSELECTLISTENTRY_H - -#include "SqlAstNode.h" -#include -#include -#include - -class SqlParser; - -namespace SqlAst { - -class Expression; - -class SelectListEntry: public Node { -public: - void setExpression(std::shared_ptr expr) { this->expression = expr; } - void setAlias(QString a) { this->alias = alias; } -private: - std::shared_ptr expression; - QString alias; -}; - -std::shared_ptr parseSelectListEntry(SqlParser &parser); - -} - - -#endif // SQLASTSELECTLISTENTRY_H diff --git a/core/SqlLexer.cpp b/core/SqlLexer.cpp index 8ad4e49..fb40150 100644 --- a/core/SqlLexer.cpp +++ b/core/SqlLexer.cpp @@ -79,147 +79,119 @@ bool SqlLexer::nextBasicToken(int &startpos, int &length, BasicTokenType &tokent while (true) { startpos = m_pos; QChar c = nextChar(); -// if (LexerState::Null == m_state) { - if (c == '\n') { - if (m_returnWhitespace) { - length = m_pos - startpos; - tokentype = BasicTokenType::NewLine; - out = "\n"; - return true; - } - } - else if (c.isSpace()) { - // Just skip whitespace - if (m_returnWhitespace) { - for (;;) { - c = peekChar(); - if (c != QChar::Null && c.isSpace() && c != '\n') - nextChar(); - else - break; - } - length = m_pos - startpos; - tokentype = BasicTokenType::WhiteSpace; - out = m_block.mid(startpos, length); - return true; - } - } - else if (c == '-' && peekChar() == '-') { // two dashes, start of comment - // Loop till end of line or end of block - c = nextChar(); - for (;;) { - c = peekChar(); - if (c != QChar::Null && c != '\n') - nextChar(); - else - break; - } - length = m_pos - startpos; - tokentype = BasicTokenType::Comment; - out = m_block.mid(startpos, length); - return true; - } - else if (c == ':') { - c = peekChar(); - if (c == ':') { - nextChar(); - length = m_pos - startpos; - tokentype = BasicTokenType::Cast; - out = m_block.mid(startpos, length); - return true; - } - } - else if (isSelf(c)) { - length = m_pos - startpos; - if (c == ',') - tokentype = BasicTokenType::Comma; - else - tokentype = BasicTokenType::Self; - out = m_block.mid(startpos, length); + if (c == '\n') { + if (m_returnWhitespace) { + length = m_pos - startpos; + tokentype = BasicTokenType::NewLine; + out = "\n"; return true; - } - else if (isOperatorChar(c)) { - while (true) { - QChar c = peekChar(); - if (isOperatorChar(c)) { - nextChar(); - } - else { - // unexpected end, pretend nothings wrong - length = m_pos - startpos; - tokentype = BasicTokenType::Operator; - out = m_block.mid(startpos, length); - return true; - } - } - } - else if (c == '\'') { - // Single quoted string so it's an SQL text literal - if (parseSingleQuotedString(startpos, length, tokentype)) { - out = m_block.mid(startpos, length); - return true; - } - return false; - } - else if (c == '"') { - // Double quoted identifier - if (parseDoubleQuotedIdentifier(startpos, length, tokentype)) { - out = m_block.mid(startpos, length); - return true; - } - return false; - } -// else if (c == '/' && peekChar() == '*') { -// nextChar(); -// m_state = LexerState::InBlockComment; -// } - else if (c == QChar::Null) { - length = 0; - tokentype = BasicTokenType::End; - return true; - } - else if (c == '$') { - return parseDollarQuote(startpos, length, tokentype, out); } - else { - // Undetermined symbol - for (;;) { - c = peekChar(); - if (c.isLetterOrNumber() || c == '_') - nextChar(); - else - break; - } - length = m_pos - startpos; - tokentype = BasicTokenType::Symbol; + } + else if (c.isSpace()) { + // Just skip whitespace + if (m_returnWhitespace) { + for (;;) { + c = peekChar(); + if (c != QChar::Null && c.isSpace() && c != '\n') + nextChar(); + else + break; + } + length = m_pos - startpos; + tokentype = BasicTokenType::WhiteSpace; out = m_block.mid(startpos, length); return true; - } -// } -// else if (LexerState::InBlockComment == m_state) { -// if (c == QChar::Null) { -// // eof current buffer, we need to return state so -// if (m_pos == startpos) { -// break; -// } -// else { -// length = m_pos - startpos; -// tokentype = BasicTokenType::OpenBlockComment; -// return true; -// } -// } -// else if (c == '*') { -// nextChar(); -// if (peekChar() == '/') { -// nextChar(); -// length = m_pos - startpos; -// tokentype = BasicTokenType::BlockComment; -// m_state = LexerState::Null; -// return true; -// } -// } -// } + } + } + else if (c == '-' && peekChar() == '-') { // two dashes, start of comment + // Loop till end of line or end of block + c = nextChar(); + for (;;) { + c = peekChar(); + if (c != QChar::Null && c != '\n') + nextChar(); + else + break; + } + length = m_pos - startpos; + tokentype = BasicTokenType::Comment; + out = m_block.mid(startpos, length); + return true; + } + else if (c == ':') { + c = peekChar(); + if (c == ':') { + nextChar(); + length = m_pos - startpos; + tokentype = BasicTokenType::Cast; + out = m_block.mid(startpos, length); + return true; + } + } + else if (isSelf(c)) { + length = m_pos - startpos; + if (c == ',') + tokentype = BasicTokenType::Comma; + else + tokentype = BasicTokenType::Self; + + out = m_block.mid(startpos, length); + return true; + } + else if (isOperatorChar(c)) { + while (true) { + QChar c = peekChar(); + if (isOperatorChar(c)) { + nextChar(); + } + else { + // unexpected end, pretend nothings wrong + length = m_pos - startpos; + tokentype = BasicTokenType::Operator; + out = m_block.mid(startpos, length); + return true; + } + } + } + else if (c == '\'') { + // Single quoted string so it's an SQL text literal + if (parseSingleQuotedString(startpos, length, tokentype)) { + out = m_block.mid(startpos, length); + return true; + } + return false; + } + else if (c == '"') { + // Double quoted identifier + if (parseDoubleQuotedIdentifier(startpos, length, tokentype)) { + out = m_block.mid(startpos, length); + return true; + } + return false; + } + else if (c == QChar::Null) { + length = 0; + tokentype = BasicTokenType::End; + return true; + } + else if (c == '$') { + return parseDollarQuote(startpos, length, tokentype, out); + } + else { + // Undetermined symbol + for (;;) { + c = peekChar(); + if (c.isLetterOrNumber() || c == '_') + nextChar(); + else + break; + } + length = m_pos - startpos; + tokentype = BasicTokenType::Symbol; + out = m_block.mid(startpos, length); + return true; + } } return false; } @@ -298,11 +270,9 @@ bool SqlLexer::parseDollarQuote(int startpos, int &length, BasicTokenType &token } if (c.isLetter()) { - // is this a dollar quote? while (true) { c = nextChar(); if (c == '$') { - // Found valid dollar quote tokentype = BasicTokenType::DollarQuote; length = m_pos - startpos; out = m_block.mid(startpos, length); @@ -310,7 +280,6 @@ bool SqlLexer::parseDollarQuote(int startpos, int &length, BasicTokenType &token } if (!c.isLetter()) { - // ERROR, unallowed character tokentype = BasicTokenType::None; length = m_pos - startpos; out = m_block.mid(startpos, length); diff --git a/core/SqlParser.cpp b/core/SqlParser.cpp deleted file mode 100644 index 5b63c68..0000000 --- a/core/SqlParser.cpp +++ /dev/null @@ -1,81 +0,0 @@ -#include "SqlParser.h" -#include "SqlAstSelect.h" -#include -#include - -using namespace SqlAst; - -Keyword isKeyword(const QString &symbol) -{ - static std::unordered_map lookup_map = { - { "as", Keyword::As }, - { "by", Keyword::By }, - { "delete", Keyword::Delete }, - { "from", Keyword::From }, - { "group", Keyword::Group }, - { "insert", Keyword::Insert }, - { "order", Keyword::Order }, - { "select", Keyword::Select }, - { "update", Keyword::Update }, - { "where", Keyword::Where } - }; - - auto res = lookup_map.find(symbol.toLower().toUtf8().data()); - if (res != lookup_map.end()) - return res->second; - - return Keyword::NotAKeyword; -} - - -SqlParser::SqlParser(SqlLexer &lexer) - : lexer(lexer) -{ - -} - -std::shared_ptr SqlParser::parse() -{ - // Basic algo: - // LOOP - // GET token - // IF NOT try_reduce(token) - // THEN SHIFT - // END LOOP - std::shared_ptr result; - while (true) { - SqlToken token = lexer.nextBasicToken(); - if (token.ok) { - if (token.tokenType == BasicTokenType::Symbol) { - Keyword kw = isKeyword(token.out); - switch (kw) { - case Keyword::Select: - parseSelect(*this); - break; - - case Keyword::NotAKeyword: - default: - // unexpected - break; - } - } - else if (token.tokenType == BasicTokenType::End) { - // Are we at the top level? - return result; - } - } - else { - // error during lexical analysis, need to recover - throw std::runtime_error("Unrecognized input"); - } - } -} - - - - -//bool try_reduce(SqkToken token) -//{ -// // what state are we in? what are we expecting - -//} diff --git a/core/SqlParser.h b/core/SqlParser.h deleted file mode 100644 index b5e9dad..0000000 --- a/core/SqlParser.h +++ /dev/null @@ -1,74 +0,0 @@ -#ifndef SQLPARSER_H -#define SQLPARSER_H - -#include "SqlLexer.h" -#include "SqlAstNode.h" -#include -#include - -enum class Keyword { - NotAKeyword, - As, - By, - Delete, - From, - Group, - Insert, - Order, - Select, - Update, - Where, - -}; - -namespace SqlAst { - - class Node; - class Select; - class SelectList; - -} -// The parsing works by calling functions that know either a global part -// or a smaller specific part and is thus recursive. At certain points a function parsing something specific -// will reach a point where it is in a valid terminal state and it encounters something that cannot be a continuation -// of what it is parsing and thus returns succesfully or it is in a non terminal state and encounters something unexpected -// In both cases it will return hoping that one of the functions above can continue (and recover from the error if needed) - -class SqlParser -{ -public: - explicit SqlParser(SqlLexer &lexer); - - std::shared_ptr parse(); - - /** Checks to see if the next token is the expected keyword. - * - * If it is the token is consumed and the function returns true. - * Otherwise false is returned - */ - std::optional expectKeyword(Keyword kw); - std::optional expectSymbol(); - std::optional expectToken(BasicTokenType tt); - - /** If the next token is Keyword kw consume it otherwise do nothing. - * In some cases the return value is unimportant as the keyword is completely optional - * in other cases the optional keywords presence might force the next token to be something specific - * - * \return true if the token was found - */ - bool consumeOptionalKeyword(Keyword kw); -private: - - //using TokenStack = std::stack; - - //TokenStack tokenStack; - - SqlLexer &lexer; - - //bool try_reduce(SqkToken token); - - -}; - - -#endif // SQLPARSER_H diff --git a/core/core.pro b/core/core.pro index 139f81f..5ccb2af 100644 --- a/core/core.pro +++ b/core/core.pro @@ -26,15 +26,8 @@ SOURCES += my_boost_assert_handler.cpp \ PasswordManager.cpp \ CsvWriter.cpp \ BackupFormatModel.cpp \ - QueuedBackgroundTask.cpp \ ExplainTreeModelItem.cpp \ - jsoncpp.cpp \ - SqlParser.cpp \ - SqlAstNode.cpp \ - SqlAstSelectList.cpp \ - SqlAstSelectListEntry.cpp \ - SqlAstSelect.cpp \ - SqlAstExpression.cpp + jsoncpp.cpp HEADERS += PasswordManager.h \ KeyStrengthener.h \ @@ -42,16 +35,9 @@ HEADERS += PasswordManager.h \ ScopeGuard.h \ CsvWriter.h \ BackupFormatModel.h \ - QueuedBackgroundTask.h \ Expected.h \ ExplainTreeModelItem.h \ json/json.h \ - SqlParser.h \ - SqlAstNode.h \ - SqlAstSelectList.h \ - SqlAstSelectListEntry.h \ - SqlAstSelect.h \ - SqlAstExpression.h \ std_utils.h \ IntegerRange.h diff --git a/ctk/ctk.pro b/ctk/ctk.pro deleted file mode 100644 index 5e69716..0000000 --- a/ctk/ctk.pro +++ /dev/null @@ -1,40 +0,0 @@ -#------------------------------------------------- -# -# Project created by QtCreator 2017-02-26T10:51:14 -# -#------------------------------------------------- - -QT += widgets - -TARGET = ctk -TEMPLATE = lib -CONFIG += staticlib - - -# The following define makes your compiler emit warnings if you use -# any feature of Qt which as been marked as deprecated (the exact warnings -# depend on your compiler). Please consult the documentation of the -# deprecated API in order to know how to port your code away from it. -DEFINES += QT_DEPRECATED_WARNINGS - -# You can also make your code fail to compile if you use deprecated APIs. -# In order to do so, uncomment the following line. -# You can also select to disable deprecated APIs only up to a certain version of Qt. -#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 - -SOURCES += ctkBasePopupWidget.cpp \ - ctkPopupWidget.cpp \ - ctkWidgetsUtils.cpp - - -HEADERS += ctkBasePopupWidget.h \ - ctkBasePopupWidget_p.h \ - ctkPopupWidget.h \ - ctkPopupWidget_p.h \ - ctkWidgetsUtils.h \ - ctkWidgetsExport.h - -unix { - target.path = /usr/lib - INSTALLS += target -} diff --git a/ctk/ctkBasePopupWidget.cpp b/ctk/ctkBasePopupWidget.cpp deleted file mode 100644 index 7c11e30..0000000 --- a/ctk/ctkBasePopupWidget.cpp +++ /dev/null @@ -1,842 +0,0 @@ -/*========================================================================= - - Library: CTK - - Copyright (c) Kitware Inc. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.commontk.org/LICENSE - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -=========================================================================*/ - -// Qt includes -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// CTK includes -#include "ctkBasePopupWidget_p.h" -#include "ctkWidgetsUtils.h" - -// ------------------------------------------------------------------------- -QGradient* duplicateGradient(const QGradient* gradient) -{ - QGradient* newGradient = 0; - switch (gradient->type()) - { - case QGradient::LinearGradient: - { - const QLinearGradient* linearGradient = static_cast(gradient); - newGradient = new QLinearGradient(linearGradient->start(), linearGradient->finalStop()); - break; - } - case QGradient::RadialGradient: - { - const QRadialGradient* radialGradient = static_cast(gradient); - newGradient = new QRadialGradient(radialGradient->center(), radialGradient->radius()); - break; - } - case QGradient::ConicalGradient: - { - const QConicalGradient* conicalGradient = static_cast(gradient); - newGradient = new QConicalGradient(conicalGradient->center(), conicalGradient->angle()); - break; - } - default: - break; - } - if (!newGradient) - { - Q_ASSERT(gradient->type() != QGradient::NoGradient); - return newGradient; - } - newGradient->setCoordinateMode(gradient->coordinateMode()); - newGradient->setSpread(gradient->spread()); - newGradient->setStops(gradient->stops()); - return newGradient; -} - -// ------------------------------------------------------------------------- -ctkBasePopupWidgetPrivate::ctkBasePopupWidgetPrivate(ctkBasePopupWidget& object) - :q_ptr(&object) -{ - this->Effect = ctkBasePopupWidget::ScrollEffect; - this->EffectDuration = 333; // in ms - this->EffectAlpha = 1.; - this->AlphaAnimation = 0; - this->ForcedTranslucent = false; - this->ScrollAnimation = 0; - this->PopupPixmapWidget = 0; - // Geometry attributes - this->Alignment = Qt::AlignJustify | Qt::AlignBottom; - this->Orientations = Qt::Vertical; - this->VerticalDirection = ctkBasePopupWidget::TopToBottom; - this->HorizontalDirection = Qt::LeftToRight; -} - -// ------------------------------------------------------------------------- -ctkBasePopupWidgetPrivate::~ctkBasePopupWidgetPrivate() -{ -} - -// ------------------------------------------------------------------------- -void ctkBasePopupWidgetPrivate::init() -{ - Q_Q(ctkBasePopupWidget); - // By default, Tooltips are shown only on active windows. In a popup widget - // case, we sometimes aren't the active window but we still would like to - // show the children tooltips. - q->setAttribute(Qt::WA_AlwaysShowToolTips, true); - //q->setAttribute(Qt::WA_MacAlwaysShowToolWindow, true); - - this->AlphaAnimation = new QPropertyAnimation(q, "effectAlpha", q); - this->AlphaAnimation->setDuration(this->EffectDuration); - this->AlphaAnimation->setStartValue(0.); - this->AlphaAnimation->setEndValue(1.); - QObject::connect(this->AlphaAnimation, SIGNAL(finished()), - q, SLOT(onEffectFinished())); - - this->PopupPixmapWidget = new QLabel(q, Qt::ToolTip | Qt::FramelessWindowHint); - - this->ScrollAnimation = new QPropertyAnimation(q, "effectGeometry", q); - this->ScrollAnimation->setDuration(this->EffectDuration); - QObject::connect(this->ScrollAnimation, SIGNAL(finished()), - q, SLOT(onEffectFinished())); - QObject::connect(this->ScrollAnimation, SIGNAL(finished()), - this->PopupPixmapWidget, SLOT(hide())); - - q->setAnimationEffect(this->Effect); - q->setEasingCurve(QEasingCurve::OutCubic); - q->setBaseWidget(q->parentWidget()); -} - -// ------------------------------------------------------------------------- -QPropertyAnimation* ctkBasePopupWidgetPrivate::currentAnimation()const -{ - return this->Effect == ctkBasePopupWidget::ScrollEffect ? - this->ScrollAnimation : this->AlphaAnimation; -} - -// ------------------------------------------------------------------------- -bool ctkBasePopupWidgetPrivate::isOpening()const -{ - return this->currentAnimation()->state() == QAbstractAnimation::Running && - this->currentAnimation()->direction() == QAbstractAnimation::Forward; -} - -// ------------------------------------------------------------------------- -bool ctkBasePopupWidgetPrivate::isClosing()const -{ - return this->currentAnimation()->state() == QAbstractAnimation::Running && - this->currentAnimation()->direction() == QAbstractAnimation::Backward; -} - -// ------------------------------------------------------------------------- -bool ctkBasePopupWidgetPrivate::wasClosing()const -{ - Q_Q(const ctkBasePopupWidget); - return qobject_cast(q->sender())->direction() - == QAbstractAnimation::Backward; -} - -// ------------------------------------------------------------------------- -QWidgetList ctkBasePopupWidgetPrivate::focusWidgets(bool onlyVisible)const -{ - Q_Q(const ctkBasePopupWidget); - QWidgetList res; - if (!onlyVisible || q->isVisible()) - { - res << const_cast(q); - } - if (!this->BaseWidget.isNull() && (!onlyVisible || this->BaseWidget->isVisible())) - { - res << this->BaseWidget; - } - if (this->PopupPixmapWidget && (!onlyVisible || this->PopupPixmapWidget->isVisible())) - { - res << this->PopupPixmapWidget; - } - return res; -} - -// ------------------------------------------------------------------------- -QWidget* ctkBasePopupWidgetPrivate::mouseOver() -{ - QList widgets = this->focusWidgets(true); - foreach(QWidget* widget, widgets) - { - if (widget->underMouse()) - { - return widget; - } - } - // Warning QApplication::widgetAt(QCursor::pos()) can be a bit slow... - const QPoint pos = QCursor::pos(); - QWidget* widgetUnderCursor = qApp->widgetAt(pos); - foreach(const QWidget* focusWidget, widgets) - { - if (this->isAncestorOf(focusWidget, widgetUnderCursor) && - // Ignore when cursor is above a title bar of a focusWidget, underMouse - // wouldn't have return false, but QApplication::widgetAt would return - // the widget - (focusWidget != widgetUnderCursor || - QRect(QPoint(0,0), focusWidget->size()).contains( - focusWidget->mapFromGlobal(pos)))) - { - return widgetUnderCursor; - } - } - return 0; -} - -// ------------------------------------------------------------------------- -bool ctkBasePopupWidgetPrivate::isAncestorOf(const QWidget* ancestor, const QWidget* child)const -{ - while (child) - { - if (child == ancestor) - { - return true; - } - child = child->parentWidget(); - } - return false; -} - -// ------------------------------------------------------------------------- -void ctkBasePopupWidgetPrivate::setupPopupPixmapWidget() -{ - Q_Q(ctkBasePopupWidget); - this->PopupPixmapWidget->setAlignment(this->pixmapAlignment()); - QPixmap pixmap; - if (q->testAttribute(Qt::WA_TranslucentBackground)) - { - // only QImage handle transparency correctly - QImage image(q->geometry().size(), QImage::Format_ARGB32); - image.fill(0); - q->render(&image); - pixmap = QPixmap::fromImage(image); - } - else - { - pixmap = QPixmap::fromImage( - ctk::grabWidget(q, QRect(QPoint(0,0), q->geometry().size()))); - } - this->PopupPixmapWidget->setPixmap(pixmap); - this->PopupPixmapWidget->setAttribute( - Qt::WA_TranslucentBackground, q->testAttribute(Qt::WA_TranslucentBackground)); - this->PopupPixmapWidget->setWindowOpacity(q->windowOpacity()); -} - -// ------------------------------------------------------------------------- -Qt::Alignment ctkBasePopupWidgetPrivate::pixmapAlignment()const -{ - Qt::Alignment alignment; - if (this->VerticalDirection == ctkBasePopupWidget::TopToBottom) - { - alignment |= Qt::AlignBottom; - } - else// if (this->VerticalDirection == ctkBasePopupWidget::BottomToTop) - { - alignment |= Qt::AlignTop; - } - - if (this->HorizontalDirection == Qt::LeftToRight) - { - alignment |= Qt::AlignRight; - } - else// if (this->VerticalDirection == ctkBasePopupWidget::BottomToTop) - { - alignment |= Qt::AlignLeft; - } - return alignment; -} - -// ------------------------------------------------------------------------- -QRect ctkBasePopupWidgetPrivate::closedGeometry()const -{ - Q_Q(const ctkBasePopupWidget); - return this->closedGeometry(q->geometry()); -} - -// ------------------------------------------------------------------------- -QRect ctkBasePopupWidgetPrivate::closedGeometry(QRect openGeom)const -{ - if (this->Orientations & Qt::Vertical) - { - if (this->VerticalDirection == ctkBasePopupWidget::BottomToTop) - { - openGeom.moveTop(openGeom.bottom()); - } - openGeom.setHeight(0); - } - if (this->Orientations & Qt::Horizontal) - { - if (this->HorizontalDirection == Qt::RightToLeft) - { - openGeom.moveLeft(openGeom.right()); - } - openGeom.setWidth(0); - } - return openGeom; -} - -// ------------------------------------------------------------------------- -QRect ctkBasePopupWidgetPrivate::baseGeometry()const -{ - if (this->BaseWidget.isNull()) - { - return QRect(); - } - return QRect(this->mapToGlobal(this->BaseWidget->geometry().topLeft()), - this->BaseWidget->size()); -} - -// ------------------------------------------------------------------------- -QPoint ctkBasePopupWidgetPrivate::mapToGlobal(const QPoint& baseWidgetPoint)const -{ - QPoint mappedPoint = baseWidgetPoint; - if (!this->BaseWidget.isNull() && this->BaseWidget->parentWidget()) - { - mappedPoint = this->BaseWidget->parentWidget()->mapToGlobal(mappedPoint); - } - return mappedPoint; -} - -// ------------------------------------------------------------------------- -QRect ctkBasePopupWidgetPrivate::desiredOpenGeometry()const -{ - return this->desiredOpenGeometry(this->baseGeometry()); -} - -// ------------------------------------------------------------------------- -QRect ctkBasePopupWidgetPrivate::desiredOpenGeometry(QRect baseGeometry)const -{ - Q_Q(const ctkBasePopupWidget); - QSize size = q->size(); - if (!q->testAttribute(Qt::WA_WState_Created)) - { - size = q->sizeHint(); - } - - if (baseGeometry.isNull()) - { - return QRect(q->pos(), size); - } - - QRect geometry; - if (this->Alignment & Qt::AlignJustify) - { - if (this->Orientations & Qt::Vertical) - { - size.setWidth(baseGeometry.width()); - } - } - if (this->Alignment & Qt::AlignTop && - this->Alignment & Qt::AlignBottom) - { - size.setHeight(baseGeometry.height()); - } - - geometry.setSize(size); - - QPoint topLeft = baseGeometry.topLeft(); - QPoint bottomRight = baseGeometry.bottomRight(); - - if (this->Alignment & Qt::AlignLeft) - { - if (this->HorizontalDirection == Qt::LeftToRight) - { - geometry.moveLeft(topLeft.x()); - } - else - { - geometry.moveRight(topLeft.x() - 1); - } - } - else if (this->Alignment & Qt::AlignRight) - { - if (this->HorizontalDirection == Qt::LeftToRight) - { - geometry.moveLeft(bottomRight.x() + 1); - } - else - { - geometry.moveRight(bottomRight.x()); - } - } - else if (this->Alignment & Qt::AlignHCenter) - { - geometry.moveLeft((topLeft.x() + bottomRight.x()) / 2 - size.width() / 2); - } - else if (this->Alignment & Qt::AlignJustify) - { - geometry.moveLeft(topLeft.x()); - } - - if (this->Alignment & Qt::AlignTop) - { - if (this->VerticalDirection == ctkBasePopupWidget::TopToBottom) - { - geometry.moveTop(topLeft.y()); - } - else - { - geometry.moveBottom(topLeft.y() - 1); - } - } - else if (this->Alignment & Qt::AlignBottom) - { - if (this->VerticalDirection == ctkBasePopupWidget::TopToBottom) - { - geometry.moveTop(bottomRight.y() + 1); - } - else - { - geometry.moveBottom(bottomRight.y()); - } - } - else if (this->Alignment & Qt::AlignVCenter) - { - geometry.moveTop((topLeft.y() + bottomRight.y()) / 2 - size.height() / 2); - } - return geometry; -} - -// ------------------------------------------------------------------------- -void ctkBasePopupWidgetPrivate::hideAll() -{ - Q_Q(ctkBasePopupWidget); - - // It is possible to have the popup widget not being a popup but inside - // a layout: maybe the popup has been pin-down in a way that it gets parented - // In that case, there is no reason to hide the popup. - if (!(q->windowFlags() & PopupWindowType)) - { - return; - } - - // Before hiding, transfer the active window flag to its parent, this will - // prevent the application to send a ApplicationDeactivate signal that - // doesn't need to be done. -#ifndef Q_OS_MAC // See Slicer issue #3850 - if (q->isActiveWindow() && !this->BaseWidget.isNull()) - { - qApp->setActiveWindow(this->BaseWidget->window()); - } -#endif - - q->hide(); - this->PopupPixmapWidget->hide(); - - // If there is a popup open in the ctkBasePopupWidget children, then hide it - // as well so we don't have a popup open while the ctkBasePopupWidget is hidden. - QPointer activePopupWidget = qApp->activePopupWidget(); - if (activePopupWidget && this->isAncestorOf(q, activePopupWidget)) - { - activePopupWidget->close(); - } -} - -// ------------------------------------------------------------------------- -// Qt::FramelessWindowHint is required on Windows for Translucent background -// Qt::Toolip is preferred to Qt::Popup as it would close itself at the first -// click outside the widget (typically a click in the BaseWidget) -ctkBasePopupWidget::ctkBasePopupWidget(QWidget* parentWidget) - //: Superclass(QApplication::desktop()->screen(QApplication::desktop()->screenNumber(parentWidget)), - : Superclass(parentWidget, - PopupWindowType | Qt::FramelessWindowHint) - , d_ptr(new ctkBasePopupWidgetPrivate(*this)) -{ - Q_D(ctkBasePopupWidget); - d->init(); -} - -// ------------------------------------------------------------------------- -ctkBasePopupWidget::ctkBasePopupWidget(ctkBasePopupWidgetPrivate* pimpl, QWidget* parentWidget) - //: //Superclass(QApplication::desktop()->screen(QApplication::desktop()->screenNumber(parentWidget)), - : Superclass(parentWidget, - PopupWindowType | Qt::FramelessWindowHint) - , d_ptr(pimpl) -{ -} - -// ------------------------------------------------------------------------- -ctkBasePopupWidget::~ctkBasePopupWidget() -{ -} - -// ------------------------------------------------------------------------- -QWidget* ctkBasePopupWidget::baseWidget()const -{ - Q_D(const ctkBasePopupWidget); - return d->BaseWidget; -} - -// ------------------------------------------------------------------------- -void ctkBasePopupWidget::setBaseWidget(QWidget* widget) -{ - Q_D(ctkBasePopupWidget); - if (!d->BaseWidget.isNull()) - { - //disconnect(d->BaseWidget, SIGNAL(destroyed(QObject*)), - // this, SLOT(onBaseWidgetDestroyed())); - } - d->BaseWidget = widget; - if (!d->BaseWidget.isNull()) - { - //connect(d->BaseWidget, SIGNAL(destroyed(QObject*)), - // this, SLOT(onBaseWidgetDestroyed())); - } -} - -// ------------------------------------------------------------------------- -void ctkBasePopupWidget::onBaseWidgetDestroyed() -{ - Q_D(ctkBasePopupWidget); - d->hideAll(); - this->setBaseWidget(0); - // could be a property. - this->deleteLater(); -} - -// ------------------------------------------------------------------------- -ctkBasePopupWidget::AnimationEffect ctkBasePopupWidget::animationEffect()const -{ - Q_D(const ctkBasePopupWidget); - return d->Effect; -} - -// ------------------------------------------------------------------------- -void ctkBasePopupWidget::setAnimationEffect(ctkBasePopupWidget::AnimationEffect effect) -{ - Q_D(ctkBasePopupWidget); - /// TODO: handle the case where there is an animation running - d->Effect = effect; -} - -// ------------------------------------------------------------------------- -int ctkBasePopupWidget::effectDuration()const -{ - Q_D(const ctkBasePopupWidget); - return d->EffectDuration; -} - -// ------------------------------------------------------------------------- -void ctkBasePopupWidget::setEffectDuration(int duration) -{ - Q_D(ctkBasePopupWidget); - d->EffectDuration = duration; - d->AlphaAnimation->setDuration(d->EffectDuration); - d->ScrollAnimation->setDuration(d->EffectDuration); -} - -// ------------------------------------------------------------------------- -QEasingCurve::Type ctkBasePopupWidget::easingCurve()const -{ - Q_D(const ctkBasePopupWidget); - return d->AlphaAnimation->easingCurve().type(); -} - -// ------------------------------------------------------------------------- -void ctkBasePopupWidget::setEasingCurve(QEasingCurve::Type easingCurve) -{ - Q_D(ctkBasePopupWidget); - d->AlphaAnimation->setEasingCurve(easingCurve); - d->ScrollAnimation->setEasingCurve(easingCurve); -} - -// ------------------------------------------------------------------------- -Qt::Alignment ctkBasePopupWidget::alignment()const -{ - Q_D(const ctkBasePopupWidget); - return d->Alignment; -} - -// ------------------------------------------------------------------------- -void ctkBasePopupWidget::setAlignment(Qt::Alignment alignment) -{ - Q_D(ctkBasePopupWidget); - d->Alignment = alignment; -} - -// ------------------------------------------------------------------------- -Qt::Orientations ctkBasePopupWidget::orientation()const -{ - Q_D(const ctkBasePopupWidget); - return d->Orientations; -} - -// ------------------------------------------------------------------------- -void ctkBasePopupWidget::setOrientation(Qt::Orientations orientations) -{ - Q_D(ctkBasePopupWidget); - d->Orientations = orientations; -} - -// ------------------------------------------------------------------------- -ctkBasePopupWidget::VerticalDirection ctkBasePopupWidget::verticalDirection()const -{ - Q_D(const ctkBasePopupWidget); - return d->VerticalDirection; -} - -// ------------------------------------------------------------------------- -void ctkBasePopupWidget::setVerticalDirection(ctkBasePopupWidget::VerticalDirection verticalDirection) -{ - Q_D(ctkBasePopupWidget); - d->VerticalDirection = verticalDirection; -} - -// ------------------------------------------------------------------------- -Qt::LayoutDirection ctkBasePopupWidget::horizontalDirection()const -{ - Q_D(const ctkBasePopupWidget); - return d->HorizontalDirection; -} - -// ------------------------------------------------------------------------- -void ctkBasePopupWidget::setHorizontalDirection(Qt::LayoutDirection horizontalDirection) -{ - Q_D(ctkBasePopupWidget); - d->HorizontalDirection = horizontalDirection; -} - -// ------------------------------------------------------------------------- -void ctkBasePopupWidget::onEffectFinished() -{ - Q_D(ctkBasePopupWidget); - if (d->ForcedTranslucent) - { - d->ForcedTranslucent = false; - this->setAttribute(Qt::WA_TranslucentBackground, false); - } - if (d->wasClosing()) - { - d->hideAll(); - emit this->popupOpened(false); - } - else - { - this->show(); - emit this->popupOpened(true); - } -} - -// ------------------------------------------------------------------------- -bool ctkBasePopupWidget::event(QEvent* event) -{ - switch(event->type()) - { - case QEvent::ParentChange: - // For now the base widget is the parent widget - this->setBaseWidget(this->parentWidget()); - break; - default: - break; - } - return this->Superclass::event(event); -} - -// ------------------------------------------------------------------------- -void ctkBasePopupWidget::paintEvent(QPaintEvent* event) -{ - Q_D(ctkBasePopupWidget); - Q_UNUSED(event); - - QPainter painter(this); - QBrush brush = this->palette().window(); - if (brush.style() == Qt::LinearGradientPattern || - brush.style() == Qt::ConicalGradientPattern || - brush.style() == Qt::RadialGradientPattern) - { - QGradient* newGradient = duplicateGradient(brush.gradient()); - QGradientStops stops; - foreach(QGradientStop stop, newGradient->stops()) - { - stop.second.setAlpha(stop.second.alpha() * d->EffectAlpha); - stops.push_back(stop); - } - newGradient->setStops(stops); - brush = QBrush(*newGradient); - delete newGradient; - } - else - { - QColor color = brush.color(); - color.setAlpha(color.alpha() * d->EffectAlpha); - brush.setColor(color); - } - //QColor semiTransparentColor = this->palette().window().color(); - //semiTransparentColor.setAlpha(d->CurrentAlpha); - painter.fillRect(this->rect(), brush); - painter.end(); - // Let the QFrame draw itself if needed - this->Superclass::paintEvent(event); -} - -// -------------------------------------------------------------------------- -void ctkBasePopupWidget::showPopup() -{ - Q_D(ctkBasePopupWidget); - - if ((this->isVisible() && - d->currentAnimation()->state() == QAbstractAnimation::Stopped) || - (!d->BaseWidget.isNull() && !d->BaseWidget->isVisible())) - { - return; - } - - // If the layout has never been activated, the widget doesn't know its - // minSize/maxSize and we then wouldn't know what's its true geometry. - if (this->layout() && !this->testAttribute(Qt::WA_WState_Created)) - { - this->layout()->activate(); - } - this->setGeometry(d->desiredOpenGeometry()); - /// Maybe the popup doesn't allow the desiredOpenGeometry if the widget - /// minimum size is larger than the desired size. - QRect openGeometry = this->geometry(); - QRect closedGeometry = d->closedGeometry(); - - d->currentAnimation()->setDirection(QAbstractAnimation::Forward); - - switch(d->Effect) - { - case WindowOpacityFadeEffect: - if (!this->testAttribute(Qt::WA_TranslucentBackground)) - { - d->ForcedTranslucent = true; - this->setAttribute(Qt::WA_TranslucentBackground, true); - } - this->show(); - break; - case ScrollEffect: - { - d->PopupPixmapWidget->setGeometry(closedGeometry); - d->ScrollAnimation->setStartValue(closedGeometry); - d->ScrollAnimation->setEndValue(openGeometry); - d->setupPopupPixmapWidget(); - d->PopupPixmapWidget->show(); - break; - } - default: - break; - } - switch(d->currentAnimation()->state()) - { - case QAbstractAnimation::Stopped: - d->currentAnimation()->start(); - break; - case QAbstractAnimation::Paused: - d->currentAnimation()->resume(); - break; - default: - case QAbstractAnimation::Running: - break; - } -} - -// -------------------------------------------------------------------------- -void ctkBasePopupWidget::hidePopup() -{ - Q_D(ctkBasePopupWidget); - - if (!this->isVisible() && - d->currentAnimation()->state() == QAbstractAnimation::Stopped) - { - return; - } - d->currentAnimation()->setDirection(QAbstractAnimation::Backward); - - QRect openGeometry = this->geometry(); - QRect closedGeometry = d->closedGeometry(); - - switch(d->Effect) - { - case WindowOpacityFadeEffect: - if (!this->testAttribute(Qt::WA_TranslucentBackground)) - { - d->ForcedTranslucent = true; - this->setAttribute(Qt::WA_TranslucentBackground, true); - } - break; - case ScrollEffect: - { - d->ScrollAnimation->setStartValue(closedGeometry); - d->ScrollAnimation->setEndValue(openGeometry); - d->setupPopupPixmapWidget(); - d->PopupPixmapWidget->setGeometry(this->geometry()); - d->PopupPixmapWidget->show(); - if (this->isActiveWindow()) - { - qApp->setActiveWindow(!d->BaseWidget.isNull() ? d->BaseWidget->window() : 0); - } - this->hide(); - break; - } - default: - break; - } - switch(d->currentAnimation()->state()) - { - case QAbstractAnimation::Stopped: - d->currentAnimation()->start(); - break; - case QAbstractAnimation::Paused: - d->currentAnimation()->resume(); - break; - default: - case QAbstractAnimation::Running: - break; - } -} - -// -------------------------------------------------------------------------- -double ctkBasePopupWidget::effectAlpha()const -{ - Q_D(const ctkBasePopupWidget); - return d->EffectAlpha; -} - -// -------------------------------------------------------------------------- -void ctkBasePopupWidget::setEffectAlpha(double alpha) -{ - Q_D(ctkBasePopupWidget); - d->EffectAlpha = alpha; - this->repaint(); -} - -// -------------------------------------------------------------------------- -QRect ctkBasePopupWidget::effectGeometry()const -{ - Q_D(const ctkBasePopupWidget); - return d->PopupPixmapWidget->geometry(); -} - -// -------------------------------------------------------------------------- -void ctkBasePopupWidget::setEffectGeometry(QRect newGeometry) -{ - Q_D(ctkBasePopupWidget); - d->PopupPixmapWidget->setGeometry(newGeometry); - d->PopupPixmapWidget->repaint(); -} diff --git a/ctk/ctkBasePopupWidget.h b/ctk/ctkBasePopupWidget.h deleted file mode 100644 index ba86e68..0000000 --- a/ctk/ctkBasePopupWidget.h +++ /dev/null @@ -1,225 +0,0 @@ -/*========================================================================= - - Library: CTK - - Copyright (c) Kitware Inc. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.commontk.org/LICENSE - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -=========================================================================*/ - -#ifndef __ctkBasePopupWidget_h -#define __ctkBasePopupWidget_h - -// Qt includes -#include -#include -#include - -// CTK includes -#include "ctkWidgetsExport.h" - -class ctkBasePopupWidgetPrivate; - -/// \ingroup Widgets -/// ctkBasePopupWidget is a popup that opens under, above or on the side of -/// another widget (baseWidget() or its parent widget by default). -/// The children (widgets and layout) of the popup define of the content -/// of the popup. Different effects can be applied during the opening or -/// closing of the popup. -/// See ctkPopupWidget for an automatic control of its opening and closing. -/// \sa baseWidget(), animationEffect, ctkPopupWidget -class CTK_WIDGETS_EXPORT ctkBasePopupWidget : public QFrame -{ - Q_OBJECT - - Q_ENUMS(AnimationEffect) - Q_ENUMS(VerticalDirection) - - /// This property controls the effect to apply when the popup is being - /// opened or closed. The total duration and the easing curve of the effect - /// are controlled by \a effectDuration and \easingCurve respectively. - /// ScrollEffect by default. - /// \sa AnimationEffect, animationEffect(), setAnimationEffect(), - /// effectDuration, easingCurve - Q_PROPERTY( AnimationEffect animationEffect READ animationEffect WRITE setAnimationEffect) - - /// The property controls the \a animationEffect duration in ms. - /// If the popup state (open or close) is being changed during the animation, - /// the active animation is stopped and a new animation is being created from - /// the current state (geometry, transparency...) to the new final state. - /// Default to 333ms - /// \sa effectDuration(), setEffectDuration(), animationEffect, easingCurve - Q_PROPERTY( int effectDuration READ effectDuration WRITE setEffectDuration); - - /// The property controls the behavior of the opening or closing curve of the - /// animation effect. - /// QEasingCurve::InOutQuad by default - /// \sa easingCurve(), setEasingCurve(), animationEffect, effectDuration - Q_PROPERTY( QEasingCurve::Type easingCurve READ easingCurve WRITE setEasingCurve); - - /// Where is the popup in relation to the BaseWidget - /// To vertically justify, use Qt::AlignTop | Qt::AlignBottom. - /// Qt::AlignJustify | Qt::AlignBottom by default - Q_PROPERTY( Qt::Alignment alignment READ alignment WRITE setAlignment); - - /// Direction of the scrolling effect, can be Qt::Vertical, Qt::Horizontal or - /// both Qt::Vertical|Qt::Horizontal. - /// Vertical by default - Q_PROPERTY( Qt::Orientations orientation READ orientation WRITE setOrientation); - - /// Control where the popup opens vertically. - /// TopToBottom by default - Q_PROPERTY( ctkBasePopupWidget::VerticalDirection verticalDirection READ verticalDirection WRITE setVerticalDirection); - - /// Control where the popup opens horizontally. - /// LeftToRight by default - Q_PROPERTY( Qt::LayoutDirection horizontalDirection READ horizontalDirection WRITE setHorizontalDirection); - -public: - typedef QFrame Superclass; - /// Although a popup widget is a top-level widget, if a parent is - /// passed the popup widget will be deleted when that parent is - /// destroyed (as with any other QObject). - /// ctkBasePopupWidget is a top-level widget (Qt::ToolTip), so - /// even if a parent is passed, the popup will display outside the possible - /// parent layout. - /// \sa baseWidget(). - explicit ctkBasePopupWidget(QWidget* parent = 0); - virtual ~ctkBasePopupWidget(); - - /// Widget the popup is attached to. It opens right under \a baseWidget - /// and if the ctkBasePopupWidget sizepolicy contains the growFlag/shrinkFlag, - /// it tries to resize itself to fit the same width of \a baseWidget. - /// By default, baseWidget is the parent widget. - /// \sa setBaseWidget() - QWidget* baseWidget()const; - - enum AnimationEffect - { - WindowOpacityFadeEffect = 0, - ScrollEffect, - FadeEffect - }; - - /// Return the animationEffect property value. - /// \sa animationEffect - AnimationEffect animationEffect()const; - /// Set the animationEffect property value. - /// \sa animationEffect - void setAnimationEffect(AnimationEffect effect); - - /// Return the effectDuration property value. - /// \sa effectDuration - int effectDuration()const; - /// Set the effectDuration property value. - /// \sa effectDuration - void setEffectDuration(int duration); - - /// Return the easingCurve property value. - /// \sa easingCurve - QEasingCurve::Type easingCurve()const; - /// Set the easingCurve property value. - /// \sa easingCurve - void setEasingCurve(QEasingCurve::Type easingCurve); - - /// Return the alignment property value. - /// \sa alignment - Qt::Alignment alignment()const; - /// Set the alignment property value. - /// \sa alignment - void setAlignment(Qt::Alignment alignment); - - /// Return the orientation property value. - /// \sa orientation - Qt::Orientations orientation()const; - /// Set the orientation property value. - /// \sa orientation - void setOrientation(Qt::Orientations orientation); - - enum VerticalDirection{ - TopToBottom = 1, - BottomToTop = 2 - }; - - /// Return the verticalDirection property value. - /// \sa verticalDirection - VerticalDirection verticalDirection()const; - /// Set the verticalDirection property value. - /// \sa verticalDirection - void setVerticalDirection(VerticalDirection direction); - - /// Return the horizontalDirection property value. - /// \sa horizontalDirection - Qt::LayoutDirection horizontalDirection()const; - /// Set the horizontalDirection property value. - /// \sa horizontalDirection - void setHorizontalDirection(Qt::LayoutDirection direction); - -public Q_SLOTS: - /// Hide the popup if open or opening. It takes around 300ms - /// for the fading effect to hide the popup. - virtual void hidePopup(); - /// Open the popup if closed or closing. It takes around 300ms - /// for the fading effect to open the popup. - virtual void showPopup(); - /// Show/hide the popup. It can be conveniently linked to a QPushButton - /// signal. - inline void showPopup(bool show); - -Q_SIGNALS: - /// Fired when the popup finished its animation: opening (true) or closing (false). - /// \sa showPopup(), hidePopup() - void popupOpened(bool open); - -protected: - explicit ctkBasePopupWidget(ctkBasePopupWidgetPrivate* pimpl, QWidget* parent = 0); - QScopedPointer d_ptr; - Q_PROPERTY(double effectAlpha READ effectAlpha WRITE setEffectAlpha DESIGNABLE false) - Q_PROPERTY(QRect effectGeometry READ effectGeometry WRITE setEffectGeometry DESIGNABLE false) - - double effectAlpha()const; - QRect effectGeometry()const; - - virtual void setBaseWidget(QWidget* baseWidget); - virtual bool event(QEvent* event); - virtual void paintEvent(QPaintEvent*); - -protected Q_SLOTS: - virtual void onEffectFinished(); - void setEffectAlpha(double alpha); - void setEffectGeometry(QRect geometry); - void onBaseWidgetDestroyed(); - -private: - Q_DECLARE_PRIVATE(ctkBasePopupWidget); - Q_DISABLE_COPY(ctkBasePopupWidget); -}; - -Q_DECLARE_METATYPE(ctkBasePopupWidget::AnimationEffect) -Q_DECLARE_METATYPE(ctkBasePopupWidget::VerticalDirection) - -// ------------------------------------------------------------------------- -void ctkBasePopupWidget::showPopup(bool show) -{ - if (show) - { - this->showPopup(); - } - else - { - this->hidePopup(); - } -} - -#endif diff --git a/ctk/ctkBasePopupWidget_p.h b/ctk/ctkBasePopupWidget_p.h deleted file mode 100644 index 2fc7e50..0000000 --- a/ctk/ctkBasePopupWidget_p.h +++ /dev/null @@ -1,108 +0,0 @@ -/*========================================================================= - - Library: CTK - - Copyright (c) Kitware Inc. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0.txt - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -=========================================================================*/ - -#ifndef __ctkBasePopupWidget_p_h -#define __ctkBasePopupWidget_p_h - -// Qt includes -#include -class QLabel; -class QPropertyAnimation; - -// CTK includes -#include "ctkBasePopupWidget.h" -#define PopupWindowType Qt::Tool - -// ------------------------------------------------------------------------- -/// \ingroup Widgets -class CTK_WIDGETS_EXPORT ctkBasePopupWidgetPrivate - : public QObject -{ - Q_OBJECT - Q_DECLARE_PUBLIC(ctkBasePopupWidget); -protected: - ctkBasePopupWidget* const q_ptr; -public: - ctkBasePopupWidgetPrivate(ctkBasePopupWidget& object); - ~ctkBasePopupWidgetPrivate(); - virtual void init(); - - bool isOpening()const; - bool isClosing()const; - /// Return true if the animation was closing (direction == backward). - /// It doesn't indicate if the action is still running or finished. - /// Can only be called in a slot as it uses sender(). - bool wasClosing()const; - - bool fitBaseWidgetSize()const; - Qt::Alignment pixmapAlignment()const; - void setupPopupPixmapWidget(); - - QWidgetList focusWidgets(bool onlyVisible = false)const; - - // Return the widget if the mouse cursor is above any of the focus widgets or their - // children. - virtual QWidget* mouseOver(); - - // Same as QWidget::isAncestorOf() but don't restrain to the same window - // and apply it to all the focusWidgets - bool isAncestorOf(const QWidget* ancestor, const QWidget* child)const; - - - /// Return the closed geometry for the popup based on the current geometry - QRect closedGeometry()const; - /// Return the closed geometry for a given open geometry - QRect closedGeometry(QRect openGeom)const; - - /// Return the desired geometry, maybe it won't happen if the size is too - /// small for the popup. - QRect desiredOpenGeometry()const; - QRect desiredOpenGeometry(QRect baseGeometry)const; - QRect baseGeometry()const; - QPoint mapToGlobal(const QPoint& baseWidgetPoint)const; - - QPropertyAnimation* currentAnimation()const; - - //void temporarilyHiddenOn(); - //void temporarilyHiddenOff(); - - void hideAll(); - -protected: - QPointer BaseWidget; - - double EffectAlpha; - - ctkBasePopupWidget::AnimationEffect Effect; - int EffectDuration; - QPropertyAnimation* AlphaAnimation; - bool ForcedTranslucent; - QPropertyAnimation* ScrollAnimation; - QLabel* PopupPixmapWidget; - - // Geometry attributes - Qt::Alignment Alignment; - Qt::Orientations Orientations; - - ctkBasePopupWidget::VerticalDirection VerticalDirection; - Qt::LayoutDirection HorizontalDirection; -}; - -#endif diff --git a/ctk/ctkPopupWidget.cpp b/ctk/ctkPopupWidget.cpp deleted file mode 100644 index 3ad6aae..0000000 --- a/ctk/ctkPopupWidget.cpp +++ /dev/null @@ -1,560 +0,0 @@ -/*========================================================================= - - Library: CTK - - Copyright (c) Kitware Inc. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0.txt - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -=========================================================================*/ - -// Qt includes -#include -//#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// CTK includes -#include "ctkPopupWidget_p.h" - -// ------------------------------------------------------------------------- -ctkPopupWidgetPrivate::ctkPopupWidgetPrivate(ctkPopupWidget& object) - :Superclass(object) -{ - this->Active = false; - this->AutoShow = true; - this->ShowDelay = 20; - this->AutoHide = true; - this->HideDelay = 200; -} - -// ------------------------------------------------------------------------- -ctkPopupWidgetPrivate::~ctkPopupWidgetPrivate() -{ -} - -// ------------------------------------------------------------------------- -void ctkPopupWidgetPrivate::init() -{ - Q_Q(ctkPopupWidget); - this->setParent(q); - q->setActive(true); - this->Superclass::init(); -} - -// ------------------------------------------------------------------------- -QWidget* ctkPopupWidgetPrivate::mouseOver() -{ - Q_Q(ctkPopupWidget); - QWidget* widgetUnderCursor = this->Superclass::mouseOver(); - if (widgetUnderCursor && - !this->focusWidgets(true).contains(widgetUnderCursor)) - { - widgetUnderCursor->installEventFilter(q); - } - return widgetUnderCursor; -} - -// ------------------------------------------------------------------------- -bool ctkPopupWidgetPrivate::eventFilter(QObject* obj, QEvent* event) -{ - Q_Q(ctkPopupWidget); - QWidget* widget = qobject_cast(obj); - if (!widget) - { - return this->Superclass::eventFilter(obj, event); - } - // Here are the application events, it's a lot of events, so we need to be - // careful to be fast. - if (event->type() == QEvent::ApplicationDeactivate) - { - // We wait to see if there is no other window being active - QTimer::singleShot(0, this, SLOT(onApplicationDeactivate())); - } - else if (event->type() == QEvent::ApplicationActivate) - { - QTimer::singleShot(0, this, SLOT(updateVisibility())); - } - if (this->BaseWidget.isNull()) - { - return false; - } - if (event->type() == QEvent::Move && widget != this->BaseWidget) - { - if (widget->isAncestorOf(this->BaseWidget)) - { - q->setGeometry(this->desiredOpenGeometry()); - } - else if (this->isHidingCandidate(widget)) - { - QTimer::singleShot(0, this, SLOT(updateVisibility())); - } - } - else if (event->type() == QEvent::Resize) - { - if (widget->isAncestorOf(this->BaseWidget)) - { - q->setGeometry(this->desiredOpenGeometry()); - } - else if (this->isHidingCandidate(widget)) - { - QTimer::singleShot(0, this, SLOT(updateVisibility())); - } - } - else if (event->type() == QEvent::WindowStateChange && - this->isHidingCandidate(widget)) - { - QTimer::singleShot(0, this, SLOT(updateVisibility())); - } - else if ((event->type() == QEvent::WindowActivate || - event->type() == QEvent::WindowDeactivate) && - widget == this->BaseWidget->window()) - { - QTimer::singleShot(0, this, SLOT(updateVisibility())); - } - else if (event->type() == QEvent::RequestSoftwareInputPanel) - { - qApp->setActiveWindow(widget->window()); - } - return false; -} - -// ------------------------------------------------------------------------- -void ctkPopupWidgetPrivate::onApplicationDeactivate() -{ - // Still no active window, that means the user now is controlling another - // application, we have no control over when the other app moves over the - // popup, so we hide the popup as it would show on top of the other app. - if (!qApp->activeWindow()) - { - this->temporarilyHiddenOn(); - } -} - -// ------------------------------------------------------------------------- -bool ctkPopupWidgetPrivate::isHidingCandidate(QWidget* widget)const -{ - // The mac window manager is keeping the Qt:Tool widgets always on top, - // so if a non modal dialog is moved near the popup widget, the popup will - // always appear on top of the dialog. For this reason we manually have to - // hide the popup when a dialog is intersecting with the popup. - bool canWindowsHidePopup = false; -#if defined Q_OS_MAC - canWindowsHidePopup = true; -#endif - bool isWindow = widget->isWindow(); - QDialog* dialog = qobject_cast(widget); - bool isModal = dialog ? dialog->isModal() : false; - bool isBasePopupWidget = qobject_cast(widget); - bool isToolTip = widget->windowType() == Qt::ToolTip; - bool isPopup = widget->windowType() == Qt::Popup; - bool isSelf = (widget == (this->BaseWidget ? this->BaseWidget->window() : 0)); - - return canWindowsHidePopup && isWindow && !isModal && !isBasePopupWidget && - !isToolTip && !isPopup && !isSelf; -} - -// ------------------------------------------------------------------------- -void ctkPopupWidgetPrivate::updateVisibility() -{ - Q_Q(ctkPopupWidget); - // If the BaseWidget window is active, then there is no reason to cover the - // popup. - if (this->BaseWidget.isNull() || - // the popupwidget active window is not active - (!this->BaseWidget->window()->isActiveWindow() && - // and no other active window - (!qApp->activeWindow() || - // or the active window is a popup - (!qobject_cast(qApp->activeWindow()) && //->windowType() != PopupWindowType && - qApp->activeWindow()->windowType() != Qt::Popup)))) - { - foreach(QWidget* topLevelWidget, qApp->topLevelWidgets()) - { - // If there is at least 1 window (active or not) that covers the popup, - // then we ensure the popup is hidden. - // We have no way of knowing which toplevel is over (z-order) which one, - // it is an OS specific information. - // Of course, tooltips and popups don't count as covering windows. - if (topLevelWidget->isVisible() && - !(topLevelWidget->windowState() & Qt::WindowMinimized) && - this->isHidingCandidate(topLevelWidget) && - topLevelWidget->frameGeometry().intersects(q->geometry())) - { - //qDebug() << "hide" << q << "because of: " << topLevelWidget - // << " with windowType: " << topLevelWidget->windowType() - // << topLevelWidget->isVisible() - // << (this->BaseWidget ? this->BaseWidget->window() : 0) - // << topLevelWidget->frameGeometry(); - this->temporarilyHiddenOn(); - return; - } - } - } - // If the base widget is hidden or minimized, we don't want to restore the - // popup. - if (!this->BaseWidget.isNull() && - (!this->BaseWidget->isVisible() || - this->BaseWidget->window()->windowState() & Qt::WindowMinimized)) - { - return; - } - // Restore the visibility of the popup if it was hidden - this->temporarilyHiddenOff(); -} - -// ------------------------------------------------------------------------- -void ctkPopupWidgetPrivate::temporarilyHiddenOn() -{ - Q_Q(ctkPopupWidget); - if (!this->AutoHide && - (q->isVisible() || this->isOpening()) && - !(q->isHidden() || this->isClosing())) - { - this->setProperty("forcedClosed", this->isOpening() ? 2 : 1); - } - this->currentAnimation()->stop(); - this->hideAll(); -} - -// ------------------------------------------------------------------------- -void ctkPopupWidgetPrivate::temporarilyHiddenOff() -{ - Q_Q(ctkPopupWidget); - - int forcedClosed = this->property("forcedClosed").toInt(); - if (forcedClosed > 0) - { - q->show(); - if (forcedClosed == 2) - { - emit q->popupOpened(true); - } - this->setProperty("forcedClosed", 0); - } - else - { - q->updatePopup(); - } -} - -// ------------------------------------------------------------------------- -// Qt::FramelessWindowHint is required on Windows for Translucent background -// Qt::Toolip is preferred to Qt::Popup as it would close itself at the first -// click outside the widget (typically a click in the BaseWidget) -ctkPopupWidget::ctkPopupWidget(QWidget* parentWidget) - : Superclass(new ctkPopupWidgetPrivate(*this), parentWidget) -{ - Q_D(ctkPopupWidget); - d->init(); -} - -// ------------------------------------------------------------------------- -ctkPopupWidget::~ctkPopupWidget() -{ -} - -// ------------------------------------------------------------------------- -bool ctkPopupWidget::isActive()const -{ - Q_D(const ctkPopupWidget); - return d->Active; -} - -// ------------------------------------------------------------------------- -void ctkPopupWidget::setActive(bool active) -{ - Q_D(ctkPopupWidget); - if (active == d->Active) - { - return; - } - d->Active = active; - if (d->Active) - { - if (!d->BaseWidget.isNull()) - { - d->BaseWidget->installEventFilter(this); - } - if (d->PopupPixmapWidget) - { - d->PopupPixmapWidget->installEventFilter(this); - } - qApp->installEventFilter(d); - } - else // not active - { - if (!d->BaseWidget.isNull()) - { - d->BaseWidget->removeEventFilter(this); - } - if (d->PopupPixmapWidget) - { - d->PopupPixmapWidget->removeEventFilter(this); - } - qApp->removeEventFilter(d); - } -} - -// ------------------------------------------------------------------------- -void ctkPopupWidget::setBaseWidget(QWidget* widget) -{ - Q_D(ctkPopupWidget); - if (!d->BaseWidget.isNull()) - { - d->BaseWidget->removeEventFilter(this); - } - this->Superclass::setBaseWidget(widget); - if (!d->BaseWidget.isNull() && d->Active) - { - d->BaseWidget->installEventFilter(this); - } - QTimer::singleShot(d->ShowDelay, this, SLOT(updatePopup())); -} - -// ------------------------------------------------------------------------- -bool ctkPopupWidget::autoShow()const -{ - Q_D(const ctkPopupWidget); - return d->AutoShow; -} - -// ------------------------------------------------------------------------- -void ctkPopupWidget::setAutoShow(bool mode) -{ - Q_D(ctkPopupWidget); - d->AutoShow = mode; - QTimer::singleShot(d->ShowDelay, this, SLOT(updatePopup())); -} - -// ------------------------------------------------------------------------- -int ctkPopupWidget::showDelay()const -{ - Q_D(const ctkPopupWidget); - return d->ShowDelay; -} - -// ------------------------------------------------------------------------- -void ctkPopupWidget::setShowDelay(int delay) -{ - Q_D(ctkPopupWidget); - d->ShowDelay = delay; -} - -// ------------------------------------------------------------------------- -bool ctkPopupWidget::autoHide()const -{ - Q_D(const ctkPopupWidget); - return d->AutoHide; -} - -// ------------------------------------------------------------------------- -void ctkPopupWidget::setAutoHide(bool mode) -{ - Q_D(ctkPopupWidget); - d->AutoHide = mode; - QTimer::singleShot(d->HideDelay, this, SLOT(updatePopup())); -} - -// ------------------------------------------------------------------------- -int ctkPopupWidget::hideDelay()const -{ - Q_D(const ctkPopupWidget); - return d->HideDelay; -} - -// ------------------------------------------------------------------------- -void ctkPopupWidget::setHideDelay(int delay) -{ - Q_D(ctkPopupWidget); - d->HideDelay = delay; -} - -// ------------------------------------------------------------------------- -void ctkPopupWidget::onEffectFinished() -{ - Q_D(ctkPopupWidget); - bool wasClosing = d->wasClosing(); - this->Superclass::onEffectFinished(); - if (wasClosing) - { - /// restore the AutoShow if needed. - if (!this->property("AutoShowOnClose").isNull()) - { - d->AutoShow = this->property("AutoShowOnClose").toBool(); - this->setProperty("AutoShowOnClose", QVariant()); - } - } -} - -// -------------------------------------------------------------------------- -void ctkPopupWidget::leaveEvent(QEvent* event) -{ - Q_D(ctkPopupWidget); - QTimer::singleShot(d->HideDelay, this, SLOT(updatePopup())); - this->Superclass::leaveEvent(event); -} - -// -------------------------------------------------------------------------- -void ctkPopupWidget::enterEvent(QEnterEvent* event) -{ - Q_D(ctkPopupWidget); - QTimer::singleShot(d->ShowDelay, this, SLOT(updatePopup())); - this->Superclass::enterEvent(event); -} - -// -------------------------------------------------------------------------- -bool ctkPopupWidget::eventFilter(QObject* obj, QEvent* event) -{ - Q_D(ctkPopupWidget); - // Here we listen to PopupPixmapWidget, BaseWidget and ctkPopupWidget - // children popups that were under the mouse - switch(event->type()) - { - case QEvent::Move: - { - if (obj != d->BaseWidget) - { - break; - } - QMoveEvent* moveEvent = dynamic_cast(event); - QRect newBaseGeometry = d->baseGeometry(); - newBaseGeometry.moveTopLeft(d->mapToGlobal(moveEvent->pos())); - QRect desiredGeometry = d->desiredOpenGeometry(newBaseGeometry); - this->move(desiredGeometry.topLeft()); - //this->move(this->pos() + moveEvent->pos() - moveEvent->oldPos()); - this->update(); - break; - } - case QEvent::Hide: - case QEvent::Close: - // if the mouse was in a base widget child popup, then when we leave - // the popup we want to check if it needs to be closed. - if (obj != d->BaseWidget) - { - if (obj != d->PopupPixmapWidget && - qobject_cast(obj)->windowType() == Qt::Popup) - { - obj->removeEventFilter(this); - QTimer::singleShot(d->HideDelay, this, SLOT(updatePopup())); - } - break; - } - d->temporarilyHiddenOn(); - break; - case QEvent::Show: - if (obj != d->BaseWidget) - { - break; - } - this->setGeometry(d->desiredOpenGeometry()); - d->temporarilyHiddenOff(); - break; - case QEvent::Enter: - if ( d->currentAnimation()->state() == QAbstractAnimation::Stopped ) - { - // Maybe the user moved the mouse on the widget by mistake, don't open - // the popup instantly... - QTimer::singleShot(d->ShowDelay, this, SLOT(updatePopup())); - } - else - { - // ... except if the popup is closing, we want to reopen it as sooon as - // possible. - this->updatePopup(); - } - break; - case QEvent::Leave: - // Don't listen to base widget children that are popups as what - // matters here is their close event instead - if (obj != d->BaseWidget && - obj != d->PopupPixmapWidget && - qobject_cast(obj)->windowType() == Qt::Popup) - { - break; - } - // The mouse might have left the area that keeps the popup open - QTimer::singleShot(d->HideDelay, this, SLOT(updatePopup())); - if (obj != d->BaseWidget && - obj != d->PopupPixmapWidget) - { - obj->removeEventFilter(this); - } - break; - default: - break; - } - return this->QObject::eventFilter(obj, event); -} - -// -------------------------------------------------------------------------- -void ctkPopupWidget::updatePopup() -{ - Q_D(ctkPopupWidget); - - // Querying mouseOver can be slow, don't do it if not needed. - QWidget* mouseOver = (d->AutoShow || d->AutoHide) ? d->mouseOver() : 0; - if ((d->AutoShow || - // Even if there is no AutoShow, we might still want to reopen the popup - // when closing it inadvertently, except if we are un-pin-ing the popup - (d->AutoHide && d->isClosing() && this->property("AutoShowOnClose").toBool())) && - // to be automatically open, the mouse has to be over a child widget - mouseOver && - // disable opening the popup when the popup is disabled - (d->BaseWidget.isNull() || d->BaseWidget->isEnabled())) - { - this->showPopup(); - } - else if (d->AutoHide && !mouseOver) - { - this->hidePopup(); - } -} - - -// -------------------------------------------------------------------------- -void ctkPopupWidget::hidePopup() -{ - // just in case it was set. - this->setProperty("forcedClosed", 0); - - this->Superclass::hidePopup(); -} - -// -------------------------------------------------------------------------- -void ctkPopupWidget::pinPopup(bool pin) -{ - Q_D(ctkPopupWidget); - this->setAutoHide(!pin); - if (pin) - { - this->showPopup(); - } - else - { - // When closing, we don't want to inadvertently re-open the menu. - this->setProperty("AutoShowOnClose", this->autoShow()); - d->AutoShow = false; - this->hidePopup(); - } -} diff --git a/ctk/ctkPopupWidget.h b/ctk/ctkPopupWidget.h deleted file mode 100644 index c23dd88..0000000 --- a/ctk/ctkPopupWidget.h +++ /dev/null @@ -1,133 +0,0 @@ -/*========================================================================= - - Library: CTK - - Copyright (c) Kitware Inc. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0.txt - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -=========================================================================*/ - -#ifndef __ctkPopupWidget_h -#define __ctkPopupWidget_h - -// CTK includes -#include "ctkBasePopupWidget.h" - -class ctkPopupWidgetPrivate; - -/// \ingroup Widgets -/// ctkPopupWidget is a specialization of ctkBasePopupWidget that handles -/// the opening and closing of the popup. -/// Below is an example of a popup slider that opens and closes next to a -/// button -/// \code -/// ctkPopupWidget* popup = new ctkPopupWidget(pushButton); -/// popup->setAlignment(Qt::AlignRight | Qt::AlignTop | Qt::AlignBottom); -/// popup->setOrientation(Qt::Horizontal); -/// QHBoxLayout* popupLayout = new QHBoxLayout(popup); -/// QSlider* popupSlider = new QSlider(popup); -/// popupLayout->addWidget(popupSlider); -/// \endcode -/// \sa ctkBasePopupWidget -class CTK_WIDGETS_EXPORT ctkPopupWidget : public ctkBasePopupWidget -{ - Q_OBJECT - - /// Control whether the popup listens to the application and baseWidget - /// events and decides if it needs to be permanently or temporarily hidden. - /// You might want to setActive(false) when embedding the popup - /// into a static layout intead of having it top-level (no parent). - /// Consider also removing its windowFlags (Qt::ToolTip | - /// Qt::FramelessWindowHint) and removing the baseWidget. - /// True by default - /// \sa isActive(), setActive() - Q_PROPERTY( bool active READ isActive WRITE setActive) - - /// Control wether the popup automatically opens when the mouse - /// enter the widget. True by default - /// \sa autoShow(), setAutoShow() - Q_PROPERTY( bool autoShow READ autoShow WRITE setAutoShow) - - /// Time in ms to wait before opening the popup if autoShow is set. - /// 20ms by default - /// \sa showDelay(), setShowDelay() - Q_PROPERTY( int showDelay READ showDelay WRITE setShowDelay) - - /// Control wether the popup automatically closes when the mouse - /// leaves the widget. True by default. - /// \sa autoHide(), setAutoHide() - Q_PROPERTY( bool autoHide READ autoHide WRITE setAutoHide) - - /// Time in ms to wait before closing the popup if autoHide is set. - /// 200ms by default - /// \sa hideDelay(), setHideDelay() - Q_PROPERTY( int hideDelay READ hideDelay WRITE setHideDelay) - -public: - typedef ctkBasePopupWidget Superclass; - /// By default, the parent is the \a baseWidget. - /// \sa baseWidget() - explicit ctkPopupWidget(QWidget* parent = 0); - virtual ~ctkPopupWidget(); - - bool isActive()const; - void setActive(bool); - - bool autoShow()const; - /// Calling setAutoShow automatically updates opens the popup if the cursor - /// is above the popup or the base widget. - void setAutoShow(bool); - - int showDelay()const; - void setShowDelay(int delay); - - bool autoHide()const; - /// Don't automatically close the popup when leaving the widget. - /// Calling setAutoHide automatically updates the state close the popup - /// if the mouse is not over the popup nor the base widget. - void setAutoHide(bool autoHide); - - int hideDelay()const; - void setHideDelay(int delay); - -public Q_SLOTS: - /// Convenient function that calls setAutoHide(!pin) and opens the popup - /// if pin is true regardless of the value of \a AutoShow. - /// It is typically connected with a checkable button to anchor the popup. - void pinPopup(bool pin); - -public: - /// Reimplemented for internal reasons - virtual void hidePopup() override; - -protected: - virtual void leaveEvent(QEvent* event) override; - virtual void enterEvent(QEnterEvent* event) override; - virtual bool eventFilter(QObject* obj, QEvent* event) override; - - /// Widget the popup is attached to. It opens right under \a baseWidget - /// and if the ctkPopupWidget sizepolicy contains the growFlag/shrinkFlag, - /// it tries to resize itself to fit the same width of \a baseWidget. - virtual void setBaseWidget(QWidget* baseWidget) override; - -protected Q_SLOTS: - void updatePopup(); - virtual void onEffectFinished() override; - -private: - Q_DECLARE_PRIVATE(ctkPopupWidget); - Q_DISABLE_COPY(ctkPopupWidget); -}; - -#endif diff --git a/ctk/ctkPopupWidget_p.h b/ctk/ctkPopupWidget_p.h deleted file mode 100644 index c2d005a..0000000 --- a/ctk/ctkPopupWidget_p.h +++ /dev/null @@ -1,67 +0,0 @@ -/*========================================================================= - - Library: CTK - - Copyright (c) Kitware Inc. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0.txt - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -=========================================================================*/ - -#ifndef __ctkPopupWidget_p_h -#define __ctkPopupWidget_p_h - -// CTK includes -#include "ctkBasePopupWidget_p.h" -#include "ctkPopupWidget.h" - -// ------------------------------------------------------------------------- -/// \ingroup Widgets -class CTK_WIDGETS_EXPORT ctkPopupWidgetPrivate - : public ctkBasePopupWidgetPrivate -{ - Q_OBJECT - Q_DECLARE_PUBLIC(ctkPopupWidget); -public: - typedef ctkBasePopupWidgetPrivate Superclass; - ctkPopupWidgetPrivate(ctkPopupWidget& object); - ~ctkPopupWidgetPrivate(); - - virtual void init(); - - // Return the widget if the mouse cursor is above any of the focus widgets or their - // children. - // If the cursor is above a child widget, install the event filter to listen - // when the cursor leaves the widget. - virtual QWidget* mouseOver(); - - virtual bool eventFilter(QObject* obj, QEvent* event); - - void temporarilyHiddenOn(); - void temporarilyHiddenOff(); - - bool isHidingCandidate(QWidget* widget)const; - -public Q_SLOTS: - void updateVisibility(); - void onApplicationDeactivate(); - -protected: - bool Active; - bool AutoShow; - int ShowDelay; - bool AutoHide; - int HideDelay; -}; - -#endif diff --git a/ctk/ctkWidgetsExport.h b/ctk/ctkWidgetsExport.h deleted file mode 100644 index 75361fe..0000000 --- a/ctk/ctkWidgetsExport.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef CTKWIDGETSEXPORT_H -#define CTKWIDGETSEXPORT_H - -#define CTK_WIDGETS_EXPORT - -#endif // CTKWIDGETSEXPORT_H diff --git a/ctk/ctkWidgetsUtils.cpp b/ctk/ctkWidgetsUtils.cpp deleted file mode 100644 index 3deb88d..0000000 --- a/ctk/ctkWidgetsUtils.cpp +++ /dev/null @@ -1,115 +0,0 @@ -/*========================================================================= - - Library: CTK - - Copyright (c) Kitware Inc. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0.txt - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -=========================================================================*/ - -// Qt includes -#include -#include -//#include -#include -#include - -// ctkWidgets includes -#include "ctkWidgetsUtils.h" - -//---------------------------------------------------------------------------- -QString ctk::base64HTMLImageTagSrc(const QImage& image) -{ - QByteArray byteArray; - QBuffer buffer(&byteArray); - buffer.open(QIODevice::WriteOnly); - image.save(&buffer, "PNG"); - return QString("data:image/png;base64,%1") - .arg(QString(buffer.data().toBase64())); -} - -//---------------------------------------------------------------------------- -//QImage ctk::grabWidget(QWidget* widget, QRect rectangle) -//{ -// if (!widget) -// { -// return QImage(); -// } -// if (!rectangle.isValid()) -// { -// // Let Qt trigger layout mechanism and compute widget size. -// rectangle = QRect(0,0,-1,-1); -// } -//#if (QT_VERSION < QT_VERSION_CHECK(5, 0, 0)) -// QPixmap widgetPixmap = QPixmap::grabWidget(widget, rectangle); -//#else -// QPixmap widgetPixmap = widget->grab(rectangle); -//#endif -// QImage widgetImage = widgetPixmap.toImage(); -// QPainter painter; -// painter.begin(&widgetImage); -// foreach(QGLWidget* glWidget, widget->findChildren()) -// { -// if (!glWidget->isVisible()) -// { -// continue; -// } -// QRect subWidgetRect = QRect(glWidget->mapTo(widget, QPoint(0,0)), glWidget->size()); -// if (!rectangle.intersects(subWidgetRect)) -// { -// continue; -// } -// QImage subImage = glWidget->grabFrameBuffer(); -// painter.drawImage(subWidgetRect, subImage); -// } -// painter.end(); -// return widgetImage; -//} - -//---------------------------------------------------------------------------- -QImage ctk::kwIconToQImage(const unsigned char *data, int width, int height, int pixelSize, unsigned int bufferLength, int options) -{ - Q_UNUSED(options); // not yet supported - - QByteArray imageData = QByteArray::fromRawData( - reinterpret_cast(data), bufferLength); - unsigned int expectedLength = width * height * pixelSize; - // Start with a zlib header ? If not, then it must be base64 encoded - if (bufferLength != expectedLength && - static_cast(imageData[0]) != 0x78 && - static_cast(imageData[1]) != 0xDA) - { - imageData = QByteArray::fromBase64(imageData); - bufferLength = imageData.size(); - } - - if (bufferLength != expectedLength && - static_cast(imageData[0]) == 0x78 && - static_cast(imageData[1]) == 0xDA) - { - imageData.prepend(static_cast((expectedLength >> 0) & 0xFF)); - imageData.prepend(static_cast((expectedLength >> 8) & 0xFF)); - imageData.prepend(static_cast((expectedLength >> 16) & 0xFF)); - imageData.prepend(static_cast((expectedLength >> 24) & 0xFF)); - imageData = qUncompress(imageData); - } - QImage image(reinterpret_cast(imageData.data()), - width, height, width * pixelSize, - pixelSize == 4 ? QImage::Format_ARGB32 : QImage::Format_RGB888); - if (pixelSize == 4) - { - return image.rgbSwapped(); - } - return image.copy(); -} diff --git a/ctk/ctkWidgetsUtils.h b/ctk/ctkWidgetsUtils.h deleted file mode 100644 index bf31222..0000000 --- a/ctk/ctkWidgetsUtils.h +++ /dev/null @@ -1,53 +0,0 @@ -/*========================================================================= - - Library: CTK - - Copyright (c) Kitware Inc. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0.txt - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - -=========================================================================*/ - -#ifndef __ctkWidgetsUtils_h -#define __ctkWidgetsUtils_h - -// Qt includes -#include -#include -class QImage; - -#include "ctkWidgetsExport.h" - -namespace ctk { -/// -/// \ingroup Widgets -/// Create a base 64 image tag. Can be used that way: -/// QString("").arg(base64HTMLImageTagSrc(myImage); -QString CTK_WIDGETS_EXPORT base64HTMLImageTagSrc(const QImage& image); - -/// -/// \ingroup Widgets -/// Grab the contents of a QWidget and all its children. -/// Handle correctly the case of QGLWidgets. -/// \sa QWidget::grab -QImage CTK_WIDGETS_EXPORT grabWidget(QWidget* widget, QRect rectangle = QRect()); - -/// -/// \ingroup Widgets -/// Convert an KWidget encoded image into a QImage -/// The data can be base64 encoded and/or zlib compressed. -QImage CTK_WIDGETS_EXPORT kwIconToQImage(const unsigned char *data, int width, int height, int pixelSize, unsigned int bufferLength, int options = 0); - -} - -#endif diff --git a/pglab/ManagedPage.h b/pglab/ManagedPage.h index 0f89488..c0ed38b 100644 --- a/pglab/ManagedPage.h +++ b/pglab/ManagedPage.h @@ -3,6 +3,9 @@ #include +/// Base class for widgets that are used as on the tabs in DatabaseWindow +/// if a widget does not inherit from managed pase DatabaseWindow will +/// fallback on default behaviour. class ManagedPage: public QWidget { Q_OBJECT @@ -11,6 +14,7 @@ public: virtual ~ManagedPage() {} + /// Tells DatabaseWindow if it is ok to close this tab virtual bool CanClose(bool prompt_user) = 0; }; diff --git a/pglab/Module.cpp b/pglab/Module.cpp deleted file mode 100644 index 58d3148..0000000 --- a/pglab/Module.cpp +++ /dev/null @@ -1,63 +0,0 @@ -#include "Module.h" -#include - -using namespace Leon; - - -void ModuleRegistry::registerModule(Module *module) -{ - modules.insert(module); -} - - - -ModuleRegistry& Leon::GetModuleRegistry() -{ - static ModuleRegistry registry; - return registry; -} - -Module::Module() = default; - -ModuleInstance::ModuleInstance() -{ - GetModuleRegistry().registerModule(this); -} - - -//class QueryModule: public ModuleInstance { -//public: -// QueryModule(); - -// virtual QString getName() const override; - -// virtual CommandContainer getCommands() const override; -//private: -//// CommandContainer commands; - -// void createNewQueryTab(); -//}; - -//QueryModule::QueryModule() -//{ -//// commands = { -//// std::make_shared>("New SQL file", "", createNewQueryTab) -//// ->setHint("") -//// ->setDescription("") -//// ->setShortCut(Qt::CTRL + Qt::Key_N) -//// ->addOnToolbar("standard", "") -//// ->setMenuPath("file") -//// }; -//} - -//QString QueryModule::getName() const -//{ -// return "Query Module"; -//} - -////QueryModule::CommandContainer QueryModule::getCommands() const -////{ -//// return commands; -////} - -////QueryModule theQueryModuleInstance; diff --git a/pglab/Module.h b/pglab/Module.h deleted file mode 100644 index f8a3c22..0000000 --- a/pglab/Module.h +++ /dev/null @@ -1,120 +0,0 @@ -#ifndef MODULE_H -#define MODULE_H - -#include "AbstractCommand.h" -#include -#include -#include -#include -#include -#include - -class QAction; - -namespace Leon { - -class Module; - -class ModuleRegistry { -public: - using ModuleContainer = std::unordered_set; - using Iterator = ModuleContainer::iterator; - - Iterator begin() { return modules.begin(); } - Iterator end() { return modules.end(); } - - void registerModule(Module *module); - -private: - - ModuleContainer modules; -}; - -ModuleRegistry& GetModuleRegistry(); - -template -class Command: public AbstractCommand { -public: - Command(QString caption, QString iconpath, Func f); - Command& setHint(QString hint); - Command& setDescription(QString description); - Command& setShortCut(QKeySequence shortcut); - Command& addOnToolbar(QString toolbar, QString group); - Command& setMenuPath(QString menu); - - - // action = new QAction(QIcon(":/icons/script_save.png"), tr("Save SQL"), this); - // action->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_S)); - // connect(action, &QAction::triggered, this, &QueryTab::save); - // actions.push_back(action); -private: - mutable QAction *action = nullptr; -}; - - -/// Abstract interface for retrieving information about a subsystem -/// -/// Each module should derive a class From ModuleInstance and implement -/// the abstract methods declared in this interface. Don't do to much in your constructor -/// as it might be called very early in the startup of the program -class Module -{ -public: - using AbstractCommandSptr = std::shared_ptr; - using CommandContainer = std::vector; - - Module(); - - // getGlobalActions - virtual QString getName() const = 0; - - virtual CommandContainer getCommands() const = 0; -}; - -/// Adds auto registration to Module so not each -/// module has to implement registration -class ModuleInstance: public Module { -protected: - ModuleInstance(); -}; - - -class Path { -public: - explicit Path(QString p) - { - int ofs = 0; - if (p.isEmpty()) - return; - - if (p[0] == '/') - ++ofs; - - while (true) { - int i = p.indexOf('/', ofs); - if (i >= ofs) { - path.push_back(p.mid(ofs, i - ofs)); - ofs = i+1; - } - else { - path.push_back(p.right(ofs)); - break; - } - } - } - - int getDepth() const { return path.size(); } - QString getElem(int i) const { return path.at(i); } -private: - using PathContainer = boost::container::small_vector; - - PathContainer path; -}; - - - - - -} - -#endif // MODULE_H diff --git a/pglab/NamespaceFilterWidget.cpp b/pglab/NamespaceFilterWidget.cpp deleted file mode 100644 index 79f8d88..0000000 --- a/pglab/NamespaceFilterWidget.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#include "NamespaceFilterWidget.h" -#include "ui_NamespaceFilterWidget.h" - -#include "NamespaceItemModel.h" - -NamespaceFilterWidget::NamespaceFilterWidget(QWidget *parent) : - QWidget(parent), - ui(new Ui::NamespaceFilterWidget) -{ - ui->setupUi(this); - - m_namespaceItemModel = new NamespaceItemModel(this); - ui->treeView->setModel(m_namespaceItemModel); - //ui->treeView->setModelColumn(0); -} - -NamespaceFilterWidget::~NamespaceFilterWidget() -{ - delete ui; -} - -void NamespaceFilterWidget::init(std::shared_ptr nsc) -{ - m_namespaceItemModel->init(nsc); - ui->treeView->expandAll(); -} - - -const NamespaceItemModel* NamespaceFilterWidget::getModel() const -{ - return m_namespaceItemModel; -} - diff --git a/pglab/NamespaceFilterWidget.h b/pglab/NamespaceFilterWidget.h deleted file mode 100644 index ee2abd6..0000000 --- a/pglab/NamespaceFilterWidget.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef NAMESPACEFILTERWIDGET_H -#define NAMESPACEFILTERWIDGET_H - -#include "Pgsql_Declare.h" -#include -#include -#include - -namespace Ui { - class NamespaceFilterWidget; -} - -class NamespaceItemModel; -class PgNamespaceContainer; - -class NamespaceFilterWidget : public QWidget -{ - Q_OBJECT - -public: - explicit NamespaceFilterWidget(QWidget *parent = 0); - ~NamespaceFilterWidget(); - - void init(std::shared_ptr nsc); - - const NamespaceItemModel* getModel() const; - -//signals: -// void onFilterChange(); - -private: - Ui::NamespaceFilterWidget *ui; - NamespaceItemModel *m_namespaceItemModel = nullptr; -}; - -#endif // NAMESPACEFILTERWIDGET_H diff --git a/pglab/NamespaceFilterWidget.ui b/pglab/NamespaceFilterWidget.ui deleted file mode 100644 index bd221d7..0000000 --- a/pglab/NamespaceFilterWidget.ui +++ /dev/null @@ -1,31 +0,0 @@ - - - NamespaceFilterWidget - - - - 0 - 0 - 698 - 611 - - - - Form - - - - - - - - - false - - - - - - - - diff --git a/pglab/NotificationListWidget.cpp b/pglab/NotificationListWidget.cpp deleted file mode 100644 index cb83182..0000000 --- a/pglab/NotificationListWidget.cpp +++ /dev/null @@ -1,9 +0,0 @@ -#include "NotificationListWidget.h" -#include - - -NotificationListWidget::NotificationListWidget() - : m_notificationList(new QListView(this)) -{ - -} diff --git a/pglab/NotificationListWidget.h b/pglab/NotificationListWidget.h deleted file mode 100644 index 2d9d097..0000000 --- a/pglab/NotificationListWidget.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef NOTIFICATIONLISTWIDGET_H -#define NOTIFICATIONLISTWIDGET_H - -#include - -class QListView; -class QTextEdit; -class Notification; -class NotificationListModel; - -class NotificationListWidget: QWidget { -public: - NotificationListWidget(); - -private: - QListView *m_notificationList = nullptr; - QTextEdit *m_detailMessage; - NotificationListModel *m_notificationListModel = nullptr; - -}; - -#endif // NOTIFICATIONLISTWIDGET_H diff --git a/pglab/NotificationModel.cpp b/pglab/NotificationModel.cpp deleted file mode 100644 index 9c0958e..0000000 --- a/pglab/NotificationModel.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#include "NotificationModel.h" -#include "NotificationService.h" - -NotificationModel::NotificationModel() -{ - -} - -int NotificationModel::rowCount(const QModelIndex &parent) const -{ - return m_notifications->count(); -} - -int NotificationModel::columnCount(const QModelIndex &) const -{ - return static_cast(Col::Count); -} - -QVariant NotificationModel::data(const QModelIndex &index, int role) const -{ - return {}; -} - -QVariant NotificationModel::headerData(int section, Qt::Orientation orientation, int role) const -{ - return {}; -} diff --git a/pglab/NotificationModel.h b/pglab/NotificationModel.h deleted file mode 100644 index 68cbcc7..0000000 --- a/pglab/NotificationModel.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef NOTIFICATIONMODEL_H -#define NOTIFICATIONMODEL_H - -#include -#include - -class NotificationService; - -class NotificationModel: public QAbstractTableModel { -public: - enum class Col { - Severity, - ShortMessage, - DetailMessage, - - Count // SHOULD BE LAST - }; - - NotificationModel(); - - virtual int rowCount(const QModelIndex &parent = {}) const override; - virtual int columnCount(const QModelIndex &parent = {}) const override; - - virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; - virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; - -private: - std::shared_ptr m_notifications; -}; - -#endif // NOTIFICATIONMODEL_H diff --git a/pglab/NotificationService.cpp b/pglab/NotificationService.cpp deleted file mode 100644 index 54611f9..0000000 --- a/pglab/NotificationService.cpp +++ /dev/null @@ -1,59 +0,0 @@ -#include "NotificationService.h" - -namespace { - - class registerMetaTypes { - public: - registerMetaTypes() - { - qRegisterMetaType(); - qRegisterMetaType(); - } - } registerMetaTypes_instance; - -} - -std::shared_ptr NotificationService::s_instance; - -std::shared_ptr NotificationService::instance() -{ - if (!s_instance) { - s_instance = std::make_shared(); - } - return s_instance; -} - -NotificationService::NotificationService() -{ -} - -void NotificationService::addInformational(const QString &msg, const QString &detail) -{ - add(NotificationSeverity::Informational, msg, detail); -} - -void NotificationService::addWarning(const QString &msg, const QString &detail) -{ - add(NotificationSeverity::Warning, msg, detail); -} - -void NotificationService::addError(const QString &msg, const QString &detail) -{ - add(NotificationSeverity::Error, msg, detail); -} - -void NotificationService::add(NotificationSeverity severity, const QString &msg, const QString &detail) -{ -// m_notifications.push_back({ severity, msg, detail }); -} - -int NotificationService::count() const -{ - return m_notifications.size(); -} - -const Notification& NotificationService::notification(int index) -{ - return m_notifications.at(index); -} - diff --git a/pglab/NotificationService.h b/pglab/NotificationService.h deleted file mode 100644 index 43d2fd4..0000000 --- a/pglab/NotificationService.h +++ /dev/null @@ -1,65 +0,0 @@ -#ifndef NOTIFICATIONSERVICE_H -#define NOTIFICATIONSERVICE_H - -#include -#include -#include -#include -#include - -enum NotificationSeverity { - Informational, ///< Use for notifications of succesful completion and other things the user likely does not need to be bothered with - Warning, ///< - Error, ///< Use for failures like not being able to save the users data - Critical ///< Don't think you should ever need this in a correct program.... -}; - -class Notification { -public: - Notification() = default; - Notification(int64_t id, NotificationSeverity severity, const QString &msg, const QString &detail = {}); - - int64_t id() const { return m_id; } - NotificationSeverity severity() const { return m_severity; } - QString shortMessage() const { return m_shortMessage; } - QString detailMessage() const { return m_detailMessage; } - -private: - int64_t m_id = 0; - NotificationSeverity m_severity = NotificationSeverity::Informational; - QString m_shortMessage; - QString m_detailMessage; - -}; - -class NotificationService: public QObject { - Q_OBJECT -public: - static std::shared_ptr instance(); - - NotificationService(); - - void addInformational(const QString &msg, const QString &detail = {}); - void addWarning(const QString &msg, const QString &detail = {}); - void addError(const QString &msg, const QString &detail = {}); - void add(NotificationSeverity severity, const QString &msg, const QString &detail = {}); - - /// Returns the number of notifications - int count() const; - const Notification& notification(int index); - -signals: - void onNewNotification(const Notification ¬ification); -private: - static std::shared_ptr s_instance; - - using NotificationContainer = QVector; - - std::shared_mutex m_nofiticationsMutex; - NotificationContainer m_notifications; -}; - -Q_DECLARE_METATYPE(NotificationSeverity) -Q_DECLARE_METATYPE(Notification) - -#endif // NOTIFICATIONSERVICE_H diff --git a/pglab/pglab.pro b/pglab/pglab.pro index fa07353..916109e 100644 --- a/pglab/pglab.pro +++ b/pglab/pglab.pro @@ -63,9 +63,6 @@ SOURCES += main.cpp\ ConnectionConfigurationWidget.cpp \ ConnectionController.cpp \ ManagedPage.cpp \ - NotificationListWidget.cpp \ - NotificationModel.cpp \ - NotificationService.cpp \ PgDumpOutputHighlighter.cpp \ CreateDatabaseDialog.cpp \ ConnectionManagerWindow.cpp \ @@ -79,9 +76,7 @@ SOURCES += main.cpp\ OpenDatabase.cpp \ ProcessStdioWidget.cpp \ ResultTableModelUtil.cpp \ - NamespaceFilterWidget.cpp \ NamespaceItemModel.cpp \ - Module.cpp \ PropertyProxyModel.cpp \ CodeGenerator.cpp \ UserConfiguration.cpp \ @@ -140,9 +135,6 @@ HEADERS += \ ConnectionController.h \ IDatabaseWindow.h \ ManagedPage.h \ - NotificationListWidget.h \ - NotificationModel.h \ - NotificationService.h \ PgDumpOutputHighlighter.h \ CreateDatabaseDialog.h \ ConnectionManagerWindow.h \ @@ -156,9 +148,7 @@ HEADERS += \ OpenDatabase.h \ ProcessStdioWidget.h \ ResultTableModelUtil.h \ - NamespaceFilterWidget.h \ NamespaceItemModel.h \ - Module.h \ AbstractCommand.h \ PropertyProxyModel.h \ CustomDataRole.h \ @@ -182,7 +172,6 @@ FORMS += \ TuplesResultWidget.ui \ querytool/QueryTab.ui \ ProcessStdioWidget.ui \ - NamespaceFilterWidget.ui \ crud/CrudTab.ui \ CodeGenerator.ui \ widgets/SingleRecordWidget.ui diff --git a/pglab/stopwatch.cpp b/pglab/stopwatch.cpp index 2a62ebf..760684e 100644 --- a/pglab/stopwatch.cpp +++ b/pglab/stopwatch.cpp @@ -23,10 +23,6 @@ void StopWatch::stop() void StopWatch::updateTimer() { -// auto nu = std::chrono::steady_clock::now(); -// std::chrono::duration diff = nu - m_startTime; -// elapsedTime = diff; -// m_timeElapsedLabel->setText(msfloatToHumanReadableString(diff.count())); if (m_elapsed.isValid()) { qint64 ms = m_elapsed.elapsed(); if (m_output) { diff --git a/pglabAll.pro b/pglabAll.pro index c6dfff3..8631a5e 100644 --- a/pglabAll.pro +++ b/pglabAll.pro @@ -3,12 +3,11 @@ TEMPLATE = subdirs DEFINES += BOOST_ENABLE_ASSERT_HANDLER SUBDIRS += core \ - ctk \ pgsql \ - pglablib \ + pglablib \ pglab -pglab.depends = core ctk pgsql pglablib +pglab.depends = core pgsql pglablib pgsql.depends = core pglablib.depends = core pgsql tests.depends = core pgsql pglablib diff --git a/pglablib/ASyncDBConnection.cpp b/pglablib/ASyncDBConnection.cpp index 13684a0..8580428 100644 --- a/pglablib/ASyncDBConnection.cpp +++ b/pglablib/ASyncDBConnection.cpp @@ -41,26 +41,16 @@ namespace { class ASyncDBConnectionThread { public: using t_CommandQueue = std::queue; -// struct { -// std::mutex m_mutex; -// on_state_callback m_func; -// } m_stateCallback; -// struct { -// std::mutex m_mutex; -// on_notice_callback m_func; -// } m_noticeCallback; struct t_Command { std::mutex m_mutex; t_CommandQueue m_queue; - //std::condition_variable m_newEvent; Win32Event m_newEvent; t_Command() : m_newEvent(Win32Event::Reset::Auto, Win32Event::Initial::Clear) {} } m_commandQueue; -// std::string m_initString; ConnectionConfig m_config; ASyncDBConnection::State m_state = ASyncDBConnection::State::NotConnected; @@ -274,20 +264,7 @@ void ASyncDBConnectionThread::doStateCallback(ASyncDBConnection::State state) void ASyncDBConnectionThread::waitForAndSendCommand() { -#if false - using namespace std::chrono_literals; - // lock the data - std::unique_lock lk(m_commandQueue.m_mutex); - if (m_commandQueue.m_queue.empty()) { - // no data wait till there is data - m_commandQueue.m_newEvent.wait_for(lk, 1000ms); - // can we use the predicate to reimplement the stop function???, []{return ready;}); - - } - doNewCommand(); - -#else - WaitHandleList whl; + WaitHandleList whl; auto wait_result_new_command = whl.add(m_commandQueue.m_newEvent); auto wait_result_stop = whl.add(m_stopEvent); @@ -301,9 +278,8 @@ void ASyncDBConnectionThread::waitForAndSendCommand() if (res == wait_result_new_command) { doNewCommand(); } - if (res == wait_result_stop) - return; -#endif + // Note if it was stop we can just return and function + // above will stop looping because terminateRequested has been set too by stop } void ASyncDBConnectionThread::doNewCommand() @@ -365,30 +341,6 @@ bool ASyncDBConnectionThread::consumeResultInput() void ASyncDBConnectionThread::waitForResult() { -#if false - int sock = m_connection.socket(); - - fd_set readfds; - timeval timeout; - bool finished = false; - while (!finished && !terminateRequested) { - FD_ZERO(&readfds); - FD_SET(sock, &readfds); - - timeout.tv_sec = 5; - timeout.tv_usec = 0; - - int select_result = select(sock + 1, &readfds, nullptr, nullptr, &timeout); - if (select_result > 0) { - if (FD_ISSET(sock, &readfds)) { - if (consumeResultInput()) { - finished = true; - } - } - } - - } -#else SOCKET sock = static_cast(m_connection.socket()); Win32Event socket_event(Win32Event::Reset::Manual, Win32Event::Initial::Clear); @@ -426,18 +378,10 @@ void ASyncDBConnectionThread::waitForResult() finished = true; } } // end while - // When last result received, remove command from queue -#endif } void ASyncDBConnectionThread::processNotice(const PGresult *result) { -// Pgsql::Result res(result); -// std::lock_guard lg(m_noticeCallback.m_mutex); -// if (m_noticeCallback.m_func) { -// Pgsql::ErrorDetails details = Pgsql::ErrorDetails::createErrorDetailsFromPGresult(result); -// m_noticeCallback.m_func(details); -// } Pgsql::ErrorDetails details = Pgsql::ErrorDetails::createErrorDetailsFromPGresult(result); Q_EMIT asyncConnObject->onNotice(details); } @@ -486,13 +430,10 @@ void ASyncDBConnection::doStateCallback(State state) void ASyncDBConnection::closeConnection() { -// doStateCallback(State::NotConnected); - // TODO also send cancel??? m_threadData->stop(); if (m_thread.joinable()) { m_thread.join(); } - } bool ASyncDBConnection::send(const std::string &command, on_result_callback on_result) diff --git a/pglablib/ASyncDBConnection.h b/pglablib/ASyncDBConnection.h index 45f568b..edec34d 100644 --- a/pglablib/ASyncDBConnection.h +++ b/pglablib/ASyncDBConnection.h @@ -48,28 +48,11 @@ public: bool send(const std::string &command, on_result_callback on_result); bool send(const std::string &command, Pgsql::Params params, on_result_callback on_result); - /** This version of send uses the signal onQueryResult and onQueryError to report back - * the completion of the query. - */ -// bool send(const std::string &command, Pgsql::Params params = Pgsql::Params()) -// { -// return send(command, params, [this] (Expected> res, qint64) { -// if (res.valid()) { -// emit onQueryResult(res.get()); -// } -// else { -// emit onQueryError(); -// } -// }); -// } - bool cancel(); Q_SIGNALS: void onStateChanged(ASyncDBConnection::State state); void onNotice(Pgsql::ErrorDetails notice); -// void onQueryResult(std::shared_ptr result); -// void onQueryError(); private: Pgsql::Connection m_connection; diff --git a/pglablib/ConnectionConfig.cpp b/pglablib/ConnectionConfig.cpp index be56ab7..7356108 100644 --- a/pglablib/ConnectionConfig.cpp +++ b/pglablib/ConnectionConfig.cpp @@ -28,23 +28,21 @@ namespace { QString SslModeToString(SslMode sm) { - for (auto e : SslModeStringTable) { - if (e.mode == sm) { + for (auto e : SslModeStringTable) + if (e.mode == sm) return QString::fromUtf8(e.string); - } - } + return {}; } SslMode StringToSslMode(QString s) { SslMode result = SslMode::allow; - for (auto e : SslModeStringTable) { - if (e.string == s) { + for (auto e : SslModeStringTable) + if (e.string == s) result = e.mode; - } - } - return {}; + + return {}; } ConnectionConfig::ConnectionConfig() @@ -64,7 +62,8 @@ void ConnectionConfig::setParent(ConnectionGroup *grp) void ConnectionConfig::setUuid(const QUuid &uuid) { - if (uuid != m_uuid) { + if (uuid != m_uuid) + { m_dirty = true; m_uuid = uuid; } @@ -79,7 +78,8 @@ const QUuid &ConnectionConfig::uuid() const void ConnectionConfig::setName(const QString& desc) { - if (m_name != desc) { + if (m_name != desc) + { m_dirty = true; m_name = std::move(desc); } @@ -92,7 +92,8 @@ const QString& ConnectionConfig::name() const void ConnectionConfig::setHost(const QString& host) { - if (m_host != host) { + if (m_host != host) + { m_dirty = true; m_host = std::move(host); } @@ -105,7 +106,8 @@ const QString& ConnectionConfig::host() const void ConnectionConfig::setHostAddr(const QString &v) { - if (m_hostaddr != v) { + if (m_hostaddr != v) + { m_dirty = true; m_hostaddr = std::move(v); } @@ -118,7 +120,8 @@ const QString& ConnectionConfig::hostAddr() const void ConnectionConfig::setPort(unsigned short port) { - if (m_port != port) { + if (m_port != port) + { m_dirty = true; m_port = port; } @@ -131,7 +134,8 @@ unsigned short ConnectionConfig::port() const void ConnectionConfig::setUser(const QString& v) { - if (m_user != v) { + if (m_user != v) + { m_dirty = true; m_user = v; } @@ -145,7 +149,8 @@ const QString& ConnectionConfig::user() const void ConnectionConfig::setPassword(const QString& v) { - if (m_password != v) { + if (m_password != v) + { m_dirty = true; m_password = v; } @@ -158,7 +163,8 @@ const QString& ConnectionConfig::password() const void ConnectionConfig::setDbname(const QString& v) { - if (m_dbname != v) { + if (m_dbname != v) + { m_dirty = true; m_dbname = v; } @@ -171,7 +177,8 @@ const QString& ConnectionConfig::dbname() const void ConnectionConfig::setSslMode(SslMode m) { - if (m_sslMode != m) { + if (m_sslMode != m) + { m_dirty = true; m_sslMode = m; } @@ -184,7 +191,8 @@ SslMode ConnectionConfig::sslMode() const void ConnectionConfig::setSslCert(const QString& v) { - if (m_sslCert != v) { + if (m_sslCert != v) + { m_dirty = true; m_sslCert = std::move(v); } @@ -197,7 +205,8 @@ const QString& ConnectionConfig::sslCert() const void ConnectionConfig::setSslKey(const QString& v) { - if (m_sslKey != v) { + if (m_sslKey != v) + { m_dirty = true; m_sslKey = std::move(v); } @@ -210,7 +219,8 @@ const QString& ConnectionConfig::sslKey() const void ConnectionConfig::setSslRootCert(const QString& v) { - if (m_sslRootCert != v) { + if (m_sslRootCert != v) + { m_dirty = true; m_sslRootCert = std::move(v); } @@ -223,7 +233,8 @@ const QString& ConnectionConfig::sslRootCert() const void ConnectionConfig::setSslCrl(const QString& v) { - if (m_sslCrl != v) { + if (m_sslCrl != v) + { m_dirty = true; m_sslCrl = std::move(v); } @@ -234,32 +245,6 @@ const QString& ConnectionConfig::sslCrl() const return m_sslCrl; } - -//const char * const * ConnectionConfig::getKeywords() const -//{ -// return s_keywords.data(); -//} - -//const char * const * ConnectionConfig::getValues() const -//{ -// m_values.resize(s_keywords.size(), nullptr); -// m_values[0] = valuePtr(m_host); -// m_values[1] = valuePtr(m_hostaddr); -// m_values[2] = valuePtr(m_port); -// m_values[3] = valuePtr(m_user); -// m_values[4] = valuePtr(m_password); -// m_values[5] = valuePtr(m_dbname); -// m_values[6] = valuePtr(m_sslMode); -// m_values[7] = valuePtr(m_sslCert); -// m_values[8] = valuePtr(m_sslKey); -// m_values[9] = valuePtr(m_sslRootCert); -// m_values[10] = valuePtr(m_sslCrl); -// m_values[11] = "utf8"; -// m_values[12] = valuePtr(m_applicationName); - -// return m_values.data(); -//} - bool ConnectionConfig::isSameDatabase(const ConnectionConfig &rhs) const { return m_host == rhs.m_host @@ -298,40 +283,32 @@ void ConnectionConfig::setEncodedPassword(const QByteArray &encodedPassword) m_encodedPassword = encodedPassword; } -//void ConnectionConfig::write(QDataStream &out) const -//{ -//// out << -//} - -//void ConnectionConfig::read(QDataStream &in) -//{ - -//} - QString ConnectionConfig::escapeConnectionStringValue(const QString &value) { bool contains_spaces = false; int escapes = 0; for (auto&& c : value) - if (c == ' ') contains_spaces = true; - else if (c == '\'' || c == '\\') ++escapes; + if (c == ' ') + contains_spaces = true; + else if (c == '\'' || c == '\\') + ++escapes; - if (contains_spaces || escapes > 0 || value.length() == 0) { + if (contains_spaces || escapes > 0 || value.length() == 0) + { QString result; result.reserve(2 + value.length() + escapes); result += '\''; - for (auto&& c : value) { - if (c == '\'' || c == '\\') { + for (auto&& c : value) + { + if (c == '\'' || c == '\\') result += '\\'; - } result += c; } result += '\''; return result; } - else { + else return value; - } } QString ConnectionConfig::connectionString() const @@ -349,19 +326,23 @@ QString ConnectionConfig::connectionString() const s += escapeConnectionStringValue(m_dbname); s += " sslmode="; s += SslModeToString(m_sslMode); - if (!m_sslCert.isEmpty()) { + if (!m_sslCert.isEmpty()) + { s += " sslcert="; s += escapeConnectionStringValue(m_sslCert); } - if (!m_sslKey.isEmpty()) { + if (!m_sslKey.isEmpty()) + { s += " sslkey="; s += escapeConnectionStringValue(m_sslKey); } - if (!m_sslRootCert.isEmpty()) { + if (!m_sslRootCert.isEmpty()) + { s += " sslrootcrt="; s += escapeConnectionStringValue(m_sslRootCert); } - if (!m_sslCrl.isEmpty()) { + if (!m_sslCrl.isEmpty()) + { s += " sslCrl="; s += escapeConnectionStringValue(m_sslCrl); } @@ -369,55 +350,9 @@ QString ConnectionConfig::connectionString() const s += " application_name="; s += escapeConnectionStringValue(m_applicationName); - // "host", "hostaddr", "port", "user", "password", "dbname", - // "sslmode", "sslcert", "sslkey", "sslrootcrt", "sslcrl", - // "client_encoding", "application_name", nullptr }; - // m_values[0] = valuePtr(m_host); - // m_values[1] = valuePtr(m_hostaddr); - // m_values[2] = valuePtr(m_port); - // m_values[3] = valuePtr(m_user); - // m_values[4] = valuePtr(m_password); - // m_values[5] = valuePtr(m_dbname); - // m_values[6] = valuePtr(m_sslMode); - // m_values[7] = valuePtr(m_sslCert); - // m_values[8] = valuePtr(m_sslKey); - // m_values[9] = valuePtr(m_sslRootCert); - // m_values[10] = valuePtr(m_sslCrl); - // m_values[11] = "utf8"; - // m_values[12] = valuePtr(m_applicationName); - return s; } -/* - - PGHOST behaves the same as the host connection parameter. - PGHOSTADDR behaves the same as the hostaddr connection parameter. This can be set instead of or in addition to PGHOST to avoid DNS lookup overhead. - PGPORT behaves the same as the port connection parameter. - PGDATABASE behaves the same as the dbname connection parameter. - PGUSER behaves the same as the user connection parameter. - PGPASSWORD behaves the same as the password connection parameter. Use of this environment variable is not recommended for security reasons, as some operating systems allow non-root users to see process environment variables via ps; instead consider using the ~/.pgpass file (see Section 31.15). - PGPASSFILE specifies the name of the password file to use for lookups. If not set, it defaults to ~/.pgpass (see Section 31.15). - PGSERVICE behaves the same as the service connection parameter. - PGSERVICEFILE specifies the name of the per-user connection service file. If not set, it defaults to ~/.pg_service.conf (see Section 31.16). - PGREALM sets the Kerberos realm to use with PostgreSQL, if it is different from the local realm. If PGREALM is set, libpq applications will attempt authentication with servers for this realm and use separate ticket files to avoid conflicts with local ticket files. This environment variable is only used if GSSAPI authentication is selected by the server. - PGOPTIONS behaves the same as the options connection parameter. - PGAPPNAME behaves the same as the application_name connection parameter. - PGSSLMODE behaves the same as the sslmode connection parameter. - PGREQUIRESSL behaves the same as the requiressl connection parameter. - PGSSLCOMPRESSION behaves the same as the sslcompression connection parameter. - PGSSLCERT behaves the same as the sslcert connection parameter. - PGSSLKEY behaves the same as the sslkey connection parameter. - PGSSLROOTCERT behaves the same as the sslrootcert connection parameter. - PGSSLCRL behaves the same as the sslcrl connection parameter. - PGREQUIREPEER behaves the same as the requirepeer connection parameter. - PGKRBSRVNAME behaves the same as the krbsrvname connection parameter. - PGGSSLIB behaves the same as the gsslib connection parameter. - PGCONNECT_TIMEOUT behaves the same as the connect_timeout connection parameter. - PGCLIENTENCODING behaves the same as the client_encoding connection parameter. - - */ - void ConnectionConfig::writeToEnvironment(QProcessEnvironment &env) const { strToEnv(env, "PGHOST", m_host); @@ -464,16 +399,3 @@ void ConnectionGroup::update(int idx, const ConnectionConfig &cc) *node = cc; node->setParent(this); } - -//QDataStream &operator<<(QDataStream &out, const ConnectionConfig &cc) -//{ -// cc.write(out); -// return out; -//} - -//QDataStream &operator>>(QDataStream &in, ConnectionConfig &cc) -//{ -// //in>>myObj.uId>>myObj.passwd>>myObj.statusType; -// cc.read(in); -// return in; -//} diff --git a/pgsql/ArrayParser.cpp b/pgsql/ArrayParser.cpp index 4d93b6b..1f29a61 100644 --- a/pgsql/ArrayParser.cpp +++ b/pgsql/ArrayParser.cpp @@ -25,17 +25,21 @@ ArrayParser::NextElemResult ArrayParser::GetNextElem() { // We should be at the start of an element or at the end of the array NextElemResult result = { false, std::nullopt }; - if (pos < end && *pos != ArrayEnd) { - if (*pos == Quote) { + if (pos < end && *pos != ArrayEnd) + { + if (*pos == Quote) + { // parse quoted value, slow path removing escapes parseQuotedValue(); result.ok = true; result.value = std::string_view(temp); } - else { + else + { // parse unquoted value, fast path no escapes const char *start = pos; - while (pos < end && *pos != Seperator && *pos != ArrayEnd) ++pos; + while (pos < end && *pos != Seperator && *pos != ArrayEnd) + ++pos; if (pos == end) // reached end of data shouldn't happen throw std::runtime_error("Invalid input"); @@ -47,7 +51,6 @@ ArrayParser::NextElemResult ArrayParser::GetNextElem() // move to start of next element ++pos; // skip seperator skipWhitespace(); - } return result; } @@ -62,12 +65,15 @@ void ArrayParser::parseQuotedValue() if (pos == end) throw std::runtime_error("Invalid input"); - while (pos < end) { - if (*pos == Quote) { + while (pos < end) + { + if (*pos == Quote) + { ++pos; break; } - if (*pos == '\\') { + if (*pos == '\\') + { ++pos; if (pos == end) throw std::runtime_error("Invalid input"); @@ -84,9 +90,11 @@ void ArrayParser::initializeParse() // Test if non empty string (empty string is an empty array) // skipWhitespace(); - if (pos < end) { + if (pos < end) + { // first character should be opening brace - if (*pos != ArrayStart) { + if (*pos != ArrayStart) + { throw std::runtime_error("Unexpected input"); } ++pos; diff --git a/pgsql/Pgsql_Canceller.cpp b/pgsql/Pgsql_Canceller.cpp index aa93b7d..887f348 100644 --- a/pgsql/Pgsql_Canceller.cpp +++ b/pgsql/Pgsql_Canceller.cpp @@ -14,19 +14,18 @@ namespace Pgsql { Canceller& Canceller::operator=(Canceller&& rhs) { - if (m_cancel) { + if (m_cancel) PQfreeCancel(m_cancel); - } - m_cancel = rhs.m_cancel; + + m_cancel = rhs.m_cancel; rhs.m_cancel = nullptr; return *this; } Canceller::~Canceller() { - if (m_cancel) { + if (m_cancel) PQfreeCancel(m_cancel); - } } bool Canceller::cancel(std::string *error) @@ -34,9 +33,8 @@ namespace Pgsql { const int errbuf_size = 256; char errbuf[errbuf_size]; bool res = PQcancel(m_cancel, errbuf, errbuf_size); - if (!res && error) { + if (!res && error) *error = errbuf; - } return res; } diff --git a/pgsql/Pgsql_Connection.cpp b/pgsql/Pgsql_Connection.cpp index 0bf75f8..1122fc8 100644 --- a/pgsql/Pgsql_Connection.cpp +++ b/pgsql/Pgsql_Connection.cpp @@ -31,7 +31,8 @@ Connection& Connection::operator=(Connection &&rhs) void Connection::close() { - if (conn) { + if (conn) + { PQfinish(conn); conn = nullptr; } @@ -86,12 +87,10 @@ int Connection::socket() std::string Connection::getErrorMessage() const { std::string result; - if (conn) { + if (conn) result = PQerrorMessage(conn); - } - else { + else result = "no connection"; - } return result; } @@ -134,24 +133,22 @@ bool Connection::sendQueryParams(const char * command, const Params ¶ms) std::shared_ptr Connection::getResult() { PGresult *r = PQgetResult(conn); - if (r) { + if (r) + { throwError(r); return std::make_shared(r); } - else { + else return nullptr; - } } std::shared_ptr Connection::getResultNoThrow() { PGresult *r = PQgetResult(conn); - if (r) { + if (r) return std::make_shared(r); - } - else { + else return nullptr; - } } bool Connection::consumeInput() @@ -179,9 +176,8 @@ std::string Connection::escapeLiteral(const std::string_view &literal) std::unique_ptr result( PQescapeLiteral(conn, literal.data(), literal.length()), [](char*p) { if (p) PQfreemem(p); }); - if (result) { + if (result) return std::string(result.get()); - } throw std::runtime_error("escapeLiteral(string_view) failed"); } @@ -191,9 +187,8 @@ QString Connection::escapeLiteral(const QString &literal) std::unique_ptr result( PQescapeLiteral(conn, u8.data(), u8.length()), [](char*p) { if (p) PQfreemem(p); }); - if (result) { + if (result) return QString::fromUtf8(result.get()); - } throw std::runtime_error("escapeLiteral(QString) failed"); } @@ -202,9 +197,8 @@ std::string Connection::escapeIdentifier(const std::string_view &ident) std::unique_ptr result( PQescapeIdentifier(conn, ident.data(), ident.length()), [](char*p) { if (p) PQfreemem(p); }); - if (result) { + if (result) return std::string(result.get()); - } throw std::runtime_error("escapeIdentifier failed"); } @@ -214,9 +208,8 @@ QString Connection::escapeIdentifier(const QString &ident) std::unique_ptr result( PQescapeIdentifier(conn, u8.data(), u8.length()), [](char*p) { if (p) PQfreemem(p); }); - if (result) { + if (result) return QString::fromUtf8(result.get()); - } throw std::runtime_error("escapeIdentifier(QString) failed"); } @@ -234,44 +227,28 @@ QString Connection::getDBName() const void Connection::testForConnectionError(PGconn *conn) { std::string error_msg; - if (conn) { + if (conn) + { ConnStatusType status = PQstatus(conn); if (status == CONNECTION_OK) return; error_msg = PQerrorMessage(conn); } - else { + else error_msg = "Unknown connection failure (maybe out of memory?)"; - } throw PgConnectionError(error_msg); } void Connection::throwError(PGresult *result) const { auto state = PQresultStatus(result); - if (state == PGRES_BAD_RESPONSE) { - // communication problem - } - else if (state == PGRES_FATAL_ERROR) { + if (state == PGRES_BAD_RESPONSE) + ; // communication problem + else if (state == PGRES_FATAL_ERROR) + { auto details = Pgsql::ErrorDetails::createErrorDetailsFromPGresult(result); throw PgResultError(details); } } -//PGRES_EMPTY_QUERY = 0, /* empty query string was executed */ -//PGRES_COMMAND_OK, /* a query command that doesn't return -// * anything was executed properly by the -// * backend */ -//PGRES_TUPLES_OK, /* a query command that returns tuples was -// * executed properly by the backend, PGresult -// * contains the result tuples */ -//PGRES_COPY_OUT, /* Copy Out data transfer in progress */ -//PGRES_COPY_IN, /* Copy In data transfer in progress */ -//PGRES_BAD_RESPONSE, /* an unexpected response was recv'd from the -// * backend */ -//PGRES_NONFATAL_ERROR, /* notice or warning message */ -//PGRES_FATAL_ERROR, /* query failed */ -//PGRES_COPY_BOTH, /* Copy In/Out data transfer in progress */ -//PGRES_SINGLE_TUPLE /* single tuple from larger resultset */ - diff --git a/tests/pglabtests/pglabtests.pro b/tests/pglabtests/pglabtests.pro index 73c4847..3e8fb6c 100644 --- a/tests/pglabtests/pglabtests.pro +++ b/tests/pglabtests/pglabtests.pro @@ -27,8 +27,7 @@ SOURCES += main.cpp \ tst_CodeBuilder.cpp \ tst_NameManglingRules.cpp \ tst_TypeMappings.cpp \ - tst_Range.cpp \ - tst_SqlParser.cpp + tst_Range.cpp win32:CONFIG(release, debug|release): LIBS += -L$$OUT_PWD/../../core/release/ -lcore else:win32:CONFIG(debug, debug|release): LIBS += -L$$OUT_PWD/../../core/debug/ -lcore diff --git a/tests/pglabtests/tst_SqlParser.cpp b/tests/pglabtests/tst_SqlParser.cpp deleted file mode 100644 index fc89026..0000000 --- a/tests/pglabtests/tst_SqlParser.cpp +++ /dev/null @@ -1,30 +0,0 @@ -#include -#include -#include "SqlLexer.h" -#include "SqlParser.h" -#include "SqlAstSelect.h" -#include "PrintTo_Qt.h" - -using namespace testing; - - -TEST(SqlParser, emptyFile) -{ - QString input; - SqlLexer lexer(input, LexerState::Null); - SqlParser parser(lexer); - auto res = parser.parse(); - - ASSERT_TRUE(res == nullptr); -} - -//TEST(SqlParser, select) -//{ -// QString input("SELECT"); -// SqlLexer lexer(input, LexerState::Null); -// SqlParser parser(lexer); -// auto res = parser.parse(); - -// ASSERT_TRUE(res != nullptr); -// ASSERT_EQ(typeid(*res), typeid(SqlAst::Select)); -//}