* Added tab bar to top of main window with UI/shortcuts similar to web browsers * ComponentManager offers components for 2 use-cases: application and tab * Application components: log view (status/errors), bookmarks, screen search, status bar, tabs, tooltips, dialogs and all tab views disabled * Tab components: graph, code, history and search * When a project is loaded there is always at least one tab, otherwise there is none * Each tab replaces the application views of the same name in the main layout when activated * Each tab has it's own TaskScheduler, to process tasks independent from other tabs * The application has a global TaskScheduler for application wide tasks * The singloton class TaskManager is responsible for managing the TaskSchedulers * MessageListeners and Messages hold an optional schedulerId, both must be set to only send to a specific TaskScheduler * Bookmark buttons where split off into a separate view per tab, bookmark managemement is done in the application * History menu processing is done by the QtMainWindow now * Screen search is an application component, the responders are always changed to the active tab * Plugin messages are opened in a new tab * Symbols can be opened in a new tab via middle click/context menu in graph, code, history dropdown * Full text index creation is mutexed now in PersistenStorage to make it fully thread-safe * All tabs are closed when switching projects * Tab contents are only animated when visible fortune cookie message = Catch your lucky star!
216 lines
5.7 KiB
C++
216 lines
5.7 KiB
C++
#include "IDECommunicationController.h"
|
|
|
|
#include "FileSystem.h"
|
|
#include "logging.h"
|
|
#include "MessageActivateWindow.h"
|
|
#include "MessagePingReceived.h"
|
|
#include "MessageProjectNew.h"
|
|
#include "MessageStatus.h"
|
|
#include "MessageTabOpenWith.h"
|
|
|
|
#include "StorageAccess.h"
|
|
#include "SourceLocationFile.h"
|
|
|
|
IDECommunicationController::IDECommunicationController(StorageAccess* storageAccess)
|
|
: m_storageAccess(storageAccess)
|
|
, m_enabled(true)
|
|
{
|
|
}
|
|
|
|
IDECommunicationController::~IDECommunicationController()
|
|
{
|
|
}
|
|
|
|
void IDECommunicationController::clear()
|
|
{
|
|
}
|
|
|
|
void IDECommunicationController::handleIncomingMessage(const std::wstring& message)
|
|
{
|
|
if (m_enabled == false)
|
|
{
|
|
return;
|
|
}
|
|
|
|
NetworkProtocolHelper::MESSAGE_TYPE type = NetworkProtocolHelper::getMessageType(message);
|
|
|
|
if (type == NetworkProtocolHelper::MESSAGE_TYPE::UNKNOWN)
|
|
{
|
|
LOG_ERROR_STREAM(<< "Invalid message type");
|
|
}
|
|
else if (type == NetworkProtocolHelper::MESSAGE_TYPE::SET_ACTIVE_TOKEN)
|
|
{
|
|
handleSetActiveTokenMessage(NetworkProtocolHelper::parseSetActiveTokenMessage(message));
|
|
}
|
|
else if (type == NetworkProtocolHelper::MESSAGE_TYPE::CREATE_CDB_MESSAGE)
|
|
{
|
|
handleCreateCDBProjectMessage(NetworkProtocolHelper::parseCreateCDBProjectMessage(message));
|
|
}
|
|
else if (type == NetworkProtocolHelper::MESSAGE_TYPE::PING)
|
|
{
|
|
handlePing(NetworkProtocolHelper::parsePingMessage(message));
|
|
}
|
|
else
|
|
{
|
|
handleCreateProjectMessage(NetworkProtocolHelper::parseCreateProjectMessage(message));
|
|
}
|
|
}
|
|
|
|
bool IDECommunicationController::getEnabled() const
|
|
{
|
|
return m_enabled;
|
|
}
|
|
|
|
void IDECommunicationController::setEnabled(const bool enabled)
|
|
{
|
|
m_enabled = enabled;
|
|
}
|
|
|
|
void IDECommunicationController::sendUpdatePing()
|
|
{
|
|
// first reset connection status
|
|
MessagePingReceived().dispatch();
|
|
|
|
// send ping to update connection status
|
|
sendMessage(NetworkProtocolHelper::buildPingMessage());
|
|
}
|
|
|
|
void IDECommunicationController::handleSetActiveTokenMessage(
|
|
const NetworkProtocolHelper::SetActiveTokenMessage& message
|
|
)
|
|
{
|
|
if (message.valid)
|
|
{
|
|
const unsigned int cursorColumn = message.column;
|
|
|
|
const Id fileId = m_storageAccess->getNodeIdForFileNode(message.filePath.getCanonical());
|
|
const FileInfo fileInfo = m_storageAccess->getFileInfoForFileId(fileId);
|
|
const FilePath filePath = fileInfo.path;
|
|
|
|
if (FileSystem::getFileInfoForPath(filePath).lastWriteTime == fileInfo.lastWriteTime)
|
|
{
|
|
// file was not modified
|
|
std::shared_ptr<SourceLocationFile> sourceLocationFile = m_storageAccess->getSourceLocationsForLinesInFile(
|
|
filePath, message.row, message.row
|
|
);
|
|
|
|
std::vector<Id> selectedLocationIds;
|
|
sourceLocationFile->forEachStartSourceLocation(
|
|
[&selectedLocationIds, &cursorColumn](SourceLocation* startLocation)
|
|
{
|
|
const SourceLocation* endLocation = startLocation->getEndLocation();
|
|
|
|
if ((startLocation->getType() == LOCATION_TOKEN || startLocation->getType() == LOCATION_QUALIFIER)
|
|
&& startLocation->getLineNumber() == endLocation->getLineNumber()
|
|
&& startLocation->getColumnNumber() <= cursorColumn
|
|
&& endLocation->getColumnNumber() + 1 >= cursorColumn)
|
|
{
|
|
selectedLocationIds.push_back(startLocation->getLocationId());
|
|
}
|
|
}
|
|
);
|
|
|
|
if (!selectedLocationIds.empty())
|
|
{
|
|
MessageStatus(
|
|
L"Activating source location from plug-in succeeded: " + filePath.wstr() + L", row: " +
|
|
std::to_wstring(message.row) + L", col: " + std::to_wstring(message.column)
|
|
).dispatch();
|
|
|
|
MessageTabOpenWith(0, selectedLocationIds[0]).showNewTab(true).dispatch();
|
|
MessageActivateWindow().dispatch();
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (fileId > 0)
|
|
{
|
|
MessageTabOpenWith(filePath, message.row).showNewTab(true).dispatch();
|
|
MessageActivateWindow().dispatch();
|
|
}
|
|
else
|
|
{
|
|
MessageStatus(
|
|
L"Activating source location from plug-in failed. File " + filePath.wstr()
|
|
+ L" was not found in the project.",
|
|
true
|
|
).dispatch();
|
|
}
|
|
}
|
|
}
|
|
|
|
void IDECommunicationController::handleCreateProjectMessage(const NetworkProtocolHelper::CreateProjectMessage& message)
|
|
{
|
|
LOG_ERROR_STREAM(<< "Network Protocol CreateProjectMessage not supported anymore.");
|
|
}
|
|
|
|
void IDECommunicationController::handleCreateCDBProjectMessage(const NetworkProtocolHelper::CreateCDBProjectMessage& message)
|
|
{
|
|
if (message.valid)
|
|
{
|
|
MessageProjectNew(message.cdbFileLocation).dispatch();
|
|
}
|
|
else
|
|
{
|
|
LOG_ERROR_STREAM(<< "Unable to parse provided CDB, invalid data received");
|
|
}
|
|
}
|
|
|
|
void IDECommunicationController::handlePing(const NetworkProtocolHelper::PingMessage& message)
|
|
{
|
|
if (message.valid)
|
|
{
|
|
MessagePingReceived msg;
|
|
msg.ideName = message.ideId;
|
|
|
|
if (msg.ideName.empty())
|
|
{
|
|
msg.ideName = L"unknown IDE";
|
|
}
|
|
|
|
LOG_INFO(msg.ideName + L" instance detected via plugin port");
|
|
msg.dispatch();
|
|
}
|
|
else
|
|
{
|
|
LOG_ERROR("Can't handle ping, message is invalid");
|
|
}
|
|
}
|
|
|
|
void IDECommunicationController::handleMessage(MessageWindowFocus* message)
|
|
{
|
|
if (message->focusIn)
|
|
{
|
|
sendUpdatePing();
|
|
}
|
|
}
|
|
|
|
void IDECommunicationController::handleMessage(MessageIDECreateCDB* message)
|
|
{
|
|
std::wstring networkMessage = NetworkProtocolHelper::buildCreateCDBMessage();
|
|
|
|
MessageStatus(L"Requesting IDE to create Compilation Database via plug-in.").dispatch();
|
|
|
|
sendMessage(networkMessage);
|
|
}
|
|
|
|
void IDECommunicationController::handleMessage(MessageMoveIDECursor* message)
|
|
{
|
|
std::wstring networkMessage = NetworkProtocolHelper::buildSetIDECursorMessage(
|
|
message->filePath, message->row, message->column
|
|
);
|
|
|
|
MessageStatus(
|
|
L"Jump to source location via plug-in: " + message->filePath.wstr() + L", row: " +
|
|
std::to_wstring(message->row) + L", col: " + std::to_wstring(message->column)
|
|
).dispatch();
|
|
|
|
sendMessage(networkMessage);
|
|
}
|
|
|
|
void IDECommunicationController::handleMessage(MessagePluginPortChange* message)
|
|
{
|
|
stopListening();
|
|
startListening();
|
|
}
|