ui: Added custom tooltipping to code and graph (issue #195)

* Tooltips show node type with access specifier, reference count and fully qualified name
* Fields and global variables include the type name
* Methods and functinos show whole signature. Gets broken into multiple lines if too long.

Included changes:

* Upgraded to C++14
* fixed clang warnings
* Pass location of .srctrlprj file to build.sh script to load on launch
* Split off QtCodeField for showing highlighted and annotated code fom QtCodeArea
* removed TokenComponentSignature
* added TaskDecoratorDelay

bug id = 195
This commit is contained in:
Eberhard Graether
2017-07-31 12:45:22 +02:00
parent 01b1e0d6f1
commit 01864b4d0c
79 changed files with 2340 additions and 1009 deletions
+1 -1
View File
@@ -57,7 +57,7 @@ if(UNIX AND NOT APPLE)
endif()
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_C_STANDARD 99)
# Settings ---------------------------------------------------------------------
-2
View File
@@ -172,8 +172,6 @@
#code_area {
background-color: transparent;
color: <color:code/snippet/syntax/normal>;
font-family: "<setting:font_name>";
font-size: <setting:font_size>px;
selection-color: <color:code/snippet/selection/text>;
selection-background-color: <color:code/snippet/selection/background>;
}
+26
View File
@@ -0,0 +1,26 @@
#tooltip {
background-color: <color:code/file/background>;
border: 1px solid <color:code/file/background>;
}
#tooltip_title {
color: <color:code/file/title/text>;
padding: 3px;
font-size: <setting:font_size>px;
font-weight: bold;
}
#tooltip_references {
background-color: <color:code/file/ref_count/background>;
color: <color:code/file/ref_count/text>;
margin: 4px;
padding: 3px 5px;
border-radius: 8px;
font-size: <setting:font_size-2>px;
}
#tooltip_widget {
background-color: <color:code/snippet/background>;
padding: 3px;
color: <color:code/snippet/syntax/normal>;
}
+8 -2
View File
@@ -12,6 +12,12 @@ fi
cd $MY_PATH/..
# determine if needs to load project
if [ ! -z "$3" ]
then
PROJECT_PATH="-p $3"
fi
# run target
if [ "$1" = "release" ] || [ "$1" = "r" ] || [ "$1" = "" ]
@@ -26,7 +32,7 @@ then
cd build/Release/license_generator && ./Sourcetrail_license_generator
else
#echo "release app"
cd build/Release/app && ./Sourcetrail
cd build/Release/app && ./Sourcetrail $PROJECT_PATH
fi
elif [ "$1" = "debug" ] || [ "$1" = "d" ]
then
@@ -40,7 +46,7 @@ then
cd build/Debug/license_generator && ./Sourcetrail_license_generator
else
#echo "debug app"
cd build/Debug/app && ./Sourcetrail
cd build/Debug/app && ./Sourcetrail $PROJECT_PATH
fi
else
echo "no arguments: first argument 'release' or 'debug', second argument 'test' for tests"
+14 -5
View File
@@ -41,6 +41,8 @@ add_files(
component/controller/StatusBarController.h
component/controller/StatusController.cpp
component/controller/StatusController.h
component/controller/TooltipController.cpp
component/controller/TooltipController.h
component/controller/UndoRedoController.cpp
component/controller/UndoRedoController.h
@@ -75,6 +77,8 @@ add_files(
component/view/StatusView.h
component/view/TabbedView.cpp
component/view/TabbedView.h
component/view/TooltipView.cpp
component/view/TooltipView.h
component/view/UndoRedoView.cpp
component/view/UndoRedoView.h
component/view/View.cpp
@@ -125,8 +129,6 @@ add_files(
data/graph/token_component/TokenComponentFilePath.cpp
data/graph/token_component/TokenComponentFilePath.h
data/graph/token_component/TokenComponentInheritanceChain.h
data/graph/token_component/TokenComponentSignature.cpp
data/graph/token_component/TokenComponentSignature.h
data/graph/token_component/TokenComponentStatic.cpp
data/graph/token_component/TokenComponentStatic.h
@@ -211,13 +213,13 @@ add_files(
data/search/SearchIndex.h
data/search/SearchMatch.cpp
data/search/SearchMatch.h
data/storage/migration/SqliteStorageMigration.cpp
data/storage/migration/SqliteStorageMigration.h
data/storage/migration/SqliteStorageMigrationLambda.cpp
data/storage/migration/SqliteStorageMigrationLambda.h
data/storage/migration/SqliteStorageMigrator.h
data/storage/sqlite/SqliteBookmarkStorage.cpp
data/storage/sqlite/SqliteBookmarkStorage.h
data/storage/sqlite/SqliteDatabaseIndex.cpp
@@ -226,7 +228,7 @@ add_files(
data/storage/sqlite/SqliteIndexStorage.h
data/storage/sqlite/SqliteStorage.cpp
data/storage/sqlite/SqliteStorage.h
data/storage/IntermediateStorage.cpp
data/storage/IntermediateStorage.h
data/storage/PersistentStorage.cpp
@@ -240,6 +242,9 @@ add_files(
data/storage/StorageTypes.h
data/storage/StorageStats.h
data/tooltip/TooltipInfo.h
data/tooltip/TooltipOrigin.h
data/DefinitionKind.cpp
data/DefinitionKind.h
data/ErrorCountInfo.h
@@ -410,6 +415,8 @@ add_files(
utility/messaging/type/MessageStatus.h
utility/messaging/type/MessageStatusFilterChanged.h
utility/messaging/type/MessageSwitchColorScheme.h
utility/messaging/type/MessageTooltipHide.h
utility/messaging/type/MessageTooltipShow.h
utility/messaging/type/MessageToUndoRedoPosition.h
utility/messaging/type/MessageUndo.h
utility/messaging/type/MessageWindowClosed.h
@@ -438,6 +445,8 @@ add_files(
utility/scheduling/TaskDecorator.h
utility/scheduling/TaskDecoratorRepeat.cpp
utility/scheduling/TaskDecoratorRepeat.h
utility/scheduling/TaskDecoratorDelay.cpp
utility/scheduling/TaskDecoratorDelay.h
utility/scheduling/TaskGroup.cpp
utility/scheduling/TaskGroup.h
utility/scheduling/TaskGroupParallel.cpp
+10
View File
@@ -11,6 +11,7 @@
#include "component/controller/SearchController.h"
#include "component/controller/StatusBarController.h"
#include "component/controller/StatusController.h"
#include "component/controller/TooltipController.h"
#include "component/controller/UndoRedoController.h"
#include "component/view/BookmarkView.h"
#include "component/view/CodeView.h"
@@ -20,6 +21,7 @@
#include "component/view/SearchView.h"
#include "component/view/StatusBarView.h"
#include "component/view/StatusView.h"
#include "component/view/TooltipView.h"
#include "component/view/UndoRedoView.h"
#include "component/view/ViewFactory.h"
@@ -56,6 +58,14 @@ std::shared_ptr<Component> ComponentFactory::createActivationComponent()
return std::make_shared<Component>(nullptr, controller);
}
std::shared_ptr<Component> ComponentFactory::createTooltipComponent(ViewLayout* viewLayout)
{
std::shared_ptr<TooltipView> view = m_viewFactory->createTooltipView(viewLayout);
std::shared_ptr<Controller> controller = std::make_shared<TooltipController>(m_storageAccess);
return std::make_shared<Component>(view, controller);
}
std::shared_ptr<Component> ComponentFactory::createBookmarkComponent(ViewLayout* viewLayout)
{
std::shared_ptr<BookmarkView> view = m_viewFactory->createBookmarkView(viewLayout);
+1
View File
@@ -29,6 +29,7 @@ public:
std::shared_ptr<Component> createSearchComponent(ViewLayout* viewLayout);
std::shared_ptr<Component> createStatusBarComponent(ViewLayout* viewLayout);
std::shared_ptr<Component> createStatusComponent(ViewLayout* viewLayout);
std::shared_ptr<Component> createTooltipComponent(ViewLayout* viewLayout);
std::shared_ptr<Component> createUndoRedoComponent(ViewLayout* viewLayout);
private:
+3
View File
@@ -51,6 +51,9 @@ void ComponentManager::setup(ViewLayout* viewLayout)
std::shared_ptr<Component> activationComponent = m_componentFactory->createActivationComponent();
m_components.push_back(activationComponent);
std::shared_ptr<Component> tooltipComponent = m_componentFactory->createTooltipComponent(viewLayout);
m_components.push_back(tooltipComponent);
m_dialogView = m_componentFactory->getViewFactory()->createDialogView(viewLayout, m_componentFactory->getStorageAccess());
std::shared_ptr<TabbedView> tabbedView =
@@ -196,7 +196,10 @@ void IDECommunicationController::handlePing(const NetworkProtocolHelper::PingMes
void IDECommunicationController::handleMessage(MessageWindowFocus* message)
{
sendUpdatePing();
if (message->focusIn)
{
sendUpdatePing();
}
}
void IDECommunicationController::handleMessage(MessageIDECreateCDB* message)
@@ -0,0 +1,141 @@
#include "TooltipController.h"
#include "component/view/CodeView.h"
#include "component/view/GraphView.h"
#include "component/view/TooltipView.h"
#include "data/access/StorageAccess.h"
#include "utility/scheduling/TaskDecoratorDelay.h"
#include "utility/scheduling/TaskLambda.h"
Id TooltipController::TooltipRequest::s_requestId = 1;
TooltipController::TooltipController(StorageAccess* storageAccess)
: m_storageAccess(storageAccess)
, m_hideRequest(false)
{
}
TooltipController::~TooltipController()
{
}
void TooltipController::clear()
{
m_showRequest.reset();
m_hideRequest = false;
getView()->hideTooltip(true);
}
void TooltipController::handleMessage(MessageActivateTokens* message)
{
clear();
}
void TooltipController::handleMessage(MessageFocusIn* message)
{
if (!message->tokenIds.size())
{
return;
}
requestTooltipShow(message->tokenIds, TooltipInfo(), message->origin);
}
void TooltipController::handleMessage(MessageFocusOut* message)
{
requestTooltipHide();
}
void TooltipController::handleMessage(MessageGraphNodeExpand* message)
{
clear();
}
void TooltipController::handleMessage(MessageTooltipHide* message)
{
clear();
}
void TooltipController::handleMessage(MessageTooltipShow* message)
{
requestTooltipShow(std::vector<Id>(), message->tooltipInfo, message->origin);
}
void TooltipController::handleMessage(MessageWindowFocus* message)
{
clear();
}
TooltipView* TooltipController::getView() const
{
return Controller::getView<TooltipView>();
}
View* TooltipController::getViewForOrigin(TooltipOrigin origin) const
{
std::string viewName = (origin == TOOLTIP_ORIGIN_CODE ? CodeView::VIEW_NAME : GraphView::VIEW_NAME);
return getView()->getViewLayout()->findFloatingView(viewName);
}
void TooltipController::requestTooltipShow(const std::vector<Id> tokenIds, TooltipInfo info, TooltipOrigin origin)
{
Id requestId = TooltipRequest::s_requestId++;
m_showRequest = std::make_unique<TooltipRequest>();
m_showRequest->requestId = requestId;
m_showRequest->tokenIds = tokenIds;
m_showRequest->info = info;
m_showRequest->origin = origin;
size_t delayMS = 700;
if (getView()->tooltipVisible())
{
delayMS = 300;
}
Task::dispatch(std::make_shared<TaskDecoratorDelay>(delayMS)->addChildTask(
std::make_shared<TaskLambda>(
[requestId, this]()
{
if (m_showRequest && m_showRequest->requestId == requestId)
{
if (!m_showRequest->info.isValid() && m_showRequest->tokenIds.size())
{
m_showRequest->info = m_storageAccess->getTooltipInfoForTokenIds(
m_showRequest->tokenIds, m_showRequest->origin);
}
TooltipView* view = getView();
if (m_showRequest->info.isValid())
{
view->showTooltip(m_showRequest->info, getViewForOrigin(m_showRequest->origin));
m_showRequest.reset();
m_hideRequest = false;
}
}
}
)
));
}
void TooltipController::requestTooltipHide()
{
m_showRequest.reset();
m_hideRequest = true;
Task::dispatch(std::make_shared<TaskDecoratorDelay>(500)->addChildTask(
std::make_shared<TaskLambda>(
[this]()
{
if (m_hideRequest)
{
m_hideRequest = false;
getView()->hideTooltip(false);
}
}
)
));
}
@@ -0,0 +1,67 @@
#ifndef TOOLTIP_CONTROLLER_H
#define TOOLTIP_CONTROLLER_H
#include "component/controller/Controller.h"
#include "utility/messaging/MessageListener.h"
#include "utility/messaging/type/MessageActivateTokens.h"
#include "utility/messaging/type/MessageFocusIn.h"
#include "utility/messaging/type/MessageFocusOut.h"
#include "utility/messaging/type/MessageGraphNodeExpand.h"
#include "utility/messaging/type/MessageTooltipHide.h"
#include "utility/messaging/type/MessageTooltipShow.h"
#include "utility/messaging/type/MessageWindowFocus.h"
class StorageAccess;
class TooltipView;
class TooltipController
: public Controller
, public MessageListener<MessageActivateTokens>
, public MessageListener<MessageFocusIn>
, public MessageListener<MessageFocusOut>
, public MessageListener<MessageGraphNodeExpand>
, public MessageListener<MessageTooltipHide>
, public MessageListener<MessageTooltipShow>
, public MessageListener<MessageWindowFocus>
{
public:
TooltipController(StorageAccess* storageAccess);
virtual ~TooltipController();
// Controller
virtual void clear();
// MessageListener
virtual void handleMessage(MessageActivateTokens* message);
virtual void handleMessage(MessageFocusIn* message);
virtual void handleMessage(MessageFocusOut* message);
virtual void handleMessage(MessageGraphNodeExpand* message);
virtual void handleMessage(MessageTooltipHide* message);
virtual void handleMessage(MessageTooltipShow* message);
virtual void handleMessage(MessageWindowFocus* message);
private:
struct TooltipRequest
{
static Id s_requestId;
Id requestId;
std::vector<Id> tokenIds;
TooltipInfo info;
TooltipOrigin origin;
};
TooltipView* getView() const;
View* getViewForOrigin(TooltipOrigin origin) const;
void requestTooltipShow(const std::vector<Id> tokenIds, TooltipInfo info, TooltipOrigin origin);
void requestTooltipHide();
StorageAccess* m_storageAccess;
std::unique_ptr<TooltipRequest> m_showRequest;
bool m_hideRequest;
};
#endif // TOOLTIP_CONTROLLER_H
+3 -1
View File
@@ -2,6 +2,8 @@
#include "component/controller/CodeController.h"
const char* CodeView::VIEW_NAME = "Code";
CodeView::CodeView(ViewLayout* viewLayout)
: View(viewLayout)
{
@@ -13,7 +15,7 @@ CodeView::~CodeView()
std::string CodeView::getName() const
{
return "Code";
return VIEW_NAME;
}
CodeController* CodeView::getController()
+2
View File
@@ -16,6 +16,8 @@ class CodeView
: public View
{
public:
static const char* VIEW_NAME;
enum FileState
{
FILE_MINIMIZED,
+3 -1
View File
@@ -1,5 +1,7 @@
#include "component/view/GraphView.h"
const char* GraphView::VIEW_NAME = "Graph";
GraphView::GraphView(ViewLayout* viewLayout)
: View(viewLayout)
{
@@ -11,5 +13,5 @@ GraphView::~GraphView()
std::string GraphView::getName() const
{
return "Graph";
return VIEW_NAME;
}
+2
View File
@@ -16,6 +16,8 @@ class GraphView
: public View
{
public:
static const char* VIEW_NAME;
struct GraphParams
{
bool animatedTransition;
+16
View File
@@ -0,0 +1,16 @@
#include "component/view/TooltipView.h"
TooltipView::TooltipView(ViewLayout* viewLayout)
: View(viewLayout)
{
}
TooltipView::~TooltipView()
{
}
std::string TooltipView::getName() const
{
return "TooltipView";
}
+27
View File
@@ -0,0 +1,27 @@
#ifndef TOOLTIP_VIEW_H
#define TOOLTIP_VIEW_H
#include <vector>
#include "component/view/View.h"
#include "data/name/NameHierarchy.h"
#include "data/tooltip/TooltipInfo.h"
#include "utility/types.h"
class TooltipView
: public View
{
public:
TooltipView(ViewLayout* viewLayout);
virtual ~TooltipView();
// View implementation
virtual std::string getName() const;
virtual void showTooltip(TooltipInfo info, const View* parent) = 0;
virtual void hideTooltip(bool force) = 0;
virtual bool tooltipVisible() const = 0;
};
#endif // TOOLTIP_VIEW_H
+2
View File
@@ -18,6 +18,7 @@ class StatusBarView;
class StatusView;
class StorageAccess;
class TabbedView;
class TooltipView;
class UndoRedoView;
class ViewLayout;
@@ -41,6 +42,7 @@ public:
virtual std::shared_ptr<SearchView> createSearchView(ViewLayout* viewLayout) const = 0;
virtual std::shared_ptr<StatusBarView> createStatusBarView(ViewLayout* viewLayout) const = 0;
virtual std::shared_ptr<StatusView> createStatusView(ViewLayout* viewLayout) const = 0;
virtual std::shared_ptr<TooltipView> createTooltipView(ViewLayout* viewLayout) const = 0;
virtual std::shared_ptr<UndoRedoView> createUndoRedoView(ViewLayout* viewLayout) const = 0;
virtual std::shared_ptr<DialogView> createDialogView(ViewLayout* viewLayout, StorageAccess* storageAccess) const = 0;
+5
View File
@@ -7,3 +7,8 @@ ViewLayout::ViewLayout()
ViewLayout::~ViewLayout()
{
}
View* ViewLayout::findFloatingView(const std::string& name) const
{
return nullptr;
}
+4
View File
@@ -1,6 +1,8 @@
#ifndef VIEW_LAYOUT_H
#define VIEW_LAYOUT_H
#include <string>
class View;
class ViewLayout
@@ -14,6 +16,8 @@ public:
virtual void showView(View* view) = 0;
virtual void hideView(View* view) = 0;
virtual View* findFloatingView(const std::string& name) const;
};
#endif // VIEW_LAYOUT_H
+15 -10
View File
@@ -16,14 +16,17 @@
#include "data/ErrorFilter.h"
#include "data/ErrorInfo.h"
#include "data/storage/StorageStats.h"
#include "data/tooltip/TooltipInfo.h"
#include "data/tooltip/TooltipOrigin.h"
class FilePath;
struct FileInfo;
class Graph;
class SourceLocationCollection;
class SourceLocationFile;
class TextAccess;
struct FileInfo;
class StorageAccess
{
public:
@@ -34,7 +37,7 @@ public:
virtual std::vector<Id> getNodeIdsForNameHierarchies(const std::vector<NameHierarchy> nameHierarchies) const = 0;
virtual NameHierarchy getNameHierarchyForNodeId(Id id) const = 0;
virtual std::vector<NameHierarchy> getNameHierarchiesForNodeIds(const std::vector<Id> nodeIds) const = 0;
virtual std::vector<NameHierarchy> getNameHierarchiesForNodeIds(const std::vector<Id>& nodeIds) const = 0;
virtual Node::NodeType getNodeTypeForNodeWithId(Id id) const = 0;
@@ -79,20 +82,22 @@ public:
virtual void setErrorFilter(const ErrorFilter& filter);
virtual Id addNodeBookmark(const NodeBookmark& bookmark) = 0; // todo: remove these from storage access
virtual Id addEdgeBookmark(const EdgeBookmark& bookmark) = 0; // todo: remove these from storage access
virtual Id addBookmarkCategory(const std::string& categoryName) = 0; // todo: remove these from storage access
// todo: remove bookmark related methods from storage access
virtual Id addNodeBookmark(const NodeBookmark& bookmark) = 0;
virtual Id addEdgeBookmark(const EdgeBookmark& bookmark) = 0;
virtual Id addBookmarkCategory(const std::string& categoryName) = 0;
virtual void updateBookmark(const Id bookmarkId, const std::string& name, const std::string& comment, const std::string& categoryName) = 0; // todo: remove these from storage access
virtual void removeBookmark(const Id id) = 0; // todo: remove these from storage access
virtual void removeBookmarkCategory(const Id id) = 0; // todo: remove these from storage access
virtual void updateBookmark(
const Id bookmarkId, const std::string& name, const std::string& comment, const std::string& categoryName) = 0;
virtual void removeBookmark(const Id id) = 0;
virtual void removeBookmarkCategory(const Id id) = 0;
virtual std::vector<NodeBookmark> getAllNodeBookmarks() const = 0;
virtual std::vector<EdgeBookmark> getAllEdgeBookmarks() const = 0;
virtual std::vector<BookmarkCategory> getAllBookmarkCategories() const = 0;
virtual TooltipInfo getTooltipInfoForTokenIds(const std::vector<Id>& tokenIds, TooltipOrigin origin) const = 0;
protected:
ErrorFilter m_errorFilter;
};
+11 -1
View File
@@ -75,7 +75,7 @@ NameHierarchy StorageAccessProxy::getNameHierarchyForNodeId(Id id) const
return NameHierarchy(NAME_DELIMITER_UNKNOWN);
}
std::vector<NameHierarchy> StorageAccessProxy::getNameHierarchiesForNodeIds(const std::vector<Id> nodeIds) const
std::vector<NameHierarchy> StorageAccessProxy::getNameHierarchiesForNodeIds(const std::vector<Id>& nodeIds) const
{
if (hasSubject())
{
@@ -415,6 +415,16 @@ std::vector<BookmarkCategory> StorageAccessProxy::getAllBookmarkCategories() con
return std::vector<BookmarkCategory>();
}
TooltipInfo StorageAccessProxy::getTooltipInfoForTokenIds(const std::vector<Id>& tokenIds, TooltipOrigin origin) const
{
if (hasSubject())
{
return m_subject->getTooltipInfoForTokenIds(tokenIds, origin);
}
return TooltipInfo();
}
void StorageAccessProxy::setErrorFilter(const ErrorFilter& filter)
{
StorageAccess::setErrorFilter(filter);
+5 -4
View File
@@ -23,7 +23,7 @@ public:
virtual std::vector<Id> getNodeIdsForNameHierarchies(const std::vector<NameHierarchy> nameHierarchies) const;
virtual NameHierarchy getNameHierarchyForNodeId(Id id) const;
virtual std::vector<NameHierarchy> getNameHierarchiesForNodeIds(const std::vector<Id> nodeIds) const;
virtual std::vector<NameHierarchy> getNameHierarchiesForNodeIds(const std::vector<Id>& nodeIds) const;
virtual Node::NodeType getNodeTypeForNodeWithId(Id id) const;
@@ -73,16 +73,17 @@ public:
virtual Id addEdgeBookmark(const EdgeBookmark& bookmark);
virtual Id addBookmarkCategory(const std::string& categoryName);
virtual void updateBookmark(const Id bookmarkId, const std::string& name, const std::string& comment, const std::string& categoryName);
virtual void updateBookmark(
const Id bookmarkId, const std::string& name, const std::string& comment, const std::string& categoryName);
virtual void removeBookmark(const Id id);
virtual void removeBookmarkCategory(const Id id);
virtual std::vector<NodeBookmark> getAllNodeBookmarks() const;
virtual std::vector<EdgeBookmark> getAllEdgeBookmarks() const;
virtual std::vector<BookmarkCategory> getAllBookmarkCategories() const;
virtual TooltipInfo getTooltipInfoForTokenIds(const std::vector<Id>& tokenIds, TooltipOrigin origin) const;
protected:
virtual void setErrorFilter(const ErrorFilter& filter);
+7 -23
View File
@@ -10,13 +10,14 @@
#include "data/graph/token_component/TokenComponentConst.h"
#include "data/graph/token_component/TokenComponentStatic.h"
#include "data/graph/token_component/TokenComponentFilePath.h"
#include "data/graph/token_component/TokenComponentSignature.h"
const Node::NodeTypeMask Node::NODE_NOT_VISIBLE = Node::NODE_NAMESPACE | Node::NODE_PACKAGE;
const Node::NodeTypeMask Node::NODE_USEABLE_TYPE = Node::NODE_NON_INDEXED | Node::NODE_BUILTIN_TYPE |
Node::NODE_STRUCT | Node::NODE_CLASS | Node::NODE_INTERFACE | Node::NODE_TYPEDEF;
const Node::NodeTypeMask Node::NODE_INHERITABLE_TYPE = Node::NODE_NON_INDEXED | Node::NODE_BUILTIN_TYPE |
NODE_TYPE | Node::NODE_STRUCT | Node::NODE_CLASS | Node::NODE_INTERFACE;
const Node::NodeTypeMask Node::NODE_NOT_VISIBLE = NODE_NAMESPACE | NODE_PACKAGE;
const Node::NodeTypeMask Node::NODE_USEABLE_TYPE = NODE_NON_INDEXED | NODE_BUILTIN_TYPE | NODE_STRUCT | NODE_CLASS |
NODE_UNION | NODE_INTERFACE | NODE_TYPEDEF;
const Node::NodeTypeMask Node::NODE_INHERITABLE_TYPE = NODE_NON_INDEXED | NODE_BUILTIN_TYPE | NODE_TYPE | NODE_STRUCT |
NODE_CLASS | NODE_INTERFACE;
const Node::NodeTypeMask Node::NODE_MEMBER_TYPE = NODE_METHOD | NODE_FIELD | NODE_CLASS | NODE_INTERFACE | NODE_STRUCT |
NODE_UNION | NODE_TYPEDEF | NODE_ENUM;
std::string Node::getUnderscoredTypeString(NodeType type)
{
@@ -469,23 +470,6 @@ void Node::addComponentFilePath(std::shared_ptr<TokenComponentFilePath> componen
}
}
void Node::addComponentSignature(std::shared_ptr<TokenComponentSignature> component)
{
if (getComponent<TokenComponentSignature>())
{
LOG_ERROR("TokenComponentSignature has been set before!");
return;
}
else if (!isType(NODE_FUNCTION | NODE_METHOD))
{
LOG_ERROR("TokenComponentFilePath can't be set on node of type: " + getReadableTypeString());
}
else
{
addComponent(component);
}
}
void Node::addComponentAccess(std::shared_ptr<TokenComponentAccess> component)
{
if (getComponent<TokenComponentAccess>())
+1
View File
@@ -58,6 +58,7 @@ public:
static const NodeTypeMask NODE_NOT_VISIBLE;
static const NodeTypeMask NODE_USEABLE_TYPE;
static const NodeTypeMask NODE_INHERITABLE_TYPE;
static const NodeTypeMask NODE_MEMBER_TYPE;
Node(Id id, NodeType type, NameHierarchy nameHierarchy, bool defined);
Node(const Node& other);
@@ -1,20 +0,0 @@
#include "data/graph/token_component/TokenComponentSignature.h"
TokenComponentSignature::TokenComponentSignature(const std::string& signature)
: m_signature(signature)
{
}
TokenComponentSignature::~TokenComponentSignature()
{
}
std::shared_ptr<TokenComponent> TokenComponentSignature::copy() const
{
return std::make_shared<TokenComponentSignature>(*this);
}
const std::string& TokenComponentSignature::getSignature() const
{
return m_signature;
}
@@ -1,23 +0,0 @@
#ifndef TOKEN_COMPONENT_SIGNATURE_H
#define TOKEN_COMPONENT_SIGNATURE_H
#include <string>
#include "data/graph/token_component/TokenComponent.h"
class TokenComponentSignature
: public TokenComponent
{
public:
TokenComponentSignature(const std::string& signature);
virtual ~TokenComponentSignature();
virtual std::shared_ptr<TokenComponent> copy() const;
const std::string& getSignature() const;
private:
const std::string m_signature;
};
#endif // TOKEN_COMPONENT_SIGNATURE_H
+10
View File
@@ -61,6 +61,16 @@ bool NameElement::Signature::isValid() const
return ((m_prefix + m_postfix).size() > 0);
}
const std::string& NameElement::Signature::getPrefix() const
{
return m_prefix;
}
const std::string& NameElement::Signature::getPostfix() const
{
return m_postfix;
}
NameElement::NameElement(const std::string& name)
: m_name(name)
{
+3
View File
@@ -21,6 +21,9 @@ public:
std::string qualifyName(const std::string& name) const;
bool isValid() const;
const std::string& getPrefix() const;
const std::string& getPostfix() const;
private:
std::string m_prefix;
std::string m_postfix;
+10
View File
@@ -161,3 +161,13 @@ std::string NameHierarchy::getRawNameWithSignature() const
}
return "";
}
NameElement::Signature NameHierarchy::getSignature() const
{
if (m_elements.size())
{
return m_elements.back()->getSignature(); // todo: use separator for signature!
}
return NameElement::Signature();
}
+2
View File
@@ -37,6 +37,8 @@ public:
std::string getRawName() const;
std::string getRawNameWithSignature() const;
NameElement::Signature getSignature() const;
private:
std::vector<std::shared_ptr<NameElement>> m_elements;
NameDelimiterType m_delimiter;
+22
View File
@@ -25,3 +25,25 @@ int accessKindToInt(AccessKind t)
return t;
}
std::string accessKindToString(AccessKind t)
{
switch (t)
{
case ACCESS_NONE:
return "";
case ACCESS_PUBLIC:
return "public";
case ACCESS_PROTECTED:
return "protected";
case ACCESS_PRIVATE:
return "private";
case ACCESS_DEFAULT:
return "default";
case ACCESS_TEMPLATE_PARAMETER:
return "template parameter";
case ACCESS_TYPE_PARAMETER:
return "type parameter";
}
return "";
}
+3
View File
@@ -1,6 +1,8 @@
#ifndef ACCESS_KIND_H
#define ACCESS_KIND_H
#include <string>
enum AccessKind
{ // these values need to be the same as AccessKind in Java code
ACCESS_NONE = 0,
@@ -14,5 +16,6 @@ enum AccessKind
AccessKind intToAccessKind(int v);
int accessKindToInt(AccessKind t);
std::string accessKindToString(AccessKind t);
#endif // ACCESS_KIND_H
-13
View File
@@ -15,14 +15,6 @@ TaskParseWrapper::~TaskParseWrapper()
{
}
void TaskParseWrapper::setTask(std::shared_ptr<Task> task)
{
if (task)
{
m_taskRunner = std::make_shared<TaskRunner>(task);
}
}
void TaskParseWrapper::doEnter(std::shared_ptr<Blackboard> blackboard)
{
int sourceFileCount = 0;
@@ -54,8 +46,3 @@ void TaskParseWrapper::doReset(std::shared_ptr<Blackboard> blackboard)
{
m_taskRunner->reset();
}
void TaskParseWrapper::doTerminate()
{
m_taskRunner->terminate();
}
-4
View File
@@ -19,19 +19,15 @@ public:
TaskParseWrapper(PersistentStorage* storage);
virtual ~TaskParseWrapper();
virtual void setTask(std::shared_ptr<Task> task);
private:
virtual void doEnter(std::shared_ptr<Blackboard> blackboard);
virtual TaskState doUpdate(std::shared_ptr<Blackboard> blackboard);
virtual void doExit(std::shared_ptr<Blackboard> blackboard);
virtual void doReset(std::shared_ptr<Blackboard> blackboard);
virtual void doTerminate();
PersistentStorage* m_storage;
TimePoint m_start;
std::shared_ptr<TaskRunner> m_taskRunner;
};
#endif // TASK_PARSE_WRAPPER_H
+366 -189
View File
@@ -18,12 +18,12 @@
#include "data/graph/token_component/TokenComponentAggregation.h"
#include "data/graph/token_component/TokenComponentFilePath.h"
#include "data/graph/token_component/TokenComponentInheritanceChain.h"
#include "data/graph/token_component/TokenComponentSignature.h"
#include "data/graph/Graph.h"
#include "data/location/SourceLocationCollection.h"
#include "data/location/SourceLocationFile.h"
#include "data/parser/AccessKind.h"
#include "data/parser/ParseLocation.h"
#include "settings/ApplicationSettings.h"
PersistentStorage::PersistentStorage(const FilePath& dbPath, const FilePath& bookmarkPath)
: m_sqliteIndexStorage(dbPath)
@@ -147,182 +147,6 @@ void PersistentStorage::addError(
);
}
Id PersistentStorage::addNodeBookmark(const NodeBookmark& bookmark)
{
const Id categoryId = addBookmarkCategory(bookmark.getCategory().getName());
const Id id = m_sqliteBookmarkStorage.addBookmark(
bookmark.getName(), bookmark.getComment(), bookmark.getTimeStamp().toString(), categoryId);
for (const Id& nodeId: bookmark.getNodeIds())
{
m_sqliteBookmarkStorage.addBookmarkedNode(id, m_sqliteIndexStorage.getNodeById(nodeId).serializedName);
}
return id;
}
Id PersistentStorage::addEdgeBookmark(const EdgeBookmark& bookmark)
{
const Id categoryId = addBookmarkCategory(bookmark.getCategory().getName());
const Id id = m_sqliteBookmarkStorage.addBookmark(
bookmark.getName(), bookmark.getComment(), bookmark.getTimeStamp().toString(), categoryId);
for (const Id& edgeId: bookmark.getEdgeIds())
{
const StorageEdge storageEdge = m_sqliteIndexStorage.getEdgeById(edgeId);
bool sourceNodeActive = storageEdge.sourceNodeId == bookmark.getActiveNodeId();
m_sqliteBookmarkStorage.addBookmarkedEdge(
id,
// todo: optimization for multiple edges in same bookmark: use a local cache here
m_sqliteIndexStorage.getNodeById(storageEdge.sourceNodeId).serializedName,
m_sqliteIndexStorage.getNodeById(storageEdge.targetNodeId).serializedName,
storageEdge.type,
sourceNodeActive
);
}
return id;
}
Id PersistentStorage::addBookmarkCategory(const std::string& name)
{
if (name.empty())
{
return 0;
}
Id id = m_sqliteBookmarkStorage.getBookmarkCategoryByName(name).id;
if (id == 0)
{
id = m_sqliteBookmarkStorage.addBookmarkCategory(name);
}
return id;
}
void PersistentStorage::updateBookmark(
const Id bookmarkId, const std::string& name, const std::string& comment, const std::string& categoryName)
{
const Id categoryId = addBookmarkCategory(categoryName); // only creates category if id didn't exist before;
m_sqliteBookmarkStorage.updateBookmark(bookmarkId, name, comment, categoryId);
}
void PersistentStorage::removeBookmark(const Id id)
{
m_sqliteBookmarkStorage.removeBookmark(id);
}
void PersistentStorage::removeBookmarkCategory(Id id)
{
m_sqliteBookmarkStorage.removeBookmarkCategory(id);
}
std::vector<NodeBookmark> PersistentStorage::getAllNodeBookmarks() const
{
std::unordered_map<Id, StorageBookmarkCategory> bookmarkCategories;
for (const StorageBookmarkCategory& bookmarkCategory: m_sqliteBookmarkStorage.getAllBookmarkCategories())
{
bookmarkCategories[bookmarkCategory.id] = bookmarkCategory;
}
std::unordered_map<Id, std::vector<Id>> bookmarkIdToBookmarkedNodeIds;
for (const StorageBookmarkedNode& bookmarkedNode: m_sqliteBookmarkStorage.getAllBookmarkedNodes())
{
bookmarkIdToBookmarkedNodeIds[bookmarkedNode.bookmarkId].push_back(
m_sqliteIndexStorage.getNodeBySerializedName(bookmarkedNode.serializedNodeName).id);
}
std::vector<NodeBookmark> nodeBookmarks;
for (const StorageBookmark& storageBookmark: m_sqliteBookmarkStorage.getAllBookmarks())
{
auto itCategories = bookmarkCategories.find(storageBookmark.categoryId);
auto itNodeIds = bookmarkIdToBookmarkedNodeIds.find(storageBookmark.id);
if (itCategories != bookmarkCategories.end() && itNodeIds != bookmarkIdToBookmarkedNodeIds.end())
{
NodeBookmark bookmark(
storageBookmark.id,
storageBookmark.name,
storageBookmark.comment,
storageBookmark.timestamp,
BookmarkCategory(itCategories->second.id, itCategories->second.name)
);
bookmark.setNodeIds(itNodeIds->second);
bookmark.setIsValid();
nodeBookmarks.push_back(bookmark);
}
}
return nodeBookmarks;
}
std::vector<EdgeBookmark> PersistentStorage::getAllEdgeBookmarks() const
{
std::unordered_map<Id, StorageBookmarkCategory> bookmarkCategories;
for (const StorageBookmarkCategory& bookmarkCategory: m_sqliteBookmarkStorage.getAllBookmarkCategories())
{
bookmarkCategories[bookmarkCategory.id] = bookmarkCategory;
}
std::unordered_map<Id, std::vector<StorageBookmarkedEdge>> bookmarkIdToBookmarkedEdges;
for (const StorageBookmarkedEdge& bookmarkedEdge: m_sqliteBookmarkStorage.getAllBookmarkedEdges())
{
bookmarkIdToBookmarkedEdges[bookmarkedEdge.bookmarkId].push_back(bookmarkedEdge);
}
std::vector<EdgeBookmark> edgeBookmarks;
Cache<std::string, Id> nodeIdCache([&](std::string serializedNodeName)
{
return m_sqliteIndexStorage.getNodeBySerializedName(serializedNodeName).id;
}
);
for (const StorageBookmark& storageBookmark: m_sqliteBookmarkStorage.getAllBookmarks())
{
auto itCategories = bookmarkCategories.find(storageBookmark.categoryId);
auto itBookmarkedEdges = bookmarkIdToBookmarkedEdges.find(storageBookmark.id);
if (itCategories != bookmarkCategories.end() && itBookmarkedEdges != bookmarkIdToBookmarkedEdges.end())
{
EdgeBookmark bookmark(
storageBookmark.id,
storageBookmark.name,
storageBookmark.comment,
storageBookmark.timestamp,
BookmarkCategory(itCategories->second.id, itCategories->second.name)
);
Id activeNodeId = 0;
for (const StorageBookmarkedEdge& bookmarkedEdge: itBookmarkedEdges->second)
{
const Id sourceNodeId = nodeIdCache.getValue(bookmarkedEdge.serializedSourceNodeName);
const Id targetNodeId = nodeIdCache.getValue(bookmarkedEdge.serializedTargetNodeName);
const Id edgeId =
m_sqliteIndexStorage.getEdgeBySourceTargetType(sourceNodeId, targetNodeId, bookmarkedEdge.edgeType).id;
bookmark.addEdgeId(edgeId);
if (activeNodeId == 0)
{
activeNodeId = bookmarkedEdge.sourceNodeActive ? sourceNodeId : targetNodeId;
}
}
bookmark.setActiveNodeId(activeNodeId);
bookmark.setIsValid();
edgeBookmarks.push_back(bookmark);
}
}
return edgeBookmarks;
}
std::vector<BookmarkCategory> PersistentStorage::getAllBookmarkCategories() const
{
std::vector<BookmarkCategory> categories;
for (const StorageBookmarkCategory storageBookmarkCategoriy: m_sqliteBookmarkStorage.getAllBookmarkCategories())
{
categories.push_back(BookmarkCategory(storageBookmarkCategoriy.id, storageBookmarkCategoriy.name));
}
return categories;
}
void PersistentStorage::forEachNode(std::function<void(const StorageNode& /*data*/)> callback) const
{
for (StorageNode& node: m_sqliteIndexStorage.getAll<StorageNode>())
@@ -602,7 +426,7 @@ NameHierarchy PersistentStorage::getNameHierarchyForNodeId(Id nodeId) const
return NameHierarchy::deserialize(m_sqliteIndexStorage.getFirstById<StorageNode>(nodeId).serializedName);
}
std::vector<NameHierarchy> PersistentStorage::getNameHierarchiesForNodeIds(const std::vector<Id> nodeIds) const
std::vector<NameHierarchy> PersistentStorage::getNameHierarchiesForNodeIds(const std::vector<Id>& nodeIds) const
{
TRACE();
@@ -1564,6 +1388,370 @@ std::shared_ptr<SourceLocationCollection> PersistentStorage::getErrorSourceLocat
return collection;
}
Id PersistentStorage::addNodeBookmark(const NodeBookmark& bookmark)
{
const Id categoryId = addBookmarkCategory(bookmark.getCategory().getName());
const Id id = m_sqliteBookmarkStorage.addBookmark(
bookmark.getName(), bookmark.getComment(), bookmark.getTimeStamp().toString(), categoryId);
for (const Id& nodeId: bookmark.getNodeIds())
{
m_sqliteBookmarkStorage.addBookmarkedNode(id, m_sqliteIndexStorage.getNodeById(nodeId).serializedName);
}
return id;
}
Id PersistentStorage::addEdgeBookmark(const EdgeBookmark& bookmark)
{
const Id categoryId = addBookmarkCategory(bookmark.getCategory().getName());
const Id id = m_sqliteBookmarkStorage.addBookmark(
bookmark.getName(), bookmark.getComment(), bookmark.getTimeStamp().toString(), categoryId);
for (const Id& edgeId: bookmark.getEdgeIds())
{
const StorageEdge storageEdge = m_sqliteIndexStorage.getEdgeById(edgeId);
bool sourceNodeActive = storageEdge.sourceNodeId == bookmark.getActiveNodeId();
m_sqliteBookmarkStorage.addBookmarkedEdge(
id,
// todo: optimization for multiple edges in same bookmark: use a local cache here
m_sqliteIndexStorage.getNodeById(storageEdge.sourceNodeId).serializedName,
m_sqliteIndexStorage.getNodeById(storageEdge.targetNodeId).serializedName,
storageEdge.type,
sourceNodeActive
);
}
return id;
}
Id PersistentStorage::addBookmarkCategory(const std::string& name)
{
if (name.empty())
{
return 0;
}
Id id = m_sqliteBookmarkStorage.getBookmarkCategoryByName(name).id;
if (id == 0)
{
id = m_sqliteBookmarkStorage.addBookmarkCategory(name);
}
return id;
}
void PersistentStorage::updateBookmark(
const Id bookmarkId, const std::string& name, const std::string& comment, const std::string& categoryName)
{
const Id categoryId = addBookmarkCategory(categoryName); // only creates category if id didn't exist before;
m_sqliteBookmarkStorage.updateBookmark(bookmarkId, name, comment, categoryId);
}
void PersistentStorage::removeBookmark(const Id id)
{
m_sqliteBookmarkStorage.removeBookmark(id);
}
void PersistentStorage::removeBookmarkCategory(Id id)
{
m_sqliteBookmarkStorage.removeBookmarkCategory(id);
}
std::vector<NodeBookmark> PersistentStorage::getAllNodeBookmarks() const
{
std::unordered_map<Id, StorageBookmarkCategory> bookmarkCategories;
for (const StorageBookmarkCategory& bookmarkCategory: m_sqliteBookmarkStorage.getAllBookmarkCategories())
{
bookmarkCategories[bookmarkCategory.id] = bookmarkCategory;
}
std::unordered_map<Id, std::vector<Id>> bookmarkIdToBookmarkedNodeIds;
for (const StorageBookmarkedNode& bookmarkedNode: m_sqliteBookmarkStorage.getAllBookmarkedNodes())
{
bookmarkIdToBookmarkedNodeIds[bookmarkedNode.bookmarkId].push_back(
m_sqliteIndexStorage.getNodeBySerializedName(bookmarkedNode.serializedNodeName).id);
}
std::vector<NodeBookmark> nodeBookmarks;
for (const StorageBookmark& storageBookmark: m_sqliteBookmarkStorage.getAllBookmarks())
{
auto itCategories = bookmarkCategories.find(storageBookmark.categoryId);
auto itNodeIds = bookmarkIdToBookmarkedNodeIds.find(storageBookmark.id);
if (itCategories != bookmarkCategories.end() && itNodeIds != bookmarkIdToBookmarkedNodeIds.end())
{
NodeBookmark bookmark(
storageBookmark.id,
storageBookmark.name,
storageBookmark.comment,
storageBookmark.timestamp,
BookmarkCategory(itCategories->second.id, itCategories->second.name)
);
bookmark.setNodeIds(itNodeIds->second);
bookmark.setIsValid();
nodeBookmarks.push_back(bookmark);
}
}
return nodeBookmarks;
}
std::vector<EdgeBookmark> PersistentStorage::getAllEdgeBookmarks() const
{
std::unordered_map<Id, StorageBookmarkCategory> bookmarkCategories;
for (const StorageBookmarkCategory& bookmarkCategory: m_sqliteBookmarkStorage.getAllBookmarkCategories())
{
bookmarkCategories[bookmarkCategory.id] = bookmarkCategory;
}
std::unordered_map<Id, std::vector<StorageBookmarkedEdge>> bookmarkIdToBookmarkedEdges;
for (const StorageBookmarkedEdge& bookmarkedEdge: m_sqliteBookmarkStorage.getAllBookmarkedEdges())
{
bookmarkIdToBookmarkedEdges[bookmarkedEdge.bookmarkId].push_back(bookmarkedEdge);
}
std::vector<EdgeBookmark> edgeBookmarks;
Cache<std::string, Id> nodeIdCache([&](std::string serializedNodeName)
{
return m_sqliteIndexStorage.getNodeBySerializedName(serializedNodeName).id;
}
);
for (const StorageBookmark& storageBookmark: m_sqliteBookmarkStorage.getAllBookmarks())
{
auto itCategories = bookmarkCategories.find(storageBookmark.categoryId);
auto itBookmarkedEdges = bookmarkIdToBookmarkedEdges.find(storageBookmark.id);
if (itCategories != bookmarkCategories.end() && itBookmarkedEdges != bookmarkIdToBookmarkedEdges.end())
{
EdgeBookmark bookmark(
storageBookmark.id,
storageBookmark.name,
storageBookmark.comment,
storageBookmark.timestamp,
BookmarkCategory(itCategories->second.id, itCategories->second.name)
);
Id activeNodeId = 0;
for (const StorageBookmarkedEdge& bookmarkedEdge: itBookmarkedEdges->second)
{
const Id sourceNodeId = nodeIdCache.getValue(bookmarkedEdge.serializedSourceNodeName);
const Id targetNodeId = nodeIdCache.getValue(bookmarkedEdge.serializedTargetNodeName);
const Id edgeId =
m_sqliteIndexStorage.getEdgeBySourceTargetType(sourceNodeId, targetNodeId, bookmarkedEdge.edgeType).id;
bookmark.addEdgeId(edgeId);
if (activeNodeId == 0)
{
activeNodeId = bookmarkedEdge.sourceNodeActive ? sourceNodeId : targetNodeId;
}
}
bookmark.setActiveNodeId(activeNodeId);
bookmark.setIsValid();
edgeBookmarks.push_back(bookmark);
}
}
return edgeBookmarks;
}
std::vector<BookmarkCategory> PersistentStorage::getAllBookmarkCategories() const
{
std::vector<BookmarkCategory> categories;
for (const StorageBookmarkCategory storageBookmarkCategoriy: m_sqliteBookmarkStorage.getAllBookmarkCategories())
{
categories.push_back(BookmarkCategory(storageBookmarkCategoriy.id, storageBookmarkCategoriy.name));
}
return categories;
}
TooltipInfo PersistentStorage::getTooltipInfoForTokenIds(const std::vector<Id>& tokenIds, TooltipOrigin origin) const
{
TRACE();
TooltipInfo info;
if (!tokenIds.size())
{
return info;
}
StorageNode node = m_sqliteIndexStorage.getFirstById<StorageNode>(tokenIds[0]);
if (node.id == 0 && origin == TOOLTIP_ORIGIN_CODE)
{
StorageEdge edge = m_sqliteIndexStorage.getFirstById<StorageEdge>(tokenIds[0]);
if (edge.id > 0)
{
node = m_sqliteIndexStorage.getFirstById<StorageNode>(edge.targetNodeId);
}
}
if (node.id == 0)
{
return info;
}
Node::NodeType type = Node::intToType(node.type);
info.title = Node::getReadableTypeString(type);
DefinitionKind defKind = DEFINITION_NONE;
StorageSymbol symbol = m_sqliteIndexStorage.getFirstById<StorageSymbol>(node.id);
if (symbol.id > 0)
{
defKind = intToDefinitionKind(symbol.definitionKind);
}
if (type & Node::NODE_MEMBER_TYPE)
{
StorageComponentAccess access = m_sqliteIndexStorage.getComponentAccessByNodeId(node.id);
if (access.nodeId != 0)
{
info.title = accessKindToString(intToAccessKind(access.type)) + " " + info.title;
}
}
if (type == Node::NODE_FILE)
{
bool complete = false;
auto it = m_fileNodeComplete.find(node.id);
if (it != m_fileNodeComplete.end())
{
complete = it->second;
}
if (!complete)
{
info.title = "incomplete " + info.title;
}
}
else if (defKind == DEFINITION_NONE && type != Node::NODE_NON_INDEXED)
{
info.title = "non-indexed " + info.title;
}
else if (defKind == DEFINITION_IMPLICIT)
{
info.title = "implicit " + info.title;
}
info.count = 0;
info.countText = "reference";
for (auto edge : m_sqliteIndexStorage.getEdgesByTargetId(node.id))
{
if (Edge::intToType(edge.type) != Edge::EDGE_MEMBER)
{
info.count++;
}
}
info.snippets.push_back(getTooltipSnippetForNode(node));
if (origin == TOOLTIP_ORIGIN_CODE)
{
info.offset = Vec2i(20, 30);
}
else
{
info.offset = Vec2i(50, 20);
}
return info;
}
TooltipSnippet PersistentStorage::getTooltipSnippetForNode(const StorageNode& node) const
{
TRACE();
TooltipSnippet snippet;
NameHierarchy nameHierarchy = NameHierarchy::deserialize(node.serializedName);
snippet.code = nameHierarchy.getQualifiedNameWithSignature();
snippet.locationFile = std::make_shared<SourceLocationFile>(
FilePath(nameHierarchy.getDelimiter() == NAME_DELIMITER_JAVA ? "main.java" : "main.cpp"), true, true);
if (Node::intToType(node.type) & (Node::NODE_FUNCTION | Node::NODE_METHOD | Node::NODE_FIELD | Node::NODE_GLOBAL_VARIABLE))
{
snippet.code = utility::breakSignature(
nameHierarchy.getSignature().getPrefix(),
nameHierarchy.getQualifiedName(),
nameHierarchy.getSignature().getPostfix(),
50,
ApplicationSettings::getInstance()->getCodeTabWidth()
);
std::vector<Id> typeNodeIds;
for (auto edge : m_sqliteIndexStorage.getEdgesBySourceId(node.id))
{
if (Edge::intToType(edge.type) == Edge::EDGE_TYPE_USAGE)
{
typeNodeIds.push_back(edge.targetNodeId);
}
}
std::set<std::pair<std::string, Id>, bool(*)(const std::pair<std::string, Id>&, const std::pair<std::string, Id>&)> typeNames(
[](const std::pair<std::string, Id>& a, const std::pair<std::string, Id>& b)
{
if (a.first.size() == b.first.size())
{
return a.first < b.first;
}
return a.first.size() > b.first.size();
}
);
typeNames.insert(std::make_pair(nameHierarchy.getQualifiedName(), node.id));
for (auto typeNode : m_sqliteIndexStorage.getAllByIds<StorageNode>(typeNodeIds))
{
typeNames.insert(std::make_pair(
NameHierarchy::deserialize(typeNode.serializedName).getQualifiedName(),
typeNode.id
));
}
Id locationId = 1;
std::vector<std::pair<size_t, size_t>> locationRanges;
for (auto p : typeNames)
{
size_t pos = 0;
while (pos != std::string::npos)
{
pos = snippet.code.find(p.first, pos);
if (pos == std::string::npos)
{
continue;
}
bool inRange = false;
for (auto p : locationRanges)
{
if (pos + 1 >= p.first && pos + 1 <= p.second)
{
inRange = true;
pos = p.second + 1;
break;
}
}
if (!inRange)
{
snippet.locationFile->addSourceLocation(
LOCATION_TOKEN, locationId, std::vector<Id>(1, p.second), 1, pos + 1, 1, pos + p.first.size());
locationRanges.push_back(std::make_pair(pos + 1, pos + p.first.size()));
pos += p.first.size();
locationId++;
}
}
}
}
else
{
snippet.locationFile->addSourceLocation(
LOCATION_TOKEN, 0, std::vector<Id>(1, node.id), 1, 1, 1, snippet.code.size());
}
return snippet;
}
Id PersistentStorage::getFileNodeId(const FilePath& filePath) const
{
if (filePath.empty())
@@ -1864,17 +2052,6 @@ void PersistentStorage::addNodesToGraph(const std::vector<Id>& newNodeIds, Graph
node->setExplicit(true);
}
if (type == Node::NODE_FUNCTION || type == Node::NODE_METHOD)
{
std::string signatureString = nameHierarchy.getRawNameWithSignature();
if (signatureString.size() > 0) // this should always be the case since functions and methods must have sigs.
{
node->addComponentSignature(
std::make_shared<TokenComponentSignature>(signatureString)
);
}
}
if (addChildCount)
{
node->setChildCount(m_hierarchyCache.getFirstNonImplicitChildIdsCountForNodeId(storageNode.id));
+16 -15
View File
@@ -30,20 +30,6 @@ public:
virtual void addComponentAccess(Id nodeId , int type);
virtual void addCommentLocation(Id fileNodeId, uint startLine, uint startCol, uint endLine, uint endCol);
virtual void addError(const std::string& message, const FilePath& filePath, uint startLine, uint startCol, bool fatal, bool indexed);
virtual Id addNodeBookmark(const NodeBookmark& bookmark);
virtual Id addEdgeBookmark(const EdgeBookmark& bookmark);
virtual Id addBookmarkCategory(const std::string& categoryName);
void updateBookmark(const Id bookmarkId, const std::string& name, const std::string& comment, const std::string& categoryName);
virtual void removeBookmark(const Id id);
virtual void removeBookmarkCategory(const Id id);
std::vector<NodeBookmark> getAllNodeBookmarks() const;
std::vector<EdgeBookmark> getAllEdgeBookmarks() const;
virtual std::vector<BookmarkCategory> getAllBookmarkCategories() const;
virtual void forEachNode(std::function<void(const StorageNode& /*data*/)> callback) const;
virtual void forEachFile(std::function<void(const StorageFile& /*data*/)> callback) const;
@@ -89,7 +75,7 @@ public:
virtual std::vector<Id> getNodeIdsForNameHierarchies(const std::vector<NameHierarchy> nameHierarchies) const;
virtual NameHierarchy getNameHierarchyForNodeId(Id nodeId) const;
virtual std::vector<NameHierarchy> getNameHierarchiesForNodeIds(const std::vector<Id> nodeIds) const;
virtual std::vector<NameHierarchy> getNameHierarchiesForNodeIds(const std::vector<Id>& nodeIds) const;
virtual Node::NodeType getNodeTypeForNodeWithId(Id nodeId) const;
@@ -138,6 +124,21 @@ public:
virtual std::vector<ErrorInfo> getErrorsLimited() const;
virtual std::shared_ptr<SourceLocationCollection> getErrorSourceLocationsLimited(std::vector<ErrorInfo>* errors) const;
virtual Id addNodeBookmark(const NodeBookmark& bookmark);
virtual Id addEdgeBookmark(const EdgeBookmark& bookmark);
virtual Id addBookmarkCategory(const std::string& categoryName);
virtual void updateBookmark(const Id bookmarkId, const std::string& name, const std::string& comment, const std::string& categoryName);
virtual void removeBookmark(const Id id);
virtual void removeBookmarkCategory(const Id id);
virtual std::vector<NodeBookmark> getAllNodeBookmarks() const;
virtual std::vector<EdgeBookmark> getAllEdgeBookmarks() const;
virtual std::vector<BookmarkCategory> getAllBookmarkCategories() const;
virtual TooltipInfo getTooltipInfoForTokenIds(const std::vector<Id>& tokenIds, TooltipOrigin origin) const;
TooltipSnippet getTooltipSnippetForNode(const StorageNode& node) const;
private:
Id getFileNodeId(const FilePath& filePath) const;
std::vector<Id> getFileNodeIds(const std::vector<FilePath>& filePaths) const;
@@ -219,9 +219,10 @@ int SqliteStorage::executeStatementScalar(CppSQLite3Statement& statement, const
if (q.eof() || q.numFields() < 1)
{
char error[] = "Invalid scalar query";
throw CppSQLite3Exception(
CPPSQLITE_ERROR,
"Invalid scalar query",
error,
false
);
}
+34
View File
@@ -0,0 +1,34 @@
#ifndef TOOLTIP_INFO_H
#define TOOLTIP_INFO_H
#include <memory>
#include "utility/math/Vector2.h"
#include "utility/types.h"
class SourceLocationFile;
struct TooltipSnippet
{
std::string code;
std::shared_ptr<SourceLocationFile> locationFile;
};
struct TooltipInfo
{
bool isValid() const
{
return title.size() || snippets.size();
}
std::string title;
int count = -1;
std::string countText;
std::vector<TooltipSnippet> snippets;
Vec2i offset;
};
#endif // TOOLTIP_INFO_H
+10
View File
@@ -0,0 +1,10 @@
#ifndef TOOLTIP_ORIGIN_H
#define TOOLTIP_ORIGIN_H
enum TooltipOrigin
{
TOOLTIP_ORIGIN_GRAPH,
TOOLTIP_ORIGIN_CODE
};
#endif // TOOLTIP_ORIGIN_H
@@ -6,12 +6,15 @@
#include "utility/messaging/Message.h"
#include "utility/types.h"
#include "data/tooltip/TooltipOrigin.h"
class MessageFocusIn
: public Message<MessageFocusIn>
{
public:
MessageFocusIn(const std::vector<Id>& tokenIds)
MessageFocusIn(const std::vector<Id>& tokenIds, TooltipOrigin origin)
: tokenIds(tokenIds)
, origin(origin)
{
setIsLogged(false);
}
@@ -30,6 +33,7 @@ public:
}
const std::vector<Id> tokenIds;
const TooltipOrigin origin;
};
#endif //MESSAGE_FOCUS_IN_H
@@ -0,0 +1,21 @@
#ifndef MESSAGE_TOOLTIP_HIDE_H
#define MESSAGE_TOOLTIP_HIDE_H
#include "utility/messaging/Message.h"
class MessageTooltipHide
: public Message<MessageTooltipHide>
{
public:
MessageTooltipHide()
{
setSendAsTask(false);
}
static const std::string getStaticType()
{
return "MessageTooltipHide";
}
};
#endif // MESSAGE_TOOLTIP_HIDE_H
@@ -0,0 +1,29 @@
#ifndef MESSAGE_TOOLTIP_SHOW_H
#define MESSAGE_TOOLTIP_SHOW_H
#include "utility/messaging/Message.h"
#include "data/tooltip/TooltipOrigin.h"
#include "data/tooltip/TooltipInfo.h"
class MessageTooltipShow
: public Message<MessageTooltipShow>
{
public:
MessageTooltipShow(TooltipInfo info, TooltipOrigin origin)
: tooltipInfo(info)
, origin(origin)
{
setSendAsTask(false);
}
static const std::string getStaticType()
{
return "MessageTooltipShow";
}
const TooltipInfo tooltipInfo;
const TooltipOrigin origin;
};
#endif // MESSAGE_TOOLTIP_SHOW_H
@@ -3,10 +3,12 @@
#include "utility/messaging/Message.h"
class MessageWindowFocus: public Message<MessageWindowFocus>
class MessageWindowFocus
: public Message<MessageWindowFocus>
{
public:
MessageWindowFocus()
MessageWindowFocus(bool focusIn)
: focusIn(focusIn)
{
}
@@ -14,6 +16,8 @@ public:
{
return "MessageWindowFocus";
}
const bool focusIn;
};
#endif // MESSAGE_WINDOW_FOCUS_H
+1
View File
@@ -11,6 +11,7 @@ public:
enum TaskState
{
STATE_RUNNING,
STATE_HOLD,
STATE_SUCCESS,
STATE_FAILURE
};
@@ -1,5 +1,7 @@
#include "utility/scheduling/TaskDecorator.h"
#include "utility/scheduling/TaskRunner.h"
TaskDecorator::TaskDecorator()
{
}
@@ -14,7 +16,20 @@ std::shared_ptr<TaskDecorator> TaskDecorator::addChildTask(std::shared_ptr<Task>
return shared_from_this();
}
void TaskDecorator::setTask(std::shared_ptr<Task> task)
{
if (task)
{
m_taskRunner = std::make_shared<TaskRunner>(task);
}
}
void TaskDecorator::terminate()
{
doTerminate();
}
void TaskDecorator::doTerminate()
{
m_taskRunner->terminate();
}
+7 -2
View File
@@ -5,6 +5,8 @@
#include "utility/scheduling/Task.h"
class TaskRunner;
class TaskDecorator
: public Task
, public std::enable_shared_from_this<TaskDecorator>
@@ -14,11 +16,14 @@ public:
virtual ~TaskDecorator();
std::shared_ptr<TaskDecorator> addChildTask(std::shared_ptr<Task> child);
virtual void setTask(std::shared_ptr<Task> task) = 0;
virtual void setTask(std::shared_ptr<Task> task);
virtual void terminate();
protected:
std::shared_ptr<TaskRunner> m_taskRunner;
private:
virtual void doTerminate() = 0;
virtual void doTerminate();
};
#endif // TASK_DECORATOR_H
@@ -0,0 +1,49 @@
#include "utility/scheduling/TaskDecoratorDelay.h"
#include <thread>
TaskDecoratorDelay::TaskDecoratorDelay(size_t delayMS)
: m_delayMS(delayMS)
, m_delayComplete(delayMS == 0)
{
}
void TaskDecoratorDelay::doEnter(std::shared_ptr<Blackboard> blackboard)
{
m_start = TimePoint::now();
}
Task::TaskState TaskDecoratorDelay::doUpdate(std::shared_ptr<Blackboard> blackboard)
{
if (m_delayComplete)
{
return m_taskRunner->update(blackboard);
}
const int SLEEP_TIME_MS = 25;
std::this_thread::sleep_for(std::chrono::microseconds(SLEEP_TIME_MS));
m_delayComplete = (TimePoint::now().deltaMS(m_start) >= m_delayMS);
return Task::STATE_HOLD;
}
void TaskDecoratorDelay::doExit(std::shared_ptr<Blackboard> blackboard)
{
}
void TaskDecoratorDelay::doReset(std::shared_ptr<Blackboard> blackboard)
{
if (m_delayComplete)
{
m_taskRunner->reset();
}
}
void TaskDecoratorDelay::doTerminate()
{
if (m_delayComplete)
{
m_taskRunner->terminate();
}
}
@@ -0,0 +1,29 @@
#ifndef TASK_DECORATOR_DELAY_H
#define TASK_DECORATOR_DELAY_H
#include <vector>
#include "utility/scheduling/TaskDecorator.h"
#include "utility/scheduling/TaskRunner.h"
#include "utility/TimePoint.h"
class TaskDecoratorDelay
: public TaskDecorator
{
public:
TaskDecoratorDelay(size_t delayMS);
private:
virtual void doEnter(std::shared_ptr<Blackboard> blackboard);
virtual TaskState doUpdate(std::shared_ptr<Blackboard> blackboard);
virtual void doExit(std::shared_ptr<Blackboard> blackboard);
virtual void doReset(std::shared_ptr<Blackboard> blackboard);
virtual void doTerminate();
const size_t m_delayMS;
TimePoint m_start;
bool m_delayComplete;
};
#endif // TASK_DECORATOR_DELAY_H
@@ -6,14 +6,6 @@ TaskDecoratorRepeat::TaskDecoratorRepeat(ConditionType condition, TaskState exit
{
}
void TaskDecoratorRepeat::setTask(std::shared_ptr<Task> task)
{
if (task)
{
m_taskRunner = std::make_shared<TaskRunner>(task);
}
}
void TaskDecoratorRepeat::doEnter(std::shared_ptr<Blackboard> blackboard)
{
}
@@ -48,8 +40,3 @@ void TaskDecoratorRepeat::doReset(std::shared_ptr<Blackboard> blackboard)
{
m_taskRunner->reset();
}
void TaskDecoratorRepeat::doTerminate()
{
m_taskRunner->terminate();
}
@@ -17,16 +17,12 @@ public:
TaskDecoratorRepeat(ConditionType condition, TaskState exitState);
virtual void setTask(std::shared_ptr<Task> task);
private:
virtual void doEnter(std::shared_ptr<Blackboard> blackboard);
virtual TaskState doUpdate(std::shared_ptr<Blackboard> blackboard);
virtual void doExit(std::shared_ptr<Blackboard> blackboard);
virtual void doReset(std::shared_ptr<Blackboard> blackboard);
virtual void doTerminate();
std::shared_ptr<TaskRunner> m_taskRunner;
const ConditionType m_condition;
const TaskState m_exitState;
};
@@ -105,7 +105,7 @@ void TaskGroupParallel::processTaskThreaded(
{
TaskState state = taskInfo->taskRunner->update(blackboard);
if (state != STATE_RUNNING)
if (state == STATE_SUCCESS || state == STATE_FAILURE)
{
if (state == STATE_FAILURE)
{
@@ -39,6 +39,10 @@ Task::TaskState TaskGroupSelector::doUpdate(std::shared_ptr<Blackboard> blackboa
{
m_taskIndex = -1;
}
else if (state == STATE_HOLD)
{
return STATE_HOLD;
}
return STATE_RUNNING;
}
@@ -39,6 +39,10 @@ Task::TaskState TaskGroupSequence::doUpdate(std::shared_ptr<Blackboard> blackboa
{
m_taskIndex = -1;
}
else if (state == STATE_HOLD)
{
return STATE_HOLD;
}
return STATE_RUNNING;
}
+8 -1
View File
@@ -146,6 +146,7 @@ void TaskScheduler::processTasks()
while (m_taskRunners.size())
{
std::shared_ptr<TaskRunner> runner = m_taskRunners.front();
Task::TaskState state = Task::STATE_RUNNING;
{
m_tasksMutex.unlock();
@@ -166,7 +167,8 @@ void TaskScheduler::processTasks()
}
}
if (runner->update(blackboard) != Task::STATE_RUNNING)
state = runner->update(blackboard);
if (state != Task::STATE_RUNNING)
{
break;
}
@@ -174,6 +176,11 @@ void TaskScheduler::processTasks()
}
m_taskRunners.pop_front();
if (state == Task::STATE_HOLD)
{
m_taskRunners.push_back(runner);
}
}
m_terminateRunningTasks = false;
+106
View File
@@ -256,6 +256,112 @@ namespace utility
return ret;
}
std::string breakSignature(
std::string returnPart, std::string namePart, std::string paramPart,
size_t maxLineLength, size_t tabWidth)
{
namePart = ' ' + namePart;
size_t totalSize = returnPart.size() + namePart.size() + paramPart.size();
if (totalSize <= maxLineLength)
{
return returnPart + namePart + paramPart;
}
if (paramPart.size())
{
namePart += paramPart[0];
paramPart.erase(0, 1);
}
size_t parenPos = paramPart.rfind(')');
std::string endPart;
if (parenPos == 0)
{
namePart += paramPart;
paramPart = "";
}
else if (parenPos != std::string::npos)
{
endPart = paramPart.substr(parenPos);
paramPart = paramPart.substr(0, parenPos);
}
if (paramPart.size() && paramPart.size() + tabWidth - endPart.size() > maxLineLength)
{
std::vector<std::string> paramLines;
while (true)
{
size_t parenCount = 0;
bool split = false;
for (size_t i = 0; i < paramPart.size(); i++)
{
char c = paramPart[i];
if (parenCount == 0 && c == ',')
{
paramLines.push_back(paramPart.substr(0, i + 1));
paramPart = paramPart.substr(i + 2);
split = true;
break;
}
else if (c == '<' || c == '(')
{
parenCount++;
}
else if (c == '>' || c == ')')
{
parenCount--;
}
}
if (!split)
{
paramLines.push_back(paramPart);
break;
}
}
paramPart = "";
for (std::string str : paramLines)
{
paramPart += "\n\t" + str;
size_t length = tabWidth + str.size();
maxLineLength = std::max(length, maxLineLength);
}
}
else if (paramPart.size())
{
paramPart = "\n\t" + paramPart;
}
if (returnPart.size() + namePart.size() <= maxLineLength)
{
namePart = returnPart + namePart;
returnPart = "";
}
std::string sig;
if (returnPart.size())
{
sig += returnPart + '\n';
}
sig += namePart;
if (paramPart.size())
{
sig += paramPart;
}
if (endPart.size())
{
sig += '\n' + endPart;
}
return sig;
}
std::string trim(const std::string &str)
{
auto wsfront = std::find_if_not(str.begin(), str.end(), [](int c){ return std::isspace(c); });
+3
View File
@@ -47,6 +47,9 @@ namespace utility
std::string replace(std::string str, const std::string& from, const std::string& to);
std::string insertLineBreaksAtBlankSpaces(const std::string& s, size_t maxLineLength);
std::string breakSignature(
std::string returnPart, std::string namePart, std::string paramPart,
size_t maxLineLength, size_t tabWidth);
std::string trim(const std::string &str);
@@ -13,8 +13,8 @@ IndexerCommandCxx::IndexerCommandCxx(
, m_systemHeaderSearchPaths(systemHeaderSearchPaths)
, m_frameworkSearchPaths(frameworkSearchPaths)
, m_compilerFlags(compilerFlags)
, m_preprocessorOnly(false)
, m_shouldApplyAnonymousTypedefTransformation(shouldApplyAnonymousTypedefTransformation)
, m_preprocessorOnly(false)
{
}
@@ -54,7 +54,6 @@ std::string CxxTemplateArgumentNameResolver::getTemplateArgumentName(const clang
case clang::TemplateArgument::Pack:
{
std::string typeName = "<";
argument.getPackAsArray();
llvm::ArrayRef<clang::TemplateArgument> pack = argument.getPackAsArray();
for (size_t i = 0; i < pack.size(); i++)
{
+6
View File
@@ -14,6 +14,8 @@ add_files(
qt/element/QtBookmarkCategory.h
qt/element/QtCodeArea.cpp
qt/element/QtCodeArea.h
qt/element/QtCodeField.cpp
qt/element/QtCodeField.h
qt/element/QtCodeFile.cpp
qt/element/QtCodeFile.h
qt/element/QtCodeFileList.cpp
@@ -54,6 +56,8 @@ add_files(
qt/element/QtStatusBar.h
qt/element/QtTable.cpp
qt/element/QtTable.h
qt/element/QtTooltip.cpp
qt/element/QtTooltip.h
qt/element/QtUndoRedo.cpp
qt/element/QtUndoRedo.h
@@ -143,6 +147,8 @@ add_files(
qt/view/QtStatusView.h
qt/view/QtTabbedView.cpp
qt/view/QtTabbedView.h
qt/view/QtTooltipView.cpp
qt/view/QtTooltipView.h
qt/view/QtUndoRedoView.cpp
qt/view/QtUndoRedoView.h
qt/view/QtViewFactory.cpp
+35 -513
View File
@@ -12,6 +12,7 @@
#include <QTextBlock>
#include <QToolTip>
#include "data/location/SourceLocationFile.h"
#include "utility/messaging/type/MessageActivateLocalSymbols.h"
#include "utility/messaging/type/MessageActivateSourceLocations.h"
#include "utility/messaging/type/MessageActivateTokenIds.h"
@@ -21,16 +22,10 @@
#include "utility/messaging/type/MessageShowErrors.h"
#include "utility/utility.h"
#include "data/location/SourceLocation.h"
#include "data/location/SourceLocationFile.h"
#include "qt/element/QtCodeNavigator.h"
#include "qt/utility/QtContextMenu.h"
#include "qt/utility/QtHighlighter.h"
#include "settings/ApplicationSettings.h"
#include "settings/ColorScheme.h"
std::vector<QtCodeArea::AnnotationColor> QtCodeArea::s_annotationColors;
MouseWheelOverScrollbarFilter::MouseWheelOverScrollbarFilter()
{
}
@@ -76,11 +71,6 @@ void QtCodeArea::LineNumberArea::paintEvent(QPaintEvent *event)
m_codeArea->lineNumberAreaPaintEvent(event);
}
void QtCodeArea::clearAnnotationColors()
{
s_annotationColors.clear();
}
QtCodeArea::QtCodeArea(
uint startLineNumber,
const std::string& code,
@@ -88,11 +78,8 @@ QtCodeArea::QtCodeArea(
QtCodeNavigator* navigator,
QWidget* parent
)
: QPlainTextEdit(parent)
: QtCodeField(startLineNumber, code, locationFile, parent)
, m_navigator(navigator)
, m_startLineNumber(startLineNumber)
, m_code(code)
, m_locationFile(locationFile)
, m_digits(0)
, m_isSelecting(false)
, m_isPanning(false)
@@ -100,53 +87,22 @@ QtCodeArea::QtCodeArea(
, m_eventPosition(0, 0)
, m_isActiveFile(false)
, m_lineNumbersHidden(false)
, m_wasAnnotated(false)
, m_endTextEditPosition(0)
{
setObjectName("code_area");
setReadOnly(true);
setFrameStyle(QFrame::NoFrame);
setLineWrapMode(QPlainTextEdit::NoWrap);
setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed);
viewport()->setCursor(Qt::ArrowCursor);
m_lineNumberArea = new LineNumberArea(this);
std::string displayCode = m_code;
if (!displayCode.empty() && *displayCode.rbegin() == '\n')
{
displayCode.pop_back();
}
setPlainText(QString::fromUtf8(displayCode.c_str()));
createLineLengthCache();
m_digits = lineNumberDigits();
updateLineNumberAreaWidth();
connect(this, SIGNAL(blockCountChanged(int)), this, SLOT(updateLineNumberAreaWidth(int)));
connect(this, SIGNAL(updateRequest(QRect,int)), this, SLOT(updateLineNumberArea(QRect,int)));
this->setMouseTracking(true);
// MouseWheelOverScrollbarFilter is deleted by parent.
horizontalScrollBar()->installEventFilter(new MouseWheelOverScrollbarFilter());
m_scrollSpeedChangeListener.setScrollBar(horizontalScrollBar());
createActions();
createAnnotations(locationFile);
FilePath path = m_locationFile->getFilePath();
LanguageType language = LANGUAGE_UNKNOWN;
if (!path.empty())
{
language = (path.extension() == ".java" ? LANGUAGE_JAVA : LANGUAGE_CPP);
}
m_highlighter = new QtHighlighter(document(), language);
m_highlighter->highlightDocument();
}
QtCodeArea::~QtCodeArea()
@@ -160,39 +116,23 @@ QtCodeArea::~QtCodeArea()
QSize QtCodeArea::sizeHint() const
{
QTextBlock block = document()->firstBlock();
double height = 0;
double width = lineNumberAreaWidth() + blockBoundingGeometry(block).translated(contentOffset()).left();
double width = 0;
while (block.isValid())
for (QTextBlock block = document()->firstBlock(); block.isValid(); block = block.next())
{
height += blockBoundingRect(block).height();
width = std::max(blockBoundingRect(block).width(), width);
block = block.next();
QRectF rect = blockBoundingGeometry(block);
height += rect.height();
width = std::max(rect.width(), width);
}
int scrollHeight = 0;
if (horizontalScrollBar()->minimum() != horizontalScrollBar()->maximum())
{
height += horizontalScrollBar()->height();
scrollHeight = horizontalScrollBar()->height();
}
return QSize(width + 1, height + 5);
}
uint QtCodeArea::getStartLineNumber() const
{
return m_startLineNumber;
}
uint QtCodeArea::getEndLineNumber() const
{
return m_startLineNumber + blockCount() - 1;
}
std::shared_ptr<SourceLocationFile> QtCodeArea::getSourceLocationFile() const
{
return m_locationFile;
return QSize(width + lineNumberAreaWidth() + 1, height + scrollHeight + 5);
}
void QtCodeArea::lineNumberAreaPaintEvent(QPaintEvent *event)
@@ -218,7 +158,7 @@ void QtCodeArea::lineNumberAreaPaintEvent(QPaintEvent *event)
{
if (block.isVisible() && bottom >= event->rect().top())
{
int number = blockNumber + m_startLineNumber;
int number = blockNumber + getStartLineNumber();
p.setColor(textColor);
@@ -232,7 +172,8 @@ void QtCodeArea::lineNumberAreaPaintEvent(QPaintEvent *event)
}
painter.setPen(p);
painter.drawText(0, top, m_lineNumberArea->width() - 16, fontMetrics().height(), Qt::AlignRight, QString::number(number));
painter.drawText(
0, top, m_lineNumberArea->width() - 16, fontMetrics().height(), Qt::AlignRight, QString::number(number));
}
block = block.next();
@@ -244,7 +185,7 @@ void QtCodeArea::lineNumberAreaPaintEvent(QPaintEvent *event)
int QtCodeArea::lineNumberDigits() const
{
int max = qMax(1, int(m_startLineNumber) + blockCount());
int max = qMax(1, int(getStartLineNumber()) + blockCount());
return utility::digits(max);
}
@@ -354,15 +295,10 @@ QRectF QtCodeArea::getLineRectForLineNumber(uint lineNumber) const
lineNumber = getEndLineNumber();
}
QTextBlock block = document()->findBlockByLineNumber(lineNumber - m_startLineNumber);
QTextBlock block = document()->findBlockByLineNumber(lineNumber - getStartLineNumber());
return blockBoundingGeometry(block);
}
std::string QtCodeArea::getCode() const
{
return m_code;
}
void QtCodeArea::hideLineNumbers()
{
m_lineNumberArea->hide();
@@ -377,101 +313,6 @@ void QtCodeArea::resizeEvent(QResizeEvent *e)
m_lineNumberArea->setGeometry(QRect(cr.left(), cr.top(), lineNumberAreaWidth(), cr.height()));
}
void QtCodeArea::showEvent(QShowEvent* event)
{
int tabWidth = ApplicationSettings::getInstance()->getCodeTabWidth();
setTabStopWidth(tabWidth * fontMetrics().width('9'));
}
void QtCodeArea::paintEvent(QPaintEvent* event)
{
QPainter painter(viewport());
QTextBlock block = firstVisibleBlock();
int top = blockBoundingGeometry(block).translated(contentOffset()).top();
int bottom = top + blockBoundingRect(block).height();
int blockHeight = blockBoundingRect(block).height();
int firstVisibleLine = -1;
int lastVisibleLine = -1;
while (block.isValid() && top <= event->rect().bottom())
{
if (block.isVisible())
{
if (firstVisibleLine < 0 && bottom >= event->rect().top())
{
firstVisibleLine = block.blockNumber();
}
lastVisibleLine = block.blockNumber();
}
block = block.next();
top = bottom;
bottom = top + static_cast<int>(blockBoundingRect(block).height());
}
std::vector<std::pair<int, int>> ranges;
for (size_t i : m_colorChangedAnnotationIndices)
{
Annotation& annotation = m_annotations[i];
ranges.push_back(std::pair<int, int>(annotation.start, annotation.end));
}
m_highlighter->highlightRange(firstVisibleLine, lastVisibleLine, ranges);
firstVisibleLine += m_startLineNumber;
lastVisibleLine += m_startLineNumber;
int borderRadius = 3;
for (const Annotation& annotation : m_annotations)
{
if (annotation.startLine > lastVisibleLine || annotation.endLine < firstVisibleLine)
{
continue;
}
const AnnotationColor& color = getAnnotationColorForAnnotation(annotation);
if (color.border == "transparent" && color.fill == "transparent")
{
continue;
}
painter.setPen(QPen(color.border.c_str()));
painter.setBrush(QBrush(color.fill.c_str()));
if (annotation.locationType == LOCATION_SCOPE)
{
painter.drawRoundedRect(
0, top + (annotation.startLine - m_startLineNumber) * blockHeight,
width(), (annotation.endLine - annotation.startLine + 1) * blockHeight,
borderRadius, borderRadius
);
}
else
{
std::vector<QRect> rects = getCursorRectsForAnnotation(annotation);
for (QRect rect : rects)
{
rect.adjust(-1, 0, 1, 1);
painter.drawRoundedRect(rect, borderRadius, borderRadius);
}
}
}
QPlainTextEdit::paintEvent(event);
}
void QtCodeArea::enterEvent(QEvent* event)
{
}
void QtCodeArea::leaveEvent(QEvent* event)
{
setHoveredAnnotations(std::vector<const Annotation*>());
}
void QtCodeArea::mousePressEvent(QMouseEvent* event)
{
clearSelection();
@@ -612,10 +453,10 @@ void QtCodeArea::contextMenuEvent(QContextMenuEvent* event)
m_eventPosition = event->pos();
QtContextMenu menu(event, this);
if (!m_locationFile->getFilePath().empty())
if (!getSourceLocationFile()->getFilePath().empty())
{
menu.addSeparator();
menu.addFileActions(m_locationFile->getFilePath());
menu.addFileActions(getSourceLocationFile()->getFilePath());
menu.addSeparator();
menu.addAction(m_setIDECursorPositionAction);
}
@@ -623,6 +464,16 @@ void QtCodeArea::contextMenuEvent(QContextMenuEvent* event)
}
}
void QtCodeArea::focusTokenIds(const std::vector<Id>& tokenIds)
{
MessageFocusIn(tokenIds, TOOLTIP_ORIGIN_CODE).dispatch();
}
void QtCodeArea::defocusTokenIds(const std::vector<Id>& tokenIds)
{
MessageFocusOut(tokenIds).dispatch();
}
void QtCodeArea::updateLineNumberAreaWidth(int /* newBlockCount */)
{
setViewportMargins(lineNumberAreaWidth(), 0, 0, 0);
@@ -668,24 +519,7 @@ void QtCodeArea::setIDECursorPosition()
{
std::pair<int, int> lineColumn = toLineColumn(this->cursorForPosition(m_eventPosition).position());
MessageMoveIDECursor(m_locationFile->getFilePath().str(), lineColumn.first, lineColumn.second).dispatch();
}
std::vector<const QtCodeArea::Annotation*> QtCodeArea::getInteractiveAnnotationsForPosition(int pos) const
{
std::vector<const QtCodeArea::Annotation*> annotations;
for (const Annotation& annotation : m_annotations)
{
const LocationType& type = annotation.locationType;
if ((type == LOCATION_TOKEN || type == LOCATION_LOCAL_SYMBOL || type == LOCATION_ERROR)
&& pos >= annotation.start && pos <= annotation.end)
{
annotations.push_back(&annotation);
}
}
return annotations;
MessageMoveIDECursor(getSourceLocationFile()->getFilePath().str(), lineColumn.first, lineColumn.second).dispatch();
}
void QtCodeArea::activateSourceLocations(const std::vector<const Annotation*>& annotations)
@@ -772,215 +606,21 @@ void QtCodeArea::activateErrors(const std::vector<const Annotation*>& annotation
}
}
void QtCodeArea::createAnnotations(std::shared_ptr<SourceLocationFile> locationFile)
{
uint endLineNumber = getEndLineNumber();
std::set<Id> locationIds;
locationFile->forEachSourceLocation(
[&](const SourceLocation* location)
{
if (locationIds.find(location->getLocationId()) != locationIds.end())
{
return;
}
locationIds.insert(location->getLocationId());
Annotation annotation;
const SourceLocation* startLocation = location->getStartLocation();
if (!startLocation || startLocation->getLineNumber() < m_startLineNumber)
{
annotation.start = startTextEditPosition();
annotation.startLine = m_startLineNumber;
annotation.startCol = 0;
}
else if (startLocation->getLineNumber() <= endLineNumber)
{
annotation.start = toTextEditPosition(startLocation->getLineNumber(), startLocation->getColumnNumber() - 1);
annotation.startLine = startLocation->getLineNumber();
annotation.startCol = startLocation->getColumnNumber() - 1;
}
else
{
return;
}
const SourceLocation* endLocation = location->getEndLocation();
if (!endLocation || endLocation->getLineNumber() > endLineNumber)
{
annotation.end = endTextEditPosition();
annotation.endLine = endLineNumber;
annotation.endCol = m_lineLengths[document()->blockCount() - 1];
}
else if (endLocation->getLineNumber() >= m_startLineNumber)
{
annotation.end = toTextEditPosition(endLocation->getLineNumber(), endLocation->getColumnNumber());
annotation.endLine = endLocation->getLineNumber();
annotation.endCol = endLocation->getColumnNumber();
}
else
{
return;
}
annotation.tokenIds.insert(location->getTokenIds().begin(), location->getTokenIds().end());
annotation.locationId = location->getLocationId();
annotation.locationType = location->getType();
annotation.isActive = false;
annotation.isFocused = false;
m_annotations.push_back(annotation);
}
);
}
void QtCodeArea::annotateText()
{
const std::set<Id>& currentActiveTokenIds = m_navigator->getCurrentActiveTokenIds();
const std::set<Id>& currentActiveLocationIds = m_navigator->getCurrentActiveLocationIds();
std::set<Id> activeSymbolIds = m_navigator->getCurrentActiveTokenIds();
utility::append(activeSymbolIds, m_navigator->getActiveLocalSymbolIds());
const std::set<Id>& activeTokenIds = m_navigator->getActiveTokenIds();
const std::set<Id>& activeLocalSymbolIds = m_navigator->getActiveLocalSymbolIds();
const std::set<Id>& focusIds = m_navigator->getFocusedTokenIds();
const std::set<Id>& activeLocationIds = m_navigator->getCurrentActiveLocationIds();
std::vector<int> linesToRehighlight;
std::set<Id> focusedSymbolIds = m_navigator->getActiveTokenIds();
utility::append(focusedSymbolIds, m_navigator->getFocusedTokenIds());
bool needsUpdate = false;
for (size_t i = 0; i < m_annotations.size(); i++)
{
Annotation& annotation = m_annotations[i];
bool wasActive = annotation.isActive;
bool wasFocused = annotation.isFocused;
const AnnotationColor& oldColor = getAnnotationColorForAnnotation(annotation);
annotation.isActive = (
utility::shareElement(currentActiveTokenIds, annotation.tokenIds) ||
utility::shareElement(activeLocalSymbolIds, annotation.tokenIds) ||
currentActiveLocationIds.find(annotation.locationId) != currentActiveLocationIds.end()
);
if (!annotation.isActive)
{
annotation.isFocused = (
utility::shareElement(focusIds, annotation.tokenIds) ||
utility::shareElement(activeTokenIds, annotation.tokenIds)
);
}
const AnnotationColor& newColor = getAnnotationColorForAnnotation(annotation);
if (newColor.text != oldColor.text || (!m_wasAnnotated && newColor.text != "transparent"))
{
if (newColor.text.size() > 0 && newColor.text != "transparent")
{
if (!annotation.oldTextColor.isValid())
{
annotation.oldTextColor = m_highlighter->getFormat(annotation.start, annotation.end).foreground().color();
}
setTextColorForAnnotation(annotation, QColor(newColor.text.c_str()));
m_colorChangedAnnotationIndices.insert(i);
}
else if (annotation.oldTextColor.isValid())
{
setTextColorForAnnotation(annotation, annotation.oldTextColor);
annotation.oldTextColor = QColor();
m_colorChangedAnnotationIndices.erase(i);
linesToRehighlight.push_back(annotation.startLine - 1);
}
}
if (wasFocused != annotation.isFocused || wasActive != annotation.isActive)
{
needsUpdate = true;
}
}
if (linesToRehighlight.size())
{
m_highlighter->rehighlightLines(linesToRehighlight);
}
if (m_wasAnnotated && needsUpdate)
bool needsUpdate = QtCodeField::annotateText(activeSymbolIds, activeLocationIds, focusedSymbolIds);
if (needsUpdate)
{
m_lineNumberArea->update();
viewport()->update();
}
m_wasAnnotated = true;
}
void QtCodeArea::setHoveredAnnotations(const std::vector<const Annotation*>& annotations)
{
if (m_hoveredAnnotations.size())
{
std::vector<Id> tokenIds;
for (const Annotation* annotation : m_hoveredAnnotations)
{
tokenIds.insert(tokenIds.end(), annotation->tokenIds.begin(), annotation->tokenIds.end());
}
MessageFocusOut(tokenIds).dispatch();
}
m_hoveredAnnotations = annotations;
if (annotations.size())
{
std::vector<Id> tokenIds;
for (const Annotation* annotation : annotations)
{
tokenIds.insert(tokenIds.end(), annotation->tokenIds.begin(), annotation->tokenIds.end());
}
MessageFocusIn(tokenIds).dispatch();
}
}
int QtCodeArea::toTextEditPosition(int lineNumber, int columnNumber) const
{
lineNumber -= m_startLineNumber - 1;
int position = 0;
for (int i = 0; i < lineNumber - 1; i++)
{
position += m_lineLengths[i];
}
position += columnNumber;
return position;
}
std::pair<int, int> QtCodeArea::toLineColumn(int textEditPosition) const
{
int lineNumber = m_startLineNumber;
for (int i = 0; i < document()->lineCount(); i++)
{
int nextTextEditPosition = textEditPosition - m_lineLengths[i];
if (nextTextEditPosition >= 0)
{
textEditPosition = nextTextEditPosition;
lineNumber++;
}
else
{
break;
}
}
return std::make_pair(lineNumber, textEditPosition);
}
int QtCodeArea::startTextEditPosition() const
{
return 0;
}
int QtCodeArea::endTextEditPosition() const
{
return m_endTextEditPosition;
}
std::set<int> QtCodeArea::getActiveLineNumbers() const
@@ -1001,111 +641,6 @@ std::set<int> QtCodeArea::getActiveLineNumbers() const
return activeLineNumbers;
}
std::vector<QRect> QtCodeArea::getCursorRectsForAnnotation(const Annotation& annotation) const
{
std::vector<QRect> rects;
QTextCursor cursor = QTextCursor(document());
cursor.setPosition(annotation.start);
QRect rectStart = cursorRect(cursor);
QRect rectEnd;
int line = annotation.startLine;
while (line <= annotation.endLine)
{
if (line == annotation.endLine)
{
// Avoid that annotations at line end span down to first column of the next line.
if (annotation.startLine != annotation.endLine ||
m_lineLengths[line - m_startLineNumber] != annotation.endCol)
{
cursor.setPosition(annotation.end);
}
}
else
{
cursor.setPosition(toTextEditPosition(line, m_lineLengths[line - m_startLineNumber] - 1));
}
rectEnd = cursorRect(cursor);
rects.push_back(QRect(
rectStart.left(),
rectStart.top(),
rectEnd.right() - rectStart.left(),
rectEnd.bottom() - rectStart.top()
));
line++;
if (int(line - m_startLineNumber) < document()->blockCount())
{
cursor.setPosition(toTextEditPosition(line, 0));
rectStart = cursorRect(cursor);
}
}
return rects;
}
const QtCodeArea::AnnotationColor& QtCodeArea::getAnnotationColorForAnnotation(const Annotation& annotation)
{
if (!s_annotationColors.size())
{
ColorScheme* scheme = ColorScheme::getInstance().get();
std::vector<std::string> types = { "token", "local_symbol", "scope", "error", "fulltext" };
std::vector<ColorScheme::ColorState> states = { ColorScheme::NORMAL, ColorScheme::FOCUS, ColorScheme::ACTIVE };
for (const std::string& type : types)
{
for (const ColorScheme::ColorState& state : states)
{
AnnotationColor color;
color.border = scheme->getCodeAnnotationTypeColor(type, "border", state);
color.fill = scheme->getCodeAnnotationTypeColor(type, "fill", state);
color.text = scheme->getCodeAnnotationTypeColor(type, "text", state);
s_annotationColors.push_back(color);
}
}
}
size_t i = 0;
if (annotation.locationType == LOCATION_LOCAL_SYMBOL)
{
i = 3;
}
else if (annotation.locationType == LOCATION_SCOPE)
{
i = 6;
}
else if (annotation.locationType == LOCATION_ERROR)
{
i = 9;
}
else if (annotation.locationType == LOCATION_FULLTEXT)
{
i = 12;
}
if (annotation.isActive)
{
i += 2;
}
else if (annotation.isFocused)
{
i += 1;
}
return s_annotationColors[i];
}
void QtCodeArea::setTextColorForAnnotation(Annotation& annotation, QColor color) const
{
QTextCharFormat format;
format.setForeground(color);
m_highlighter->applyFormat(annotation.start, annotation.end, format);
}
void QtCodeArea::createActions()
{
m_setIDECursorPositionAction = new QAction(tr("Set IDE Cursor"), this);
@@ -1113,16 +648,3 @@ void QtCodeArea::createActions()
m_setIDECursorPositionAction->setToolTip(tr("Set the IDE Cursor to this code position"));
connect(m_setIDECursorPositionAction, SIGNAL(triggered()), this, SLOT(setIDECursorPosition()));
}
void QtCodeArea::createLineLengthCache()
{
m_endTextEditPosition = -1;
m_lineLengths.clear();
for (QTextBlock it = document()->begin(); it != document()->end(); it = it.next())
{
m_lineLengths.push_back(it.length());
m_endTextEditPosition += it.length();
}
}
+5 -85
View File
@@ -2,25 +2,17 @@
#define QT_CODE_AREA_H
#include <memory>
#include <set>
#include <vector>
#include <QPlainTextEdit>
#include "data/location/LocationType.h"
#include "qt/element/QtCodeField.h"
#include "qt/utility/QtScrollSpeedChangeListener.h"
#include "utility/types.h"
class QDragMoveEvent;
class QPaintEvent;
class QResizeEvent;
class QSize;
class QtCodeNavigator;
class QtHighlighter;
class QWidget;
class SourceLocation;
class SourceLocationFile;
class MouseWheelOverScrollbarFilter
: public QObject
@@ -36,7 +28,7 @@ protected:
class QtCodeArea
: public QPlainTextEdit
: public QtCodeField
{
Q_OBJECT
@@ -57,8 +49,6 @@ public:
QtCodeArea* m_codeArea;
};
static void clearAnnotationColors();
QtCodeArea(
uint startLineNumber,
const std::string& code,
@@ -70,11 +60,6 @@ public:
virtual QSize sizeHint() const Q_DECL_OVERRIDE;
uint getStartLineNumber() const;
uint getEndLineNumber() const;
std::shared_ptr<SourceLocationFile> getSourceLocationFile() const;
void lineNumberAreaPaintEvent(QPaintEvent* event);
int lineNumberDigits() const;
int lineNumberAreaWidth() const;
@@ -94,16 +79,10 @@ public:
QRectF getLineRectForLineNumber(uint lineNumber) const;
std::string getCode() const;
void hideLineNumbers();
protected:
virtual void resizeEvent(QResizeEvent* event) Q_DECL_OVERRIDE;
virtual void showEvent(QShowEvent* event) Q_DECL_OVERRIDE;
virtual void paintEvent(QPaintEvent* event) Q_DECL_OVERRIDE;
virtual void enterEvent(QEvent* event) Q_DECL_OVERRIDE;
virtual void leaveEvent(QEvent* event) Q_DECL_OVERRIDE;
virtual void mouseReleaseEvent(QMouseEvent* event) Q_DECL_OVERRIDE;
virtual void mousePressEvent(QMouseEvent* event) Q_DECL_OVERRIDE;
virtual void mouseMoveEvent(QMouseEvent* event) Q_DECL_OVERRIDE;
@@ -111,6 +90,9 @@ protected:
virtual void contextMenuEvent(QContextMenuEvent* event) Q_DECL_OVERRIDE;
virtual void focusTokenIds(const std::vector<Id>& tokenIds) override;
virtual void defocusTokenIds(const std::vector<Id>& tokenIds) override;
private slots:
void updateLineNumberAreaWidth(int newBlockCount = 0);
void updateLineNumberArea(const QRect&, int);
@@ -119,76 +101,18 @@ private slots:
void setIDECursorPosition();
private:
struct Annotation
{
int startLine;
int endLine;
int startCol;
int endCol;
int start;
int end;
std::set<Id> tokenIds;
Id locationId;
LocationType locationType;
bool isActive;
bool isFocused;
QColor oldTextColor;
};
struct AnnotationColor
{
std::string border;
std::string fill;
std::string text;
};
std::vector<const Annotation*> getInteractiveAnnotationsForPosition(int pos) const;
void activateSourceLocations(const std::vector<const Annotation*>& annotations);
void activateLocalSymbols(const std::vector<const Annotation*>& annotations);
void activateErrors(const std::vector<const Annotation*>& annotations);
void createAnnotations(std::shared_ptr<SourceLocationFile> locationFile);
void annotateText();
void setHoveredAnnotations(const std::vector<const Annotation*>& annotations);
int toTextEditPosition(int lineNumber, int columnNumber) const;
std::pair<int, int> toLineColumn(int textEditPosition) const;
int startTextEditPosition() const;
int endTextEditPosition() const;
std::set<int> getActiveLineNumbers() const;
std::vector<QRect> getCursorRectsForAnnotation(const Annotation& annotation) const;
const AnnotationColor& getAnnotationColorForAnnotation(const Annotation& annotation);
void setTextColorForAnnotation(Annotation& annotation, QColor color) const;
void createActions();
void createLineLengthCache();
static std::vector<AnnotationColor> s_annotationColors;
QtCodeNavigator* m_navigator;
QWidget* m_lineNumberArea;
QtHighlighter* m_highlighter;
const uint m_startLineNumber;
const std::string m_code;
std::shared_ptr<SourceLocationFile> m_locationFile;
std::vector<Annotation> m_annotations;
std::vector<const Annotation*> m_hoveredAnnotations;
std::set<size_t> m_colorChangedAnnotationIndices;
int m_digits;
@@ -203,10 +127,6 @@ private:
bool m_isActiveFile;
bool m_lineNumbersHidden;
bool m_wasAnnotated;
std::vector<int> m_lineLengths;
int m_endTextEditPosition;
QtScrollSpeedChangeListener m_scrollSpeedChangeListener;
};
+613
View File
@@ -0,0 +1,613 @@
#include "QtCodeField.h"
#include <QPainter>
#include <QTextBlock>
#include "data/location/SourceLocation.h"
#include "data/location/SourceLocationFile.h"
#include "qt/utility/QtHighlighter.h"
#include "settings/ApplicationSettings.h"
#include "settings/ColorScheme.h"
#include "utility/messaging/type/MessageActivateTokenIds.h"
#include "utility/utility.h"
std::vector<QtCodeField::AnnotationColor> QtCodeField::s_annotationColors;
void QtCodeField::clearAnnotationColors()
{
s_annotationColors.clear();
}
QtCodeField::QtCodeField(
uint startLineNumber,
const std::string& code,
std::shared_ptr<SourceLocationFile> locationFile,
QWidget* parent
)
: QPlainTextEdit(parent)
, m_startLineNumber(startLineNumber)
, m_code(code)
, m_locationFile(locationFile)
, m_endTextEditPosition(0)
, m_wasAnnotated(false)
{
setObjectName("code_area");
setReadOnly(true);
setFrameStyle(QFrame::NoFrame);
setLineWrapMode(QPlainTextEdit::NoWrap);
setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
viewport()->setCursor(Qt::ArrowCursor);
std::string displayCode = m_code;
if (!displayCode.empty() && *displayCode.rbegin() == '\n')
{
displayCode.pop_back();
}
setPlainText(QString::fromUtf8(displayCode.c_str()));
createLineLengthCache();
this->setMouseTracking(true);
createAnnotations(locationFile);
FilePath path = m_locationFile->getFilePath();
LanguageType language = LANGUAGE_UNKNOWN;
if (!path.empty())
{
language = (path.extension() == ".java" ? LANGUAGE_JAVA : LANGUAGE_CPP);
}
m_highlighter = new QtHighlighter(document(), language);
m_highlighter->highlightDocument();
ApplicationSettings* appSettings = ApplicationSettings::getInstance().get();
setFont(QFont(appSettings->getFontName().c_str(), appSettings->getFontSize()));
setTabStopWidth(appSettings->getCodeTabWidth() * fontMetrics().width('9'));
}
QtCodeField::~QtCodeField()
{
}
QSize QtCodeField::sizeHint() const
{
double height = 0;
int width = 0;
QFontMetrics fm = fontMetrics();
int maxTextSize = 0;
for (QTextBlock block = document()->firstBlock(); block.isValid(); block = block.next())
{
QRectF rect = blockBoundingGeometry(block);
height += rect.height();
{
int blockWidth = fm.boundingRect(
0, 0, 1000000, 1000000,
Qt::AlignLeft | Qt::AlignTop | Qt::TextExpandTabs, block.text(), tabStopWidth()).width();
width = std::max(blockWidth, width);
maxTextSize = block.text().size();
}
}
return QSize(width + 1, height + 5);
}
uint QtCodeField::getStartLineNumber() const
{
return m_startLineNumber;
}
uint QtCodeField::getEndLineNumber() const
{
return m_startLineNumber + blockCount() - 1;
}
std::string QtCodeField::getCode() const
{
return m_code;
}
std::shared_ptr<SourceLocationFile> QtCodeField::getSourceLocationFile() const
{
return m_locationFile;
}
void QtCodeField::annotateText()
{
annotateText(std::set<Id>(), std::set<Id>(), std::set<Id>());
}
void QtCodeField::paintEvent(QPaintEvent* event)
{
QPainter painter(viewport());
QTextBlock block = firstVisibleBlock();
int top = blockBoundingGeometry(block).translated(contentOffset()).top();
int bottom = top + blockBoundingRect(block).height();
int blockHeight = blockBoundingRect(block).height();
int firstVisibleLine = -1;
int lastVisibleLine = -1;
while (block.isValid() && top <= event->rect().bottom())
{
if (block.isVisible())
{
if (firstVisibleLine < 0 && bottom >= event->rect().top())
{
firstVisibleLine = block.blockNumber();
}
lastVisibleLine = block.blockNumber();
}
block = block.next();
top = bottom;
bottom = top + static_cast<int>(blockBoundingRect(block).height());
}
std::vector<std::pair<int, int>> ranges;
for (size_t i : m_colorChangedAnnotationIndices)
{
Annotation& annotation = m_annotations[i];
ranges.push_back(std::pair<int, int>(annotation.start, annotation.end));
}
m_highlighter->highlightRange(firstVisibleLine, lastVisibleLine, ranges);
firstVisibleLine += m_startLineNumber;
lastVisibleLine += m_startLineNumber;
int borderRadius = 3;
for (const Annotation& annotation : m_annotations)
{
if (annotation.startLine > lastVisibleLine || annotation.endLine < firstVisibleLine)
{
continue;
}
const AnnotationColor& color = getAnnotationColorForAnnotation(annotation);
if (color.border == "transparent" && color.fill == "transparent")
{
continue;
}
painter.setPen(QPen(color.border.c_str()));
painter.setBrush(QBrush(color.fill.c_str()));
if (annotation.locationType == LOCATION_SCOPE)
{
painter.drawRoundedRect(
0, top + (annotation.startLine - m_startLineNumber) * blockHeight,
width(), (annotation.endLine - annotation.startLine + 1) * blockHeight,
borderRadius, borderRadius
);
}
else
{
std::vector<QRect> rects = getCursorRectsForAnnotation(annotation);
for (QRect rect : rects)
{
rect.adjust(-1, 0, 1, 1);
painter.drawRoundedRect(rect, borderRadius, borderRadius);
}
}
}
QPlainTextEdit::paintEvent(event);
}
void QtCodeField::enterEvent(QEvent* event)
{
}
void QtCodeField::leaveEvent(QEvent* event)
{
setHoveredAnnotations(std::vector<const Annotation*>());
}
void QtCodeField::mouseMoveEvent(QMouseEvent* event)
{
QTextCursor cursor = this->cursorForPosition(event->pos());
std::vector<const Annotation*> annotations = getInteractiveAnnotationsForPosition(cursor.position());
bool same = annotations.size() == m_hoveredAnnotations.size();
if (same)
{
for (size_t i = 0; i < annotations.size(); i++)
{
if (annotations[i] != m_hoveredAnnotations[i])
{
same = false;
break;
}
}
}
if (!same)
{
setHoveredAnnotations(annotations);
}
}
void QtCodeField::mouseReleaseEvent(QMouseEvent* event)
{
if (event->button() != Qt::LeftButton)
{
return;
}
viewport()->setCursor(Qt::ArrowCursor);
QTextCursor cursor = this->cursorForPosition(event->pos());
std::vector<const Annotation*> annotations = getInteractiveAnnotationsForPosition(cursor.position());
if (!annotations.size())
{
return;
}
std::set<Id> tokenIds;
for (const Annotation* annotation : annotations)
{
tokenIds.insert(annotation->tokenIds.begin(), annotation->tokenIds.end());
}
if (tokenIds.size())
{
MessageActivateTokenIds(utility::toVector(tokenIds)).dispatch();
}
}
void QtCodeField::focusTokenIds(const std::vector<Id>& tokenIds)
{
annotateText(std::set<Id>(), std::set<Id>(), std::set<Id>(tokenIds.begin(), tokenIds.end()));
}
void QtCodeField::defocusTokenIds(const std::vector<Id>& tokenIds)
{
annotateText(std::set<Id>(), std::set<Id>(), std::set<Id>());
}
bool QtCodeField::annotateText(
const std::set<Id>& activeSymbolIds, const std::set<Id>& activeLocationIds, const std::set<Id>& focusedSymbolIds)
{
std::vector<int> linesToRehighlight;
bool needsUpdate = false;
for (size_t i = 0; i < m_annotations.size(); i++)
{
Annotation& annotation = m_annotations[i];
bool wasActive = annotation.isActive;
bool wasFocused = annotation.isFocused;
const AnnotationColor& oldColor = getAnnotationColorForAnnotation(annotation);
annotation.isActive = (
utility::shareElement(activeSymbolIds, annotation.tokenIds) ||
activeLocationIds.find(annotation.locationId) != activeLocationIds.end()
);
if (!annotation.isActive)
{
annotation.isFocused = utility::shareElement(focusedSymbolIds, annotation.tokenIds);
}
const AnnotationColor& newColor = getAnnotationColorForAnnotation(annotation);
if (newColor.text != oldColor.text || (!m_wasAnnotated && newColor.text != "transparent"))
{
if (newColor.text.size() > 0 && newColor.text != "transparent")
{
if (!annotation.oldTextColor.isValid())
{
annotation.oldTextColor =
m_highlighter->getFormat(annotation.start, annotation.end).foreground().color();
}
setTextColorForAnnotation(annotation, QColor(newColor.text.c_str()));
m_colorChangedAnnotationIndices.insert(i);
}
else if (annotation.oldTextColor.isValid())
{
setTextColorForAnnotation(annotation, annotation.oldTextColor);
annotation.oldTextColor = QColor();
m_colorChangedAnnotationIndices.erase(i);
linesToRehighlight.push_back(annotation.startLine - 1);
}
}
if (wasFocused != annotation.isFocused || wasActive != annotation.isActive)
{
needsUpdate = true;
}
}
if (linesToRehighlight.size())
{
m_highlighter->rehighlightLines(linesToRehighlight);
}
needsUpdate = (needsUpdate && m_wasAnnotated);
if (needsUpdate)
{
viewport()->update();
}
m_wasAnnotated = true;
return needsUpdate;
}
void QtCodeField::createAnnotations(std::shared_ptr<SourceLocationFile> locationFile)
{
uint endLineNumber = getEndLineNumber();
std::set<Id> locationIds;
locationFile->forEachSourceLocation(
[&](const SourceLocation* location)
{
if (locationIds.find(location->getLocationId()) != locationIds.end())
{
return;
}
locationIds.insert(location->getLocationId());
Annotation annotation;
const SourceLocation* startLocation = location->getStartLocation();
if (!startLocation || startLocation->getLineNumber() < m_startLineNumber)
{
annotation.start = startTextEditPosition();
annotation.startLine = m_startLineNumber;
annotation.startCol = 0;
}
else if (startLocation->getLineNumber() <= endLineNumber)
{
annotation.start = toTextEditPosition(startLocation->getLineNumber(), startLocation->getColumnNumber() - 1);
annotation.startLine = startLocation->getLineNumber();
annotation.startCol = startLocation->getColumnNumber() - 1;
}
else
{
return;
}
const SourceLocation* endLocation = location->getEndLocation();
if (!endLocation || endLocation->getLineNumber() > endLineNumber)
{
annotation.end = endTextEditPosition();
annotation.endLine = endLineNumber;
annotation.endCol = m_lineLengths[document()->blockCount() - 1];
}
else if (endLocation->getLineNumber() >= m_startLineNumber)
{
annotation.end = toTextEditPosition(endLocation->getLineNumber(), endLocation->getColumnNumber());
annotation.endLine = endLocation->getLineNumber();
annotation.endCol = endLocation->getColumnNumber();
}
else
{
return;
}
annotation.tokenIds.insert(location->getTokenIds().begin(), location->getTokenIds().end());
annotation.locationId = location->getLocationId();
annotation.locationType = location->getType();
annotation.isActive = false;
annotation.isFocused = false;
m_annotations.push_back(annotation);
}
);
}
int QtCodeField::toTextEditPosition(int lineNumber, int columnNumber) const
{
lineNumber -= m_startLineNumber - 1;
int position = 0;
for (int i = 0; i < lineNumber - 1; i++)
{
position += m_lineLengths[i];
}
position += columnNumber;
return position;
}
std::pair<int, int> QtCodeField::toLineColumn(int textEditPosition) const
{
int lineNumber = m_startLineNumber;
for (int i = 0; i < document()->lineCount(); i++)
{
int nextTextEditPosition = textEditPosition - m_lineLengths[i];
if (nextTextEditPosition >= 0)
{
textEditPosition = nextTextEditPosition;
lineNumber++;
}
else
{
break;
}
}
return std::make_pair(lineNumber, textEditPosition);
}
int QtCodeField::startTextEditPosition() const
{
return 0;
}
int QtCodeField::endTextEditPosition() const
{
return m_endTextEditPosition;
}
void QtCodeField::setHoveredAnnotations(const std::vector<const Annotation*>& annotations)
{
if (m_hoveredAnnotations.size())
{
std::vector<Id> tokenIds;
for (const Annotation* annotation : m_hoveredAnnotations)
{
tokenIds.insert(tokenIds.end(), annotation->tokenIds.begin(), annotation->tokenIds.end());
}
defocusTokenIds(tokenIds);
}
m_hoveredAnnotations = annotations;
if (annotations.size())
{
std::vector<Id> tokenIds;
for (const Annotation* annotation : annotations)
{
tokenIds.insert(tokenIds.end(), annotation->tokenIds.begin(), annotation->tokenIds.end());
}
focusTokenIds(tokenIds);
}
}
std::vector<QRect> QtCodeField::getCursorRectsForAnnotation(const Annotation& annotation) const
{
std::vector<QRect> rects;
QTextCursor cursor = QTextCursor(document());
cursor.setPosition(annotation.start);
QRect rectStart = cursorRect(cursor);
QRect rectEnd;
int line = annotation.startLine;
while (line <= annotation.endLine)
{
if (line == annotation.endLine)
{
// Avoid that annotations at line end span down to first column of the next line.
if (annotation.startLine != annotation.endLine ||
m_lineLengths[line - m_startLineNumber] != annotation.endCol)
{
cursor.setPosition(annotation.end);
}
}
else
{
cursor.setPosition(toTextEditPosition(line, m_lineLengths[line - m_startLineNumber] - 1));
}
rectEnd = cursorRect(cursor);
rects.push_back(QRect(
rectStart.left(),
rectStart.top(),
rectEnd.right() - rectStart.left(),
rectEnd.bottom() - rectStart.top()
));
line++;
if (int(line - m_startLineNumber) < document()->blockCount())
{
cursor.setPosition(toTextEditPosition(line, 0));
rectStart = cursorRect(cursor);
}
}
return rects;
}
const QtCodeField::AnnotationColor& QtCodeField::getAnnotationColorForAnnotation(const Annotation& annotation)
{
if (!s_annotationColors.size())
{
ColorScheme* scheme = ColorScheme::getInstance().get();
std::vector<std::string> types = { "token", "local_symbol", "scope", "error", "fulltext" };
std::vector<ColorScheme::ColorState> states = { ColorScheme::NORMAL, ColorScheme::FOCUS, ColorScheme::ACTIVE };
for (const std::string& type : types)
{
for (const ColorScheme::ColorState& state : states)
{
AnnotationColor color;
color.border = scheme->getCodeAnnotationTypeColor(type, "border", state);
color.fill = scheme->getCodeAnnotationTypeColor(type, "fill", state);
color.text = scheme->getCodeAnnotationTypeColor(type, "text", state);
s_annotationColors.push_back(color);
}
}
}
size_t i = 0;
if (annotation.locationType == LOCATION_LOCAL_SYMBOL)
{
i = 3;
}
else if (annotation.locationType == LOCATION_SCOPE)
{
i = 6;
}
else if (annotation.locationType == LOCATION_ERROR)
{
i = 9;
}
else if (annotation.locationType == LOCATION_FULLTEXT)
{
i = 12;
}
if (annotation.isActive)
{
i += 2;
}
else if (annotation.isFocused)
{
i += 1;
}
return s_annotationColors[i];
}
void QtCodeField::setTextColorForAnnotation(Annotation& annotation, QColor color) const
{
QTextCharFormat format;
format.setForeground(color);
m_highlighter->applyFormat(annotation.start, annotation.end, format);
}
std::vector<const QtCodeField::Annotation*> QtCodeField::getInteractiveAnnotationsForPosition(int pos) const
{
std::vector<const QtCodeField::Annotation*> annotations;
for (const Annotation& annotation : m_annotations)
{
const LocationType& type = annotation.locationType;
if ((type == LOCATION_TOKEN || type == LOCATION_LOCAL_SYMBOL || type == LOCATION_ERROR)
&& pos >= annotation.start && pos <= annotation.end)
{
annotations.push_back(&annotation);
}
}
return annotations;
}
void QtCodeField::createLineLengthCache()
{
m_endTextEditPosition = -1;
m_lineLengths.clear();
for (QTextBlock it = document()->begin(); it != document()->end(); it = it.next())
{
m_lineLengths.push_back(it.length());
m_endTextEditPosition += it.length();
}
}
+122
View File
@@ -0,0 +1,122 @@
#ifndef QT_CODE_FIELD_H
#define QT_CODE_FIELD_H
#include <set>
#include <QPlainTextEdit>
#include "data/location/LocationType.h"
#include "utility/types.h"
class QtHighlighter;
class SourceLocation;
class SourceLocationFile;
class QtCodeField
: public QPlainTextEdit
{
Q_OBJECT
public:
static void clearAnnotationColors();
QtCodeField(
uint startLineNumber,
const std::string& code,
std::shared_ptr<SourceLocationFile> locationFile,
QWidget* parent = nullptr);
~QtCodeField();
virtual QSize sizeHint() const Q_DECL_OVERRIDE;
uint getStartLineNumber() const;
uint getEndLineNumber() const;
std::string getCode() const;
std::shared_ptr<SourceLocationFile> getSourceLocationFile() const;
void annotateText();
protected:
virtual void paintEvent(QPaintEvent* event) Q_DECL_OVERRIDE;
virtual void enterEvent(QEvent* event) Q_DECL_OVERRIDE;
virtual void leaveEvent(QEvent* event) Q_DECL_OVERRIDE;
virtual void mouseMoveEvent(QMouseEvent* event) Q_DECL_OVERRIDE;
virtual void mouseReleaseEvent(QMouseEvent* event) Q_DECL_OVERRIDE;
virtual void focusTokenIds(const std::vector<Id>& tokenIds);
virtual void defocusTokenIds(const std::vector<Id>& tokenIds);
struct Annotation
{
int startLine;
int endLine;
int startCol;
int endCol;
int start;
int end;
std::set<Id> tokenIds;
Id locationId;
LocationType locationType;
bool isActive;
bool isFocused;
QColor oldTextColor;
};
struct AnnotationColor
{
std::string border;
std::string fill;
std::string text;
};
bool annotateText(
const std::set<Id>& activeSymbolIds, const std::set<Id>& activeLocationIds, const std::set<Id>& focusedSymbolIds);
void createAnnotations(std::shared_ptr<SourceLocationFile> locationFile);
int toTextEditPosition(int lineNumber, int columnNumber) const;
std::pair<int, int> toLineColumn(int textEditPosition) const;
int startTextEditPosition() const;
int endTextEditPosition() const;
void setHoveredAnnotations(const std::vector<const Annotation*>& annotations);
std::vector<QRect> getCursorRectsForAnnotation(const Annotation& annotation) const;
const AnnotationColor& getAnnotationColorForAnnotation(const Annotation& annotation);
void setTextColorForAnnotation(Annotation& annotation, QColor color) const;
std::vector<const Annotation*> getInteractiveAnnotationsForPosition(int pos) const;
std::vector<Annotation> m_annotations;
std::vector<const Annotation*> m_hoveredAnnotations;
private:
static std::vector<AnnotationColor> s_annotationColors;
void createLineLengthCache();
const uint m_startLineNumber;
const std::string m_code;
std::shared_ptr<SourceLocationFile> m_locationFile;
QtHighlighter* m_highlighter;
std::vector<int> m_lineLengths;
std::set<size_t> m_colorChangedAnnotationIndices;
int m_endTextEditPosition;
bool m_wasAnnotated;
};
#endif // QT_CODE_FIELD_H
+9 -6
View File
@@ -876,10 +876,13 @@ void QtCodeNavigator::handleMessage(MessageSwitchColorScheme* message)
void QtCodeNavigator::handleMessage(MessageWindowFocus* message)
{
m_onQtThread(
[=]()
{
m_current->onWindowFocus();
}
);
if (message->focusIn)
{
m_onQtThread(
[=]()
{
m_current->onWindowFocus();
}
);
}
}
+179
View File
@@ -0,0 +1,179 @@
#include "qt/element/QtTooltip.h"
#include <QApplication>
#include <QCursor>
#include <QHBoxLayout>
#include <QLabel>
#include <QPoint>
#include <QStyle>
#include <QTimer>
#include "data/location/SourceLocationFile.h"
#include "data/tooltip/TooltipInfo.h"
#include "qt/element/QtCodeField.h"
QtTooltip::QtTooltip(QWidget* parent)
: QFrame(parent)
, m_parentView(nullptr)
, m_isHovered(false)
{
QWidget::setWindowFlags(Qt::ToolTip);
setObjectName("tooltip");
QVBoxLayout* layout = new QVBoxLayout();
layout->setContentsMargins(0, 0, 0, 0);
layout->setSpacing(0);
setLayout(layout);
}
QtTooltip::~QtTooltip()
{
}
void QtTooltip::setTooltipInfo(TooltipInfo info)
{
if (info.title.size())
{
addTitle(info.title.c_str(), info.count, info.countText.c_str());
}
for (TooltipSnippet snippet : info.snippets)
{
QtCodeField* field = new QtCodeField(1, snippet.code, snippet.locationFile);
QSize size = field->sizeHint() + QSize(15, 5);
if (size.width() > 600)
{
field->setMinimumSize(QSize(600, size.height() + QApplication::style()->pixelMetric(QStyle::PM_ScrollBarExtent)));
}
else
{
field->setMinimumSize(size);
field->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
}
field->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
field->annotateText();
addWidget(field);
}
m_offset = QPoint(info.offset.x(), info.offset.y());
}
void QtTooltip::setParentView(QWidget* parentView)
{
m_parentView = parentView;
}
bool QtTooltip::isHovered() const
{
return m_isHovered;
}
void QtTooltip::show()
{
QWidget* parent = m_parentView ? m_parentView : parentWidget();
if (!parent)
{
return;
}
QWidget::show();
QPoint pos = QCursor::pos() + m_offset;
if (pos.x() + width() > parent->pos().x() + parent->width())
{
pos.setX(pos.x() - width() - m_offset.x() * 2);
}
if (pos.x() < parent->pos().x())
{
pos.setX(parent->pos().x() + 10);
}
if (pos.y() + height() > parent->pos().y() + parent->height())
{
pos.setY(pos.y() - height() - m_offset.y() * 2);
}
if (pos.y() < parent->pos().y())
{
pos.setY(parent->pos().y() + 10);
}
move(pos);
}
void QtTooltip::hide(bool force)
{
if (!m_isHovered || force)
{
QWidget::hide();
clearLayout(layout());
m_parentView = nullptr;
m_offset = QPoint();
}
}
void QtTooltip::leaveEvent(QEvent *event)
{
m_isHovered = false;
QTimer::singleShot(500, this, SLOT(hide()));
}
void QtTooltip::enterEvent(QEvent *event)
{
m_isHovered = true;
}
void QtTooltip::addTitle(QString title, int count, QString countText)
{
QHBoxLayout* titleLayout = new QHBoxLayout();
titleLayout->setContentsMargins(0, 0, 0, 0);
titleLayout->setSpacing(0);
QLabel* titleLabel = new QLabel(title);
titleLabel->setObjectName("tooltip_title");
titleLayout->addWidget(titleLabel);
if (count >= 0)
{
QLabel* referenceLabel = new QLabel(QString::number(count) + " " + countText + (count != 1 ? "s" : ""));
referenceLabel->setObjectName("tooltip_references");
titleLayout->addWidget(referenceLabel, 0, Qt::AlignRight);
}
QWidget* titleWidget = new QWidget();
titleWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum);
titleWidget->setLayout(titleLayout);
layout()->addWidget(titleWidget);
}
void QtTooltip::addWidget(QWidget *widget)
{
widget->setObjectName("tooltip_widget");
layout()->addWidget(widget);
}
void QtTooltip::clearLayout(QLayout* layout)
{
while (QLayoutItem* item = layout->takeAt(0))
{
if (QWidget* widget = item->widget())
{
widget->deleteLater();
}
if (QLayout* childLayout = item->layout())
{
clearLayout(childLayout);
}
delete item;
}
}
+43
View File
@@ -0,0 +1,43 @@
#ifndef QT_TOOLTIP_H
#define QT_TOOLTIP_H
#include <QFrame>
struct TooltipInfo;
class QtTooltip
: public QFrame
{
Q_OBJECT
public:
QtTooltip(QWidget* parent = nullptr);
virtual ~QtTooltip();
void setTooltipInfo(TooltipInfo info);
void setParentView(QWidget* parentView);
bool isHovered() const;
public slots:
virtual void show();
virtual void hide(bool force = false);
protected:
virtual void leaveEvent(QEvent* event);
virtual void enterEvent(QEvent* event);
private:
void addTitle(QString title, int count, QString countText);
void addWidget(QWidget* widget);
void clearLayout(QLayout* layout);
QWidget* m_parentView;
QPoint m_offset;
bool m_isHovered;
};
#endif // QT_TOOLTIP_H
+5
View File
@@ -55,6 +55,11 @@ void QtMainView::hideView(View* view)
);
}
View* QtMainView::findFloatingView(const std::string& name) const
{
return m_window->findFloatingView(name);
}
void QtMainView::loadLayout()
{
m_window->loadLayout();
+2
View File
@@ -38,6 +38,8 @@ public:
virtual void showView(View* view);
virtual void hideView(View* view);
virtual View* findFloatingView(const std::string& name) const;
virtual QStatusBar* getStatusBar();
virtual void setStatusBar(QStatusBar* statusBar);
+77
View File
@@ -0,0 +1,77 @@
#include "qt/view/QtTooltipView.h"
#include "qt/element/QtTooltip.h"
#include "qt/utility/utilityQt.h"
#include "qt/view/QtMainView.h"
#include "qt/view/QtViewWidgetWrapper.h"
#include "qt/window/QtMainWindow.h"
#include "settings/ColorScheme.h"
#include "utility/ResourcePaths.h"
QtTooltipView::QtTooltipView(ViewLayout* viewLayout)
: TooltipView(viewLayout)
{
m_widget = new QtTooltip(dynamic_cast<QtMainView*>(getViewLayout())->getMainWindow());
}
QtTooltipView::~QtTooltipView()
{
}
void QtTooltipView::createWidgetWrapper()
{
setWidgetWrapper(std::make_shared<QtViewWidgetWrapper>(m_widget));
}
void QtTooltipView::initView()
{
}
void QtTooltipView::refreshView()
{
m_onQtThread([=]()
{
setStyleSheet();
});
}
void QtTooltipView::showTooltip(TooltipInfo info, const View* parent)
{
m_onQtThread([=]()
{
if (m_widget->isHovered())
{
return;
}
m_widget->hide();
m_widget->setTooltipInfo(info);
if (parent)
{
m_widget->setParentView(QtViewWidgetWrapper::getWidgetOfView(parent)->parentWidget());
}
m_widget->show();
});
}
void QtTooltipView::hideTooltip(bool force)
{
m_onQtThread([=]()
{
m_widget->hide(force);
});
}
bool QtTooltipView::tooltipVisible() const
{
return m_widget->isVisible();
}
void QtTooltipView::setStyleSheet()
{
m_widget->setStyleSheet(
utility::getStyleSheet(ResourcePaths::getGuiPath().concat(FilePath("tooltip_view/tooltip.css"))).c_str()
);
}
+36
View File
@@ -0,0 +1,36 @@
#ifndef QT_TOOLTIP_VIEW
#define QT_TOOLTIP_VIEW
#include "component/view/TooltipView.h"
#include "qt/utility/QtThreadedFunctor.h"
class QTimer;
class QtTooltip;
class QtTooltipView
: public TooltipView
{
public:
QtTooltipView(ViewLayout* viewLayout);
~QtTooltipView();
// View implementation
virtual void createWidgetWrapper();
virtual void initView();
virtual void refreshView();
virtual void showTooltip(TooltipInfo info, const View* parent);
virtual void hideTooltip(bool force);
virtual bool tooltipVisible() const;
private:
void setStyleSheet();
void doRefreshView();
QtThreadedLambdaFunctor m_onQtThread;
QtTooltip* m_widget;
};
#endif // QT_TOOLTIP_VIEW
+6
View File
@@ -15,6 +15,7 @@
#include "qt/view/QtStatusBarView.h"
#include "qt/view/QtStatusView.h"
#include "qt/view/QtTabbedView.h"
#include "qt/view/QtTooltipView.h"
#include "qt/view/QtUndoRedoView.h"
QtViewFactory::QtViewFactory()
@@ -93,6 +94,11 @@ std::shared_ptr<StatusBarView> QtViewFactory::createStatusBarView(ViewLayout* vi
return View::createAndInit<QtStatusBarView>(viewLayout);
}
std::shared_ptr<TooltipView> QtViewFactory::createTooltipView(ViewLayout* viewLayout) const
{
return View::createAndInit<QtTooltipView>(viewLayout);
}
std::shared_ptr<UndoRedoView> QtViewFactory::createUndoRedoView(ViewLayout* viewLayout) const
{
return View::createInitAndAddToLayout<QtUndoRedoView>(viewLayout);
+1
View File
@@ -23,6 +23,7 @@ public:
virtual std::shared_ptr<SearchView> createSearchView(ViewLayout* viewLayout) const;
virtual std::shared_ptr<StatusBarView> createStatusBarView(ViewLayout* viewLayout) const;
virtual std::shared_ptr<StatusView> createStatusView(ViewLayout* viewLayout) const;
virtual std::shared_ptr<TooltipView> createTooltipView(ViewLayout* viewLayout) const;
virtual std::shared_ptr<UndoRedoView> createUndoRedoView(ViewLayout* viewLayout) const;
virtual std::shared_ptr<DialogView> createDialogView(ViewLayout* viewLayout, StorageAccess* storageAccess) const;
@@ -16,8 +16,11 @@
#include "utility/messaging/type/MessageFocusIn.h"
#include "utility/messaging/type/MessageFocusOut.h"
#include "utility/messaging/type/MessageGraphNodeBundleSplit.h"
#include "utility/messaging/type/MessageTooltipShow.h"
#include "utility/messaging/type/MessageTooltipHide.h"
#include "utility/utility.h"
QtGraphEdge* QtGraphEdge::s_focusedEdge = nullptr;
QtGraphEdge* QtGraphEdge::s_focusedBezierEdge = nullptr;
QtGraphEdge::QtGraphEdge(
@@ -52,6 +55,7 @@ QtGraphEdge::QtGraphEdge(
m_fromActive = m_owner.lock()->getIsActive();
m_toActive = m_target.lock()->getIsActive();
s_focusedEdge = nullptr;
s_focusedBezierEdge = nullptr;
}
@@ -85,26 +89,7 @@ void QtGraphEdge::updateLine()
return;
}
Edge::EdgeType type;
if (getData())
{
type = getData()->getType();
}
else
{
type = Edge::EDGE_AGGREGATION;
}
QString toolTip = Edge::getReadableTypeString(type).c_str();
if (type == Edge::EDGE_AGGREGATION)
{
toolTip += ": " + QString::number(m_weight) + " edge";
if (m_weight != 1)
{
toolTip += "s";
}
}
Edge::EdgeType type = (getData() ? getData()->getType() : Edge::EDGE_AGGREGATION);
GraphViewStyle::EdgeStyle style = GraphViewStyle::getStyleForEdgeType(type, m_isActive | m_isFocused, false, m_isTrailEdge);
if (m_useBezier)
@@ -130,10 +115,8 @@ void QtGraphEdge::updateLine()
bezier->updateLine(ownerRect, rect, ownerParentRect, rect, style, m_weight, false);
bezier->setRoute(route);
bezier->setPivot(QtLineItemBase::PIVOT_MIDDLE);
bezier->setToolTip(toolTip);
QtLineItemStraight* line = new QtLineItemStraight(this);
line->setToolTip(toolTip);
if (route == QtLineItemBase::ROUTE_HORIZONTAL)
{
line->updateLine(Vec2i(rect.x(), (rect.y() + rect.w()) / 2), Vec2i(rect.z(), (rect.y() + rect.w()) / 2), style);
@@ -155,7 +138,6 @@ void QtGraphEdge::updateLine()
style, m_weight, showArrow);
bezier->setRoute(route);
bezier->setPivot(QtLineItemBase::PIVOT_MIDDLE);
bezier->setToolTip(toolTip);
if (owner->getLastParent() == target->getLastParent())
{
@@ -221,8 +203,6 @@ void QtGraphEdge::updateLine()
owner->getBoundingRect(), target->getBoundingRect(),
owner->getParentBoundingRect(), target->getParentBoundingRect(),
style, m_weight, showArrow);
child->setToolTip(toolTip);
}
this->setZValue(style.zValue);
@@ -301,6 +281,22 @@ void QtGraphEdge::focusIn()
{
m_isFocused = true;
updateLine();
if (s_focusedEdge == this)
{
Edge::EdgeType type = (getData() ? getData()->getType() : Edge::EDGE_AGGREGATION);
TooltipInfo info;
info.title = Edge::getReadableTypeString(type);
if (type == Edge::EDGE_AGGREGATION)
{
info.count = m_weight;
info.countText = "edge";
}
info.offset = Vec2i(10, 20);
MessageTooltipShow(info, TOOLTIP_ORIGIN_GRAPH).dispatch();
}
}
}
@@ -310,6 +306,11 @@ void QtGraphEdge::focusOut()
{
m_isFocused = false;
updateLine();
if (s_focusedEdge == this)
{
MessageTooltipHide().dispatch();
}
}
}
@@ -349,9 +350,11 @@ void QtGraphEdge::hoverEnterEvent(QGraphicsSceneHoverEvent* event)
s_focusedBezierEdge = this;
}
s_focusedEdge = this;
if (getData() && !m_useBezier)
{
MessageFocusIn(std::vector<Id>(1, getData()->getId())).dispatch();
MessageFocusIn(std::vector<Id>(1, getData()->getId()), TOOLTIP_ORIGIN_GRAPH).dispatch();
}
else
{
@@ -371,6 +374,8 @@ void QtGraphEdge::hoverLeaveEvent(QGraphicsSceneHoverEvent* event)
{
focusOut();
}
s_focusedEdge = nullptr;
}
void QtGraphEdge::setDirection(TokenComponentAggregation::Direction direction)
@@ -64,6 +64,9 @@ protected:
virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent* event);
private:
// used to send tooltip message on focusIn(), because both focus messages are filtered out if sent close together
static QtGraphEdge* s_focusedEdge;
// used to unfocus recent edge, because hover leave event is not always received for bezier edges
static QtGraphEdge* s_focusedBezierEdge;
@@ -8,7 +8,6 @@
#include "utility/messaging/type/MessageGraphNodeMove.h"
#include "data/graph/token_component/TokenComponentFilePath.h"
#include "data/graph/token_component/TokenComponentSignature.h"
QtGraphNodeData::QtGraphNodeData(const Node* data, const std::string& name, bool hasParent, bool childVisible, bool hasQualifier)
: m_data(data)
@@ -18,39 +17,6 @@ QtGraphNodeData::QtGraphNodeData(const Node* data, const std::string& name, bool
this->setAcceptHoverEvents(true);
this->setName(name);
std::string toolTip = data->getReadableTypeString();
if (!data->isDefined() && data->isType(Node::NODE_FILE))
{
toolTip = "incomplete " + toolTip;
}
else if (!data->isDefined() && !data->isType(Node::NODE_NON_INDEXED))
{
toolTip = "non-indexed " + toolTip;
}
else if (data->isImplicit())
{
toolTip = "implicit " + toolTip;
}
if (data->isType(Node::NODE_FUNCTION | Node::NODE_METHOD))
{
TokenComponentSignature* sig = data->getComponent<TokenComponentSignature>();
if (sig)
{
toolTip += ": " + sig->getSignature();
}
}
else
{
FilePath path = getFilePath();
if (!path.empty())
{
toolTip += ": " + path.str();
}
}
this->setToolTip(QString::fromStdString(toolTip));
}
QtGraphNodeData::~QtGraphNodeData()
@@ -113,7 +79,7 @@ void QtGraphNodeData::updateStyle()
void QtGraphNodeData::hoverEnterEvent(QGraphicsSceneHoverEvent* event)
{
MessageFocusIn(std::vector<Id>(1, m_data->getId())).dispatch();
MessageFocusIn(std::vector<Id>(1, m_data->getId()), TOOLTIP_ORIGIN_GRAPH).dispatch();
}
void QtGraphNodeData::hoverLeaveEvent(QGraphicsSceneHoverEvent* event)
+18 -1
View File
@@ -200,6 +200,19 @@ void QtMainWindow::hideView(View* view)
getDockWidgetForView(view)->widget->setHidden(true);
}
View* QtMainWindow::findFloatingView(const std::string& name) const
{
for (size_t i = 0; i < m_dockWidgets.size(); i++)
{
if (std::string(m_dockWidgets[i].view->getName()) == name && m_dockWidgets[i].widget->isFloating())
{
return m_dockWidgets[i].view;
}
}
return nullptr;
}
void QtMainWindow::loadLayout()
{
QSettings settings(UserPaths::getWindowSettingsPath().str().c_str(), QSettings::IniFormat);
@@ -337,7 +350,11 @@ bool QtMainWindow::event(QEvent* event)
{
if (event->type() == QEvent::WindowActivate)
{
MessageWindowFocus().dispatch();
MessageWindowFocus(true).dispatch();
}
else if (event->type() == QEvent::WindowDeactivate)
{
MessageWindowFocus(false).dispatch();
}
return QMainWindow::event(event);
+2
View File
@@ -63,6 +63,8 @@ public:
void showView(View* view);
void hideView(View* view);
View* findFloatingView(const std::string& name) const;
void loadLayout();
void saveLayout();
@@ -107,7 +107,7 @@ public:
std::shared_ptr<SourceGroupSettings> settings, QtProjectWizzardWindow* window, bool isCDB = false);
// QtProjectWizzardContent implementation
virtual void populate(QGridLayout* layout, int& row);
virtual void populate(QGridLayout* layout, int& row) override;
virtual void load() override;
virtual void save() override;
virtual bool isScrollAble() const override;