ui: improvements proposed by Julian Mautner

* automatically expand active class
* increase arrow size
* return child nodes in autocompletions
* always return filters in autocompletions
This commit is contained in:
Eberhard Graether
2015-01-12 23:47:57 +01:00
parent 8242454104
commit 7596c699d6
13 changed files with 103 additions and 55 deletions
+1 -1
View File
@@ -190,7 +190,7 @@ std::shared_ptr<QtGraphNode> QtGraphView::createNodeRecursive(
} }
else else
{ {
newNode = std::make_shared<QtGraphNodeAccess>(node.accessType, node.expanded, node.invisibleSubNodeCount); newNode = std::make_shared<QtGraphNodeAccess>(node.accessType, node.isExpanded(), node.invisibleSubNodeCount);
} }
newNode->setPosition(node.position); newNode->setPosition(node.position);
+12 -7
View File
@@ -90,6 +90,11 @@ QtCorneredConnection::QtCorneredConnection(
, m_targetParentRect(targetParentRect) , m_targetParentRect(targetParentRect)
{ {
this->setAcceptHoverEvents(true); this->setAcceptHoverEvents(true);
m_ownerRect.x = m_ownerRect.x - 1;
m_ownerRect.z = m_ownerRect.z + 1;
m_targetRect.x = m_targetRect.x - 1;
m_targetRect.z = m_targetRect.z + 1;
} }
QtCorneredConnection::~QtCorneredConnection() QtCorneredConnection::~QtCorneredConnection()
@@ -214,8 +219,8 @@ void QtCorneredConnection::paint(QPainter *painter, const QStyleOptionGraphicsIt
} }
} }
int arrowLength = 3; int arrowLength = 5;
int arrowWidth = 6; int arrowWidth = 8;
QPointF arrow = poly.at(0) + QPointF((poly.at(0).x() - poly.at(1).x() > 0 ? -1 : 1) * arrowLength, -arrowWidth / 2); QPointF arrow = poly.at(0) + QPointF((poly.at(0).x() - poly.at(1).x() > 0 ? -1 : 1) * arrowLength, -arrowWidth / 2);
path.lineTo(arrow); path.lineTo(arrow);
@@ -410,7 +415,7 @@ void QtGraphEdge::updateLine()
break; break;
} }
m_child->setPen(QPen(color, getPenWidth())); m_child->setPen(QPen(color, getPenWidth(), Qt::SolidLine, Qt::RoundCap));
setIsActive(m_isActive); setIsActive(m_isActive);
} }
@@ -433,7 +438,7 @@ void QtGraphEdge::setIsActive(bool isActive)
else else
{ {
QPen p = m_child->pen(); QPen p = m_child->pen();
p.setWidth(getPenWidth() + 1); p.setWidthF(getPenWidth() + 1);
m_child->setPen(p); m_child->setPen(p);
} }
this->setZValue(getZValue(isActive)); this->setZValue(getZValue(isActive));
@@ -447,7 +452,7 @@ void QtGraphEdge::setIsActive(bool isActive)
else else
{ {
QPen p = m_child->pen(); QPen p = m_child->pen();
p.setWidth(getPenWidth()); p.setWidthF(getPenWidth());
m_child->setPen(p); m_child->setPen(p);
} }
this->setZValue(getZValue(isActive)); this->setZValue(getZValue(isActive));
@@ -530,13 +535,13 @@ int QtGraphEdge::getZValue(bool active) const
return 1; return 1;
} }
int QtGraphEdge::getPenWidth() const float QtGraphEdge::getPenWidth() const
{ {
if (isAggregation()) if (isAggregation())
{ {
return getAggregationCount() + 1; return getAggregationCount() + 1;
} }
return 1; return 1.5;
} }
int QtGraphEdge::getAggregationCount() const int QtGraphEdge::getAggregationCount() const
+1 -1
View File
@@ -77,7 +77,7 @@ protected:
private: private:
bool isAggregation() const; bool isAggregation() const;
int getZValue(bool active) const; int getZValue(bool active) const;
int getPenWidth() const; float getPenWidth() const;
int getAggregationCount() const; int getAggregationCount() const;
std::weak_ptr<GraphNode> m_owner; std::weak_ptr<GraphNode> m_owner;
@@ -61,7 +61,15 @@ void GraphController::handleMessage(MessageGraphNodeExpand* message)
DummyNode* node = findDummyNodeAccessRecursive(m_dummyNodes, message->tokenId, message->access); DummyNode* node = findDummyNodeAccessRecursive(m_dummyNodes, message->tokenId, message->access);
if (node) if (node)
{ {
node->expanded = !node->expanded; if (node->autoExpanded)
{
node->autoExpanded = false;
node->expanded = false;
}
else
{
node->expanded = !node->expanded;
}
setActiveAndVisibility(m_currentActiveTokenIds); setActiveAndVisibility(m_currentActiveTokenIds);
layoutNesting(); layoutNesting();
@@ -125,6 +133,7 @@ void GraphController::createDummyGraphForTokenIds(const std::vector<Id>& tokenId
m_dummyNodes = dummyNodes; m_dummyNodes = dummyNodes;
autoExpandActiveNode(tokenIds);
setActiveAndVisibility(tokenIds); setActiveAndVisibility(tokenIds);
layoutNesting(); layoutNesting();
@@ -210,6 +219,28 @@ DummyNode GraphController::createDummyNodeTopDown(Node* node)
return result; return result;
} }
void GraphController::autoExpandActiveNode(const std::vector<Id>& activeTokenIds)
{
DummyNode* node = nullptr;
if (activeTokenIds.size() == 1)
{
node = findDummyNodeRecursive(m_dummyNodes, activeTokenIds[0]);
}
if (!node)
{
return;
}
if (node->data->isType(Node::NODE_CLASS | Node::NODE_STRUCT))
{
for (DummyNode& subNode : node->subNodes)
{
subNode.autoExpanded = true;
}
}
}
void GraphController::setActiveAndVisibility(const std::vector<Id>& activeTokenIds) void GraphController::setActiveAndVisibility(const std::vector<Id>& activeTokenIds)
{ {
for (DummyNode& node : m_dummyNodes) for (DummyNode& node : m_dummyNodes)
@@ -262,7 +293,7 @@ void GraphController::setNodeVisibilityRecursiveTopDown(DummyNode& node) const
for (DummyNode& subNode : node.subNodes) for (DummyNode& subNode : node.subNodes)
{ {
if (subNode.accessType != TokenComponentAccess::ACCESS_NONE || node.expanded || if (subNode.accessType != TokenComponentAccess::ACCESS_NONE || node.isExpanded() ||
(node.data && node.data->isType(Node::NODE_ENUM)) || (node.data && node.data->isType(Node::NODE_ENUM)) ||
(node.active && node.data && node.data->isType(Node::NODE_NAMESPACE | Node::NODE_UNDEFINED))) (node.active && node.data && node.data->isType(Node::NODE_NAMESPACE | Node::NODE_UNDEFINED)))
{ {
@@ -308,7 +339,7 @@ void GraphController::layoutNestingRecursive(DummyNode& node) const
layoutNestingRecursive(subNode); layoutNestingRecursive(subNode);
if (subNode.data || subNode.expanded || subNode.invisibleSubNodeCount != subNode.subNodes.size()) if (subNode.data || subNode.isExpanded() || subNode.invisibleSubNodeCount != subNode.subNodes.size())
{ {
layoutHorizontal = false; layoutHorizontal = false;
} }
@@ -441,7 +472,7 @@ GraphController::Margins GraphController::getMarginsForDummyNode(DummyNode& node
{ {
margins.minWidth = 82; margins.minWidth = 82;
if (node.expanded) if (node.isExpanded())
{ {
margins.bottom = 15; margins.bottom = 15;
} }
@@ -57,6 +57,8 @@ private:
void createDummyGraphForTokenIds(const std::vector<Id>& tokenIds); void createDummyGraphForTokenIds(const std::vector<Id>& tokenIds);
DummyNode createDummyNodeTopDown(Node* node); DummyNode createDummyNodeTopDown(Node* node);
void autoExpandActiveNode(const std::vector<Id>& activeTokenIds);
void setActiveAndVisibility(const std::vector<Id>& activeTokenIds); void setActiveAndVisibility(const std::vector<Id>& activeTokenIds);
bool setNodeActiveAndVisibilityRecursiveBottomUp( bool setNodeActiveAndVisibilityRecursiveBottomUp(
DummyNode& node, const std::vector<Id>& activeTokenIds, bool aggregated) const; DummyNode& node, const std::vector<Id>& activeTokenIds, bool aggregated) const;
@@ -54,6 +54,7 @@ struct DummyNode
, connected(false) , connected(false)
, aggregated(false) , aggregated(false)
, expanded(false) , expanded(false)
, autoExpanded(false)
, invisibleSubNodeCount(0) , invisibleSubNodeCount(0)
, visible(false) , visible(false)
{ {
@@ -66,11 +67,17 @@ struct DummyNode
, connected(false) , connected(false)
, aggregated(false) , aggregated(false)
, expanded(false) , expanded(false)
, autoExpanded(false)
, invisibleSubNodeCount(0) , invisibleSubNodeCount(0)
, visible(false) , visible(false)
{ {
} }
bool isExpanded() const
{
return expanded || autoExpanded;
}
const Node* data; const Node* data;
TokenComponentAccess::AccessType accessType; TokenComponentAccess::AccessType accessType;
@@ -82,6 +89,7 @@ struct DummyNode
bool aggregated; bool aggregated;
bool expanded; bool expanded;
bool autoExpanded;
size_t invisibleSubNodeCount; size_t invisibleSubNodeCount;
bool visible; bool visible;
+7 -12
View File
@@ -474,11 +474,8 @@ std::vector<SearchMatch> Storage::getAutocompletionMatches(
tokenResults = m_tokenIndex.runFuzzySearch(word); tokenResults = m_tokenIndex.runFuzzySearch(word);
} }
if (word.size()) SearchResults filterResults = m_filterIndex.runFuzzySearch(word);
{ tokenResults.insert(filterResults.begin(), filterResults.end());
SearchResults filterResults = m_filterIndex.runFuzzySearch(word);
tokenResults.insert(filterResults.begin(), filterResults.end());
}
std::vector<SearchMatch> matches = SearchIndex::getMatches(tokenResults, word); std::vector<SearchMatch> matches = SearchIndex::getMatches(tokenResults, word);
SearchMatch::log(matches, word); SearchMatch::log(matches, word);
@@ -904,7 +901,6 @@ bool Storage::getSubQuerySearchResults(
SearchResults* results SearchResults* results
) const { ) const {
std::string q = query; std::string q = query;
bool returnChilds = false;
if (QueryOperator::getOperatorType(q.back()) == QueryOperator::OPERATOR_SUB) if (QueryOperator::getOperatorType(q.back()) == QueryOperator::OPERATOR_SUB)
{ {
@@ -913,7 +909,6 @@ bool Storage::getSubQuerySearchResults(
else if (QueryOperator::getOperatorType(q.back()) == QueryOperator::OPERATOR_HAS) else if (QueryOperator::getOperatorType(q.back()) == QueryOperator::OPERATOR_HAS)
{ {
q.pop_back(); q.pop_back();
returnChilds = true;
} }
else if (QueryOperator::getOperatorType(q.back()) != QueryOperator::OPERATOR_NONE) else if (QueryOperator::getOperatorType(q.back()) != QueryOperator::OPERATOR_NONE)
{ {
@@ -946,19 +941,19 @@ bool Storage::getSubQuerySearchResults(
{ {
if (word.size()) if (word.size())
{ {
SearchResults res = node->runFuzzySearch(word, returnChilds); SearchResults res = node->runFuzzySearch(word);
results->insert(res.begin(), res.end()); results->insert(res.begin(), res.end());
} }
else if (returnChilds) else if (searchNodes.size() == 1)
{ {
for (const std::shared_ptr<SearchNode>& child : node->getChildren()) for (const std::shared_ptr<SearchNode>& child : node->getChildren())
{ {
results->insert(SearchResult(0, child.get(), child.get())); child->addResultsRecursive(*results, 0, child.get());
} }
} }
else if (searchNodes.size() > 1) else
{ {
results->insert(SearchResult(0, node, node)); node->addResultsRecursive(*results, 0, node);
} }
} }
@@ -18,10 +18,11 @@ GraphFilterConductor::~GraphFilterConductor()
{ {
} }
void GraphFilterConductor::filter(const QueryTree* tree, const FilterableGraph* in, FilterableGraph* out) const void GraphFilterConductor::filter(const QueryTree* tree, const FilterableGraph* in, FilterableGraph* out)
{ {
if (tree->isValid()) if (tree->isValid())
{ {
m_inGraph = in;
filterRecursively(tree->getRoot().get(), in, out); filterRecursively(tree->getRoot().get(), in, out);
} }
} }
@@ -38,7 +39,7 @@ void GraphFilterConductor::filterRecursively(const QueryNode* node, const Filter
} }
else if (node->isToken()) else if (node->isToken())
{ {
filterTokenNode(dynamic_cast<const QueryToken*>(node), in, out); filterTokenNode(dynamic_cast<const QueryToken*>(node), out);
} }
} }
@@ -172,7 +173,7 @@ void GraphFilterConductor::filterCommandNode(const QueryCommand* node, const Fil
} }
} }
void GraphFilterConductor::filterTokenNode(const QueryToken* node, const FilterableGraph* in, FilterableGraph* out) const void GraphFilterConductor::filterTokenNode(const QueryToken* node, FilterableGraph* out) const
{ {
GraphFilterToken(node->getTokenName(), node->getTokenIds()).apply(in, out); GraphFilterToken(node->getTokenName(), node->getTokenIds()).apply(m_inGraph, out);
} }
@@ -14,13 +14,15 @@ public:
GraphFilterConductor(); GraphFilterConductor();
~GraphFilterConductor(); ~GraphFilterConductor();
void filter(const QueryTree* tree, const FilterableGraph* in, FilterableGraph* out) const; void filter(const QueryTree* tree, const FilterableGraph* in, FilterableGraph* out);
private: private:
void filterRecursively(const QueryNode* node, const FilterableGraph* in, FilterableGraph* out) const; void filterRecursively(const QueryNode* node, const FilterableGraph* in, FilterableGraph* out) const;
void filterOperatorNode(const QueryOperator* node, const FilterableGraph* in, FilterableGraph* out) const; void filterOperatorNode(const QueryOperator* node, const FilterableGraph* in, FilterableGraph* out) const;
void filterCommandNode(const QueryCommand* node, const FilterableGraph* in, FilterableGraph* out) const; void filterCommandNode(const QueryCommand* node, const FilterableGraph* in, FilterableGraph* out) const;
void filterTokenNode(const QueryToken* node, const FilterableGraph* in, FilterableGraph* out) const; void filterTokenNode(const QueryToken* node, FilterableGraph* out) const;
const FilterableGraph* m_inGraph;
}; };
#endif // GRAPH_FILTER_CONDUCTOR_H #endif // GRAPH_FILTER_CONDUCTOR_H
+1 -1
View File
@@ -73,7 +73,7 @@ SearchNode* SearchIndex::getNode(const std::string& fullName) const
SearchResults SearchIndex::runFuzzySearch(const std::string& query) const SearchResults SearchIndex::runFuzzySearch(const std::string& query) const
{ {
return m_root.runFuzzySearch(query, true); return m_root.runFuzzySearch(query);
} }
std::vector<SearchMatch> SearchIndex::runFuzzySearchAndGetMatches(const std::string& query) const std::vector<SearchMatch> SearchIndex::runFuzzySearchAndGetMatches(const std::string& query) const
+15 -19
View File
@@ -89,30 +89,16 @@ const std::set<std::shared_ptr<SearchNode>>& SearchNode::getChildren() const
return m_nodes; return m_nodes;
} }
SearchResults SearchNode::runFuzzySearch(const std::string& query, bool recursive) const SearchResults SearchNode::runFuzzySearch(const std::string& query) const
{ {
SearchResults result; SearchResults result;
if (recursive) for (std::shared_ptr<SearchNode> n: m_nodes)
{ {
for (std::shared_ptr<SearchNode> n: m_nodes) FuzzyMap m = n->fuzzyMatchRecursive(query, 0, 0, 0);
for (const std::pair<size_t, const SearchNode*>& p : m)
{ {
FuzzyMap m = n->fuzzyMatchRecursive(query, 0, 0, 0); addResultsRecursive(result, p.first, p.second);
for (const std::pair<size_t, const SearchNode*>& p : m)
{
result.insert(SearchResult(p.first, p.second, this));
}
}
}
else
{
std::pair<size_t, size_t> p = fuzzyMatch(query, 0, 0);
size_t pos = p.first;
size_t weight = p.second;
if (pos == query.size())
{
result.insert(SearchResult(weight, this, this));
} }
} }
@@ -121,6 +107,16 @@ SearchResults SearchNode::runFuzzySearch(const std::string& query, bool recursiv
return result; return result;
} }
void SearchNode::addResultsRecursive(SearchResults& result, size_t weight, const SearchNode* node) const
{
result.insert(SearchResult(weight, node, this));
for (std::shared_ptr<SearchNode> n: node->m_nodes)
{
addResultsRecursive(result, weight, n.get());
}
}
std::shared_ptr<SearchNode> SearchNode::addNodeRecursive( std::shared_ptr<SearchNode> SearchNode::addNodeRecursive(
std::deque<Id>* nameIds, const Dictionary& dictionary std::deque<Id>* nameIds, const Dictionary& dictionary
){ ){
+3 -1
View File
@@ -36,12 +36,14 @@ public:
const std::set<std::shared_ptr<SearchNode>>& getChildren() const; const std::set<std::shared_ptr<SearchNode>>& getChildren() const;
SearchResults runFuzzySearch(const std::string& query, bool recursive) const; SearchResults runFuzzySearch(const std::string& query) const;
void addResultsRecursive(SearchResults& result, size_t weight, const SearchNode* node) const;
private: private:
typedef std::multimap<size_t, const SearchNode*> FuzzyMap; typedef std::multimap<size_t, const SearchNode*> FuzzyMap;
typedef FuzzyMap::const_iterator FuzzyMapIterator; typedef FuzzyMap::const_iterator FuzzyMapIterator;
// Accessed by SearchIndex // Accessed by SearchIndex
std::shared_ptr<SearchNode> addNodeRecursive(std::deque<Id>* nameIds, const Dictionary& dictionary); std::shared_ptr<SearchNode> addNodeRecursive(std::deque<Id>* nameIds, const Dictionary& dictionary);
std::shared_ptr<SearchNode> getNodeRecursive(std::deque<Id>* nameIds) const; std::shared_ptr<SearchNode> getNodeRecursive(std::deque<Id>* nameIds) const;
+9 -3
View File
@@ -189,8 +189,13 @@ public:
std::vector<SearchMatch> matches = index.runFuzzySearchAndGetMatches("t"); std::vector<SearchMatch> matches = index.runFuzzySearchAndGetMatches("t");
TS_ASSERT_EQUALS(1, matches.size()); TS_ASSERT_EQUALS(6, matches.size());
TS_ASSERT_EQUALS("util", matches[0].fullName); TS_ASSERT_EQUALS("util", matches[0].fullName);
TS_ASSERT_EQUALS("util::math", matches[1].fullName);
TS_ASSERT_EQUALS("util::math::ceil", matches[2].fullName);
TS_ASSERT_EQUALS("util::math::floor", matches[3].fullName);
TS_ASSERT_EQUALS("util::string", matches[4].fullName);
TS_ASSERT_EQUALS("util::string::concat", matches[5].fullName);
matches = index.runFuzzySearchAndGetMatches("uml"); matches = index.runFuzzySearchAndGetMatches("uml");
@@ -208,9 +213,10 @@ public:
std::vector<SearchMatch> matches = index.runFuzzySearchAndGetMatches("u:i"); std::vector<SearchMatch> matches = index.runFuzzySearchAndGetMatches("u:i");
TS_ASSERT_EQUALS(2, matches.size()); TS_ASSERT_EQUALS(3, matches.size());
TS_ASSERT_EQUALS("util::string", matches[0].fullName); TS_ASSERT_EQUALS("util::string", matches[0].fullName);
TS_ASSERT_EQUALS("util::math::ceil", matches[1].fullName); TS_ASSERT_EQUALS("util::string::concat", matches[1].fullName);
TS_ASSERT_EQUALS("util::math::ceil", matches[2].fullName);
matches = index.runFuzzySearchAndGetMatches("u:t:i"); matches = index.runFuzzySearchAndGetMatches("u:t:i");