diff --git a/bin/app/data/color_schemes/bad_rainbow.xml b/bin/app/data/color_schemes/bad_rainbow.xml index 1538f87b..db6cd8a0 100644 --- a/bin/app/data/color_schemes/bad_rainbow.xml +++ b/bin/app/data/color_schemes/bad_rainbow.xml @@ -534,12 +534,21 @@ #808080 #BEBEBE diff --git a/bin/app/data/color_schemes/bright.xml b/bin/app/data/color_schemes/bright.xml index 6df33d8b..7dbdd530 100644 --- a/bin/app/data/color_schemes/bright.xml +++ b/bin/app/data/color_schemes/bright.xml @@ -67,7 +67,7 @@ black - #5EA071 + #6DB080 black @@ -508,12 +508,21 @@ #E0E0E0 #BEBEBE diff --git a/bin/app/data/color_schemes/dark.xml b/bin/app/data/color_schemes/dark.xml index 7fbe57cd..4c9aee0e 100644 --- a/bin/app/data/color_schemes/dark.xml +++ b/bin/app/data/color_schemes/dark.xml @@ -511,12 +511,21 @@ #555555 #BEBEBE diff --git a/bin/app/data/gui/main/main.css b/bin/app/data/gui/main/main.css index f42f9e1a..785331b1 100644 --- a/bin/app/data/gui/main/main.css +++ b/bin/app/data/gui/main/main.css @@ -13,6 +13,10 @@ QMainWindow::separator { width: 1px; } +QToolBar { + border: none; +} + QDockWidget { color: ; font-size: 10pt; diff --git a/bin/app/data/gui/tabbed_view/tabbed_view.css b/bin/app/data/gui/tabbed_view/tabbed_view.css index 4355800e..8a21d2aa 100644 --- a/bin/app/data/gui/tabbed_view/tabbed_view.css +++ b/bin/app/data/gui/tabbed_view/tabbed_view.css @@ -15,7 +15,7 @@ QTabBar::tab { border: 1px solid ; border-top-left-radius: 7px; border-top-right-radius: 7px; - color: ; + color: ; font-size: px; height: ; margin-left: 3px; @@ -25,11 +25,13 @@ QTabBar::tab { QTabBar::tab:hover { background-color: ; + color: ; } QTabBar::tab:selected, QTabBar::tab:pressed { background-color: ; border-bottom: 1px solid ; + color: ; } QTabWidget #tab_content { diff --git a/bin/app/data/gui/tabs_view/images/add.png b/bin/app/data/gui/tabs_view/images/add.png new file mode 100644 index 00000000..79f5052a Binary files /dev/null and b/bin/app/data/gui/tabs_view/images/add.png differ diff --git a/bin/app/data/gui/tabs_view/images/close.png b/bin/app/data/gui/tabs_view/images/close.png new file mode 100644 index 00000000..bf6e88a3 Binary files /dev/null and b/bin/app/data/gui/tabs_view/images/close.png differ diff --git a/bin/app/data/gui/tabs_view/tabs_view.css b/bin/app/data/gui/tabs_view/tabs_view.css new file mode 100644 index 00000000..acf6c2d4 --- /dev/null +++ b/bin/app/data/gui/tabs_view/tabs_view.css @@ -0,0 +1,81 @@ +QTabBar { + background-color: ; + border-bottom: 1px solid ; + font-size: px; + padding-left: 4px; + min-height: 30px; +} + +QTabBar::tab { + background-color: ; + border: 1px solid ; + border-top-left-radius: 11px; + border-top-right-radius: 11px; + color: ; + min-height: 25px; + margin-left: 3px; + margin-top: 4px; +} + +QTabBar::tab:hover { + background-color: ; + color: ; +} + +QTabBar::tab:selected, QTabBar::tab:pressed { + background-color: ; + border-bottom: 1px solid ; + color: ; +} + +#side_area { + background-color: ; + border-bottom: 1px solid ; +} + +#type_circle { + background-color: ; + border: 1px solid ; + border-radius: 6px; + margin: 0; + height: 10px; + width: 10px; + margin-top: 3px; + margin-left: 6px; +} + +#type_circle[selected=true] { + border: 1px solid ; +} + +#close_button { + background-color: transparent; + border: 1px solid transparent; + border-radius: 8px; + color: ; + font-size: 12px; + margin: 0; + height: 14px; + width: 14px; + margin-top: 5px; + margin-right: 0px; +} + +#close_button:hover { + border: 1px solid ; +} + +#add_button { + background-color: ; + border: 1px solid ; + border-radius: 11px; + color: ; + margin: 5px 0 3px 0; + height: 20px; + width: 20px; +} + +#add_button:hover { + background-color: ; + color: ; +} diff --git a/src/lib/Application.cpp b/src/lib/Application.cpp index 3ce07a55..5ab30bc0 100644 --- a/src/lib/Application.cpp +++ b/src/lib/Application.cpp @@ -22,6 +22,8 @@ #include "MessageForceEnterLicense.h" #include "MessageQuitApplication.h" #include "MessageStatus.h" +#include "TabId.h" +#include "TaskManager.h" #include "TaskScheduler.h" #include "tracing.h" #include "UserPaths.h" @@ -45,7 +47,8 @@ void Application::createInstance( collector->run(Application::getUUID()); } - TaskScheduler::getInstance(); + TaskManager::createScheduler(TabId::app()); + TaskManager::createScheduler(TabId::background()); MessageQueue::getInstance(); bool hasGui = (viewFactory != nullptr); @@ -55,15 +58,11 @@ void Application::createInstance( if (hasGui) { - s_instance->m_componentManager = ComponentManager::create(viewFactory, s_instance->m_storageCache.get()); - - s_instance->m_mainView = viewFactory->createMainView(); + s_instance->m_mainView = viewFactory->createMainView(s_instance->m_storageCache.get()); + s_instance->m_mainView->setup(); s_instance->updateTitle(); - s_instance->m_componentManager->setup(s_instance->m_mainView.get()); - s_instance->m_mainView->loadLayout(); - - s_instance->m_componentManager->refreshViews(); + GraphViewStyle::setImpl(viewFactory->createGraphStyleImpl()); } if (networkFactory != nullptr) @@ -86,7 +85,8 @@ std::shared_ptr Application::getInstance() void Application::destroyInstance() { MessageQueue::getInstance()->stopMessageLoop(); - TaskScheduler::getInstance()->stopSchedulerLoop(); + TaskManager::destroyScheduler(TabId::background()); + TaskManager::destroyScheduler(TabId::app()); s_instance.reset(); } @@ -145,6 +145,15 @@ const std::shared_ptr Application::getCurrentProject() return m_project; } +bool Application::isProjectLoaded() const +{ + if (m_project) + { + return m_project->isLoaded(); + } + return false; +} + bool Application::hasGUI() { return m_hasGUI; @@ -172,17 +181,17 @@ int Application::handleDialog(const std::wstring& message, const std::vector Application::getDialogView(DialogView::UseCase useCase) { - if (m_componentManager) + if (m_mainView) { - return m_componentManager->getDialogView(useCase); + return m_mainView->getDialogView(useCase); } return std::make_shared(useCase, nullptr); } -void Application::updateHistoryMenu(const std::vector>& historyMenuItems) +void Application::updateHistoryMenu(std::shared_ptr message) { - m_mainView->updateHistoryMenu(historyMenuItems); + m_mainView->updateHistoryMenu(message); } void Application::updateBookmarks(const std::vector>& bookmarks) @@ -209,8 +218,7 @@ void Application::handleMessage(MessageEnteredLicense* message) if (m_hasGUI) { - m_mainView->refreshView(); - m_componentManager->refreshViews(); + m_mainView->refreshViews(); } } @@ -264,6 +272,13 @@ void Application::handleMessage(MessageLoadProject* message) projectSettingsFilePath = migrateProjectSettings(projectSettingsFilePath); + m_project.reset(); + + if (m_hasGUI) + { + m_mainView->clear(); + } + try { updateRecentProjects(projectSettingsFilePath); @@ -297,11 +312,6 @@ void Application::handleMessage(MessageLoadProject* message) MessageStatus(L"Failed to load project, unknown exception was thrown: " + projectSettingsFilePath.wstr(), true).dispatch(); } - if (m_hasGUI) - { - m_componentManager->clearComponents(); - } - if (message->refreshMode != REFRESH_NONE) { refreshProject(message->refreshMode); @@ -327,8 +337,7 @@ void Application::handleMessage(MessageRefreshUI* message) loadStyle(ApplicationSettings::getInstance()->getColorSchemePath()); } - m_mainView->refreshView(); - m_componentManager->refreshViews(); + m_mainView->refreshViews(); } } @@ -396,7 +405,8 @@ FilePath Application::migrateProjectSettings(const FilePath& projectSettingsFile void Application::startMessagingAndScheduling() { - TaskScheduler::getInstance()->startSchedulerLoopThreaded(); + TaskManager::getScheduler(TabId::app())->startSchedulerLoopThreaded(); + TaskManager::getScheduler(TabId::background())->startSchedulerLoopThreaded(); MessageQueue* queue = MessageQueue::getInstance().get(); queue->addMessageFilter(std::make_shared()); diff --git a/src/lib/Application.h b/src/lib/Application.h index 6ad82df3..9130695f 100644 --- a/src/lib/Application.h +++ b/src/lib/Application.h @@ -3,8 +3,7 @@ #include -#include "ComponentManager.h" -#include "Project.h" +#include "DialogView.h" #include "MessageListener.h" #include "MessageIndexingFinished.h" #include "MessageActivateWindow.h" @@ -14,9 +13,10 @@ #include "MessageRefreshUI.h" #include "MessageSwitchColorScheme.h" #include "MessageWindowFocus.h" +#include "Project.h" +#include "TimeStamp.h" class Bookmark; -class DialogView; class IDECommunicationController; class MainView; class NetworkFactory; @@ -48,6 +48,7 @@ public: ~Application(); const std::shared_ptr getCurrentProject(); + bool isProjectLoaded() const; bool hasGUI(); @@ -57,7 +58,7 @@ public: int handleDialog(const std::wstring& message, const std::vector& options); std::shared_ptr getDialogView(DialogView::UseCase useCase); - void updateHistoryMenu(const std::vector>& historyMenuItems); + void updateHistoryMenu(std::shared_ptr message); void updateBookmarks(const std::vector>& bookmarks); private: @@ -92,7 +93,6 @@ private: std::shared_ptr m_storageCache; std::shared_ptr m_mainView; - std::shared_ptr m_componentManager; std::shared_ptr m_ideCommunicationController; std::shared_ptr m_updateChecker; diff --git a/src/lib/CMakeLists.txt b/src/lib/CMakeLists.txt index 956d7e46..9d094eed 100644 --- a/src/lib/CMakeLists.txt +++ b/src/lib/CMakeLists.txt @@ -40,6 +40,8 @@ add_files( component/controller/StatusBarController.h component/controller/StatusController.cpp component/controller/StatusController.h + component/controller/TabsController.cpp + component/controller/TabsController.h component/controller/TooltipController.cpp component/controller/TooltipController.h component/controller/UndoRedoController.cpp @@ -47,6 +49,8 @@ add_files( component/view/helper/CodeSnippetParams.cpp component/view/helper/CodeSnippetParams.h + component/view/BookmarkButtonsView.cpp + component/view/BookmarkButtonsView.h component/view/BookmarkView.cpp component/view/BookmarkView.h component/view/CodeView.cpp @@ -76,13 +80,14 @@ add_files( component/view/StatusView.h component/view/TabbedView.cpp component/view/TabbedView.h + component/view/TabsView.cpp + component/view/TabsView.h component/view/TooltipView.cpp component/view/TooltipView.h component/view/UndoRedoView.cpp component/view/UndoRedoView.h component/view/View.cpp component/view/View.h - component/view/ViewFactory.cpp component/view/ViewFactory.h component/view/ViewLayout.cpp component/view/ViewLayout.h @@ -97,6 +102,10 @@ add_files( component/ComponentManager.h component/NetworkFactory.cpp component/NetworkFactory.h + component/Tab.cpp + component/Tab.h + component/TabId.cpp + component/TabId.h data/access/StorageAccess.h data/access/StorageAccessProxy.cpp @@ -424,6 +433,13 @@ add_files( utility/messaging/type/activation/MessageActivateLegend.h + utility/messaging/type/bookmark/MessageBookmarkActivate.h + utility/messaging/type/bookmark/MessageBookmarkBrowse.h + utility/messaging/type/bookmark/MessageBookmarkButtonState.h + utility/messaging/type/bookmark/MessageBookmarkCreate.h + utility/messaging/type/bookmark/MessageBookmarkDelete.h + utility/messaging/type/bookmark/MessageBookmarkEdit.h + utility/messaging/type/code/MessageCodeShowDefinition.h utility/messaging/type/error/MessageActivateErrors.h @@ -443,9 +459,14 @@ add_files( utility/messaging/type/indexing/MessageIndexingStarted.h utility/messaging/type/indexing/MessageIndexingStatus.h + utility/messaging/type/tab/MessageTabClose.h + utility/messaging/type/tab/MessageTabOpen.h + utility/messaging/type/tab/MessageTabOpenWith.h + utility/messaging/type/tab/MessageTabSelect.h + utility/messaging/type/tab/MessageTabState.h + utility/messaging/type/MessageActivateAll.h utility/messaging/type/MessageActivateBase.h - utility/messaging/type/MessageActivateBookmark.h utility/messaging/type/MessageActivateEdge.h utility/messaging/type/MessageActivateFile.h utility/messaging/type/MessageActivateFullTextSearch.h @@ -462,8 +483,6 @@ add_files( utility/messaging/type/MessageClearStatusView.h utility/messaging/type/MessageCodeReference.h utility/messaging/type/MessageDeactivateEdge.h - utility/messaging/type/MessageDisplayBookmarkCreator.h - utility/messaging/type/MessageDisplayBookmarks.h utility/messaging/type/MessageEnteredLicense.h utility/messaging/type/MessageFind.h utility/messaging/type/MessageFlushUpdates.h @@ -540,6 +559,8 @@ add_files( utility/scheduling/TaskGroupSequence.h utility/scheduling/TaskLambda.cpp utility/scheduling/TaskLambda.h + utility/scheduling/TaskManager.cpp + utility/scheduling/TaskManager.h utility/scheduling/TaskReturnSuccessIf.h utility/scheduling/TaskRunner.cpp utility/scheduling/TaskRunner.h diff --git a/src/lib/component/Component.cpp b/src/lib/component/Component.cpp index 79faf5a0..4a016b34 100644 --- a/src/lib/component/Component.cpp +++ b/src/lib/component/Component.cpp @@ -6,6 +6,7 @@ Component::Component(std::shared_ptr view, std::shared_ptr controller) : m_controller(controller) , m_view(view) + , m_tabId(0) { if (m_controller) { @@ -40,3 +41,13 @@ View* Component::getViewPtr() const { return m_view.get(); } + +void Component::setTabId(Id tabId) +{ + m_tabId = tabId; +} + +Id Component::getTabId() const +{ + return m_tabId; +} diff --git a/src/lib/component/Component.h b/src/lib/component/Component.h index a7ad841a..9a7cd5a6 100644 --- a/src/lib/component/Component.h +++ b/src/lib/component/Component.h @@ -3,6 +3,8 @@ #include +#include "types.h" + class View; class Controller; @@ -22,9 +24,14 @@ public: View* getViewPtr() const; + void setTabId(Id tabId); + Id getTabId() const; + private: const std::shared_ptr m_controller; const std::shared_ptr m_view; + + Id m_tabId; }; diff --git a/src/lib/component/ComponentFactory.cpp b/src/lib/component/ComponentFactory.cpp index 3e329eae..484e834d 100644 --- a/src/lib/component/ComponentFactory.cpp +++ b/src/lib/component/ComponentFactory.cpp @@ -11,6 +11,7 @@ #include "SearchController.h" #include "StatusBarController.h" #include "StatusController.h" +#include "TabsController.h" #include "TooltipController.h" #include "UndoRedoController.h" #include "BookmarkView.h" @@ -21,25 +22,18 @@ #include "SearchView.h" #include "StatusBarView.h" #include "StatusView.h" +#include "TabsView.h" #include "TooltipView.h" #include "UndoRedoView.h" #include "ViewFactory.h" -std::shared_ptr ComponentFactory::create(ViewFactory* viewFactory, StorageAccess* storageAccess) -{ - std::shared_ptr ptr(new ComponentFactory()); - - ptr->m_viewFactory = viewFactory; - ptr->m_storageAccess = storageAccess; - - return ptr; -} - -ComponentFactory::~ComponentFactory() +ComponentFactory::ComponentFactory(const ViewFactory* viewFactory, StorageAccess* storageAccess) + : m_viewFactory(viewFactory) + , m_storageAccess(storageAccess) { } -ViewFactory* ComponentFactory::getViewFactory() const +const ViewFactory* ComponentFactory::getViewFactory() const { return m_viewFactory; } @@ -128,6 +122,16 @@ std::shared_ptr ComponentFactory::createStatusComponent(ViewLayout* v return std::make_shared(view, controller); } +std::shared_ptr ComponentFactory::createTabsComponent( + ViewLayout* viewLayout, ScreenSearchSender* screenSearchSender) +{ + std::shared_ptr view = m_viewFactory->createTabsView(viewLayout); + std::shared_ptr controller = std::make_shared( + viewLayout, m_viewFactory, m_storageAccess, screenSearchSender); + + return std::make_shared(view, controller); +} + std::shared_ptr ComponentFactory::createTooltipComponent(ViewLayout* viewLayout) { std::shared_ptr view = m_viewFactory->createTooltipView(viewLayout); @@ -143,7 +147,3 @@ std::shared_ptr ComponentFactory::createUndoRedoComponent(ViewLayout* return std::make_shared(view, controller); } - -ComponentFactory::ComponentFactory() -{ -} diff --git a/src/lib/component/ComponentFactory.h b/src/lib/component/ComponentFactory.h index db27cbe8..1326d92d 100644 --- a/src/lib/component/ComponentFactory.h +++ b/src/lib/component/ComponentFactory.h @@ -8,15 +8,14 @@ class Component; class ViewFactory; class ViewLayout; +class ScreenSearchSender; class ComponentFactory { public: - static std::shared_ptr create(ViewFactory* viewFactory, StorageAccess* storageAccess); + ComponentFactory(const ViewFactory* viewFactory, StorageAccess* storageAccess); - ~ComponentFactory(); - - ViewFactory* getViewFactory() const; + const ViewFactory* getViewFactory() const; StorageAccess* getStorageAccess() const; std::shared_ptr createActivationComponent(); @@ -29,14 +28,12 @@ public: std::shared_ptr createSearchComponent(ViewLayout* viewLayout); std::shared_ptr createStatusBarComponent(ViewLayout* viewLayout); std::shared_ptr createStatusComponent(ViewLayout* viewLayout); + std::shared_ptr createTabsComponent(ViewLayout* viewLayout, ScreenSearchSender* screenSearchSender); std::shared_ptr createTooltipComponent(ViewLayout* viewLayout); std::shared_ptr createUndoRedoComponent(ViewLayout* viewLayout); private: - ComponentFactory(); - ComponentFactory(const ComponentFactory&); - - ViewFactory* m_viewFactory; + const ViewFactory* m_viewFactory; StorageAccess* m_storageAccess; }; diff --git a/src/lib/component/ComponentManager.cpp b/src/lib/component/ComponentManager.cpp index 3ec98e4e..9d4d45b5 100644 --- a/src/lib/component/ComponentManager.cpp +++ b/src/lib/component/ComponentManager.cpp @@ -1,87 +1,147 @@ #include "ComponentManager.h" -#include "logging.h" - -#include "Controller.h" -#include "ScreenSearchController.h" #include "CompositeView.h" +#include "Controller.h" #include "DialogView.h" +#include "logging.h" +#include "ScreenSearchController.h" #include "TabbedView.h" #include "ViewFactory.h" +#include "BookmarkButtonsView.h" +#include "BookmarkView.h" +#include "CodeView.h" +#include "GraphView.h" +#include "RefreshView.h" +#include "SearchView.h" +#include "UndoRedoView.h" -std::shared_ptr ComponentManager::create(ViewFactory* viewFactory, StorageAccess* storageAccess) -{ - std::shared_ptr ptr(new ComponentManager()); - - ptr->m_componentFactory = ComponentFactory::create(viewFactory, storageAccess); - - return ptr; -} - -ComponentManager::~ComponentManager() +ComponentManager::ComponentManager(const ViewFactory* viewFactory, StorageAccess* storageAccess) + : m_componentFactory(viewFactory, storageAccess) { } -void ComponentManager::setup(ViewLayout* viewLayout) +void ComponentManager::clear() +{ + m_dialogViews.clear(); + m_components.clear(); + m_singleViews.clear(); +} + +void ComponentManager::setupMain(ViewLayout* viewLayout, Id appId) { std::shared_ptr compositeView = - m_componentFactory->getViewFactory()->createCompositeView(viewLayout, CompositeView::DIRECTION_HORIZONTAL, "Search"); - m_compositeViews.push_back(compositeView); + m_componentFactory.getViewFactory()->createCompositeView(viewLayout, CompositeView::DIRECTION_HORIZONTAL, "Search"); + m_singleViews.push_back(compositeView); - std::shared_ptr undoRedoComponent = m_componentFactory->createUndoRedoComponent(compositeView.get()); - m_components.push_back(undoRedoComponent); + std::shared_ptr undoRedoView = m_componentFactory.getViewFactory()->createUndoRedoView(compositeView.get()); + std::shared_ptr refreshView = m_componentFactory.getViewFactory()->createRefreshView(compositeView.get()); + std::shared_ptr searchView = m_componentFactory.getViewFactory()->createSearchView(compositeView.get()); - std::shared_ptr refreshComponent = m_componentFactory->createRefreshComponent(compositeView.get()); - m_components.push_back(refreshComponent); + std::shared_ptr bookmarkView = + m_componentFactory.getViewFactory()->createBookmarkButtonsView(compositeView.get()); + bookmarkView->setTabId(appId); - std::shared_ptr searchComponent = m_componentFactory->createSearchComponent(compositeView.get()); - m_components.push_back(searchComponent); + std::shared_ptr graphView = m_componentFactory.getViewFactory()->createGraphView(viewLayout); + std::shared_ptr codeView = m_componentFactory.getViewFactory()->createCodeView(viewLayout); - std::shared_ptr bookmarkComponent = m_componentFactory->createBookmarkComponent(compositeView.get()); - m_components.push_back(bookmarkComponent); + for (std::shared_ptr view : + std::vector>({ undoRedoView, searchView, bookmarkView, graphView, codeView })) + { + view->setEnabled(false); + } - std::shared_ptr graphComponent = m_componentFactory->createGraphComponent(viewLayout); - m_components.push_back(graphComponent); + m_singleViews.push_back(undoRedoView); + m_singleViews.push_back(refreshView); + m_singleViews.push_back(searchView); + m_singleViews.push_back(bookmarkView); + m_singleViews.push_back(graphView); + m_singleViews.push_back(codeView); - std::shared_ptr codeComponent = m_componentFactory->createCodeComponent(viewLayout); - m_components.push_back(codeComponent); + std::shared_ptr screenSearchComponent = m_componentFactory.createScreenSearchComponent(viewLayout); + ScreenSearchController* screenSearchController = screenSearchComponent->getController(); + screenSearchController->addResponder(graphView.get()); + screenSearchController->addResponder(codeView.get()); + m_components.push_back(screenSearchComponent); - std::shared_ptr statusBarComponent = m_componentFactory->createStatusBarComponent(viewLayout); + std::shared_ptr tabsComponent = m_componentFactory.createTabsComponent(viewLayout, screenSearchController); + m_components.push_back(tabsComponent); + + std::shared_ptr statusBarComponent = m_componentFactory.createStatusBarComponent(viewLayout); m_components.push_back(statusBarComponent); - std::shared_ptr activationComponent = m_componentFactory->createActivationComponent(); - m_components.push_back(activationComponent); - - std::shared_ptr tooltipComponent = m_componentFactory->createTooltipComponent(viewLayout); + std::shared_ptr tooltipComponent = m_componentFactory.createTooltipComponent(viewLayout); m_components.push_back(tooltipComponent); - std::shared_ptr screenSearchComponent = m_componentFactory->createScreenSearchComponent(viewLayout); - ScreenSearchController* screenSearchController = screenSearchComponent->getController(); - screenSearchController->addResponder(dynamic_cast(graphComponent->getViewPtr())); - screenSearchController->addResponder(dynamic_cast(codeComponent->getViewPtr())); - m_components.push_back(screenSearchComponent); - for (DialogView::UseCase useCase : { DialogView::UseCase::GENERAL, DialogView::UseCase::INDEXING, DialogView::UseCase::PROJECT_SETUP }) { m_dialogViews.emplace( useCase, - m_componentFactory->getViewFactory()->createDialogView(viewLayout, useCase, m_componentFactory->getStorageAccess()) + m_componentFactory.getViewFactory()->createDialogView(viewLayout, useCase, m_componentFactory.getStorageAccess()) ); } m_dialogViews[DialogView::UseCase::INDEXING]->setDialogsHideable(true); std::shared_ptr tabbedView = - m_componentFactory->getViewFactory()->createTabbedView(viewLayout, "Status"); - m_tabbedViews.push_back(tabbedView); + m_componentFactory.getViewFactory()->createTabbedView(viewLayout, "Status"); + m_singleViews.push_back(tabbedView); - std::shared_ptr statusComponent = m_componentFactory->createStatusComponent(tabbedView.get()); + std::shared_ptr statusComponent = m_componentFactory.createStatusComponent(tabbedView.get()); m_components.push_back(statusComponent); - std::shared_ptr errorComponent = m_componentFactory->createErrorComponent(tabbedView.get()); + std::shared_ptr errorComponent = m_componentFactory.createErrorComponent(tabbedView.get()); m_components.push_back(errorComponent); + std::shared_ptr bookmarkComponent = m_componentFactory.createBookmarkComponent(compositeView.get()); + m_components.push_back(bookmarkComponent); + + std::shared_ptr activationComponent = m_componentFactory.createActivationComponent(); + m_components.push_back(activationComponent); +} + +void ComponentManager::setupTab(ViewLayout* viewLayout, Id tabId, ScreenSearchSender* screenSearchSender) +{ + std::shared_ptr compositeView = + m_componentFactory.getViewFactory()->createCompositeView(viewLayout, CompositeView::DIRECTION_HORIZONTAL, "Search"); + m_singleViews.push_back(compositeView); + + std::shared_ptr undoRedoComponent = m_componentFactory.createUndoRedoComponent(compositeView.get()); + undoRedoComponent->setTabId(tabId); + m_components.push_back(undoRedoComponent); + + std::shared_ptr refreshComponent = m_componentFactory.createRefreshComponent(compositeView.get()); + refreshComponent->setTabId(tabId); + m_components.push_back(refreshComponent); + + std::shared_ptr searchComponent = m_componentFactory.createSearchComponent(compositeView.get()); + searchComponent->setTabId(tabId); + m_components.push_back(searchComponent); + + std::shared_ptr bookmarkView = + m_componentFactory.getViewFactory()->createBookmarkButtonsView(compositeView.get()); + bookmarkView->setTabId(tabId); + m_singleViews.push_back(bookmarkView); + + std::shared_ptr graphComponent = m_componentFactory.createGraphComponent(viewLayout); + graphComponent->setTabId(tabId); + m_components.push_back(graphComponent); + + std::shared_ptr codeComponent = m_componentFactory.createCodeComponent(viewLayout); + codeComponent->setTabId(tabId); + m_components.push_back(codeComponent); + + screenSearchSender->addResponder(graphComponent->getView()); + screenSearchSender->addResponder(codeComponent->getView()); +} + +void ComponentManager::teardownTab(ScreenSearchSender* screenSearchSender) +{ + for (const std::shared_ptr& component : m_components) + { + screenSearchSender->removeResponder(component->getView()); + screenSearchSender->removeResponder(component->getView()); + } } void ComponentManager::clearComponents() @@ -109,12 +169,7 @@ void ComponentManager::refreshViews() } } - for (const std::shared_ptr& view : m_compositeViews) - { - view->refreshView(); - } - - for (const std::shared_ptr& view : m_tabbedViews) + for (const std::shared_ptr& view : m_singleViews) { view->refreshView(); } @@ -131,7 +186,3 @@ std::shared_ptr ComponentManager::getDialogView(DialogView::UseCase return it->second; } - -ComponentManager::ComponentManager() -{ -} diff --git a/src/lib/component/ComponentManager.h b/src/lib/component/ComponentManager.h index e61a6c9d..fa24ff78 100644 --- a/src/lib/component/ComponentManager.h +++ b/src/lib/component/ComponentManager.h @@ -10,6 +10,7 @@ class CompositeView; class DialogView; +class ScreenSearchSender; class StorageAccess; class TabbedView; class View; @@ -19,11 +20,13 @@ class ViewLayout; class ComponentManager { public: - static std::shared_ptr create(ViewFactory* viewFactory, StorageAccess* graphAccess); + ComponentManager(const ViewFactory* viewFactory, StorageAccess* storageAccess); - ~ComponentManager(); + void clear(); - void setup(ViewLayout* viewLayout); + void setupMain(ViewLayout* viewLayout, Id appId); + void setupTab(ViewLayout* viewLayout, Id tabId, ScreenSearchSender* screenSearchSender); + void teardownTab(ScreenSearchSender* screenSearchSender); void clearComponents(); void refreshViews(); @@ -31,13 +34,9 @@ public: std::shared_ptr getDialogView(DialogView::UseCase useCase) const; private: - ComponentManager(); - ComponentManager(const ComponentManager&); + ComponentFactory m_componentFactory; - std::shared_ptr m_componentFactory; - - std::vector> m_compositeViews; - std::vector> m_tabbedViews; + std::vector> m_singleViews; std::vector> m_components; std::map> m_dialogViews; diff --git a/src/lib/component/Tab.cpp b/src/lib/component/Tab.cpp new file mode 100644 index 00000000..722b4b23 --- /dev/null +++ b/src/lib/component/Tab.cpp @@ -0,0 +1,74 @@ +#include "Tab.h" + +Tab::Tab(Id tabId, const ViewFactory* viewFactory, StorageAccess* storageAccess, ScreenSearchSender* screenSearchSender) + : m_tabId(tabId) + , m_componentManager(viewFactory, storageAccess) + , m_parentLayout(nullptr) + , m_screenSearchSender(screenSearchSender) +{ + m_componentManager.setupTab(this, m_tabId, m_screenSearchSender); + m_componentManager.refreshViews(); +} + +Tab::~Tab() +{ + m_componentManager.teardownTab(m_screenSearchSender); +} + +void Tab::setParentLayout(ViewLayout* parentLayout) +{ + m_parentLayout = parentLayout; + + if (parentLayout) + { + for (View* view : m_views) + { + parentLayout->overrideView(view); + } + } +} + +void Tab::addView(View* view) +{ + m_views.push_back(view); +} + +void Tab::removeView(View* view) +{ + std::vector::iterator it = std::find(m_views.begin(), m_views.end(), view); + if (it == m_views.end()) + { + return; + } + + m_views.erase(it); +} + +void Tab::showView(View* view) +{ + if (m_parentLayout) + { + m_parentLayout->showView(view); + } +} + +void Tab::hideView(View* view) +{ + if (m_parentLayout) + { + m_parentLayout->hideView(view); + } +} + +void Tab::setViewEnabled(View* view, bool enabled) +{ + if (m_parentLayout) + { + m_parentLayout->setViewEnabled(view, enabled); + } +} + +void Tab::handleMessage(MessageRefreshUI* message) +{ + m_componentManager.refreshViews(); +} diff --git a/src/lib/component/Tab.h b/src/lib/component/Tab.h new file mode 100644 index 00000000..0f8a6754 --- /dev/null +++ b/src/lib/component/Tab.h @@ -0,0 +1,43 @@ +#ifndef TAB_H +#define TAB_H + +#include + +#include "ComponentManager.h" +#include "MessageListener.h" +#include "MessageRefreshUI.h" +#include "View.h" +#include "ViewLayout.h" + +class Tab + : public ViewLayout + , public MessageListener +{ +public: + Tab(Id tabId, const ViewFactory* viewFactory, StorageAccess* storageAccess, ScreenSearchSender* screenSearchSender); + virtual ~Tab(); + + void setParentLayout(ViewLayout* parentLayout); + + // ViewLayout implementation + void addView(View* view) override; + void removeView(View* view) override; + + void showView(View* view) override; + void hideView(View* view) override; + + void setViewEnabled(View* view, bool enabled) override; + +private: + void handleMessage(MessageRefreshUI* message) override; + + const Id m_tabId; + + ComponentManager m_componentManager; + std::vector m_views; + + ViewLayout* m_parentLayout; + ScreenSearchSender* m_screenSearchSender; +}; + +#endif // TAB_H diff --git a/src/lib/component/TabId.cpp b/src/lib/component/TabId.cpp new file mode 100644 index 00000000..b8aafa53 --- /dev/null +++ b/src/lib/component/TabId.cpp @@ -0,0 +1,34 @@ +#include "TabId.h" + +Id TabId::s_nextTabId = 10; +Id TabId::s_currentTabId = 0; + +Id TabId::app() +{ + return 1; +} + +Id TabId::background() +{ + return 2; +} + +Id TabId::ignore() +{ + return 3; +} + +Id TabId::nextTab() +{ + return s_nextTabId++; +} + +Id TabId::currentTab() +{ + return s_currentTabId; +} + +void TabId::setCurrentTabId(Id currentTabId) +{ + s_currentTabId = currentTabId; +} diff --git a/src/lib/component/TabId.h b/src/lib/component/TabId.h new file mode 100644 index 00000000..afe47f47 --- /dev/null +++ b/src/lib/component/TabId.h @@ -0,0 +1,23 @@ +#ifndef TAB_ID_H +#define TAB_ID_H + +#include "types.h" + +class TabId +{ +public: + static Id app(); + static Id background(); + static Id ignore(); + + static Id nextTab(); + static Id currentTab(); + + static void setCurrentTabId(Id currentTabId); + +private: + static Id s_nextTabId; + static Id s_currentTabId; +}; + +#endif // TAB_ID_H diff --git a/src/lib/component/controller/ActivationController.cpp b/src/lib/component/controller/ActivationController.cpp index 5cc8aa7f..f1eac641 100644 --- a/src/lib/component/controller/ActivationController.cpp +++ b/src/lib/component/controller/ActivationController.cpp @@ -19,10 +19,6 @@ ActivationController::ActivationController(StorageAccess* storageAccess) { } -ActivationController::~ActivationController() -{ -} - void ActivationController::clear() { } @@ -66,12 +62,15 @@ void ActivationController::handleMessage(MessageActivateFile* message) true, true ); + msg.setSchedulerId(message->getSchedulerId()); msg.dispatchImmediately(); } if (message->line > 0) { - MessageScrollToLine(message->filePath, message->line).dispatch(); + MessageScrollToLine msg(message->filePath, message->line); + msg.setSchedulerId(message->getSchedulerId()); + msg.dispatch(); } } @@ -105,12 +104,13 @@ void ActivationController::handleMessage(MessageActivateTokenIds* message) void ActivationController::handleMessage(MessageActivateSourceLocations* message) { - MessageActivateNodes m; + MessageActivateNodes msg; for (Id nodeId : m_storageAccess->getNodeIdsForLocationIds(message->locationIds)) { - m.addNode(nodeId); + msg.addNode(nodeId); } - m.dispatchImmediately(); + msg.setSchedulerId(message->getSchedulerId()); + msg.dispatchImmediately(); } void ActivationController::handleMessage(MessageResetZoom* message) @@ -140,19 +140,25 @@ void ActivationController::handleMessage(MessageSearch* message) case SearchMatch::COMMAND_ALL: case SearchMatch::COMMAND_NODE_FILTER: { - MessageActivateAll(message->acceptedNodeTypes).dispatchImmediately(); + MessageActivateAll msg(message->acceptedNodeTypes); + msg.setSchedulerId(message->getSchedulerId()); + msg.dispatch(); return; } case SearchMatch::COMMAND_ERROR: { - MessageErrorsAll().dispatch(); + MessageErrorsAll msg; + msg.setSchedulerId(message->getSchedulerId()); + msg.dispatch(); return; } case SearchMatch::COMMAND_LEGEND: { - MessageActivateLegend().dispatch(); + MessageActivateLegend msg; + msg.setSchedulerId(message->getSchedulerId()); + msg.dispatch(); return; } } diff --git a/src/lib/component/controller/ActivationController.h b/src/lib/component/controller/ActivationController.h index 55ee325e..ba243cee 100644 --- a/src/lib/component/controller/ActivationController.h +++ b/src/lib/component/controller/ActivationController.h @@ -30,19 +30,18 @@ class ActivationController { public: ActivationController(StorageAccess* storageAccess); - ~ActivationController(); - virtual void clear(); + void clear() override; private: - virtual void handleMessage(MessageActivateEdge* message); - virtual void handleMessage(MessageActivateFile* message); - virtual void handleMessage(MessageActivateNodes* message); - virtual void handleMessage(MessageActivateTokenIds* message); - virtual void handleMessage(MessageActivateSourceLocations* message); - virtual void handleMessage(MessageResetZoom* message); - virtual void handleMessage(MessageSearch* message); - virtual void handleMessage(MessageZoom* message); + void handleMessage(MessageActivateEdge* message) override; + void handleMessage(MessageActivateFile* message) override; + void handleMessage(MessageActivateNodes* message) override; + void handleMessage(MessageActivateTokenIds* message) override; + void handleMessage(MessageActivateSourceLocations* message) override; + void handleMessage(MessageResetZoom* message) override; + void handleMessage(MessageSearch* message) override; + void handleMessage(MessageZoom* message) override; StorageAccess* m_storageAccess; }; diff --git a/src/lib/component/controller/BookmarkController.cpp b/src/lib/component/controller/BookmarkController.cpp index 250dc0df..a4a22eaf 100644 --- a/src/lib/component/controller/BookmarkController.cpp +++ b/src/lib/component/controller/BookmarkController.cpp @@ -10,7 +10,9 @@ #include "MessageActivateEdge.h" #include "MessageActivateNodes.h" +#include "MessageBookmarkButtonState.h" #include "logging.h" +#include "TabId.h" #include "utilityString.h" #include "utility.h" @@ -33,8 +35,6 @@ void BookmarkController::clear() { m_activeNodeIds.clear(); m_activeEdgeIds.clear(); - - getView()->setCreateButtonState(BookmarkView::CreateButtonState::CANNOT_CREATE); } void BookmarkController::displayBookmarks() @@ -62,18 +62,20 @@ void BookmarkController::createBookmark( ){ LOG_INFO("Attempting to create new bookmark"); + Id tabId = TabId::currentTab(); + BookmarkCategory bookmarkCategory(0, category.empty() ? s_defaultCategoryName : category); - if (!m_activeEdgeIds.empty()) + if (!m_activeEdgeIds[tabId].empty()) { LOG_INFO("Creating Edge Bookmark"); EdgeBookmark bookmark(0, name, comment, TimeStamp::now(), bookmarkCategory); - bookmark.setEdgeIds(m_activeEdgeIds); + bookmark.setEdgeIds(m_activeEdgeIds[tabId]); - if (!m_activeNodeIds.empty()) + if (!m_activeNodeIds[TabId::currentTab()].empty()) { - bookmark.setActiveNodeId(m_activeNodeIds.front()); + bookmark.setActiveNodeId(m_activeNodeIds[tabId].front()); } else { @@ -93,16 +95,17 @@ void BookmarkController::createBookmark( } else { - bookmark.setNodeIds(m_activeNodeIds); + bookmark.setNodeIds(m_activeNodeIds[TabId::currentTab()]); } + m_storageAccess->addNodeBookmark(bookmark); } m_bookmarkCache.clear(); - if (!nodeId || (m_activeNodeIds.size() == 1 && m_activeNodeIds[0] == nodeId)) + if (!nodeId || (m_activeNodeIds[TabId::currentTab()].size() == 1 && m_activeNodeIds[TabId::currentTab()][0] == nodeId)) { - getView()->setCreateButtonState(BookmarkView::CreateButtonState::ALREADY_CREATED); + MessageBookmarkButtonState(TabId::currentTab(), MessageBookmarkButtonState::ALREADY_CREATED).dispatch(); } update(); @@ -128,9 +131,9 @@ void BookmarkController::deleteBookmark(Id bookmarkId) cleanBookmarkCategories(); - if (!getBookmarkForActiveToken()) + if (!getBookmarkForActiveToken(TabId::currentTab())) { - getView()->setCreateButtonState(BookmarkView::CreateButtonState::CAN_CREATE); + MessageBookmarkButtonState(TabId::currentTab(), MessageBookmarkButtonState::CAN_CREATE).dispatch(); } update(); @@ -142,9 +145,9 @@ void BookmarkController::deleteBookmarkCategory(Id categoryId) m_bookmarkCache.clear(); - if (!getBookmarkForActiveToken()) + if (!getBookmarkForActiveToken(TabId::currentTab())) { - getView()->setCreateButtonState(BookmarkView::CreateButtonState::CAN_CREATE); + MessageBookmarkButtonState(TabId::currentTab(), MessageBookmarkButtonState::CAN_CREATE).dispatch(); } update(); @@ -152,7 +155,7 @@ void BookmarkController::deleteBookmarkCategory(Id categoryId) void BookmarkController::deleteBookmarkForActiveTokens() { - if (std::shared_ptr bookmark = getBookmarkForActiveToken()) + if (std::shared_ptr bookmark = getBookmarkForActiveToken(TabId::currentTab())) { LOG_INFO(L"Deleting bookmark " + bookmark->getName()); @@ -160,7 +163,7 @@ void BookmarkController::deleteBookmarkForActiveTokens() cleanBookmarkCategories(); - getView()->setCreateButtonState(BookmarkView::CreateButtonState::CAN_CREATE); + MessageBookmarkButtonState(TabId::currentTab(), MessageBookmarkButtonState::CAN_CREATE).dispatch(); update(); } else @@ -223,7 +226,8 @@ void BookmarkController::activateBookmark(const std::shared_ptr bookma void BookmarkController::showBookmarkCreator(Id nodeId) { - if (!canCreateBookmark() && !nodeId) + Id tabId = TabId::currentTab(); + if (!m_activeNodeIds[tabId].size() && !m_activeEdgeIds[tabId].size() && !nodeId) { return; } @@ -244,7 +248,7 @@ void BookmarkController::showBookmarkCreator(Id nodeId) } else { - std::shared_ptr bookmark = getBookmarkForActiveToken(); + std::shared_ptr bookmark = getBookmarkForActiveToken(tabId); if (bookmark != nullptr) { view->displayBookmarkEditor(bookmark, getAllBookmarkCategories()); @@ -297,69 +301,89 @@ void BookmarkController::handleMessage(MessageActivateAll* message) clear(); } -void BookmarkController::handleMessage(MessageActivateBookmark* message) +void BookmarkController::handleMessage(MessageActivateErrors* message) { - activateBookmark(message->bookmark); + clear(); } -void BookmarkController::handleMessage(MessageActivateErrors* message) +void BookmarkController::handleMessage(MessageActivateFullTextSearch* message) +{ + clear(); +} + +void BookmarkController::handleMessage(MessageActivateLegend* message) { clear(); } void BookmarkController::handleMessage(MessageActivateTokens* message) { - m_activeEdgeIds.clear(); + Id tabId = message->getSchedulerId(); + m_activeEdgeIds[tabId].clear(); if (message->isEdge || message->isAggregation) { - m_activeEdgeIds = message->tokenIds; + m_activeEdgeIds[tabId] = message->tokenIds; - if (getBookmarkForActiveToken()) + if (getBookmarkForActiveToken(tabId)) { - getView()->setCreateButtonState(BookmarkView::CreateButtonState::ALREADY_CREATED); + MessageBookmarkButtonState(tabId, MessageBookmarkButtonState::ALREADY_CREATED).dispatch(); } else { - getView()->setCreateButtonState(BookmarkView::CreateButtonState::CAN_CREATE); + MessageBookmarkButtonState(tabId, MessageBookmarkButtonState::CAN_CREATE).dispatch(); } } else if (!message->isEdge) { - m_activeNodeIds = message->tokenIds; + m_activeNodeIds[tabId] = message->tokenIds; - if (getBookmarkForActiveToken()) + if (getBookmarkForActiveToken(tabId)) { - getView()->setCreateButtonState(BookmarkView::CreateButtonState::ALREADY_CREATED); + MessageBookmarkButtonState(tabId, MessageBookmarkButtonState::ALREADY_CREATED).dispatch(); } else { - getView()->setCreateButtonState(BookmarkView::CreateButtonState::CAN_CREATE); + MessageBookmarkButtonState(tabId, MessageBookmarkButtonState::CAN_CREATE).dispatch(); } } } -void BookmarkController::handleMessage(MessageDisplayBookmarks* message) +void BookmarkController::handleMessage(MessageBookmarkActivate* message) +{ + activateBookmark(message->bookmark); +} + +void BookmarkController::handleMessage(MessageBookmarkBrowse* message) { displayBookmarksFor(message->filter, message->order); } -void BookmarkController::handleMessage(MessageDisplayBookmarkCreator* message) +void BookmarkController::handleMessage(MessageBookmarkCreate* message) { showBookmarkCreator(message->nodeId); } +void BookmarkController::handleMessage(MessageBookmarkDelete* message) +{ + deleteBookmarkForActiveTokens(); +} + +void BookmarkController::handleMessage(MessageBookmarkEdit* message) +{ + showBookmarkCreator(0); +} + void BookmarkController::handleMessage(MessageIndexingFinished* message) { m_bookmarkCache.clear(); - getView()->enableDisplayBookmarks(true); update(); } std::vector BookmarkController::getActiveTokenDisplayNames() const { - if (m_activeEdgeIds.size() > 0) + if (m_activeEdgeIds[TabId::currentTab()].size() > 0) { return getActiveEdgeDisplayNames(); } @@ -379,14 +403,14 @@ std::vector BookmarkController::getAllBookmarkCategories() con return m_storageAccess->getAllBookmarkCategories(); } -std::shared_ptr BookmarkController::getBookmarkForActiveToken() const +std::shared_ptr BookmarkController::getBookmarkForActiveToken(Id tabId) const { - if (!m_activeEdgeIds.empty()) + if (!m_activeEdgeIds[tabId].empty()) { for (const std::shared_ptr& edgeBookmark: getAllEdgeBookmarks()) { - if (!m_activeNodeIds.empty() && edgeBookmark->getActiveNodeId() == m_activeNodeIds.front() && - utility::isPermutation(edgeBookmark->getEdgeIds(), m_activeEdgeIds)) + if (!m_activeNodeIds[tabId].empty() && edgeBookmark->getActiveNodeId() == m_activeNodeIds[tabId].front() && + utility::isPermutation(edgeBookmark->getEdgeIds(), m_activeEdgeIds[tabId])) { return std::make_shared(*(edgeBookmark.get())); } @@ -396,7 +420,7 @@ std::shared_ptr BookmarkController::getBookmarkForActiveToken() const { for (const std::shared_ptr& nodeBookmark: getAllNodeBookmarks()) { - if (utility::isPermutation(nodeBookmark->getNodeIds(), m_activeNodeIds)) + if (utility::isPermutation(nodeBookmark->getNodeIds(), m_activeNodeIds[tabId])) { return std::make_shared(*(nodeBookmark.get())); } @@ -419,11 +443,6 @@ std::shared_ptr BookmarkController::getBookmarkForNodeId(Id nodeId) co return std::shared_ptr(); } -bool BookmarkController::canCreateBookmark() const -{ - return m_activeNodeIds.size() || m_activeEdgeIds.size(); -} - std::vector> BookmarkController::getAllBookmarks() const { LOG_INFO("Retrieving all bookmarks"); @@ -476,7 +495,7 @@ std::vector> BookmarkController::getBookmarks( std::vector BookmarkController::getActiveNodeDisplayNames() const { std::vector names; - for (Id nodeId : m_activeNodeIds) + for (Id nodeId : m_activeNodeIds[TabId::currentTab()]) { names.push_back(getNodeDisplayName(nodeId)); } @@ -486,7 +505,7 @@ std::vector BookmarkController::getActiveNodeDisplayNames() const std::vector BookmarkController::getActiveEdgeDisplayNames() const { std::vector activeEdgeDisplayNames; - for (Id activeEdgeId: m_activeEdgeIds) + for (Id activeEdgeId: m_activeEdgeIds[TabId::currentTab()]) { const StorageEdge activeEdge = m_storageAccess->getEdgeById(activeEdgeId); const std::wstring sourceDisplayName = getNodeDisplayName(activeEdge.sourceNodeId); diff --git a/src/lib/component/controller/BookmarkController.h b/src/lib/component/controller/BookmarkController.h index 4dc9f6c4..b377bede 100644 --- a/src/lib/component/controller/BookmarkController.h +++ b/src/lib/component/controller/BookmarkController.h @@ -6,13 +6,17 @@ #include "EdgeBookmark.h" #include "MessageListener.h" -#include "MessageActivateErrors.h" -#include "MessageIndexingFinished.h" #include "MessageActivateAll.h" -#include "MessageActivateBookmark.h" +#include "MessageActivateErrors.h" +#include "MessageActivateFullTextSearch.h" +#include "MessageActivateLegend.h" #include "MessageActivateTokens.h" -#include "MessageDisplayBookmarkCreator.h" -#include "MessageDisplayBookmarks.h" +#include "MessageBookmarkActivate.h" +#include "MessageBookmarkBrowse.h" +#include "MessageBookmarkCreate.h" +#include "MessageBookmarkDelete.h" +#include "MessageBookmarkEdit.h" +#include "MessageIndexingFinished.h" #include "Controller.h" @@ -21,18 +25,22 @@ class StorageAccess; class BookmarkController : public Controller , public MessageListener - , public MessageListener , public MessageListener + , public MessageListener + , public MessageListener , public MessageListener - , public MessageListener - , public MessageListener + , public MessageListener + , public MessageListener + , public MessageListener + , public MessageListener + , public MessageListener , public MessageListener { public: BookmarkController(StorageAccess* storageAccess); virtual ~BookmarkController(); - virtual void clear(); + void clear() override; void displayBookmarks(); void displayBookmarksFor(Bookmark::BookmarkFilter filter, Bookmark::BookmarkOrder order); @@ -68,20 +76,24 @@ private: bool m_edgeBookmarksValid; }; - virtual void handleMessage(MessageActivateAll* message); - virtual void handleMessage(MessageActivateBookmark* message); - virtual void handleMessage(MessageActivateErrors* message); - virtual void handleMessage(MessageActivateTokens* message); - virtual void handleMessage(MessageDisplayBookmarkCreator* message); - virtual void handleMessage(MessageDisplayBookmarks* message); - virtual void handleMessage(MessageIndexingFinished* message); + void handleMessage(MessageActivateAll* message) override; + void handleMessage(MessageActivateErrors* message) override; + void handleMessage(MessageActivateFullTextSearch* message) override; + void handleMessage(MessageActivateLegend* message) override; + void handleMessage(MessageActivateTokens* message) override; + void handleMessage(MessageBookmarkActivate* message) override; + void handleMessage(MessageBookmarkBrowse* message) override; + void handleMessage(MessageBookmarkCreate* message) override; + void handleMessage(MessageBookmarkDelete* message) override; + void handleMessage(MessageBookmarkEdit* message) override; + void handleMessage(MessageIndexingFinished* message) override; std::vector getActiveTokenDisplayNames() const; std::vector getDisplayNamesForNodeId(Id nodeId) const; std::vector getAllBookmarkCategories() const; - std::shared_ptr getBookmarkForActiveToken() const; + std::shared_ptr getBookmarkForActiveToken(Id tabId) const; std::shared_ptr getBookmarkForNodeId(Id nodeId) const; bool canCreateBookmark() const; @@ -118,8 +130,8 @@ private: StorageAccess* m_storageAccess; mutable BookmarkCache m_bookmarkCache; - std::vector m_activeNodeIds; - std::vector m_activeEdgeIds; + mutable std::map> m_activeNodeIds; + mutable std::map> m_activeEdgeIds; Bookmark::BookmarkFilter m_filter; Bookmark::BookmarkOrder m_order; diff --git a/src/lib/component/controller/CodeController.cpp b/src/lib/component/controller/CodeController.cpp index e85f4c93..1a7dfbc5 100644 --- a/src/lib/component/controller/CodeController.cpp +++ b/src/lib/component/controller/CodeController.cpp @@ -20,8 +20,9 @@ CodeController::CodeController(StorageAccess* storageAccess) { } -CodeController::~CodeController() +Id CodeController::getSchedulerId() const { + return Controller::getTabId(); } const uint CodeController::s_lineRadius = 2; diff --git a/src/lib/component/controller/CodeController.h b/src/lib/component/controller/CodeController.h index a3dda681..f2e55b02 100644 --- a/src/lib/component/controller/CodeController.h +++ b/src/lib/component/controller/CodeController.h @@ -58,33 +58,35 @@ class CodeController { public: CodeController(StorageAccess* storageAccess); - ~CodeController(); + virtual ~CodeController() = default; + + Id getSchedulerId() const override; private: static const uint s_lineRadius; - virtual void handleMessage(MessageActivateAll* message); - virtual void handleMessage(MessageActivateErrors* message); - virtual void handleMessage(MessageActivateFullTextSearch* message); - virtual void handleMessage(MessageActivateLegend* message); - virtual void handleMessage(MessageActivateLocalSymbols* message); - virtual void handleMessage(MessageActivateTokens* message); - virtual void handleMessage(MessageActivateTrailEdge* message); - virtual void handleMessage(MessageChangeFileView* message); - virtual void handleMessage(MessageCodeShowDefinition* message); - virtual void handleMessage(MessageDeactivateEdge* message); - virtual void handleMessage(MessageErrorCountClear* message); - virtual void handleMessage(MessageFlushUpdates* message); - virtual void handleMessage(MessageFocusIn* message); - virtual void handleMessage(MessageFocusOut* message); - virtual void handleMessage(MessageScrollCode* message); - virtual void handleMessage(MessageScrollToLine* message); - virtual void handleMessage(MessageShowError* message); - virtual void handleMessage(MessageShowScope* message); + void handleMessage(MessageActivateAll* message) override; + void handleMessage(MessageActivateErrors* message) override; + void handleMessage(MessageActivateFullTextSearch* message) override; + void handleMessage(MessageActivateLegend* message) override; + void handleMessage(MessageActivateLocalSymbols* message) override; + void handleMessage(MessageActivateTokens* message) override; + void handleMessage(MessageActivateTrailEdge* message) override; + void handleMessage(MessageChangeFileView* message) override; + void handleMessage(MessageCodeShowDefinition* message) override; + void handleMessage(MessageDeactivateEdge* message) override; + void handleMessage(MessageErrorCountClear* message) override; + void handleMessage(MessageFlushUpdates* message) override; + void handleMessage(MessageFocusIn* message) override; + void handleMessage(MessageFocusOut* message) override; + void handleMessage(MessageScrollCode* message) override; + void handleMessage(MessageScrollToLine* message) override; + void handleMessage(MessageShowError* message) override; + void handleMessage(MessageShowScope* message) override; CodeView* getView() const; - virtual void clear(); + void clear() override; std::vector getSnippetsForFileWithState(const FilePath& filePath, CodeView::FileState state) const; std::vector getSnippetsForActiveSourceLocations( diff --git a/src/lib/component/controller/Controller.cpp b/src/lib/component/controller/Controller.cpp index d3be3d22..f98e929f 100644 --- a/src/lib/component/controller/Controller.cpp +++ b/src/lib/component/controller/Controller.cpp @@ -1,6 +1,7 @@ #include "component/controller/Controller.h" Controller::Controller() + : m_component(nullptr) { } @@ -12,3 +13,13 @@ void Controller::setComponent(Component* component) { m_component = component; } + +Id Controller::getTabId() const +{ + if (m_component) + { + return m_component->getTabId(); + } + + return 0; +} diff --git a/src/lib/component/controller/Controller.h b/src/lib/component/controller/Controller.h index 9201578f..9e63f3ea 100644 --- a/src/lib/component/controller/Controller.h +++ b/src/lib/component/controller/Controller.h @@ -13,6 +13,8 @@ public: virtual void clear() = 0; + Id getTabId() const; + protected: template ViewType* getView() const; diff --git a/src/lib/component/controller/ErrorController.cpp b/src/lib/component/controller/ErrorController.cpp index 2c445dab..4461bbdf 100644 --- a/src/lib/component/controller/ErrorController.cpp +++ b/src/lib/component/controller/ErrorController.cpp @@ -1,10 +1,11 @@ #include "ErrorController.h" #include "Application.h" -#include "DialogView.h" -#include "StorageAccess.h" -#include "Project.h" #include "ApplicationSettings.h" +#include "DialogView.h" +#include "Project.h" +#include "StorageAccess.h" +#include "TabId.h" ErrorController::ErrorController(StorageAccess* storageAccess) : m_storageAccess(storageAccess) @@ -17,19 +18,19 @@ ErrorController::~ErrorController() void ErrorController::errorFilterChanged(const ErrorFilter& filter) { - if (m_activeFilePath.empty()) + if (m_tabActiveFilePath[TabId::currentTab()].empty()) { MessageActivateErrors(filter).dispatch(); } else { - MessageActivateErrors(filter, m_activeFilePath).dispatch(); + MessageActivateErrors(filter, m_tabActiveFilePath[TabId::currentTab()]).dispatch(); } } void ErrorController::showError(Id errorId) { - if (!m_showsErrors) + if (!m_tabShowsErrors[TabId::currentTab()]) { errorFilterChanged(getView()->getErrorFilter()); } @@ -39,15 +40,15 @@ void ErrorController::showError(Id errorId) void ErrorController::handleMessage(MessageActivateAll* message) { - m_showsErrors = false; + m_tabShowsErrors[message->getSchedulerId()] = false; } void ErrorController::handleMessage(MessageActivateErrors* message) { clear(); - m_showsErrors = true; - m_activeFilePath = message->file; + m_tabShowsErrors[message->getSchedulerId()] = true; + m_tabActiveFilePath[message->getSchedulerId()] = message->file; ErrorView* view = getView(); view->setErrorFilter(message->filter); @@ -60,12 +61,12 @@ void ErrorController::handleMessage(MessageActivateErrors* message) void ErrorController::handleMessage(MessageActivateFullTextSearch* message) { - m_showsErrors = false; + m_tabShowsErrors[message->getSchedulerId()] = false; } void ErrorController::handleMessage(MessageActivateTokens* message) { - m_showsErrors = false; + m_tabShowsErrors[message->getSchedulerId()] = false; } void ErrorController::handleMessage(MessageErrorCountClear* message) @@ -178,9 +179,9 @@ ErrorView* ErrorController::getView() const void ErrorController::clear() { - m_showsErrors = false; m_errorCount = 0; - m_activeFilePath = FilePath(); + m_tabShowsErrors.clear(); + m_tabActiveFilePath.clear(); getView()->clear(); } @@ -193,13 +194,13 @@ bool ErrorController::showErrors(const ErrorFilter& filter, bool scrollTo) filterUnlimited.limit = 0; std::vector errors; - if (m_activeFilePath.empty()) + if (m_tabActiveFilePath[TabId::currentTab()].empty()) { errors = m_storageAccess->getErrorsLimited(filterUnlimited); } else { - errors = m_storageAccess->getErrorsForFileLimited(filter, m_activeFilePath); + errors = m_storageAccess->getErrorsForFileLimited(filter, m_tabActiveFilePath[TabId::currentTab()]); } ErrorCountInfo errorCount(errors); diff --git a/src/lib/component/controller/ErrorController.h b/src/lib/component/controller/ErrorController.h index 30b3eb8e..0b161c48 100644 --- a/src/lib/component/controller/ErrorController.h +++ b/src/lib/component/controller/ErrorController.h @@ -65,9 +65,10 @@ private: StorageAccess* m_storageAccess; - bool m_showsErrors = false; size_t m_errorCount = 0; - FilePath m_activeFilePath; + + std::map m_tabShowsErrors; + std::map m_tabActiveFilePath; }; #endif // ERROR_CONTROLLER_H diff --git a/src/lib/component/controller/GraphController.cpp b/src/lib/component/controller/GraphController.cpp index fc506974..efc38026 100644 --- a/src/lib/component/controller/GraphController.cpp +++ b/src/lib/component/controller/GraphController.cpp @@ -28,8 +28,9 @@ GraphController::GraphController(StorageAccess* storageAccess) { } -GraphController::~GraphController() +Id GraphController::getSchedulerId() const { + return Controller::getTabId(); } void GraphController::handleMessage(MessageActivateAll* message) diff --git a/src/lib/component/controller/GraphController.h b/src/lib/component/controller/GraphController.h index 5434282b..ecd797e7 100644 --- a/src/lib/component/controller/GraphController.h +++ b/src/lib/component/controller/GraphController.h @@ -52,29 +52,31 @@ class GraphController { public: GraphController(StorageAccess* storageAccess); - ~GraphController(); + ~GraphController() = default; + + Id getSchedulerId() const override; private: - virtual void handleMessage(MessageActivateAll* message); - virtual void handleMessage(MessageActivateErrors* message); - virtual void handleMessage(MessageActivateFullTextSearch* message); - virtual void handleMessage(MessageActivateLegend* message); - virtual void handleMessage(MessageActivateTokens* message); - virtual void handleMessage(MessageActivateTrail* message); - virtual void handleMessage(MessageActivateTrailEdge* message); - virtual void handleMessage(MessageFlushUpdates* message); - virtual void handleMessage(MessageFocusIn* message); - virtual void handleMessage(MessageFocusOut* message); - virtual void handleMessage(MessageGraphNodeBundleSplit* message); - virtual void handleMessage(MessageGraphNodeExpand* message); - virtual void handleMessage(MessageGraphNodeHide* message); - virtual void handleMessage(MessageGraphNodeMove* message); - virtual void handleMessage(MessageScrollGraph* message); - virtual void handleMessage(MessageShowReference* message); + void handleMessage(MessageActivateAll* message) override; + void handleMessage(MessageActivateErrors* message) override; + void handleMessage(MessageActivateFullTextSearch* message) override; + void handleMessage(MessageActivateLegend* message) override; + void handleMessage(MessageActivateTokens* message) override; + void handleMessage(MessageActivateTrail* message) override; + void handleMessage(MessageActivateTrailEdge* message) override; + void handleMessage(MessageFlushUpdates* message) override; + void handleMessage(MessageFocusIn* message) override; + void handleMessage(MessageFocusOut* message) override; + void handleMessage(MessageGraphNodeBundleSplit* message) override; + void handleMessage(MessageGraphNodeExpand* message) override; + void handleMessage(MessageGraphNodeHide* message) override; + void handleMessage(MessageGraphNodeMove* message) override; + void handleMessage(MessageScrollGraph* message) override; + void handleMessage(MessageShowReference* message) override; GraphView* getView() const; - virtual void clear(); + void clear() override; void createDummyGraph(const std::shared_ptr graph); void createDummyGraphAndSetActiveAndVisibility( diff --git a/src/lib/component/controller/IDECommunicationController.cpp b/src/lib/component/controller/IDECommunicationController.cpp index 13764fec..56643664 100644 --- a/src/lib/component/controller/IDECommunicationController.cpp +++ b/src/lib/component/controller/IDECommunicationController.cpp @@ -2,12 +2,11 @@ #include "FileSystem.h" #include "logging.h" -#include "MessageActivateSourceLocations.h" #include "MessageActivateWindow.h" +#include "MessagePingReceived.h" #include "MessageProjectNew.h" #include "MessageStatus.h" -#include "MessageActivateFile.h" -#include "MessagePingReceived.h" +#include "MessageTabOpenWith.h" #include "StorageAccess.h" #include "SourceLocationFile.h" @@ -118,7 +117,7 @@ void IDECommunicationController::handleSetActiveTokenMessage( std::to_wstring(message.row) + L", col: " + std::to_wstring(message.column) ).dispatch(); - MessageActivateSourceLocations(selectedLocationIds).dispatch(); + MessageTabOpenWith(0, selectedLocationIds[0]).showNewTab(true).dispatch(); MessageActivateWindow().dispatch(); return; } @@ -126,7 +125,7 @@ void IDECommunicationController::handleSetActiveTokenMessage( if (fileId > 0) { - MessageActivateFile(filePath, message.row).dispatchImmediately(); + MessageTabOpenWith(filePath, message.row).showNewTab(true).dispatch(); MessageActivateWindow().dispatch(); } else diff --git a/src/lib/component/controller/ScreenSearchController.cpp b/src/lib/component/controller/ScreenSearchController.cpp index c25c4d9f..c43994d5 100644 --- a/src/lib/component/controller/ScreenSearchController.cpp +++ b/src/lib/component/controller/ScreenSearchController.cpp @@ -2,14 +2,6 @@ #include "ScreenSearchView.h" -ScreenSearchController::ScreenSearchController() -{ -} - -ScreenSearchController::~ScreenSearchController() -{ -} - void ScreenSearchController::clear() { } @@ -54,15 +46,21 @@ void ScreenSearchController::addResponder(ScreenSearchResponder* responder) } } +void ScreenSearchController::removeResponder(ScreenSearchResponder* responder) +{ + if (responder) + { + auto it = std::find(m_responders.begin(), m_responders.end(), responder); + if (it != m_responders.end()) + { + m_responders.erase(it); + } + } +} + void ScreenSearchController::search(const std::wstring& query, const std::set& responderNames) { - { - std::lock_guard lock(m_matchMutex); - m_matches.clear(); - m_matchIndex = 0; - } - - getView()->setMatchCount(0); + clearMatches(); for (ScreenSearchResponder* responder : m_responders) { @@ -75,10 +73,6 @@ void ScreenSearchController::search(const std::wstring& query, const std::setfindMatches(this, query); } - else - { - responder->clearMatches(); - } } } @@ -133,6 +127,8 @@ void ScreenSearchController::clearMatches() m_matchIndex = 0; } + getView()->setMatchCount(0); + for (ScreenSearchResponder* responder : m_responders) { responder->clearMatches(); diff --git a/src/lib/component/controller/ScreenSearchController.h b/src/lib/component/controller/ScreenSearchController.h index 74d26954..5bd78df2 100644 --- a/src/lib/component/controller/ScreenSearchController.h +++ b/src/lib/component/controller/ScreenSearchController.h @@ -13,19 +13,19 @@ class ScreenSearchController , public ScreenSearchSender { public: - ScreenSearchController(); - virtual ~ScreenSearchController(); + virtual ~ScreenSearchController() = default; // Controller implementation - virtual void clear(); + void clear() override; // ScreenSearchSender implementation - virtual void foundMatches(ScreenSearchResponder* responder, size_t matchCount); + void foundMatches(ScreenSearchResponder* responder, size_t matchCount) override; + void addResponder(ScreenSearchResponder* responder) override; + void removeResponder(ScreenSearchResponder* responder) override; + void clearMatches() override; - void addResponder(ScreenSearchResponder* responder); void search(const std::wstring& query, const std::set& responderNames); void activateMatch(bool next); - void clearMatches(); private: size_t getResponderId(ScreenSearchResponder* responder) const; diff --git a/src/lib/component/controller/SearchController.cpp b/src/lib/component/controller/SearchController.cpp index 5cbc0969..8f2df7d3 100644 --- a/src/lib/component/controller/SearchController.cpp +++ b/src/lib/component/controller/SearchController.cpp @@ -1,8 +1,9 @@ #include "SearchController.h" +#include "logging.h" +#include "MessageTabState.h" #include "SearchView.h" #include "StorageAccess.h" -#include "logging.h" #include "tracing.h" SearchController::SearchController(StorageAccess* storageAccess) @@ -10,38 +11,37 @@ SearchController::SearchController(StorageAccess* storageAccess) { } -SearchController::~SearchController() +Id SearchController::getSchedulerId() const { + return Controller::getTabId(); } void SearchController::handleMessage(MessageActivateAll* message) { - getView()->setMatches(message->getSearchMatches()); + updateMatches(message); } void SearchController::handleMessage(MessageActivateErrors* message) { - getView()->setMatches(message->getSearchMatches()); + updateMatches(message); } void SearchController::handleMessage(MessageActivateFullTextSearch* message) { - getView()->setMatches(message->getSearchMatches()); + updateMatches(message); } void SearchController::handleMessage(MessageActivateLegend* message) { - getView()->setMatches(message->getSearchMatches()); + updateMatches(message); } void SearchController::handleMessage(MessageActivateTokens* message) { - if (message->keepContent()) + if (!message->isEdge) { - return; + updateMatches(message, !message->keepContent()); } - - getView()->setMatches(message->getSearchMatches()); } void SearchController::handleMessage(MessageFind* message) @@ -79,5 +79,22 @@ SearchView* SearchController::getView() void SearchController::clear() { - getView()->setMatches(std::vector()); + updateMatches(nullptr); +} + +void SearchController::updateMatches(MessageActivateBase* message, bool updateView) +{ + std::vector matches; + + if (message) + { + matches = message->getSearchMatches(); + } + + if (updateView) + { + getView()->setMatches(matches); + } + + MessageTabState(Controller::getTabId(), matches).dispatch(); } diff --git a/src/lib/component/controller/SearchController.h b/src/lib/component/controller/SearchController.h index 27da44ae..159f44e2 100644 --- a/src/lib/component/controller/SearchController.h +++ b/src/lib/component/controller/SearchController.h @@ -26,20 +26,24 @@ class SearchController { public: SearchController(StorageAccess* storageAccess); - ~SearchController(); + ~SearchController() = default; + + Id getSchedulerId() const override; private: - virtual void handleMessage(MessageActivateAll* message); - virtual void handleMessage(MessageActivateErrors* message); - virtual void handleMessage(MessageActivateFullTextSearch* message); - virtual void handleMessage(MessageActivateLegend* message); - virtual void handleMessage(MessageActivateTokens* message); - virtual void handleMessage(MessageFind* message); - virtual void handleMessage(MessageSearchAutocomplete* message); + void handleMessage(MessageActivateAll* message) override; + void handleMessage(MessageActivateErrors* message) override; + void handleMessage(MessageActivateFullTextSearch* message) override; + void handleMessage(MessageActivateLegend* message) override; + void handleMessage(MessageActivateTokens* message) override; + void handleMessage(MessageFind* message) override; + void handleMessage(MessageSearchAutocomplete* message) override; SearchView* getView(); - virtual void clear(); + void clear() override; + + void updateMatches(MessageActivateBase* message, bool updateView = true); StorageAccess* m_storageAccess; }; diff --git a/src/lib/component/controller/TabsController.cpp b/src/lib/component/controller/TabsController.cpp new file mode 100644 index 00000000..f489daf8 --- /dev/null +++ b/src/lib/component/controller/TabsController.cpp @@ -0,0 +1,224 @@ +#include "TabsController.h" + +#include "Application.h" +#include "MessageFind.h" +#include "MessageIndexingFinished.h" +#include "MessageSearch.h" +#include "MessageScrollToLine.h" +#include "ScreenSearchInterfaces.h" +#include "TabId.h" +#include "TaskLambda.h" +#include "TaskManager.h" +#include "TaskScheduler.h" + +TabsController::TabsController( + ViewLayout* mainLayout, + const ViewFactory* viewFactory, + StorageAccess* storageAccess, + ScreenSearchSender* screenSearchSender +) + : m_mainLayout(mainLayout) + , m_viewFactory(viewFactory) + , m_storageAccess(storageAccess) + , m_screenSearchSender(screenSearchSender) +{ +} + +void TabsController::clear() +{ + getView()->clear(); + + while (true) + { + { + std::lock_guard lock(m_tabsMutex); + if (m_tabs.empty()) + { + break; + } + } + + std::this_thread::sleep_for(std::chrono::milliseconds(100)); + } +} + +void TabsController::addTab(Id tabId, SearchMatch match) +{ + std::lock_guard lock(m_tabsMutex); + + TaskManager::createScheduler(tabId)->startSchedulerLoopThreaded(); + + m_tabs.emplace(tabId, std::make_shared(tabId, m_viewFactory, m_storageAccess, m_screenSearchSender)); + + if (match.isValid()) + { + MessageSearch msg({ match }, NodeTypeSet::all()); + msg.setSchedulerId(tabId); + msg.dispatch(); + + if (match.tokenIds.size() && std::get<0>(m_scrollToLine) == match.tokenIds[0]) + { + MessageScrollToLine scrollMsg(std::get<1>(m_scrollToLine), std::get<2>(m_scrollToLine)); + scrollMsg.setSchedulerId(tabId); + scrollMsg.dispatch(); + } + } + else + { + MessageFind msg; + msg.setSchedulerId(tabId); + msg.dispatch(); + } + + m_scrollToLine = std::make_tuple(0, FilePath(), 0); +} + +void TabsController::showTab(Id tabId) +{ + std::lock_guard lock(m_tabsMutex); + + auto it = m_tabs.find(tabId); + if (it != m_tabs.end()) + { + TabId::setCurrentTabId(tabId); + it->second->setParentLayout(m_mainLayout); + } + else + { + TabId::setCurrentTabId(0); + m_mainLayout->showOriginalViews(); + } + + Task::dispatch( + TabId::app(), + std::make_shared( + [this]() + { + m_screenSearchSender->clearMatches(); + } + ) + ); +} + +void TabsController::removeTab(Id tabId) +{ + // use app task scheduler thread to stop running tasks of tab + Task::dispatch( + TabId::background(), + std::make_shared( + [tabId, this]() + { + m_screenSearchSender->clearMatches(); + + TaskScheduler* scheduler = TaskManager::getScheduler(tabId).get(); + scheduler->terminateRunningTasks(); + scheduler->stopSchedulerLoop(); + + TaskManager::destroyScheduler(tabId); + + getView()->destroyTab(tabId); + } + ) + ); +} + +void TabsController::destroyTab(Id tabId) +{ + std::lock_guard lock(m_tabsMutex); + + // destroy the tab on the qt thread to allow view destruction + m_tabs.erase(tabId); + + if (m_tabs.empty() && Application::getInstance()->isProjectLoaded()) + { + MessageTabOpen().dispatch(); + } +} + +void TabsController::onClearTabs() +{ + TabId::setCurrentTabId(0); + m_mainLayout->showOriginalViews(); +} + +TabsView* TabsController::getView() const +{ + return Controller::getView(); +} + +void TabsController::handleMessage(MessageIndexingFinished* message) +{ + if (m_tabs.empty() && Application::getInstance()->isProjectLoaded()) + { + MessageTabOpenWith(SearchMatch::createCommand(SearchMatch::COMMAND_ALL)).dispatch(); + } +} + +void TabsController::handleMessage(MessageTabClose* message) +{ + getView()->closeTab(); +} + +void TabsController::handleMessage(MessageTabOpen* message) +{ + if (Application::getInstance()->isProjectLoaded()) + { + getView()->openTab(true, SearchMatch()); + } +} + +void TabsController::handleMessage(MessageTabOpenWith* message) +{ + if (!Application::getInstance()->isProjectLoaded()) + { + return; + } + + SearchMatch match = message->match; + if (!match.isValid()) + { + Id tokenId = message->tokenId; + if (!tokenId && message->locationId) + { + std::vector tokenIds = m_storageAccess->getNodeIdsForLocationIds({ message->locationId }); + if (tokenIds.size()) + { + tokenId = tokenIds[0]; + } + } + + if (!tokenId && !message->filePath.empty()) + { + tokenId = m_storageAccess->getNodeIdForFileNode(message->filePath); + + if (message->line) + { + m_scrollToLine = std::make_tuple(tokenId, message->filePath, message->line); + } + } + + if (tokenId) + { + std::vector matches = m_storageAccess->getSearchMatchesForTokenIds({ tokenId }); + if (matches.size()) + { + match = matches[0]; + } + } + } + + if (match.isValid()) + { + getView()->openTab(message->showTab, match); + } +} + +void TabsController::handleMessage(MessageTabSelect* message) +{ + getView()->selectTab(message->next); +} + +void TabsController::handleMessage(MessageTabState* message) +{ + getView()->updateTab(message->tabId, message->searchMatches); +} diff --git a/src/lib/component/controller/TabsController.h b/src/lib/component/controller/TabsController.h new file mode 100644 index 00000000..02a28df9 --- /dev/null +++ b/src/lib/component/controller/TabsController.h @@ -0,0 +1,69 @@ +#ifndef TABS_CONTROLLER_H +#define TABS_CONTROLLER_H + +#include "MessageListener.h" +#include "MessageIndexingFinished.h" +#include "MessageTabClose.h" +#include "MessageTabOpen.h" +#include "MessageTabOpenWith.h" +#include "MessageTabSelect.h" +#include "MessageTabState.h" + +#include "Controller.h" +#include "Tab.h" +#include "TabsView.h" + +struct SearchMatch; + +class StorageAccess; +class ViewFactory; +class ViewLayout; + +class TabsController + : public Controller + , public MessageListener + , public MessageListener + , public MessageListener + , public MessageListener + , public MessageListener + , public MessageListener +{ +public: + TabsController( + ViewLayout* mainLayout, + const ViewFactory* viewFactory, + StorageAccess* storageAccess, + ScreenSearchSender* screenSearchSender + ); + + // Controller implementation + virtual void clear(); + + void addTab(Id tabId, SearchMatch match); + void showTab(Id tabId); + void removeTab(Id tabId); + void destroyTab(Id tabId); + void onClearTabs(); + +private: + virtual void handleMessage(MessageIndexingFinished* message); + virtual void handleMessage(MessageTabClose* message); + virtual void handleMessage(MessageTabOpen* message); + virtual void handleMessage(MessageTabOpenWith* message); + virtual void handleMessage(MessageTabSelect* message); + virtual void handleMessage(MessageTabState* message); + + TabsView* getView() const; + + ViewLayout* m_mainLayout; + const ViewFactory* m_viewFactory; + StorageAccess* m_storageAccess; + ScreenSearchSender* m_screenSearchSender; + + std::map> m_tabs; + std::mutex m_tabsMutex; + + std::tuple m_scrollToLine; +}; + +#endif // TABS_CONTROLLER_H diff --git a/src/lib/component/controller/TooltipController.cpp b/src/lib/component/controller/TooltipController.cpp index 4231d87b..9f56f8b8 100644 --- a/src/lib/component/controller/TooltipController.cpp +++ b/src/lib/component/controller/TooltipController.cpp @@ -6,6 +6,7 @@ #include "StorageAccess.h" #include "MessageActivateSourceLocations.h" +#include "TabId.h" #include "TaskDecoratorDelay.h" #include "TaskLambda.h" @@ -143,7 +144,7 @@ void TooltipController::requestTooltipShow(const std::vector tokenIds, Toolt delayMS = 300; } - Task::dispatch(std::make_shared(delayMS)->addChildTask( + Task::dispatch(TabId::app(), std::make_shared(delayMS)->addChildTask( std::make_shared( [requestId, this]() { @@ -180,7 +181,7 @@ void TooltipController::requestTooltipHide() } m_hideRequest = true; - Task::dispatch(std::make_shared(500)->addChildTask( + Task::dispatch(TabId::app(), std::make_shared(500)->addChildTask( std::make_shared( [this]() { diff --git a/src/lib/component/controller/UndoRedoController.cpp b/src/lib/component/controller/UndoRedoController.cpp index d89ee8c8..dc362ad6 100644 --- a/src/lib/component/controller/UndoRedoController.cpp +++ b/src/lib/component/controller/UndoRedoController.cpp @@ -15,8 +15,9 @@ UndoRedoController::UndoRedoController(StorageAccess* storageAccess) m_iterator = m_list.end(); } -UndoRedoController::~UndoRedoController() +Id UndoRedoController::getSchedulerId() const { + return Controller::getTabId(); } UndoRedoView* UndoRedoController::getView() @@ -269,7 +270,10 @@ void UndoRedoController::handleMessage(MessageHistoryToPosition* message) else { replayCommand(m_iterator); - MessageFlushUpdates(false).dispatch(); + + MessageFlushUpdates msg(false); + msg.setSchedulerId(getSchedulerId()); + msg.dispatch(); } } @@ -359,7 +363,9 @@ void UndoRedoController::handleMessage(MessageRefreshUI* message) { if (m_iterator == m_list.begin()) { - MessageActivateAll().dispatch(); + MessageActivateAll msg; + msg.setSchedulerId(getSchedulerId()); + msg.dispatch(); } else { @@ -466,7 +472,9 @@ void UndoRedoController::replayCommands(std::list::iterator it) std::advance(it, 1); } - MessageFlushUpdates(keepsContent).dispatch(); + MessageFlushUpdates msg(keepsContent); + msg.setSchedulerId(getSchedulerId()); + msg.dispatch(); } void UndoRedoController::replayCommand(std::list::iterator it) @@ -512,6 +520,7 @@ void UndoRedoController::replayCommand(std::list::iterator it) filter.unindexedFatal = false; MessageActivateErrors msg(filter); + msg.setSchedulerId(getSchedulerId()); msg.setIsReplayed(true); msg.setIsLast(it == std::prev(m_iterator)); msg.dispatch(); @@ -608,34 +617,7 @@ MessageBase* UndoRedoController::lastMessage() const void UndoRedoController::updateHistoryMenu(std::shared_ptr message) { - const size_t historyMenuSize = 20; - - if (message && dynamic_cast(message.get())) - { - std::vector matches = dynamic_cast(message.get())->getSearchMatches(); - if (matches.size() && !matches[0].text.empty()) - { - std::vector> history = { message }; - std::set uniqueMatches = { matches[0] }; - - for (std::shared_ptr m : m_history) - { - if (uniqueMatches.insert(dynamic_cast(m.get())->getSearchMatches()[0]).second) - { - history.push_back(m); - - if (history.size() >= historyMenuSize) - { - break; - } - } - } - - m_history = history; - } - } - - Application::getInstance()->updateHistoryMenu(m_history); + Application::getInstance()->updateHistoryMenu(message); } void UndoRedoController::updateHistory() diff --git a/src/lib/component/controller/UndoRedoController.h b/src/lib/component/controller/UndoRedoController.h index ea7bae6b..19ba3d79 100644 --- a/src/lib/component/controller/UndoRedoController.h +++ b/src/lib/component/controller/UndoRedoController.h @@ -66,7 +66,9 @@ class UndoRedoController { public: UndoRedoController(StorageAccess* storageAccess); - virtual ~UndoRedoController(); + virtual ~UndoRedoController() = default; + + Id getSchedulerId() const override; UndoRedoView* getView(); diff --git a/src/lib/component/controller/helper/ControllerProxy.h b/src/lib/component/controller/helper/ControllerProxy.h index 4c324ba5..44162f66 100644 --- a/src/lib/component/controller/helper/ControllerProxy.h +++ b/src/lib/component/controller/helper/ControllerProxy.h @@ -11,8 +11,9 @@ template class ControllerProxy { public: - ControllerProxy(View* view) + ControllerProxy(View* view, Id schedulerId) : m_view(view) + , m_schedulerId(schedulerId) { } @@ -30,7 +31,7 @@ public: ControllerType* controller = m_view->getController(); if (controller) { - Task::dispatch(std::make_shared( + Task::dispatch(m_schedulerId, std::make_shared( std::bind(callback, controller) )); } @@ -42,7 +43,7 @@ public: ControllerType* controller = m_view->getController(); if (controller) { - Task::dispatch(std::make_shared( + Task::dispatch(m_schedulerId, std::make_shared( [func = std::bind(callback, controller, args...)]() { func(); @@ -53,6 +54,7 @@ public: private: View* m_view; + Id m_schedulerId; }; #endif // CONTROLLER_PROXY_H diff --git a/src/lib/component/controller/helper/ScreenSearchInterfaces.h b/src/lib/component/controller/helper/ScreenSearchInterfaces.h index 44cc7406..01ba054e 100644 --- a/src/lib/component/controller/helper/ScreenSearchInterfaces.h +++ b/src/lib/component/controller/helper/ScreenSearchInterfaces.h @@ -6,15 +6,20 @@ class ScreenSearchResponder; class ScreenSearchSender { public: - virtual ~ScreenSearchSender() {} + virtual ~ScreenSearchSender() = default; virtual void foundMatches(ScreenSearchResponder* responder, size_t matchCount) = 0; + + virtual void addResponder(ScreenSearchResponder* responder) = 0; + virtual void removeResponder(ScreenSearchResponder* responder) = 0; + + virtual void clearMatches() = 0; }; class ScreenSearchResponder { public: - virtual ~ScreenSearchResponder() {} + virtual ~ScreenSearchResponder() = default; virtual std::string getName() const = 0; virtual bool isVisible() const = 0; diff --git a/src/lib/component/view/BookmarkButtonsView.cpp b/src/lib/component/view/BookmarkButtonsView.cpp new file mode 100644 index 00000000..98559208 --- /dev/null +++ b/src/lib/component/view/BookmarkButtonsView.cpp @@ -0,0 +1,27 @@ +#include "BookmarkButtonsView.h" + +BookmarkButtonsView::BookmarkButtonsView(ViewLayout* viewLayout) + : View(viewLayout) + , m_schedulerId(0) +{ +} + +std::string BookmarkButtonsView::getName() const +{ + return "BookmarkButtons"; +} + +Id BookmarkButtonsView::getSchedulerId() const +{ + return m_schedulerId; +} + +void BookmarkButtonsView::setTabId(Id schedulerId) +{ + m_schedulerId = schedulerId; +} + +void BookmarkButtonsView::handleMessage(MessageBookmarkButtonState* message) +{ + setCreateButtonState(message->state); +} diff --git a/src/lib/component/view/BookmarkButtonsView.h b/src/lib/component/view/BookmarkButtonsView.h new file mode 100644 index 00000000..759b77e7 --- /dev/null +++ b/src/lib/component/view/BookmarkButtonsView.h @@ -0,0 +1,29 @@ +#ifndef BOOKMARK_BUTTONS_VIEW_H +#define BOOKMARK_BUTTONS_VIEW_H + +#include "MessageBookmarkButtonState.h" +#include "MessageListener.h" +#include "View.h" + +class BookmarkButtonsView + : public View + , public MessageListener +{ +public: + BookmarkButtonsView(ViewLayout* viewLayout); + virtual ~BookmarkButtonsView() = default; + + std::string getName() const override; + + Id getSchedulerId() const override; + void setTabId(Id schedulerId); + + virtual void setCreateButtonState(const MessageBookmarkButtonState::ButtonState& state) = 0; + +private: + void handleMessage(MessageBookmarkButtonState* message) override; + + Id m_schedulerId; +}; + +#endif // BOOKMARK_BUTTONS_VIEW_H diff --git a/src/lib/component/view/BookmarkView.cpp b/src/lib/component/view/BookmarkView.cpp index e76a848e..5c256941 100644 --- a/src/lib/component/view/BookmarkView.cpp +++ b/src/lib/component/view/BookmarkView.cpp @@ -7,10 +7,6 @@ BookmarkView::BookmarkView(ViewLayout* viewLayout) { } -BookmarkView::~BookmarkView() -{ -} - std::string BookmarkView::getName() const { return "BookmarkView"; diff --git a/src/lib/component/view/BookmarkView.h b/src/lib/component/view/BookmarkView.h index ed79cc16..ab5c5f3b 100644 --- a/src/lib/component/view/BookmarkView.h +++ b/src/lib/component/view/BookmarkView.h @@ -1,8 +1,8 @@ #ifndef BOOKMARK_VIEW_H #define BOOKMARK_VIEW_H -#include "View.h" #include "Bookmark.h" +#include "View.h" class BookmarkController; @@ -11,25 +11,15 @@ class BookmarkView { public: BookmarkView(ViewLayout* viewLayout); - virtual ~BookmarkView(); + virtual ~BookmarkView() = default; virtual std::string getName() const; - enum CreateButtonState - { - CAN_CREATE = 0, - CANNOT_CREATE, - ALREADY_CREATED - }; - - virtual void setCreateButtonState(const CreateButtonState& state) = 0; - virtual void displayBookmarks(const std::vector>& bookmarks) = 0; virtual void displayBookmarkEditor( std::shared_ptr bookmark, const std::vector& categories) = 0; virtual void displayBookmarkCreator( const std::vector& names, const std::vector& categories, Id nodeId) = 0; - virtual void enableDisplayBookmarks(bool enable) = 0; virtual bool bookmarkBrowserIsVisible() const = 0; diff --git a/src/lib/component/view/CodeView.h b/src/lib/component/view/CodeView.h index 6084c4b8..52110fc2 100644 --- a/src/lib/component/view/CodeView.h +++ b/src/lib/component/view/CodeView.h @@ -96,7 +96,7 @@ public: virtual bool hasSingleFileCached(const FilePath& filePath) const = 0; -private: +protected: CodeController* getController(); }; diff --git a/src/lib/component/view/MainView.cpp b/src/lib/component/view/MainView.cpp index 5833216e..e9ec45da 100644 --- a/src/lib/component/view/MainView.cpp +++ b/src/lib/component/view/MainView.cpp @@ -1,9 +1,35 @@ #include "MainView.h" -MainView::MainView() +#include "TabId.h" + +MainView::MainView(const ViewFactory* viewFactory, StorageAccess* storageAccess) + : m_componentManager(viewFactory, storageAccess) { } -MainView::~MainView() +void MainView::setup() { + m_componentManager.setupMain(this, TabId::app()); + + loadLayout(); + + m_componentManager.refreshViews(); +} + +void MainView::clear() +{ + m_componentManager.clearComponents(); + clearHistoryMenu(); + clearBookmarksMenu(); +} + +void MainView::refreshViews() +{ + refreshView(); + m_componentManager.refreshViews(); +} + +std::shared_ptr MainView::getDialogView(DialogView::UseCase useCase) +{ + return m_componentManager.getDialogView(useCase); } diff --git a/src/lib/component/view/MainView.h b/src/lib/component/view/MainView.h index a6c0244f..f7efd39f 100644 --- a/src/lib/component/view/MainView.h +++ b/src/lib/component/view/MainView.h @@ -5,18 +5,27 @@ #include #include +#include "ComponentManager.h" +#include "DialogView.h" #include "ViewLayout.h" -struct SearchMatch; class Bookmark; class MessageBase; +class StorageAccess; +class ViewFactory; class MainView : public ViewLayout { public: - MainView(); - virtual ~MainView(); + MainView(const ViewFactory* viewFactory, StorageAccess* storageAccess); + virtual ~MainView() = default; + + void setup(); + void clear(); + void refreshViews(); + + std::shared_ptr getDialogView(DialogView::UseCase useCase); virtual void loadLayout() = 0; virtual void saveLayout() = 0; @@ -30,8 +39,15 @@ public: virtual void activateWindow() = 0; virtual void updateRecentProjectMenu() = 0; - virtual void updateHistoryMenu(const std::vector>& historyMenuItems) = 0; + + virtual void updateHistoryMenu(std::shared_ptr message) = 0; + virtual void clearHistoryMenu() = 0; + virtual void updateBookmarksMenu(const std::vector>& bookmarks) = 0; + virtual void clearBookmarksMenu() = 0; + +protected: + ComponentManager m_componentManager; }; #endif // MAIN_VIEW_H diff --git a/src/lib/component/view/TabsView.cpp b/src/lib/component/view/TabsView.cpp new file mode 100644 index 00000000..9485dcd5 --- /dev/null +++ b/src/lib/component/view/TabsView.cpp @@ -0,0 +1,11 @@ +#include "TabsView.h" + +TabsView::TabsView(ViewLayout* viewLayout) + : View(viewLayout) +{ +} + +std::string TabsView::getName() const +{ + return "Tabs"; +} diff --git a/src/lib/component/view/TabsView.h b/src/lib/component/view/TabsView.h new file mode 100644 index 00000000..4e7cd878 --- /dev/null +++ b/src/lib/component/view/TabsView.h @@ -0,0 +1,28 @@ +#ifndef TABS_VIEW_H +#define TABS_VIEW_H + +#include + +#include "View.h" + +struct SearchMatch; + +class TabsView + : public View +{ +public: + TabsView(ViewLayout* viewLayout); + virtual ~TabsView() = default; + + virtual std::string getName() const; + + virtual void clear() = 0; + + virtual void openTab(bool showTab, SearchMatch match) = 0; + virtual void closeTab() = 0; + virtual void destroyTab(Id tabId) = 0; + virtual void selectTab(bool next) = 0; + virtual void updateTab(Id tabId, std::vector matches) = 0; +}; + +#endif // TABS_VIEW_H diff --git a/src/lib/component/view/View.cpp b/src/lib/component/view/View.cpp index a988f50e..0afa5219 100644 --- a/src/lib/component/view/View.cpp +++ b/src/lib/component/view/View.cpp @@ -3,16 +3,12 @@ #include "ViewWidgetWrapper.h" View::View(ViewLayout* viewLayout) - : m_viewLayout(viewLayout) + : m_component(nullptr) + , m_viewLayout(viewLayout) , m_widgetWrapper(nullptr) { } -View::~View() -{ - m_viewLayout->removeView(this); -} - void View::init() { createWidgetWrapper(); diff --git a/src/lib/component/view/View.h b/src/lib/component/view/View.h index de03db99..07bcca3e 100644 --- a/src/lib/component/view/View.h +++ b/src/lib/component/view/View.h @@ -22,7 +22,7 @@ public: static std::shared_ptr createAndInit(ViewLayout* viewLayout); View(ViewLayout* viewLayout); - virtual ~View(); + virtual ~View() = default; virtual std::string getName() const = 0; diff --git a/src/lib/component/view/ViewFactory.cpp b/src/lib/component/view/ViewFactory.cpp deleted file mode 100644 index 7e2a7f42..00000000 --- a/src/lib/component/view/ViewFactory.cpp +++ /dev/null @@ -1,5 +0,0 @@ -#include "ViewFactory.h" - -ViewFactory::ViewFactory() -{ -} diff --git a/src/lib/component/view/ViewFactory.h b/src/lib/component/view/ViewFactory.h index b3e0f939..3643ae55 100644 --- a/src/lib/component/view/ViewFactory.h +++ b/src/lib/component/view/ViewFactory.h @@ -6,10 +6,12 @@ #include "CompositeView.h" #include "DialogView.h" +class BookmarkButtonsView; class BookmarkView; class CodeView; class ErrorView; class GraphView; +class GraphViewStyleImpl; class MainView; class RefreshView; class ScreenSearchView; @@ -18,6 +20,7 @@ class StatusBarView; class StatusView; class StorageAccess; class TabbedView; +class TabsView; class TooltipView; class UndoRedoView; class ViewLayout; @@ -25,14 +28,14 @@ class ViewLayout; class ViewFactory { public: - ViewFactory(); virtual ~ViewFactory() = default; - virtual std::shared_ptr createMainView() const = 0; + virtual std::shared_ptr createMainView(StorageAccess* storageAccess) const = 0; virtual std::shared_ptr createCompositeView( ViewLayout* viewLayout, CompositeView::CompositeDirection direction, const std::string& name) const = 0; virtual std::shared_ptr createTabbedView(ViewLayout* viewLayout, const std::string& name) const = 0; + virtual std::shared_ptr createBookmarkButtonsView(ViewLayout* viewLayout) const = 0; virtual std::shared_ptr createBookmarkView(ViewLayout* viewLayout) const = 0; virtual std::shared_ptr createCodeView(ViewLayout* viewLayout) const = 0; virtual std::shared_ptr createErrorView(ViewLayout* viewLayout) const = 0; @@ -42,11 +45,14 @@ public: virtual std::shared_ptr createSearchView(ViewLayout* viewLayout) const = 0; virtual std::shared_ptr createStatusBarView(ViewLayout* viewLayout) const = 0; virtual std::shared_ptr createStatusView(ViewLayout* viewLayout) const = 0; + virtual std::shared_ptr createTabsView(ViewLayout* viewLayout) const = 0; virtual std::shared_ptr createTooltipView(ViewLayout* viewLayout) const = 0; virtual std::shared_ptr createUndoRedoView(ViewLayout* viewLayout) const = 0; virtual std::shared_ptr createDialogView( ViewLayout* viewLayout, DialogView::UseCase useCase, StorageAccess* storageAccess) const = 0; + + virtual std::shared_ptr createGraphStyleImpl() const = 0; }; #endif // VIEW_FACTORY_H diff --git a/src/lib/component/view/ViewLayout.cpp b/src/lib/component/view/ViewLayout.cpp index 88a877bf..08db54b9 100644 --- a/src/lib/component/view/ViewLayout.cpp +++ b/src/lib/component/view/ViewLayout.cpp @@ -1,10 +1,6 @@ #include "ViewLayout.h" -ViewLayout::ViewLayout() -{ -} - -ViewLayout::~ViewLayout() +void ViewLayout::overrideView(View* view) { } @@ -12,3 +8,7 @@ View* ViewLayout::findFloatingView(const std::string& name) const { return nullptr; } + +void ViewLayout::showOriginalViews() +{ +} diff --git a/src/lib/component/view/ViewLayout.h b/src/lib/component/view/ViewLayout.h index f0252f92..93294693 100644 --- a/src/lib/component/view/ViewLayout.h +++ b/src/lib/component/view/ViewLayout.h @@ -8,10 +8,10 @@ class View; class ViewLayout { public: - ViewLayout(); - virtual ~ViewLayout(); + virtual ~ViewLayout() = default; virtual void addView(View* view) = 0; + virtual void overrideView(View* view); virtual void removeView(View* view) = 0; virtual void showView(View* view) = 0; @@ -20,6 +20,8 @@ public: virtual void setViewEnabled(View* view, bool enabled) = 0; virtual View* findFloatingView(const std::string& name) const; + + virtual void showOriginalViews(); }; #endif // VIEW_LAYOUT_H diff --git a/src/lib/data/storage/PersistentStorage.cpp b/src/lib/data/storage/PersistentStorage.cpp index 1ddb9184..d839f2fa 100644 --- a/src/lib/data/storage/PersistentStorage.cpp +++ b/src/lib/data/storage/PersistentStorage.cpp @@ -513,18 +513,21 @@ std::shared_ptr PersistentStorage::getFullTextSearchLo { TRACE(); - const TextCodec codec(ApplicationSettings::getInstance()->getTextEncoding()); - std::shared_ptr collection = std::make_shared(); if (searchTerm.empty()) { return collection; } - if (m_fullTextSearchCodec != codec.getName()) + const TextCodec codec(ApplicationSettings::getInstance()->getTextEncoding()); { - MessageStatus(L"Building fulltext search index", false, true).dispatch(); - buildFullTextSearchIndex(); + std::lock_guard lock(m_fullTextSearchMutex); + + if (m_fullTextSearchCodec != codec.getName()) + { + MessageStatus(L"Building fulltext search index", false, true).dispatch(); + buildFullTextSearchIndex(); + } } MessageStatus( diff --git a/src/lib/data/storage/PersistentStorage.h b/src/lib/data/storage/PersistentStorage.h index 3849d369..83440c90 100644 --- a/src/lib/data/storage/PersistentStorage.h +++ b/src/lib/data/storage/PersistentStorage.h @@ -212,6 +212,7 @@ private: mutable FullTextSearchIndex m_fullTextSearchIndex; mutable std::string m_fullTextSearchCodec; + mutable std::mutex m_fullTextSearchMutex; SqliteIndexStorage m_sqliteIndexStorage; SqliteBookmarkStorage m_sqliteBookmarkStorage; diff --git a/src/lib/project/Project.cpp b/src/lib/project/Project.cpp index b2ea8590..d26fef25 100644 --- a/src/lib/project/Project.cpp +++ b/src/lib/project/Project.cpp @@ -28,6 +28,7 @@ #include "MessageIndexingStatus.h" #include "MessageRefresh.h" #include "MessageStatus.h" +#include "TabId.h" #include "TaskDecoratorRepeat.h" #include "TaskFindKeyOnBlackboard.h" #include "TaskGroupSelector.h" @@ -71,6 +72,23 @@ std::string Project::getDescription() const return m_settings->getDescription(); } +bool Project::isLoaded() const +{ + switch (m_state) + { + case PROJECT_STATE_EMPTY: + case PROJECT_STATE_LOADED: + case PROJECT_STATE_OUTDATED: + case PROJECT_STATE_NEEDS_MIGRATION: + return true; + + default: + break; + } + + return false; +} + bool Project::isIndexing() const { return m_refreshStage == RefreshStageType::INDEXING; @@ -238,8 +256,6 @@ void Project::refresh(RefreshMode refreshMode, std::shared_ptr dialo return; } - m_refreshStage = RefreshStageType::REFRESHING; - if (m_state == PROJECT_STATE_NOT_LOADED) { return; @@ -312,6 +328,8 @@ void Project::refresh(RefreshMode refreshMode, std::shared_ptr dialo } } + m_refreshStage = RefreshStageType::REFRESHING; + if (m_state == PROJECT_STATE_NEEDS_MIGRATION) { m_settings->migrate(); @@ -324,6 +342,7 @@ void Project::refresh(RefreshMode refreshMode, std::shared_ptr dialo { if (!sourceGroup->prepareIndexing()) { + m_refreshStage = RefreshStageType::NONE; return; } } @@ -554,7 +573,7 @@ void Project::buildIndex(const RefreshInfo& info, std::shared_ptr di std::make_shared()->addChildTasks( std::make_shared("keep_database"), std::make_shared([dialogView, this]() { - Task::dispatch(std::make_shared([dialogView, this]() { + Task::dispatch(TabId::app(), std::make_shared([dialogView, this]() { swapToTempStorage(dialogView); })); }) @@ -562,7 +581,7 @@ void Project::buildIndex(const RefreshInfo& info, std::shared_ptr di std::make_shared()->addChildTasks( std::make_shared("discard_database"), std::make_shared([this]() { - Task::dispatch(std::make_shared([this]() { + Task::dispatch(TabId::app(), std::make_shared([this]() { discardTempStorage(); })); }) @@ -575,7 +594,7 @@ void Project::buildIndex(const RefreshInfo& info, std::shared_ptr di })); taskSequential->setIsBackgroundTask(true); - Task::dispatch(taskSequential); + Task::dispatch(TabId::app(), taskSequential); m_refreshStage = RefreshStageType::INDEXING; MessageIndexingStarted().dispatch(); diff --git a/src/lib/project/Project.h b/src/lib/project/Project.h index bb9f7330..4b99dffe 100644 --- a/src/lib/project/Project.h +++ b/src/lib/project/Project.h @@ -30,6 +30,7 @@ public: FilePath getProjectSettingsFilePath() const; std::string getDescription() const; + bool isLoaded() const; bool isIndexing() const; bool settingsEqualExceptNameAndLocation(const ProjectSettings& otherSettings) const; diff --git a/src/lib/utility/messaging/MessageBase.h b/src/lib/utility/messaging/MessageBase.h index 33c12b7f..f70566bb 100644 --- a/src/lib/utility/messaging/MessageBase.h +++ b/src/lib/utility/messaging/MessageBase.h @@ -12,6 +12,7 @@ class MessageBase public: MessageBase() : m_id(s_nextId++) + , m_schedulerId(0) , m_isParallel(false) , m_isReplayed(false) , m_sendAsTask(true) @@ -21,9 +22,7 @@ public: { } - virtual ~MessageBase() - { - } + virtual ~MessageBase() = default; virtual std::string getType() const = 0; virtual void dispatch() = 0; @@ -33,6 +32,16 @@ public: return m_id; } + Id getSchedulerId() const + { + return m_schedulerId; + } + + void setSchedulerId(Id schedulerId) + { + m_schedulerId = schedulerId; + } + bool sendAsTask() const { return m_sendAsTask; @@ -107,6 +116,7 @@ private: static Id s_nextId; Id m_id; + Id m_schedulerId; bool m_isParallel; bool m_isReplayed; diff --git a/src/lib/utility/messaging/MessageListenerBase.h b/src/lib/utility/messaging/MessageListenerBase.h index fb6c6ada..ba04dadb 100644 --- a/src/lib/utility/messaging/MessageListenerBase.h +++ b/src/lib/utility/messaging/MessageListenerBase.h @@ -53,6 +53,11 @@ public: m_alive = false; } + virtual Id getSchedulerId() const + { + return 0; + } + private: virtual std::string doGetType() const = 0; virtual void doHandleMessageBase(MessageBase*) = 0; diff --git a/src/lib/utility/messaging/MessageQueue.cpp b/src/lib/utility/messaging/MessageQueue.cpp index b6946d6b..79629e93 100644 --- a/src/lib/utility/messaging/MessageQueue.cpp +++ b/src/lib/utility/messaging/MessageQueue.cpp @@ -10,6 +10,7 @@ #include "TaskGroupParallel.h" #include "TaskGroupSequence.h" #include "TaskLambda.h" +#include "TabId.h" std::shared_ptr MessageQueue::getInstance() { @@ -252,7 +253,9 @@ void MessageQueue::sendMessage(std::shared_ptr message) { MessageListenerBase* listener = m_listeners[m_currentListenerIndex]; - if (listener->getType() == message->getType()) + if (listener->getType() == message->getType() && + (message->getSchedulerId() == 0 || listener->getSchedulerId() == 0 || + listener->getSchedulerId() == message->getSchedulerId())) { // The listenersMutex gets unlocked so changes to listeners are possible while message handling. m_listenersMutex.unlock(); @@ -280,7 +283,9 @@ void MessageQueue::sendMessageAsTask(std::shared_ptr message, bool { MessageListenerBase* listener = m_listeners[i]; - if (listener->getType() == message->getType()) + if (listener->getType() == message->getType() && + (message->getSchedulerId() == 0 || listener->getSchedulerId() == 0 || + listener->getSchedulerId() == message->getSchedulerId())) { Id listenerId = listener->getId(); taskGroup->addTask(std::make_shared( @@ -297,12 +302,18 @@ void MessageQueue::sendMessageAsTask(std::shared_ptr message, bool } } + Id schedulerId = message->getSchedulerId(); + if (!schedulerId) + { + schedulerId = TabId::app(); + } + if (asNextTask) { - Task::dispatchNext(taskGroup); + Task::dispatchNext(schedulerId, taskGroup); } else { - Task::dispatch(taskGroup); + Task::dispatch(schedulerId, taskGroup); } } diff --git a/src/lib/utility/messaging/type/MessageActivateAll.h b/src/lib/utility/messaging/type/MessageActivateAll.h index 89c1cd36..65cc812d 100644 --- a/src/lib/utility/messaging/type/MessageActivateAll.h +++ b/src/lib/utility/messaging/type/MessageActivateAll.h @@ -5,6 +5,7 @@ #include "MessageActivateBase.h" #include "NodeTypeSet.h" +#include "TabId.h" class MessageActivateAll : public Message @@ -20,6 +21,7 @@ public: : acceptedNodeTypes(acceptedNodeTypes) { setIsParallel(true); + setSchedulerId(TabId::currentTab()); } std::vector getSearchMatches() const override diff --git a/src/lib/utility/messaging/type/MessageActivateBookmark.h b/src/lib/utility/messaging/type/MessageActivateBookmark.h deleted file mode 100644 index a7108ebc..00000000 --- a/src/lib/utility/messaging/type/MessageActivateBookmark.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef MESSAGE_ACTIVATE_BOOKMARK_H -#define MESSAGE_ACTIVATE_BOOKMARK_H - -#include "Message.h" - -#include "Bookmark.h" - -class MessageActivateBookmark - : public Message -{ -public: - MessageActivateBookmark(const std::shared_ptr& bookmark) - : bookmark(bookmark) - { - } - - virtual ~MessageActivateBookmark() - { - } - - static const std::string getStaticType() - { - return "MessageActivateBookmark"; - } - - const std::shared_ptr bookmark; -}; - -#endif // MESSAGE_ACTIVATE_BOOKMARK_H \ No newline at end of file diff --git a/src/lib/utility/messaging/type/MessageActivateEdge.h b/src/lib/utility/messaging/type/MessageActivateEdge.h index 482f1025..742afcf2 100644 --- a/src/lib/utility/messaging/type/MessageActivateEdge.h +++ b/src/lib/utility/messaging/type/MessageActivateEdge.h @@ -7,6 +7,7 @@ #include "Message.h" #include "types.h" #include "utilityString.h" +#include "TabId.h" class MessageActivateEdge : public Message @@ -22,6 +23,8 @@ public: { setKeepContent(true); } + + setSchedulerId(TabId::currentTab()); } static const std::string getStaticType() diff --git a/src/lib/utility/messaging/type/MessageActivateFile.h b/src/lib/utility/messaging/type/MessageActivateFile.h index 3325d043..175c9821 100644 --- a/src/lib/utility/messaging/type/MessageActivateFile.h +++ b/src/lib/utility/messaging/type/MessageActivateFile.h @@ -3,14 +3,17 @@ #include "Message.h" #include "FilePath.h" +#include "TabId.h" -class MessageActivateFile: public Message +class MessageActivateFile + : public Message { public: MessageActivateFile(const FilePath& filePath, unsigned int line = 0) : filePath(filePath) , line(line) { + setSchedulerId(TabId::currentTab()); } static const std::string getStaticType() diff --git a/src/lib/utility/messaging/type/MessageActivateFullTextSearch.h b/src/lib/utility/messaging/type/MessageActivateFullTextSearch.h index f52ba0e4..99e3591f 100644 --- a/src/lib/utility/messaging/type/MessageActivateFullTextSearch.h +++ b/src/lib/utility/messaging/type/MessageActivateFullTextSearch.h @@ -3,6 +3,7 @@ #include "Message.h" #include "MessageActivateBase.h" +#include "TabId.h" class MessageActivateFullTextSearch : public Message @@ -18,6 +19,7 @@ public: : searchTerm(searchTerm) , caseSensitive(caseSensitive) { + setSchedulerId(TabId::currentTab()); } void print(std::wostream& os) const override diff --git a/src/lib/utility/messaging/type/MessageActivateLocalSymbols.h b/src/lib/utility/messaging/type/MessageActivateLocalSymbols.h index 49f71084..da31b9be 100644 --- a/src/lib/utility/messaging/type/MessageActivateLocalSymbols.h +++ b/src/lib/utility/messaging/type/MessageActivateLocalSymbols.h @@ -3,6 +3,7 @@ #include "Message.h" #include "types.h" +#include "TabId.h" class MessageActivateLocalSymbols : public Message @@ -10,11 +11,13 @@ class MessageActivateLocalSymbols public: MessageActivateLocalSymbols() { + setSchedulerId(TabId::currentTab()); } MessageActivateLocalSymbols(const std::vector& symbolIds) : symbolIds(symbolIds) { + setSchedulerId(TabId::currentTab()); } void addSymbol(Id symbolId) diff --git a/src/lib/utility/messaging/type/MessageActivateNodes.h b/src/lib/utility/messaging/type/MessageActivateNodes.h index 92f97268..93334b9a 100644 --- a/src/lib/utility/messaging/type/MessageActivateNodes.h +++ b/src/lib/utility/messaging/type/MessageActivateNodes.h @@ -2,6 +2,7 @@ #define MESSAGE_ACTIVATE_NODES_H #include "Message.h" +#include "TabId.h" #include "types.h" class MessageActivateNodes @@ -24,6 +25,8 @@ public: { addNode(tokenId); } + + setSchedulerId(TabId::currentTab()); } void addNode(Id tokenId) diff --git a/src/lib/utility/messaging/type/MessageActivateSourceLocations.h b/src/lib/utility/messaging/type/MessageActivateSourceLocations.h index 0ef8cfdc..4dcdadf1 100644 --- a/src/lib/utility/messaging/type/MessageActivateSourceLocations.h +++ b/src/lib/utility/messaging/type/MessageActivateSourceLocations.h @@ -2,6 +2,7 @@ #define MESSAGE_ACTIVATE_SOURCE_LOCATIONS_H #include "Message.h" +#include "TabId.h" #include "types.h" class MessageActivateSourceLocations @@ -11,6 +12,7 @@ public: MessageActivateSourceLocations(const std::vector& locationIds) : locationIds(locationIds) { + setSchedulerId(TabId::currentTab()); } static const std::string getStaticType() diff --git a/src/lib/utility/messaging/type/MessageActivateTokenIds.h b/src/lib/utility/messaging/type/MessageActivateTokenIds.h index 95a276f3..556607dc 100644 --- a/src/lib/utility/messaging/type/MessageActivateTokenIds.h +++ b/src/lib/utility/messaging/type/MessageActivateTokenIds.h @@ -2,6 +2,7 @@ #define MESSAGE_ACTIVATE_TOKEN_IDS_H #include "Message.h" +#include "TabId.h" #include "types.h" class MessageActivateTokenIds @@ -11,6 +12,7 @@ public: MessageActivateTokenIds(const std::vector& tokenIds) : tokenIds(tokenIds) { + setSchedulerId(TabId::currentTab()); } static const std::string getStaticType() diff --git a/src/lib/utility/messaging/type/MessageActivateTokens.h b/src/lib/utility/messaging/type/MessageActivateTokens.h index 5c6bebae..ad92267d 100644 --- a/src/lib/utility/messaging/type/MessageActivateTokens.h +++ b/src/lib/utility/messaging/type/MessageActivateTokens.h @@ -24,6 +24,7 @@ public: { setIsParallel(true); setKeepContent(other->keepContent()); + setSchedulerId(other->getSchedulerId()); } void print(std::wostream& os) const override diff --git a/src/lib/utility/messaging/type/MessageActivateTrail.h b/src/lib/utility/messaging/type/MessageActivateTrail.h index 126eeefd..06bd7db9 100644 --- a/src/lib/utility/messaging/type/MessageActivateTrail.h +++ b/src/lib/utility/messaging/type/MessageActivateTrail.h @@ -3,6 +3,7 @@ #include "Message.h" #include "types.h" +#include "TabId.h" class MessageActivateTrail : public Message @@ -15,6 +16,7 @@ public: , depth(depth) , horizontalLayout(horizontalLayout) { + setSchedulerId(TabId::currentTab()); } static const std::string getStaticType() diff --git a/src/lib/utility/messaging/type/MessageActivateTrailEdge.h b/src/lib/utility/messaging/type/MessageActivateTrailEdge.h index f83dceb6..f6715a51 100644 --- a/src/lib/utility/messaging/type/MessageActivateTrailEdge.h +++ b/src/lib/utility/messaging/type/MessageActivateTrailEdge.h @@ -5,6 +5,7 @@ #include "NameHierarchy.h" #include "Message.h" +#include "TabId.h" #include "types.h" #include "utilityString.h" @@ -21,6 +22,7 @@ public: , sourceNameHierarchy(sourceNameHierarchy) , targetNameHierarchy(targetNameHierarchy) { + setSchedulerId(TabId::currentTab()); } static const std::string getStaticType() diff --git a/src/lib/utility/messaging/type/MessageChangeFileView.h b/src/lib/utility/messaging/type/MessageChangeFileView.h index e9c28bf5..aa2fad22 100644 --- a/src/lib/utility/messaging/type/MessageChangeFileView.h +++ b/src/lib/utility/messaging/type/MessageChangeFileView.h @@ -3,6 +3,7 @@ #include "FilePath.h" #include "Message.h" +#include "TabId.h" class MessageChangeFileView : public Message @@ -37,6 +38,7 @@ public: , showErrors(showErrors) , switchesViewMode(switchesViewMode) { + setSchedulerId(TabId::currentTab()); } static const std::string getStaticType() diff --git a/src/lib/utility/messaging/type/MessageCodeReference.h b/src/lib/utility/messaging/type/MessageCodeReference.h index dc089c2c..70b4c2f5 100644 --- a/src/lib/utility/messaging/type/MessageCodeReference.h +++ b/src/lib/utility/messaging/type/MessageCodeReference.h @@ -2,6 +2,7 @@ #define MESSAGE_CODE_REFERENCE_H #include "Message.h" +#include "TabId.h" class MessageCodeReference : public Message @@ -17,6 +18,7 @@ public: : type(type) , localReference(localReference) { + setSchedulerId(TabId::currentTab()); } static const std::string getStaticType() diff --git a/src/lib/utility/messaging/type/MessageDeactivateEdge.h b/src/lib/utility/messaging/type/MessageDeactivateEdge.h index 5f158c6e..e4b718f7 100644 --- a/src/lib/utility/messaging/type/MessageDeactivateEdge.h +++ b/src/lib/utility/messaging/type/MessageDeactivateEdge.h @@ -2,6 +2,7 @@ #define MESSAGE_DEACTIVATE_EDGE_H #include "Message.h" +#include "TabId.h" class MessageDeactivateEdge : public Message @@ -10,6 +11,7 @@ public: MessageDeactivateEdge(bool scrollToDefinition) : scrollToDefinition(scrollToDefinition) { + setSchedulerId(TabId::currentTab()); } static const std::string getStaticType() diff --git a/src/lib/utility/messaging/type/MessageDisplayBookmarkCreator.h b/src/lib/utility/messaging/type/MessageDisplayBookmarkCreator.h deleted file mode 100644 index dd2c4596..00000000 --- a/src/lib/utility/messaging/type/MessageDisplayBookmarkCreator.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef MESSAGE_DISPLAY_BOOKMARK_CREATOR_H -#define MESSAGE_DISPLAY_BOOKMARK_CREATOR_H - -#include "Message.h" - -class MessageDisplayBookmarkCreator - : public Message -{ -public: - MessageDisplayBookmarkCreator(Id nodeId = 0) - : nodeId(nodeId) - { - } - - static const std::string getStaticType() - { - return "MessageDisplayBookmarkCreator"; - } - - const Id nodeId; -}; - -#endif // MESSAGE_DISPLAY_BOOKMARK_CREATOR_H \ No newline at end of file diff --git a/src/lib/utility/messaging/type/MessageFind.h b/src/lib/utility/messaging/type/MessageFind.h index 24345019..f958fff0 100644 --- a/src/lib/utility/messaging/type/MessageFind.h +++ b/src/lib/utility/messaging/type/MessageFind.h @@ -2,6 +2,7 @@ #define MESSAGE_FIND_H #include "Message.h" +#include "TabId.h" class MessageFind : public Message @@ -10,6 +11,7 @@ public: MessageFind(bool fulltext = false) : findFulltext(fulltext) { + setSchedulerId(TabId::currentTab()); } static const std::string getStaticType() diff --git a/src/lib/utility/messaging/type/MessageFlushUpdates.h b/src/lib/utility/messaging/type/MessageFlushUpdates.h index ad0b9e15..5cb6a1f1 100644 --- a/src/lib/utility/messaging/type/MessageFlushUpdates.h +++ b/src/lib/utility/messaging/type/MessageFlushUpdates.h @@ -2,6 +2,7 @@ #define MESSAGE_FLUSH_UPDATES_H #include "Message.h" +#include "TabId.h" class MessageFlushUpdates: public Message @@ -10,6 +11,7 @@ public: MessageFlushUpdates(bool keepsContent = false) { setKeepContent(keepsContent); + setSchedulerId(TabId::currentTab()); } static const std::string getStaticType() diff --git a/src/lib/utility/messaging/type/MessageFocusIn.h b/src/lib/utility/messaging/type/MessageFocusIn.h index 872d992a..929bfcc2 100644 --- a/src/lib/utility/messaging/type/MessageFocusIn.h +++ b/src/lib/utility/messaging/type/MessageFocusIn.h @@ -4,6 +4,7 @@ #include #include "Message.h" +#include "TabId.h" #include "types.h" #include "TooltipOrigin.h" @@ -17,6 +18,7 @@ public: , origin(origin) { setIsLogged(false); + setSchedulerId(TabId::currentTab()); } static const std::string getStaticType() diff --git a/src/lib/utility/messaging/type/MessageFocusOut.h b/src/lib/utility/messaging/type/MessageFocusOut.h index 8712bb87..c77d619f 100644 --- a/src/lib/utility/messaging/type/MessageFocusOut.h +++ b/src/lib/utility/messaging/type/MessageFocusOut.h @@ -4,6 +4,7 @@ #include #include "Message.h" +#include "TabId.h" #include "types.h" class MessageFocusOut @@ -14,6 +15,7 @@ public: : tokenIds(tokenIds) { setIsLogged(false); + setSchedulerId(TabId::currentTab()); } static const std::string getStaticType() diff --git a/src/lib/utility/messaging/type/MessageGraphNodeBundleSplit.h b/src/lib/utility/messaging/type/MessageGraphNodeBundleSplit.h index c55c07ec..5870b954 100644 --- a/src/lib/utility/messaging/type/MessageGraphNodeBundleSplit.h +++ b/src/lib/utility/messaging/type/MessageGraphNodeBundleSplit.h @@ -2,6 +2,7 @@ #define MESSAGE_GRAPH_NODE_BUNDLE_SPLIT_H #include "Message.h" +#include "TabId.h" #include "types.h" class MessageGraphNodeBundleSplit @@ -13,6 +14,7 @@ public: , removeOtherNodes(removeOtherNodes) , layoutToList(layoutToList) { + setSchedulerId(TabId::currentTab()); } static const std::string getStaticType() diff --git a/src/lib/utility/messaging/type/MessageGraphNodeExpand.h b/src/lib/utility/messaging/type/MessageGraphNodeExpand.h index cab34790..1ebfe53e 100644 --- a/src/lib/utility/messaging/type/MessageGraphNodeExpand.h +++ b/src/lib/utility/messaging/type/MessageGraphNodeExpand.h @@ -3,6 +3,7 @@ #include "Message.h" #include "types.h" +#include "TabId.h" class MessageGraphNodeExpand : public Message @@ -13,6 +14,7 @@ public: , expand(expand) , ignoreIfNotReplayed(ignoreIfNotReplayed) { + setSchedulerId(TabId::currentTab()); } static const std::string getStaticType() diff --git a/src/lib/utility/messaging/type/MessageGraphNodeHide.h b/src/lib/utility/messaging/type/MessageGraphNodeHide.h index 5814257f..e2efd196 100644 --- a/src/lib/utility/messaging/type/MessageGraphNodeHide.h +++ b/src/lib/utility/messaging/type/MessageGraphNodeHide.h @@ -2,6 +2,7 @@ #define MESSAGE_GRAPH_NODE_HIDE_H #include "Message.h" +#include "TabId.h" #include "types.h" class MessageGraphNodeHide @@ -11,6 +12,7 @@ public: MessageGraphNodeHide(Id tokenId) : tokenId(tokenId) { + setSchedulerId(TabId::currentTab()); } static const std::string getStaticType() diff --git a/src/lib/utility/messaging/type/MessageGraphNodeMove.h b/src/lib/utility/messaging/type/MessageGraphNodeMove.h index 087f67e0..d414bedd 100644 --- a/src/lib/utility/messaging/type/MessageGraphNodeMove.h +++ b/src/lib/utility/messaging/type/MessageGraphNodeMove.h @@ -1,9 +1,10 @@ #ifndef MESSAGE_GRAPH_NODE_MOVE_H #define MESSAGE_GRAPH_NODE_MOVE_H -#include "Vector2.h" #include "Message.h" +#include "TabId.h" #include "types.h" +#include "Vector2.h" class MessageGraphNodeMove : public Message @@ -13,6 +14,7 @@ public: : tokenId(tokenId) , delta(delta) { + setSchedulerId(TabId::currentTab()); } static const std::string getStaticType() diff --git a/src/lib/utility/messaging/type/MessageScrollCode.h b/src/lib/utility/messaging/type/MessageScrollCode.h index 2adc0808..8bb61fe5 100644 --- a/src/lib/utility/messaging/type/MessageScrollCode.h +++ b/src/lib/utility/messaging/type/MessageScrollCode.h @@ -2,6 +2,7 @@ #define MESSAGE_SCROLL_CODE_H #include "Message.h" +#include "TabId.h" class MessageScrollCode : public Message @@ -12,6 +13,7 @@ public: , inListMode(inListMode) { setIsLogged(false); + setSchedulerId(TabId::currentTab()); } static const std::string getStaticType() diff --git a/src/lib/utility/messaging/type/MessageScrollGraph.h b/src/lib/utility/messaging/type/MessageScrollGraph.h index 355e1a87..438b36d4 100644 --- a/src/lib/utility/messaging/type/MessageScrollGraph.h +++ b/src/lib/utility/messaging/type/MessageScrollGraph.h @@ -2,6 +2,7 @@ #define MESSAGE_SCROLL_GRAPH_H #include "Message.h" +#include "TabId.h" class MessageScrollGraph : public Message @@ -12,6 +13,7 @@ public: , yValue(yValue) { setIsLogged(false); + setSchedulerId(TabId::currentTab()); } static const std::string getStaticType() diff --git a/src/lib/utility/messaging/type/MessageScrollToLine.h b/src/lib/utility/messaging/type/MessageScrollToLine.h index 8015a26d..9fe33588 100644 --- a/src/lib/utility/messaging/type/MessageScrollToLine.h +++ b/src/lib/utility/messaging/type/MessageScrollToLine.h @@ -3,6 +3,7 @@ #include "FilePath.h" #include "Message.h" +#include "TabId.h" class MessageScrollToLine : public Message @@ -12,6 +13,7 @@ public: : filePath(filePath) , line(line) { + setSchedulerId(TabId::currentTab()); } static const std::string getStaticType() diff --git a/src/lib/utility/messaging/type/MessageSearch.h b/src/lib/utility/messaging/type/MessageSearch.h index 11f908d7..3b4b03ce 100644 --- a/src/lib/utility/messaging/type/MessageSearch.h +++ b/src/lib/utility/messaging/type/MessageSearch.h @@ -5,6 +5,7 @@ #include "NodeTypeSet.h" #include "SearchMatch.h" +#include "TabId.h" class MessageSearch : public Message @@ -19,6 +20,7 @@ public: : acceptedNodeTypes(acceptedNodeTypes) , m_matches(matches) { + setSchedulerId(TabId::currentTab()); } const std::vector& getMatches() const diff --git a/src/lib/utility/messaging/type/MessageSearchAutocomplete.h b/src/lib/utility/messaging/type/MessageSearchAutocomplete.h index 6e7e77b9..5df28a7f 100644 --- a/src/lib/utility/messaging/type/MessageSearchAutocomplete.h +++ b/src/lib/utility/messaging/type/MessageSearchAutocomplete.h @@ -4,6 +4,7 @@ #include "Node.h" #include "NodeTypeSet.h" #include "Message.h" +#include "TabId.h" class MessageSearchAutocomplete : public Message @@ -13,6 +14,7 @@ public: : query(query) , acceptedNodeTypes(acceptedNodeTypes) { + setSchedulerId(TabId::currentTab()); } static const std::string getStaticType() diff --git a/src/lib/utility/messaging/type/MessageShowReference.h b/src/lib/utility/messaging/type/MessageShowReference.h index e350b0a4..79962bc5 100644 --- a/src/lib/utility/messaging/type/MessageShowReference.h +++ b/src/lib/utility/messaging/type/MessageShowReference.h @@ -2,6 +2,7 @@ #define MESSAGE_SHOW_REFERENCE_H #include "Message.h" +#include "TabId.h" #include "types.h" class MessageShowReference @@ -14,6 +15,7 @@ public: , locationId(locationId) , fromUser(fromUser) { + setSchedulerId(TabId::currentTab()); } static const std::string getStaticType() diff --git a/src/lib/utility/messaging/type/MessageShowScope.h b/src/lib/utility/messaging/type/MessageShowScope.h index 8d0969ba..613744ac 100644 --- a/src/lib/utility/messaging/type/MessageShowScope.h +++ b/src/lib/utility/messaging/type/MessageShowScope.h @@ -3,6 +3,7 @@ #include "Message.h" #include "types.h" +#include "TabId.h" class MessageShowScope : public Message @@ -12,6 +13,7 @@ public: : scopeLocationId(scopeLocationId) , showErrors(showErrors) { + setSchedulerId(TabId::currentTab()); } static const std::string getStaticType() diff --git a/src/lib/utility/messaging/type/activation/MessageActivateLegend.h b/src/lib/utility/messaging/type/activation/MessageActivateLegend.h index d759ac8f..c999db69 100644 --- a/src/lib/utility/messaging/type/activation/MessageActivateLegend.h +++ b/src/lib/utility/messaging/type/activation/MessageActivateLegend.h @@ -3,12 +3,18 @@ #include "Message.h" #include "MessageActivateBase.h" +#include "TabId.h" class MessageActivateLegend : public Message , public MessageActivateBase { public: + MessageActivateLegend() + { + setSchedulerId(TabId::currentTab()); + } + static const std::string getStaticType() { return "MessageActivateLegend"; diff --git a/src/lib/utility/messaging/type/bookmark/MessageBookmarkActivate.h b/src/lib/utility/messaging/type/bookmark/MessageBookmarkActivate.h new file mode 100644 index 00000000..5970fe58 --- /dev/null +++ b/src/lib/utility/messaging/type/bookmark/MessageBookmarkActivate.h @@ -0,0 +1,24 @@ +#ifndef MESSAGE_BOOKMARK_ACTIVATE_H +#define MESSAGE_BOOKMARK_ACTIVATE_H + +#include "Bookmark.h" +#include "Message.h" + +class MessageBookmarkActivate + : public Message +{ +public: + MessageBookmarkActivate(const std::shared_ptr& bookmark) + : bookmark(bookmark) + { + } + + static const std::string getStaticType() + { + return "MessageBookmarkActivate"; + } + + const std::shared_ptr bookmark; +}; + +#endif // MESSAGE_BOOKMARK_ACTIVATE_H diff --git a/src/lib/utility/messaging/type/MessageDisplayBookmarks.h b/src/lib/utility/messaging/type/bookmark/MessageBookmarkBrowse.h similarity index 58% rename from src/lib/utility/messaging/type/MessageDisplayBookmarks.h rename to src/lib/utility/messaging/type/bookmark/MessageBookmarkBrowse.h index 1864b087..1e7995dc 100644 --- a/src/lib/utility/messaging/type/MessageDisplayBookmarks.h +++ b/src/lib/utility/messaging/type/bookmark/MessageBookmarkBrowse.h @@ -1,14 +1,14 @@ -#ifndef MESSAGE_DISPLAY_BOOKMARKS_H -#define MESSAGE_DISPLAY_BOOKMARKS_H +#ifndef MESSAGE_BOOKMARKS_BROWSE_H +#define MESSAGE_BOOKMARKS_BROWSE_H #include "Bookmark.h" #include "Message.h" -class MessageDisplayBookmarks - : public Message +class MessageBookmarkBrowse + : public Message { public: - MessageDisplayBookmarks( + MessageBookmarkBrowse( Bookmark::BookmarkFilter filter = Bookmark::FILTER_UNKNOWN, Bookmark::BookmarkOrder order = Bookmark::ORDER_NONE ) @@ -19,11 +19,11 @@ public: static const std::string getStaticType() { - return "MessageDisplayBookmarks"; + return "MessageBookmarkBrowse"; } const Bookmark::BookmarkFilter filter; const Bookmark::BookmarkOrder order; }; -#endif // MESSAGE_DISPLAY_BOOKMARKS_H \ No newline at end of file +#endif // MESSAGE_BOOKMARKS_BROWSE_H diff --git a/src/lib/utility/messaging/type/bookmark/MessageBookmarkButtonState.h b/src/lib/utility/messaging/type/bookmark/MessageBookmarkButtonState.h new file mode 100644 index 00000000..c1b9bad8 --- /dev/null +++ b/src/lib/utility/messaging/type/bookmark/MessageBookmarkButtonState.h @@ -0,0 +1,31 @@ +#ifndef MESSAGE_BOOKMARK_BUTTON_STATE_H +#define MESSAGE_BOOKMARK_BUTTON_STATE_H + +#include "Message.h" + +class MessageBookmarkButtonState: + public Message +{ +public: + enum ButtonState + { + CAN_CREATE = 0, + CANNOT_CREATE, + ALREADY_CREATED + }; + + static const std::string getStaticType() + { + return "MessageBookmarkButtonState"; + } + + MessageBookmarkButtonState(Id schedulerId, ButtonState state) + : state(state) + { + setSchedulerId(schedulerId); + } + + const ButtonState state; +}; + +#endif // MESSAGE_BOOKMARK_BUTTON_STATE_H diff --git a/src/lib/utility/messaging/type/bookmark/MessageBookmarkCreate.h b/src/lib/utility/messaging/type/bookmark/MessageBookmarkCreate.h new file mode 100644 index 00000000..561106d1 --- /dev/null +++ b/src/lib/utility/messaging/type/bookmark/MessageBookmarkCreate.h @@ -0,0 +1,23 @@ +#ifndef MESSAGE_BOOKMARK_CREATE_H +#define MESSAGE_BOOKMARK_CREATE_H + +#include "Message.h" + +class MessageBookmarkCreate + : public Message +{ +public: + MessageBookmarkCreate(Id nodeId = 0) + : nodeId(nodeId) + { + } + + static const std::string getStaticType() + { + return "MessageBookmarkCreate"; + } + + const Id nodeId; +}; + +#endif // MESSAGE_BOOKMARK_CREATE_H \ No newline at end of file diff --git a/src/lib/utility/messaging/type/bookmark/MessageBookmarkDelete.h b/src/lib/utility/messaging/type/bookmark/MessageBookmarkDelete.h new file mode 100644 index 00000000..e9e7df88 --- /dev/null +++ b/src/lib/utility/messaging/type/bookmark/MessageBookmarkDelete.h @@ -0,0 +1,16 @@ +#ifndef MESSAGE_BOOKMARK_DELETE_H +#define MESSAGE_BOOKMARK_DELETE_H + +#include "Message.h" + +class MessageBookmarkDelete: + public Message +{ +public: + static const std::string getStaticType() + { + return "MessageBookmarkDelete"; + } +}; + +#endif // MESSAGE_BOOKMARK_DELETE_H diff --git a/src/lib/utility/messaging/type/bookmark/MessageBookmarkEdit.h b/src/lib/utility/messaging/type/bookmark/MessageBookmarkEdit.h new file mode 100644 index 00000000..0c6db75f --- /dev/null +++ b/src/lib/utility/messaging/type/bookmark/MessageBookmarkEdit.h @@ -0,0 +1,16 @@ +#ifndef MESSAGE_BOOKMARK_EDIT_H +#define MESSAGE_BOOKMARK_EDIT_H + +#include "Message.h" + +class MessageBookmarkEdit: + public Message +{ +public: + static const std::string getStaticType() + { + return "MessageBookmarkEdit"; + } +}; + +#endif // MESSAGE_BOOKMARK_EDIT_H diff --git a/src/lib/utility/messaging/type/code/MessageCodeShowDefinition.h b/src/lib/utility/messaging/type/code/MessageCodeShowDefinition.h index 192ca465..27356951 100644 --- a/src/lib/utility/messaging/type/code/MessageCodeShowDefinition.h +++ b/src/lib/utility/messaging/type/code/MessageCodeShowDefinition.h @@ -2,6 +2,7 @@ #define MESSAGE_CODE_SHOW_DEFINITION_H #include "Message.h" +#include "TabId.h" #include "types.h" class MessageCodeShowDefinition @@ -16,6 +17,7 @@ public: MessageCodeShowDefinition(Id nodeId) : nodeId(nodeId) { + setSchedulerId(TabId::currentTab()); } virtual void print(std::wostream& os) const diff --git a/src/lib/utility/messaging/type/error/MessageActivateErrors.h b/src/lib/utility/messaging/type/error/MessageActivateErrors.h index d3ec2428..ec0e0f61 100644 --- a/src/lib/utility/messaging/type/error/MessageActivateErrors.h +++ b/src/lib/utility/messaging/type/error/MessageActivateErrors.h @@ -5,6 +5,7 @@ #include "MessageActivateBase.h" #include "ErrorFilter.h" +#include "TabId.h" class MessageActivateErrors : public Message @@ -20,6 +21,7 @@ public: : filter(filter) , file(file) { + setSchedulerId(TabId::currentTab()); } std::vector getSearchMatches() const override diff --git a/src/lib/utility/messaging/type/error/MessageShowError.h b/src/lib/utility/messaging/type/error/MessageShowError.h index 779fb1ab..bbcfebbe 100644 --- a/src/lib/utility/messaging/type/error/MessageShowError.h +++ b/src/lib/utility/messaging/type/error/MessageShowError.h @@ -2,6 +2,7 @@ #define MESSAGE_SHOW_ERROR_H #include "Message.h" +#include "TabId.h" class MessageShowError : public Message @@ -15,6 +16,7 @@ public: MessageShowError(Id errorId) : errorId(errorId) { + setSchedulerId(TabId::currentTab()); } const Id errorId; diff --git a/src/lib/utility/messaging/type/history/MessageHistoryRedo.h b/src/lib/utility/messaging/type/history/MessageHistoryRedo.h index 8c996e4d..18a421a5 100644 --- a/src/lib/utility/messaging/type/history/MessageHistoryRedo.h +++ b/src/lib/utility/messaging/type/history/MessageHistoryRedo.h @@ -2,6 +2,7 @@ #define MESSAGE_HISTORY_REDO_H #include "Message.h" +#include "TabId.h" class MessageHistoryRedo : public Message @@ -14,6 +15,7 @@ public: MessageHistoryRedo() { + setSchedulerId(TabId::currentTab()); } }; diff --git a/src/lib/utility/messaging/type/history/MessageHistoryToPosition.h b/src/lib/utility/messaging/type/history/MessageHistoryToPosition.h index 8614e6e0..73461f8f 100644 --- a/src/lib/utility/messaging/type/history/MessageHistoryToPosition.h +++ b/src/lib/utility/messaging/type/history/MessageHistoryToPosition.h @@ -2,6 +2,7 @@ #define MESSAGE_HISTORY_TO_POSITION_H #include "Message.h" +#include "TabId.h" class MessageHistoryToPosition : public Message @@ -15,6 +16,7 @@ public: MessageHistoryToPosition(size_t index) : index(index) { + setSchedulerId(TabId::currentTab()); } const size_t index; diff --git a/src/lib/utility/messaging/type/history/MessageHistoryUndo.h b/src/lib/utility/messaging/type/history/MessageHistoryUndo.h index a6da0713..1c6140d2 100644 --- a/src/lib/utility/messaging/type/history/MessageHistoryUndo.h +++ b/src/lib/utility/messaging/type/history/MessageHistoryUndo.h @@ -2,6 +2,7 @@ #define MESSAGE_HISTORY_UNDO_H #include "Message.h" +#include "TabId.h" class MessageHistoryUndo : public Message @@ -14,6 +15,7 @@ public: MessageHistoryUndo() { + setSchedulerId(TabId::currentTab()); } }; diff --git a/src/lib/utility/messaging/type/tab/MessageTabClose.h b/src/lib/utility/messaging/type/tab/MessageTabClose.h new file mode 100644 index 00000000..ce99c68b --- /dev/null +++ b/src/lib/utility/messaging/type/tab/MessageTabClose.h @@ -0,0 +1,16 @@ +#ifndef MESSAGE_TAB_CLOSE_H +#define MESSAGE_TAB_CLOSE_H + +#include "Message.h" + +class MessageTabClose + : public Message +{ +public: + static const std::string getStaticType() + { + return "MessageTabClose"; + } +}; + +#endif // MESSAGE_TAB_CLOSE_H diff --git a/src/lib/utility/messaging/type/tab/MessageTabOpen.h b/src/lib/utility/messaging/type/tab/MessageTabOpen.h new file mode 100644 index 00000000..54990b3f --- /dev/null +++ b/src/lib/utility/messaging/type/tab/MessageTabOpen.h @@ -0,0 +1,16 @@ +#ifndef MESSAGE_TAB_OPEN_H +#define MESSAGE_TAB_OPEN_H + +#include "Message.h" + +class MessageTabOpen + : public Message +{ +public: + static const std::string getStaticType() + { + return "MessageTabOpen"; + } +}; + +#endif // MESSAGE_TAB_OPEN_H diff --git a/src/lib/utility/messaging/type/tab/MessageTabOpenWith.h b/src/lib/utility/messaging/type/tab/MessageTabOpenWith.h new file mode 100644 index 00000000..525086b4 --- /dev/null +++ b/src/lib/utility/messaging/type/tab/MessageTabOpenWith.h @@ -0,0 +1,51 @@ +#ifndef MESSAGE_TAB_OPEN_WITH_H +#define MESSAGE_TAB_OPEN_WITH_H + +#include "FilePath.h" +#include "Message.h" +#include "SearchMatch.h" + +class MessageTabOpenWith + : public Message +{ +public: + static const std::string getStaticType() + { + return "MessageTabOpenWith"; + } + + MessageTabOpenWith(Id tokenId, Id locationId = 0) + : tokenId(tokenId) + , locationId(locationId) + { + } + + MessageTabOpenWith(const FilePath& path, size_t line = 0) + : filePath(path) + , line(line) + { + } + + MessageTabOpenWith(const SearchMatch& match) + : match(match) + { + } + + MessageTabOpenWith& showNewTab(bool show) + { + showTab = show; + return *this; + } + + const Id tokenId = 0; + const Id locationId = 0; + + const FilePath filePath; + const SearchMatch match; + + const size_t line = 0; + + bool showTab = false; +}; + +#endif // MESSAGE_TAB_OPEN_WITH_H diff --git a/src/lib/utility/messaging/type/tab/MessageTabSelect.h b/src/lib/utility/messaging/type/tab/MessageTabSelect.h new file mode 100644 index 00000000..24bba64a --- /dev/null +++ b/src/lib/utility/messaging/type/tab/MessageTabSelect.h @@ -0,0 +1,23 @@ +#ifndef MESSAGE_TAB_SELECT_H +#define MESSAGE_TAB_SELECT_H + +#include "Message.h" + +class MessageTabSelect + : public Message +{ +public: + MessageTabSelect(bool next) + : next(next) + { + } + + static const std::string getStaticType() + { + return "MessageTabSelect"; + } + + bool next; +}; + +#endif // MESSAGE_TAB_SELECT_H diff --git a/src/lib/utility/messaging/type/tab/MessageTabState.h b/src/lib/utility/messaging/type/tab/MessageTabState.h new file mode 100644 index 00000000..a3e926d0 --- /dev/null +++ b/src/lib/utility/messaging/type/tab/MessageTabState.h @@ -0,0 +1,26 @@ +#ifndef MESSAGE_TAB_STATE_H +#define MESSAGE_TAB_STATE_H + +#include "Message.h" +#include "SearchMatch.h" + +class MessageTabState + : public Message +{ +public: + MessageTabState(Id tabId, const std::vector& searchMatches) + : tabId(tabId) + , searchMatches(searchMatches) + { + } + + static const std::string getStaticType() + { + return "MessageTabState"; + } + + const Id tabId; + const std::vector searchMatches; +}; + +#endif // MESSAGE_TAB_STATE_H diff --git a/src/lib/utility/scheduling/Task.cpp b/src/lib/utility/scheduling/Task.cpp index dbf57af5..3558bedd 100644 --- a/src/lib/utility/scheduling/Task.cpp +++ b/src/lib/utility/scheduling/Task.cpp @@ -1,15 +1,16 @@ #include "Task.h" +#include "TaskManager.h" #include "TaskScheduler.h" -void Task::dispatch(std::shared_ptr task) +void Task::dispatch(Id schedulerId, std::shared_ptr task) { - TaskScheduler::getInstance()->pushTask(task); + TaskManager::getScheduler(schedulerId)->pushTask(task); } -void Task::dispatchNext(std::shared_ptr task) +void Task::dispatchNext(Id schedulerId, std::shared_ptr task) { - TaskScheduler::getInstance()->pushNextTask(task); + TaskManager::getScheduler(schedulerId)->pushNextTask(task); } void Task::setIsBackgroundTask(bool background) diff --git a/src/lib/utility/scheduling/Task.h b/src/lib/utility/scheduling/Task.h index 21acbf7b..6b780c16 100644 --- a/src/lib/utility/scheduling/Task.h +++ b/src/lib/utility/scheduling/Task.h @@ -3,6 +3,8 @@ #include +#include "types.h" + class Blackboard; class Task @@ -16,8 +18,8 @@ public: STATE_FAILURE }; - static void dispatch(std::shared_ptr task); - static void dispatchNext(std::shared_ptr task); + static void dispatch(Id schedulerId, std::shared_ptr task); + static void dispatchNext(Id schedulerId, std::shared_ptr task); virtual ~Task() = default; diff --git a/src/lib/utility/scheduling/TaskManager.cpp b/src/lib/utility/scheduling/TaskManager.cpp new file mode 100644 index 00000000..20ca9049 --- /dev/null +++ b/src/lib/utility/scheduling/TaskManager.cpp @@ -0,0 +1,37 @@ +#include "TaskManager.h" + +#include "TaskScheduler.h" + +std::map> TaskManager::s_schedulers; +std::mutex TaskManager::s_schedulersMutex; + +std::shared_ptr TaskManager::createScheduler(Id schedulerId) +{ + return getScheduler(schedulerId); +} + +void TaskManager::destroyScheduler(Id schedulerId) +{ + std::lock_guard lock(s_schedulersMutex); + + auto it = s_schedulers.find(schedulerId); + if (it != s_schedulers.end()) + { + s_schedulers.erase(it); + } +} + +std::shared_ptr TaskManager::getScheduler(Id schedulerId) +{ + std::lock_guard lock(s_schedulersMutex); + + auto it = s_schedulers.find(schedulerId); + if (it != s_schedulers.end()) + { + return it->second; + } + + std::shared_ptr scheduler = std::make_shared(schedulerId); + s_schedulers.emplace(schedulerId, scheduler); + return scheduler; +} diff --git a/src/lib/utility/scheduling/TaskManager.h b/src/lib/utility/scheduling/TaskManager.h new file mode 100644 index 00000000..0bd1eca7 --- /dev/null +++ b/src/lib/utility/scheduling/TaskManager.h @@ -0,0 +1,25 @@ +#ifndef TASK_MANAGER_H +#define TASK_MANAGER_H + +#include +#include +#include + +#include "types.h" + +class TaskScheduler; + +class TaskManager +{ +public: + static std::shared_ptr createScheduler(Id schedulerId); + static void destroyScheduler(Id schedulerId); + + static std::shared_ptr getScheduler(Id schedulerId); + +private: + static std::map> s_schedulers; + static std::mutex s_schedulersMutex; +}; + +#endif // TASK_MANAGER_H diff --git a/src/lib/utility/scheduling/TaskRunner.cpp b/src/lib/utility/scheduling/TaskRunner.cpp index 4e0ec3c9..5b7083df 100644 --- a/src/lib/utility/scheduling/TaskRunner.cpp +++ b/src/lib/utility/scheduling/TaskRunner.cpp @@ -1,7 +1,8 @@ #include "TaskRunner.h" -#include "logging.h" #include "Blackboard.h" +#include "logging.h" +#include "TaskManager.h" #include "TaskScheduler.h" TaskRunner::TaskRunner(std::shared_ptr task) @@ -10,6 +11,17 @@ TaskRunner::TaskRunner(std::shared_ptr task) { } +Task::TaskState TaskRunner::update(Id schedulerId) +{ + if (!m_blackboard) + { + m_blackboard = std::make_shared(); + m_blackboard->set("scheduler_id", schedulerId); + } + + return update(m_blackboard); +} + Task::TaskState TaskRunner::update(std::shared_ptr blackboard) { if (!blackboard) @@ -41,7 +53,12 @@ Task::TaskState TaskRunner::update(std::shared_ptr blackboard) LOG_ERROR("Unknown exception thrown during task running"); } - TaskScheduler::getInstance()->terminateRunningTasks(); + Id schedulerId = 0; + if (blackboard->get("scheduler_id", schedulerId)) + { + TaskManager::getScheduler(schedulerId)->terminateRunningTasks(); + } + return Task::STATE_FAILURE; } diff --git a/src/lib/utility/scheduling/TaskRunner.h b/src/lib/utility/scheduling/TaskRunner.h index 12a31aa2..575f64c8 100644 --- a/src/lib/utility/scheduling/TaskRunner.h +++ b/src/lib/utility/scheduling/TaskRunner.h @@ -10,6 +10,7 @@ class TaskRunner public: TaskRunner(std::shared_ptr task); + Task::TaskState update(Id schedulerId); Task::TaskState update(std::shared_ptr blackboard); void reset(); void terminate(); // caution: this should only be called just before quitting the app. diff --git a/src/lib/utility/scheduling/TaskScheduler.cpp b/src/lib/utility/scheduling/TaskScheduler.cpp index 87ccb8c0..a45fae15 100644 --- a/src/lib/utility/scheduling/TaskScheduler.cpp +++ b/src/lib/utility/scheduling/TaskScheduler.cpp @@ -6,14 +6,17 @@ #include "logging.h" #include "ScopedFunctor.h" -std::shared_ptr TaskScheduler::getInstance() +TaskScheduler::TaskScheduler(Id schedulerId) + : m_schedulerId(schedulerId) + , m_loopIsRunning(false) + , m_threadIsRunning(false) + , m_terminateRunningTasks(false) { - if (!s_instance) - { - s_instance = std::shared_ptr(new TaskScheduler()); - } +} - return s_instance; +TaskScheduler::~TaskScheduler() +{ + stopSchedulerLoop(); } void TaskScheduler::pushTask(std::shared_ptr task) @@ -127,15 +130,6 @@ void TaskScheduler::terminateRunningTasks() m_terminateRunningTasks = true; } -std::shared_ptr TaskScheduler::s_instance; - -TaskScheduler::TaskScheduler() - : m_loopIsRunning(false) - , m_threadIsRunning(false) - , m_terminateRunningTasks(false) -{ -} - void TaskScheduler::processTasks() { std::lock_guard lock(m_tasksMutex); @@ -163,7 +157,7 @@ void TaskScheduler::processTasks() } } - state = runner->update(nullptr); + state = runner->update(m_schedulerId); if (state != Task::STATE_RUNNING) { break; diff --git a/src/lib/utility/scheduling/TaskScheduler.h b/src/lib/utility/scheduling/TaskScheduler.h index 08afc81b..41ee49e4 100644 --- a/src/lib/utility/scheduling/TaskScheduler.h +++ b/src/lib/utility/scheduling/TaskScheduler.h @@ -7,11 +7,13 @@ #include "Task.h" #include "TaskRunner.h" +#include "types.h" class TaskScheduler { public: - static std::shared_ptr getInstance(); + TaskScheduler(Id schedulerId); + ~TaskScheduler(); void pushTask(std::shared_ptr task); void pushNextTask(std::shared_ptr task); @@ -26,14 +28,9 @@ public: void terminateRunningTasks(); private: - static std::shared_ptr s_instance; - - TaskScheduler(); - TaskScheduler(const TaskScheduler&); - void operator=(const TaskScheduler&); - void processTasks(); + const Id m_schedulerId; bool m_loopIsRunning; bool m_threadIsRunning; diff --git a/src/lib_gui/CMakeLists.txt b/src/lib_gui/CMakeLists.txt index eab2dc79..d7b801af 100644 --- a/src/lib_gui/CMakeLists.txt +++ b/src/lib_gui/CMakeLists.txt @@ -67,6 +67,8 @@ add_files( qt/element/QtStringListBoxItem.h qt/element/QtStatusBar.cpp qt/element/QtStatusBar.h + qt/element/QtTabBar.cpp + qt/element/QtTabBar.h qt/element/QtTable.cpp qt/element/QtTable.h qt/element/QtTextEdit.cpp @@ -150,6 +152,8 @@ add_files( qt/view/graphElements/QtGraphNodeText.cpp qt/view/graphElements/QtGraphNodeText.h + qt/view/QtBookmarkButtonsView.cpp + qt/view/QtBookmarkButtonsView.h qt/view/QtBookmarkView.cpp qt/view/QtBookmarkView.h qt/view/QtCodeView.cpp @@ -180,6 +184,8 @@ add_files( qt/view/QtTabbedView.h qt/view/QtTooltipView.cpp qt/view/QtTooltipView.h + qt/view/QtTabsView.cpp + qt/view/QtTabsView.h qt/view/QtUndoRedoView.cpp qt/view/QtUndoRedoView.h qt/view/QtViewFactory.cpp diff --git a/src/lib_gui/qt/element/QtCodeArea.cpp b/src/lib_gui/qt/element/QtCodeArea.cpp index 7da960d4..a07bcea7 100644 --- a/src/lib_gui/qt/element/QtCodeArea.cpp +++ b/src/lib_gui/qt/element/QtCodeArea.cpp @@ -620,6 +620,7 @@ void QtCodeArea::mousePressEvent(QMouseEvent* event) void QtCodeArea::mouseReleaseEvent(QMouseEvent* event) { const int panningThreshold = 5; + if (event->button() == Qt::LeftButton) { m_isSelecting = false; @@ -636,9 +637,7 @@ void QtCodeArea::mouseReleaseEvent(QMouseEvent* event) } else { - QTextCursor cursor = this->cursorForPosition(event->pos()); - std::vector annotations = getInteractiveAnnotationsForPosition(cursor.position()); - + std::vector annotations = getInteractiveAnnotationsForPosition(event->pos()); if (annotations.size()) { if (m_navigator->hasErrors()) @@ -657,6 +656,10 @@ void QtCodeArea::mouseReleaseEvent(QMouseEvent* event) } } } + else + { + QtCodeField::mouseReleaseEvent(event); + } } void QtCodeArea::mouseMoveEvent(QMouseEvent* event) @@ -681,8 +684,7 @@ void QtCodeArea::mouseMoveEvent(QMouseEvent* event) scrollbar->setValue(scrollbar->value() - utility::roundToInt(deltaPosRatio * scrollbar->pageStep())); } - QTextCursor cursor = this->cursorForPosition(event->pos()); - std::vector annotations = getInteractiveAnnotationsForPosition(cursor.position()); + std::vector annotations = getInteractiveAnnotationsForPosition(event->pos()); bool same = annotations.size() == m_hoveredAnnotations.size(); if (same) @@ -730,9 +732,12 @@ void QtCodeArea::contextMenuEvent(QContextMenuEvent* event) { m_eventPosition = event->pos(); + checkOpenInTabActionEnabled(event->pos()); m_setIDECursorPositionAction->setEnabled(!getSourceLocationFile()->getFilePath().empty()); QtContextMenu menu(event, this); + menu.addAction(m_openInTabAction); + menu.addUndoActions(); menu.addSeparator(); menu.addFileActions(getSourceLocationFile()->getFilePath()); menu.addSeparator(); diff --git a/src/lib_gui/qt/element/QtCodeField.cpp b/src/lib_gui/qt/element/QtCodeField.cpp index ff3fa1aa..8d7ab86a 100644 --- a/src/lib_gui/qt/element/QtCodeField.cpp +++ b/src/lib_gui/qt/element/QtCodeField.cpp @@ -1,17 +1,20 @@ #include "QtCodeField.h" +#include #include #include #include #include "SourceLocation.h" #include "SourceLocationFile.h" +#include "QtContextMenu.h" #include "QtHighlighter.h" #include "ApplicationSettings.h" #include "ColorScheme.h" #include "MessageActivateLocalSymbols.h" #include "MessageActivateSourceLocations.h" #include "MessageActivateTokenIds.h" +#include "MessageTabOpenWith.h" #include "MessageTooltipShow.h" #include "TextCodec.h" #include "tracing.h" @@ -99,6 +102,12 @@ QtCodeField::QtCodeField( font.setPixelSize(appSettings->getFontSize()); setFont(font); setTabStopWidth(appSettings->getCodeTabWidth() * fontMetrics().width('9')); + + m_openInTabAction = new QAction("Open in New Tab", this); + m_openInTabAction->setStatusTip("Opens the node in a new tab"); + m_openInTabAction->setToolTip("Opens the node in a new tab"); + m_openInTabAction->setEnabled(false); + connect(m_openInTabAction, &QAction::triggered, this, &QtCodeField::openInTab); } QtCodeField::~QtCodeField() @@ -251,8 +260,7 @@ void QtCodeField::leaveEvent(QEvent* event) void QtCodeField::mouseMoveEvent(QMouseEvent* event) { - QTextCursor cursor = this->cursorForPosition(event->pos()); - std::vector annotations = getInteractiveAnnotationsForPosition(cursor.position()); + std::vector annotations = getInteractiveAnnotationsForPosition(event->pos()); bool same = annotations.size() == m_hoveredAnnotations.size(); if (same) @@ -275,6 +283,13 @@ void QtCodeField::mouseMoveEvent(QMouseEvent* event) void QtCodeField::mouseReleaseEvent(QMouseEvent* event) { + if (event->button() == Qt::MiddleButton) + { + checkOpenInTabActionEnabled(event->pos()); + openInTab(); + return; + } + if (event->button() != Qt::LeftButton) { return; @@ -282,9 +297,7 @@ void QtCodeField::mouseReleaseEvent(QMouseEvent* event) viewport()->setCursor(Qt::ArrowCursor); - QTextCursor cursor = this->cursorForPosition(event->pos()); - std::vector annotations = getInteractiveAnnotationsForPosition(cursor.position()); - + std::vector annotations = getInteractiveAnnotationsForPosition(event->pos()); if (!annotations.size()) { return; @@ -293,6 +306,16 @@ void QtCodeField::mouseReleaseEvent(QMouseEvent* event) activateAnnotations(annotations); } +void QtCodeField::contextMenuEvent(QContextMenuEvent* event) +{ + checkOpenInTabActionEnabled(event->pos()); + + QtContextMenu menu(event, nullptr); + menu.addAction(m_openInTabAction); + menu.addUndoActions(); + menu.show(); +} + void QtCodeField::focusTokenIds(const std::vector& focusedTokenIds) { annotateText(std::set(), std::set(), std::set(focusedTokenIds.begin(), focusedTokenIds.end())); @@ -639,10 +662,13 @@ void QtCodeField::setTextColorForAnnotation(const Annotation& annotation, QColor m_highlighter->applyFormat(annotation.start, annotation.end, format); } -std::vector QtCodeField::getInteractiveAnnotationsForPosition(int pos) const +std::vector QtCodeField::getInteractiveAnnotationsForPosition(QPoint position) const { std::vector annotations; + QTextCursor cursor = this->cursorForPosition(position); + int pos = cursor.position(); + for (const Annotation& annotation : m_annotations) { const LocationType& type = annotation.locationType; @@ -656,6 +682,38 @@ std::vector QtCodeField::getInteractiveAnnotatio return annotations; } +void QtCodeField::checkOpenInTabActionEnabled(QPoint position) +{ + std::vector locationIds; + for (const Annotation* annotation : getInteractiveAnnotationsForPosition(position)) + { + const LocationType& type = annotation->locationType; + if (type == LOCATION_TOKEN || type == LOCATION_QUALIFIER) + { + locationIds.emplace_back(annotation->locationId); + } + } + + if (locationIds.size()) + { + m_openInTabLocationId = locationIds[0]; + } + else + { + m_openInTabLocationId = 0; + } + + m_openInTabAction->setEnabled(m_openInTabLocationId); +} + +void QtCodeField::openInTab() +{ + if (m_openInTabLocationId) + { + MessageTabOpenWith(0, m_openInTabLocationId).dispatch(); + } +} + void QtCodeField::createLineLengthCache() { m_endTextEditPosition = -1; diff --git a/src/lib_gui/qt/element/QtCodeField.h b/src/lib_gui/qt/element/QtCodeField.h index 4e8ae553..9f12fc78 100644 --- a/src/lib_gui/qt/element/QtCodeField.h +++ b/src/lib_gui/qt/element/QtCodeField.h @@ -51,6 +51,8 @@ protected: virtual void mouseMoveEvent(QMouseEvent* event) Q_DECL_OVERRIDE; virtual void mouseReleaseEvent(QMouseEvent* event) Q_DECL_OVERRIDE; + virtual void contextMenuEvent(QContextMenuEvent* event) Q_DECL_OVERRIDE; + virtual void focusTokenIds(const std::vector& tokenIds); virtual void defocusTokenIds(const std::vector& tokenIds); @@ -99,12 +101,20 @@ protected: const AnnotationColor& getAnnotationColorForAnnotation(const Annotation& annotation); void setTextColorForAnnotation(const Annotation& annotation, QColor color) const; - std::vector getInteractiveAnnotationsForPosition(int pos) const; + std::vector getInteractiveAnnotationsForPosition(QPoint position) const; + std::vector getInteractiveTokenIdsForPosition(QPoint position) const; + + void checkOpenInTabActionEnabled(QPoint position); std::vector m_annotations; std::vector m_hoveredAnnotations; std::vector m_linesToRehighlight; + QAction* m_openInTabAction; + +private slots: + void openInTab(); + private: static std::vector s_annotationColors; @@ -123,6 +133,8 @@ private: std::vector>> m_multibyteCharacterLocations; int m_endTextEditPosition; + + Id m_openInTabLocationId; }; #endif // QT_CODE_FIELD_H diff --git a/src/lib_gui/qt/element/QtCodeFileTitleButton.cpp b/src/lib_gui/qt/element/QtCodeFileTitleButton.cpp index 526f51e5..d363212f 100644 --- a/src/lib_gui/qt/element/QtCodeFileTitleButton.cpp +++ b/src/lib_gui/qt/element/QtCodeFileTitleButton.cpp @@ -1,8 +1,11 @@ #include "QtCodeFileTitleButton.h" +#include + #include "FileSystem.h" #include "MessageActivateFile.h" #include "MessageProjectEdit.h" +#include "MessageTabOpenWith.h" #include "ResourcePaths.h" #include "utilityString.h" @@ -25,6 +28,12 @@ QtCodeFileTitleButton::QtCodeFileTitleButton(QWidget* parent) setIconSize(QSize(16, 16)); connect(this, &QtCodeFileTitleButton::clicked, this, &QtCodeFileTitleButton::clickedTitle); + + m_openInTabAction = new QAction("Open in New Tab", this); + m_openInTabAction->setStatusTip("Opens the file in a new tab"); + m_openInTabAction->setToolTip("Opens the file in a new tab"); + m_openInTabAction->setEnabled(false); + connect(m_openInTabAction, &QAction::triggered, this, &QtCodeFileTitleButton::openInTab); } QtCodeFileTitleButton::~QtCodeFileTitleButton() @@ -147,6 +156,17 @@ void QtCodeFileTitleButton::updateFromOther(const QtCodeFileTitleButton* other) updateTexts(); } +void QtCodeFileTitleButton::mouseReleaseEvent(QMouseEvent* event) +{ + if (event->button() == Qt::MiddleButton) + { + openInTab(); + return; + } + + QtSelfRefreshIconButton::mouseReleaseEvent(event); +} + void QtCodeFileTitleButton::contextMenuEvent(QContextMenuEvent* event) { FilePath path = m_filePath; @@ -161,7 +181,11 @@ void QtCodeFileTitleButton::contextMenuEvent(QContextMenuEvent* event) path = currentProject->getProjectSettingsFilePath(); } + m_openInTabAction->setEnabled(!m_filePath.empty()); + QtContextMenu menu(event, this); + menu.addAction(m_openInTabAction); + menu.addUndoActions(); menu.addSeparator(); menu.addFileActions(path); menu.show(); @@ -186,6 +210,14 @@ void QtCodeFileTitleButton::clickedTitle() } } +void QtCodeFileTitleButton::openInTab() +{ + if (!m_filePath.empty()) + { + MessageTabOpenWith(m_filePath).dispatch(); + } +} + void QtCodeFileTitleButton::updateIcon() { if (m_filePath.empty()) diff --git a/src/lib_gui/qt/element/QtCodeFileTitleButton.h b/src/lib_gui/qt/element/QtCodeFileTitleButton.h index a4c60a73..d783d65a 100644 --- a/src/lib_gui/qt/element/QtCodeFileTitleButton.h +++ b/src/lib_gui/qt/element/QtCodeFileTitleButton.h @@ -31,12 +31,14 @@ public: void updateFromOther(const QtCodeFileTitleButton* other); protected: + void mouseReleaseEvent(QMouseEvent* event); void contextMenuEvent(QContextMenuEvent* event); virtual void refresh(); private slots: void clickedTitle(); + void openInTab(); private: void updateIcon(); @@ -46,6 +48,8 @@ private: TimeStamp m_modificationTime; bool m_isComplete; bool m_isIndexed; + + QAction* m_openInTabAction; }; #endif // QT_CODE_FILE_TITLE_BUTTON_H diff --git a/src/lib_gui/qt/element/QtCodeNavigateable.cpp b/src/lib_gui/qt/element/QtCodeNavigateable.cpp index a244b962..99f8628a 100644 --- a/src/lib_gui/qt/element/QtCodeNavigateable.cpp +++ b/src/lib_gui/qt/element/QtCodeNavigateable.cpp @@ -64,7 +64,7 @@ void QtCodeNavigateable::ensureWidgetVisibleAnimated( QScrollBar* scrollBar = area->verticalScrollBar(); if (scrollBar && value) { - if (animated && ApplicationSettings::getInstance()->getUseAnimations()) + if (animated && ApplicationSettings::getInstance()->getUseAnimations() && area->isVisible()) { QPropertyAnimation* anim = new QPropertyAnimation(scrollBar, "value"); anim->setDuration(300); @@ -136,7 +136,7 @@ void QtCodeNavigateable::ensurePercentVisibleAnimated(double percentA, double pe int diff = value - scrollBar->value(); if (diff > 5 || diff < -5) { - if (animated && ApplicationSettings::getInstance()->getUseAnimations()) + if (animated && ApplicationSettings::getInstance()->getUseAnimations() && area->isVisible()) { QPropertyAnimation* anim = new QPropertyAnimation(scrollBar, "value"); anim->setDuration(300); diff --git a/src/lib_gui/qt/element/QtCodeNavigator.cpp b/src/lib_gui/qt/element/QtCodeNavigator.cpp index 5b1a396b..d0c2fcf3 100644 --- a/src/lib_gui/qt/element/QtCodeNavigator.cpp +++ b/src/lib_gui/qt/element/QtCodeNavigator.cpp @@ -10,6 +10,7 @@ #include "MessageShowError.h" #include "MessageScrollCode.h" #include "ResourcePaths.h" +#include "TabId.h" #include "utility.h" #include "SourceLocation.h" @@ -26,6 +27,7 @@ QtCodeNavigator::QtCodeNavigator(QWidget* parent) : QWidget(parent) , m_mode(MODE_NONE) , m_oldMode(MODE_NONE) + , m_schedulerId(TabId::ignore()) , m_activeTokenId(0) , m_value(0) , m_refIndex(0) @@ -338,6 +340,16 @@ void QtCodeNavigator::setMode(Mode mode) } } +Id QtCodeNavigator::getSchedulerId() const +{ + return m_schedulerId; +} + +void QtCodeNavigator::setSchedulerId(Id schedulerId) +{ + m_schedulerId = schedulerId; +} + const std::set& QtCodeNavigator::getCurrentActiveTokenIds() const { return m_currentActiveTokenIds; @@ -708,6 +720,11 @@ void QtCodeNavigator::deactivateScreenMatch(size_t matchIndex) m_activeScreenMatchId = 0; } +bool QtCodeNavigator::hasScreenMatches() const +{ + return !m_screenMatches.empty(); +} + void QtCodeNavigator::clearScreenMatches() { if (m_activeScreenMatchId) @@ -847,7 +864,7 @@ void QtCodeNavigator::requestScroll( void QtCodeNavigator::handleScrollRequest() { const ScrollRequest& req = m_scrollRequest; - if (req.filePath.empty()) + if (req.filePath.empty() || !isVisible()) { return; } @@ -871,6 +888,11 @@ void QtCodeNavigator::scrolled(int value) MessageScrollCode(value, m_mode == MODE_LIST).dispatch(); } +void QtCodeNavigator::showEvent(QShowEvent* event) +{ + emit scrollRequest(); +} + void QtCodeNavigator::setValue() { QAbstractScrollArea* area = m_current->getScrollArea(); diff --git a/src/lib_gui/qt/element/QtCodeNavigator.h b/src/lib_gui/qt/element/QtCodeNavigator.h index a2338834..ff1d594b 100644 --- a/src/lib_gui/qt/element/QtCodeNavigator.h +++ b/src/lib_gui/qt/element/QtCodeNavigator.h @@ -56,6 +56,9 @@ public: void setMode(Mode mode); + Id getSchedulerId() const override; + void setSchedulerId(Id schedulerId); + const std::set& getCurrentActiveTokenIds() const; void setCurrentActiveTokenIds(const std::vector& currentActiveTokenIds); @@ -101,6 +104,7 @@ public: size_t findScreenMatches(const std::wstring& query); void activateScreenMatch(size_t matchIndex); void deactivateScreenMatch(size_t matchIndex); + bool hasScreenMatches() const; void clearScreenMatches(); void scrollToValue(int value, bool inListMode); @@ -118,6 +122,9 @@ signals: public slots: void scrolled(int value); +protected: + void showEvent(QShowEvent* event) override; + private slots: void handleScrollRequest(); void setValue(); @@ -172,11 +179,11 @@ private: QtCodeNavigateable::ScrollTarget target; }; - void handleMessage(MessageCodeReference* message); - void handleMessage(MessageIndexingFinished* message); - void handleMessage(MessageShowReference* message); - void handleMessage(MessageSwitchColorScheme* message); - void handleMessage(MessageWindowFocus* message); + void handleMessage(MessageCodeReference* message) override; + void handleMessage(MessageIndexingFinished* message) override; + void handleMessage(MessageShowReference* message) override; + void handleMessage(MessageSwitchColorScheme* message) override; + void handleMessage(MessageWindowFocus* message) override; QtThreadedLambdaFunctor m_onQtThread; @@ -187,6 +194,8 @@ private: Mode m_mode; Mode m_oldMode; + Id m_schedulerId; + std::set m_currentActiveTokenIds; std::set m_currentActiveLocationIds; std::set m_currentActiveLocalLocationIds; diff --git a/src/lib_gui/qt/element/QtHistoryList.cpp b/src/lib_gui/qt/element/QtHistoryList.cpp index 18d75ead..f33d540a 100644 --- a/src/lib_gui/qt/element/QtHistoryList.cpp +++ b/src/lib_gui/qt/element/QtHistoryList.cpp @@ -2,9 +2,11 @@ #include #include +#include #include #include "MessageHistoryToPosition.h" +#include "MessageTabOpenWith.h" #include "ResourcePaths.h" #include "utilityString.h" @@ -12,11 +14,11 @@ #include "utilityQt.h" #include "GraphViewStyle.h" -#include "SearchMatch.h" #include "ColorScheme.h" QtHistoryItem::QtHistoryItem(const SearchMatch& match, size_t index, bool isCurrent) : index(index) + , m_match(match) { QBoxLayout* layout = new QHBoxLayout(); layout->setSpacing(0); @@ -74,6 +76,11 @@ QSize QtHistoryItem::getSizeHint() const return QSize(m_name->fontMetrics().width(m_name->text()) + 40, m_name->fontMetrics().height() + 8); } +const SearchMatch& QtHistoryItem::getMatch() const +{ + return m_match; +} + void QtHistoryItem::enterEvent(QEvent *event) { QWidget::enterEvent(event); @@ -111,13 +118,36 @@ void QtHistoryItem::leaveEvent(QEvent *event) } + +QtHistoryListWidget::QtHistoryListWidget(QWidget* parent) + : QListWidget(parent) +{ +} + +void QtHistoryListWidget::mouseReleaseEvent(QMouseEvent* event) +{ + if (event->button() == Qt::MiddleButton) + { + QtHistoryItem* item = dynamic_cast(itemWidget(itemAt(event->pos()))); + if (item) + { + MessageTabOpenWith(item->getMatch()).dispatch(); + } + return; + } + + QListWidget::mouseReleaseEvent(event); +} + + + QtHistoryList::QtHistoryList(const std::vector& history, size_t currentIndex) : m_currentIndex(currentIndex) { setWindowFlags(Qt::Popup); setObjectName("history"); - m_list = new QListWidget(this); + m_list = new QtHistoryListWidget(this); m_list->setObjectName("history_list"); m_list->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); m_list->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); @@ -141,8 +171,8 @@ void QtHistoryList::showPopup(QPoint pos) QSize size(50, 2); for (int i = 0; i < m_list->count(); i++) { - QtHistoryItem* it = dynamic_cast(m_list->itemWidget(m_list->item(i))); - QSize itemSize = it->getSizeHint(); + QtHistoryItem* item = dynamic_cast(m_list->itemWidget(m_list->item(i))); + QSize itemSize = item->getSizeHint(); if (itemSize.width() > size.width()) { size.setWidth(itemSize.width()); diff --git a/src/lib_gui/qt/element/QtHistoryList.h b/src/lib_gui/qt/element/QtHistoryList.h index c03933c5..402b5464 100644 --- a/src/lib_gui/qt/element/QtHistoryList.h +++ b/src/lib_gui/qt/element/QtHistoryList.h @@ -3,8 +3,9 @@ #include +#include "SearchMatch.h" + class QLabel; -struct SearchMatch; class QtHistoryItem : public QWidget @@ -16,6 +17,8 @@ public: QSize getSizeHint() const; + const SearchMatch& getMatch() const; + size_t index; protected: @@ -29,6 +32,19 @@ private: QWidget* m_indicator; std::string m_indicatorColor; std::string m_indicatorHoverColor; + + const SearchMatch m_match; +}; + + +class QtHistoryListWidget + : public QListWidget +{ +public: + QtHistoryListWidget(QWidget* parent = nullptr); + +protected: + void mouseReleaseEvent(QMouseEvent* event); }; @@ -52,7 +68,7 @@ private slots: void onItemClicked(QListWidgetItem *item); private: - QListWidget* m_list; + QtHistoryListWidget* m_list; size_t m_currentIndex; }; diff --git a/src/lib_gui/qt/element/QtScreenSearchBox.cpp b/src/lib_gui/qt/element/QtScreenSearchBox.cpp index cd6ee3d0..447e244c 100644 --- a/src/lib_gui/qt/element/QtScreenSearchBox.cpp +++ b/src/lib_gui/qt/element/QtScreenSearchBox.cpp @@ -141,10 +141,15 @@ void QtScreenSearchBox::setMatchIndex(size_t matchIndex) void QtScreenSearchBox::addResponder(const std::string& name) { + if (m_checkBoxes.find(name) != m_checkBoxes.end()) + { + return; + } + QCheckBox* box = new QCheckBox(name.c_str()); box->setObjectName("filter_checkbox"); box->setChecked(true); - m_checkBoxes.push_back(box); + m_checkBoxes.emplace(name, box); m_checkboxLayout->addWidget(box); connect(box, &QCheckBox::stateChanged, this, &QtScreenSearchBox::findMatches); @@ -173,11 +178,11 @@ void QtScreenSearchBox::findMatches() [this](ScreenSearchController* controller) { std::set responderNames; - for (QCheckBox* box : m_checkBoxes) + for (auto p : m_checkBoxes) { - if (box->isChecked()) + if (p.second->isChecked()) { - responderNames.insert(box->text().toStdString()); + responderNames.insert(p.first); } } diff --git a/src/lib_gui/qt/element/QtScreenSearchBox.h b/src/lib_gui/qt/element/QtScreenSearchBox.h index 713cd88f..2d273020 100644 --- a/src/lib_gui/qt/element/QtScreenSearchBox.h +++ b/src/lib_gui/qt/element/QtScreenSearchBox.h @@ -74,7 +74,7 @@ private: QtSelfRefreshIconButton* m_closeButton; QHBoxLayout* m_checkboxLayout; - std::vector m_checkBoxes; + std::map m_checkBoxes; size_t m_matchCount = 0; size_t m_matchIndex = 0; diff --git a/src/lib_gui/qt/element/QtTabBar.cpp b/src/lib_gui/qt/element/QtTabBar.cpp new file mode 100644 index 00000000..3ea87e1e --- /dev/null +++ b/src/lib_gui/qt/element/QtTabBar.cpp @@ -0,0 +1,22 @@ +#include "QtTabBar.h" + +QtTabBar::QtTabBar(QWidget* parent) + : QTabBar(parent) +{ + setFocusPolicy(Qt::NoFocus); +} + +QSize QtTabBar::minimumSizeHint() const +{ + return QSize(0, QTabBar::minimumSizeHint().height()); +} + +QSize QtTabBar::tabSizeHint(int index) const +{ + return QSize(300, QTabBar::tabSizeHint(index).height()); +} + +QSize QtTabBar::minimumTabSizeHint(int index) const +{ + return QSize(45, QTabBar::minimumTabSizeHint(index).height()); +} diff --git a/src/lib_gui/qt/element/QtTabBar.h b/src/lib_gui/qt/element/QtTabBar.h new file mode 100644 index 00000000..d0feb8b6 --- /dev/null +++ b/src/lib_gui/qt/element/QtTabBar.h @@ -0,0 +1,19 @@ +#ifndef QT_TAB_BAR_H +#define QT_TAB_BAR_H + +#include + +class QtTabBar + : public QTabBar +{ +public: + QtTabBar(QWidget* parent = nullptr); + +protected: + QSize minimumSizeHint() const override; + + QSize tabSizeHint(int index) const override; + QSize minimumTabSizeHint(int index) const override; +}; + +#endif // QT_TAB_BAR_H diff --git a/src/lib_gui/qt/graphics/QtGraphicsView.cpp b/src/lib_gui/qt/graphics/QtGraphicsView.cpp index 80523c5d..7376e412 100644 --- a/src/lib_gui/qt/graphics/QtGraphicsView.cpp +++ b/src/lib_gui/qt/graphics/QtGraphicsView.cpp @@ -22,10 +22,11 @@ #include "utilityQt.h" #include "ApplicationSettings.h" #include "MessageActivateLegend.h" +#include "MessageBookmarkCreate.h" #include "MessageCodeShowDefinition.h" -#include "MessageDisplayBookmarkCreator.h" #include "MessageGraphNodeExpand.h" #include "MessageGraphNodeHide.h" +#include "MessageTabOpenWith.h" #include "ResourcePaths.h" #include "utilityApp.h" @@ -55,10 +56,10 @@ QtGraphicsView::QtGraphicsView(QWidget* parent) m_zoomLabelTimer = std::make_shared(this); connect(m_zoomLabelTimer.get(), &QTimer::timeout, this, &QtGraphicsView::hideZoomLabel); - m_exportGraphAction = new QAction("Save as Image", this); - m_exportGraphAction->setStatusTip("Save this graph as image file"); - m_exportGraphAction->setToolTip("Save this graph as image file"); - connect(m_exportGraphAction, &QAction::triggered, this, &QtGraphicsView::exportGraph); + m_openInTabAction = new QAction("Open in New Tab", this); + m_openInTabAction->setStatusTip("Open this node in a new tab"); + m_openInTabAction->setToolTip("Open this node in a new tab"); + connect(m_openInTabAction, &QAction::triggered, this, &QtGraphicsView::openInTab); m_copyNodeNameAction = new QAction("Copy Name", this); m_copyNodeNameAction->setStatusTip("Copies the name of this node to the clipboard"); @@ -98,6 +99,11 @@ QtGraphicsView::QtGraphicsView(QWidget* parent) m_bookmarkNodeAction->setToolTip("Create a bookmark for this node"); connect(m_bookmarkNodeAction, &QAction::triggered, this, &QtGraphicsView::bookmarkNode); + m_exportGraphAction = new QAction("Save as Image", this); + m_exportGraphAction->setStatusTip("Save this graph as image file"); + m_exportGraphAction->setToolTip("Save this graph as image file"); + connect(m_exportGraphAction, &QAction::triggered, this, &QtGraphicsView::exportGraph); + m_zoomState = new QPushButton(this); m_zoomState->setObjectName("zoom_state"); m_zoomState->hide(); @@ -175,7 +181,7 @@ void QtGraphicsView::ensureVisibleAnimated(const QRectF& rect, int xmargin, int ensureVisible(rect, xmargin, ymargin); - if (ApplicationSettings::getInstance()->getUseAnimations()) + if (ApplicationSettings::getInstance()->getUseAnimations() && isVisible()) { int xval2 = horizontalScrollBar()->value(); int yval2 = verticalScrollBar()->value(); @@ -345,6 +351,7 @@ void QtGraphicsView::wheelEvent(QWheelEvent* event) void QtGraphicsView::contextMenuEvent(QContextMenuEvent* event) { + m_openInTabNodeId = 0; m_clipboardNodeName = L""; m_collapseNodeId = 0; m_expandNodeId = 0; @@ -369,6 +376,7 @@ void QtGraphicsView::contextMenuEvent(QContextMenuEvent* event) if (dataNode) { m_clipboardNodeName = dataNode->getName(); + m_openInTabNodeId = dataNode->getTokenId(); m_bookmarkNodeId = dataNode->getTokenId(); clipboardFilePath = dataNode->getFilePath(); } @@ -408,6 +416,7 @@ void QtGraphicsView::contextMenuEvent(QContextMenuEvent* event) } } + m_openInTabAction->setEnabled(m_openInTabNodeId); m_collapseAction->setEnabled(m_collapseNodeId); m_expandAction->setEnabled(m_expandNodeId); m_showDefinitionAction->setEnabled(m_hideNodeId); @@ -419,8 +428,8 @@ void QtGraphicsView::contextMenuEvent(QContextMenuEvent* event) QtContextMenu menu(event, this); - menu.addSeparator(); - menu.addAction(m_exportGraphAction); + menu.addAction(m_openInTabAction); + menu.addUndoActions(); menu.addSeparator(); @@ -438,6 +447,9 @@ void QtGraphicsView::contextMenuEvent(QContextMenuEvent* event) menu.addAction(m_hideEdgeAction); menu.addAction(m_bookmarkNodeAction); + menu.addSeparator(); + menu.addAction(m_exportGraphAction); + menu.addSeparator(); menu.addAction(m_copyNodeNameAction); menu.addFileActions(clipboardFilePath); @@ -507,6 +519,11 @@ void QtGraphicsView::stopTimer() m_timer->stop(); } +void QtGraphicsView::openInTab() +{ + MessageTabOpenWith(m_openInTabNodeId).dispatch(); +} + void QtGraphicsView::exportGraph() { const QString exportNotice = "Exported from Sourcetrail"; @@ -616,7 +633,7 @@ void QtGraphicsView::hideEdge() void QtGraphicsView::bookmarkNode() { - MessageDisplayBookmarkCreator(m_bookmarkNodeId).dispatch(); + MessageBookmarkCreate(m_bookmarkNodeId).dispatch(); } void QtGraphicsView::zoomInPressed() diff --git a/src/lib_gui/qt/graphics/QtGraphicsView.h b/src/lib_gui/qt/graphics/QtGraphicsView.h index e7fdd8b2..3d206e87 100644 --- a/src/lib_gui/qt/graphics/QtGraphicsView.h +++ b/src/lib_gui/qt/graphics/QtGraphicsView.h @@ -55,6 +55,8 @@ private slots: void updateTimer(); void stopTimer(); + void openInTab(); + void exportGraph(); void copyNodeName(); @@ -91,6 +93,7 @@ private: bool m_shift; std::wstring m_clipboardNodeName; + Id m_openInTabNodeId; Id m_hideNodeId; Id m_hideEdgeId; Id m_bookmarkNodeId; @@ -101,7 +104,8 @@ private: std::shared_ptr m_timerStopper; std::shared_ptr m_zoomLabelTimer; - QAction* m_exportGraphAction; + QAction* m_openInTabAction; + QAction* m_copyNodeNameAction; QAction* m_collapseAction; QAction* m_expandAction; @@ -110,6 +114,8 @@ private: QAction* m_hideEdgeAction; QAction* m_bookmarkNodeAction; + QAction* m_exportGraphAction; + QPushButton* m_zoomState; QtSelfRefreshIconButton* m_zoomInButton; QtSelfRefreshIconButton* m_zoomOutButton; diff --git a/src/lib_gui/qt/utility/QtContextMenu.cpp b/src/lib_gui/qt/utility/QtContextMenu.cpp index 17c57d2b..eac0ed47 100644 --- a/src/lib_gui/qt/utility/QtContextMenu.cpp +++ b/src/lib_gui/qt/utility/QtContextMenu.cpp @@ -25,8 +25,6 @@ QtContextMenu::QtContextMenu(QContextMenuEvent* event, QWidget* origin) , m_point(event->globalPos()) { getInstance(); - - addUndoActions(); } void QtContextMenu::addAction(QAction* action) diff --git a/src/lib_gui/qt/view/QtBookmarkButtonsView.cpp b/src/lib_gui/qt/view/QtBookmarkButtonsView.cpp new file mode 100644 index 00000000..9e2f8d11 --- /dev/null +++ b/src/lib_gui/qt/view/QtBookmarkButtonsView.cpp @@ -0,0 +1,134 @@ +#include "QtBookmarkButtonsView.h" + +#include +#include +#include +#include + +#include "MessageBookmarkBrowse.h" +#include "MessageBookmarkCreate.h" +#include "MessageBookmarkDelete.h" +#include "MessageBookmarkEdit.h" +#include "QtSearchBarButton.h" +#include "QtViewWidgetWrapper.h" +#include "ResourcePaths.h" +#include "utilityQt.h" + +QtBookmarkButtonsView::QtBookmarkButtonsView(ViewLayout* viewLayout) + : BookmarkButtonsView(viewLayout) + , m_createButtonState(MessageBookmarkButtonState::CANNOT_CREATE) +{ + m_widget = new QFrame(); +} + +void QtBookmarkButtonsView::createWidgetWrapper() +{ + setWidgetWrapper(std::make_shared(m_widget)); +} + +void QtBookmarkButtonsView::initView() +{ + m_widget->setObjectName("bookmark_bar"); + + QBoxLayout* layout = new QHBoxLayout(); + layout->setSpacing(0); + layout->setContentsMargins(0, 0, 0, 0); + layout->setAlignment(Qt::AlignTop); + m_widget->setLayout(layout); + + m_createBookmarkButton = new QtSearchBarButton( + ResourcePaths::getGuiPath().concatenate(L"bookmark_view/images/edit_bookmark_icon.png")); + m_createBookmarkButton->setObjectName("bookmark_button"); + m_createBookmarkButton->setToolTip("create a bookmark for the active symbol"); + m_createBookmarkButton->setEnabled(false); + layout->addWidget(m_createBookmarkButton); + + connect(m_createBookmarkButton, &QPushButton::clicked, this, &QtBookmarkButtonsView::createBookmarkClicked); + + m_showBookmarksButton = new QtSearchBarButton( + ResourcePaths::getGuiPath().concatenate(L"bookmark_view/images/bookmark_list_icon.png")); + m_showBookmarksButton->setObjectName("show_bookmark_button"); + m_showBookmarksButton->setToolTip("Show bookmarks"); + layout->addWidget(m_showBookmarksButton); + + connect(m_showBookmarksButton, &QPushButton::clicked, this, &QtBookmarkButtonsView::showBookmarksClicked); +} + +void QtBookmarkButtonsView::refreshView() +{ + m_onQtThread( + [=]() + { + m_widget->setStyleSheet(utility::getStyleSheet( + ResourcePaths::getGuiPath().concatenate(L"bookmark_view/bookmark_view.css") + ).c_str()); + } + ); +} + +void QtBookmarkButtonsView::setCreateButtonState(const MessageBookmarkButtonState::ButtonState& state) +{ + m_onQtThread( + [=]() + { + m_createButtonState = state; + + m_createBookmarkButton->setIconPath( + ResourcePaths::getGuiPath().concatenate(L"bookmark_view/images/edit_bookmark_icon.png")); + + if (state == MessageBookmarkButtonState::CAN_CREATE) + { + m_createBookmarkButton->setEnabled(true); + } + else if (state == MessageBookmarkButtonState::CANNOT_CREATE) + { + m_createBookmarkButton->setEnabled(false); + } + else if (state == MessageBookmarkButtonState::ALREADY_CREATED) + { + m_createBookmarkButton->setEnabled(true); + + m_createBookmarkButton->setIconPath( + ResourcePaths::getGuiPath().concatenate(L"bookmark_view/images/bookmark_active.png")); + } + else + { + m_createBookmarkButton->setEnabled(false); + } + } + ); +} + +void QtBookmarkButtonsView::createBookmarkClicked() +{ + if (m_createButtonState == MessageBookmarkButtonState::CAN_CREATE) + { + MessageBookmarkCreate().dispatch(); + } + else if (m_createButtonState == MessageBookmarkButtonState::ALREADY_CREATED) + { + QMessageBox msgBox; + msgBox.setText("Edit Bookmark"); + msgBox.setInformativeText("Do you want to edit or delete the bookmark for this symbol?"); + msgBox.addButton("Edit", QMessageBox::ButtonRole::YesRole); + msgBox.addButton("Delete", QMessageBox::ButtonRole::NoRole); + QPushButton* cancelButton = msgBox.addButton("Cancel", QMessageBox::ButtonRole::RejectRole); + msgBox.setDefaultButton(cancelButton); + msgBox.setIcon(QMessageBox::Icon::Question); + int ret = msgBox.exec(); + + if (ret == 0) // QMessageBox::Yes + { + MessageBookmarkEdit().dispatch(); + } + else if (ret == 1) + { + MessageBookmarkDelete().dispatch(); + } + } +} + +void QtBookmarkButtonsView::showBookmarksClicked() +{ + MessageBookmarkBrowse().dispatch(); +} diff --git a/src/lib_gui/qt/view/QtBookmarkButtonsView.h b/src/lib_gui/qt/view/QtBookmarkButtonsView.h new file mode 100644 index 00000000..f529fbbb --- /dev/null +++ b/src/lib_gui/qt/view/QtBookmarkButtonsView.h @@ -0,0 +1,44 @@ +#ifndef QT_BOOKMARK_BUTTONS_VIEW_H +#define QT_BOOKMARK_BUTTONS_VIEW_H + +#include "BookmarkButtonsView.h" + +#include "QtThreadedFunctor.h" + +class QFrame; +class QtSearchBarButton; + +class QtBookmarkButtonsView + : public QObject + , public BookmarkButtonsView +{ + Q_OBJECT + +public: + QtBookmarkButtonsView(ViewLayout* viewLayout); + virtual ~QtBookmarkButtonsView() = default; + + // View implementation + void createWidgetWrapper() override; + void initView() override; + void refreshView() override; + + // BookmarkView implementation + void setCreateButtonState(const MessageBookmarkButtonState::ButtonState& state) override; + +private slots: + void createBookmarkClicked(); + void showBookmarksClicked(); + +private: + QtThreadedLambdaFunctor m_onQtThread; + + QFrame* m_widget; + + QtSearchBarButton* m_createBookmarkButton; + QtSearchBarButton* m_showBookmarksButton; + + MessageBookmarkButtonState::ButtonState m_createButtonState; +}; + +#endif // QT_BOOKMARK_BUTTONS_VIEW_H diff --git a/src/lib_gui/qt/view/QtBookmarkView.cpp b/src/lib_gui/qt/view/QtBookmarkView.cpp index 74380c82..1d2bf55f 100644 --- a/src/lib_gui/qt/view/QtBookmarkView.cpp +++ b/src/lib_gui/qt/view/QtBookmarkView.cpp @@ -1,109 +1,28 @@ #include "QtBookmarkView.h" -#include -#include -#include -#include - -#include "QtSearchBarButton.h" -#include "utilityQt.h" -#include "QtMainView.h" -#include "QtViewWidgetWrapper.h" #include "QtBookmarkBrowser.h" #include "QtBookmarkCreator.h" +#include "QtMainView.h" #include "QtMainWindow.h" -#include "ResourcePaths.h" +#include "TabId.h" QtBookmarkView::QtBookmarkView(ViewLayout* viewLayout) : BookmarkView(viewLayout) - , m_controllerProxy(this) + , m_controllerProxy(this, TabId::app()) , m_bookmarkBrowser(nullptr) - , m_createButtonState(BookmarkView::CreateButtonState::CANNOT_CREATE) -{ - m_widget = new QFrame(); -} - -QtBookmarkView::~QtBookmarkView() { } void QtBookmarkView::createWidgetWrapper() { - setWidgetWrapper(std::make_shared(m_widget)); } void QtBookmarkView::initView() { - m_widget->setObjectName("bookmark_bar"); - - QBoxLayout* layout = new QHBoxLayout(); - layout->setSpacing(0); - layout->setContentsMargins(0, 0, 0, 0); - layout->setAlignment(Qt::AlignTop); - m_widget->setLayout(layout); - - m_createBookmarkButton = new QtSearchBarButton( - ResourcePaths::getGuiPath().concatenate(L"bookmark_view/images/edit_bookmark_icon.png")); - m_createBookmarkButton->setObjectName("bookmark_button"); - m_createBookmarkButton->setToolTip("create a bookmark for the active symbol"); - m_createBookmarkButton->setEnabled(false); - layout->addWidget(m_createBookmarkButton); - - connect(m_createBookmarkButton, &QPushButton::clicked, this, &QtBookmarkView::createBookmarkClicked); - - m_showBookmarksButton = new QtSearchBarButton( - ResourcePaths::getGuiPath().concatenate(L"bookmark_view/images/bookmark_list_icon.png")); - m_showBookmarksButton->setObjectName("show_bookmark_button"); - m_showBookmarksButton->setToolTip("Show bookmarks"); - m_showBookmarksButton->setEnabled(false); - layout->addWidget(m_showBookmarksButton); - - connect(m_showBookmarksButton, &QPushButton::clicked, this, &QtBookmarkView::showBookmarksClicked); } void QtBookmarkView::refreshView() { - m_onQtThread( - [=]() - { - m_widget->setStyleSheet(utility::getStyleSheet( - ResourcePaths::getGuiPath().concatenate(L"bookmark_view/bookmark_view.css") - ).c_str()); - } - ); -} - -void QtBookmarkView::setCreateButtonState(const CreateButtonState& state) -{ - m_onQtThread( - [=]() - { - m_createButtonState = state; - - m_createBookmarkButton->setIconPath( - ResourcePaths::getGuiPath().concatenate(L"bookmark_view/images/edit_bookmark_icon.png")); - - if (state == BookmarkView::CreateButtonState::CAN_CREATE) - { - m_createBookmarkButton->setEnabled(true); - } - else if (state == BookmarkView::CreateButtonState::CANNOT_CREATE) - { - m_createBookmarkButton->setEnabled(false); - } - else if (state == BookmarkView::CreateButtonState::ALREADY_CREATED) - { - m_createBookmarkButton->setEnabled(true); - - m_createBookmarkButton->setIconPath( - ResourcePaths::getGuiPath().concatenate(L"bookmark_view/images/bookmark_active.png")); - } - else - { - m_createBookmarkButton->setEnabled(false); - } - } - ); } void QtBookmarkView::displayBookmarkCreator( @@ -185,16 +104,6 @@ void QtBookmarkView::displayBookmarks(const std::vectorsetEnabled(enable); - } - ); -} - bool QtBookmarkView::bookmarkBrowserIsVisible() const { if (m_bookmarkBrowser != nullptr) @@ -206,37 +115,3 @@ bool QtBookmarkView::bookmarkBrowserIsVisible() const return false; } } - -void QtBookmarkView::createBookmarkClicked() -{ - if (m_createButtonState == BookmarkView::CreateButtonState::CAN_CREATE) - { - m_controllerProxy.executeAsTaskWithArgs(&BookmarkController::showBookmarkCreator, 0); - } - else if (m_createButtonState == BookmarkView::CreateButtonState::ALREADY_CREATED) - { - QMessageBox msgBox; - msgBox.setText("Edit Bookmark"); - msgBox.setInformativeText("Do you want to edit or delete the bookmark for this symbol?"); - msgBox.addButton("Edit", QMessageBox::ButtonRole::YesRole); - msgBox.addButton("Delete", QMessageBox::ButtonRole::NoRole); - QPushButton* cancelButton = msgBox.addButton("Cancel", QMessageBox::ButtonRole::RejectRole); - msgBox.setDefaultButton(cancelButton); - msgBox.setIcon(QMessageBox::Icon::Question); - int ret = msgBox.exec(); - - if (ret == 0) // QMessageBox::Yes - { - m_controllerProxy.executeAsTaskWithArgs(&BookmarkController::showBookmarkCreator, 0); - } - else if (ret == 1) - { - m_controllerProxy.executeAsTask(&BookmarkController::deleteBookmarkForActiveTokens); - } - } -} - -void QtBookmarkView::showBookmarksClicked() -{ - m_controllerProxy.executeAsTask(&BookmarkController::displayBookmarks); -} diff --git a/src/lib_gui/qt/view/QtBookmarkView.h b/src/lib_gui/qt/view/QtBookmarkView.h index da201ba9..5795e7cb 100644 --- a/src/lib_gui/qt/view/QtBookmarkView.h +++ b/src/lib_gui/qt/view/QtBookmarkView.h @@ -2,24 +2,19 @@ #define QT_BOOKMARK_VIEW_H #include "BookmarkController.h" -#include "ControllerProxy.h" #include "BookmarkView.h" - +#include "ControllerProxy.h" #include "QtThreadedFunctor.h" class QFrame; class QtBookmarkBrowser; -class QtSearchBarButton; class QtBookmarkView - : public QObject - , public BookmarkView + : public BookmarkView { - Q_OBJECT - public: QtBookmarkView(ViewLayout* viewLayout); - virtual ~QtBookmarkView(); + virtual ~QtBookmarkView() = default; // View implementation virtual void createWidgetWrapper(); @@ -27,34 +22,19 @@ public: virtual void refreshView(); // BookmarkView implementation - virtual void setCreateButtonState(const CreateButtonState& state); - virtual void displayBookmarkCreator( const std::vector& names, const std::vector& categories, Id nodeId); virtual void displayBookmarkEditor( std::shared_ptr bookmark, const std::vector& categories); virtual void displayBookmarks(const std::vector>& bookmarks); - virtual void enableDisplayBookmarks(bool enable); - virtual bool bookmarkBrowserIsVisible() const; -private slots: - void createBookmarkClicked(); - void showBookmarksClicked(); - private: ControllerProxy m_controllerProxy; QtThreadedLambdaFunctor m_onQtThread; - QFrame* m_widget; - - QtSearchBarButton* m_createBookmarkButton; - QtSearchBarButton* m_showBookmarksButton; - QtBookmarkBrowser* m_bookmarkBrowser; - - BookmarkView::CreateButtonState m_createButtonState; }; #endif // QT_BOOKMARK_VIEW_H diff --git a/src/lib_gui/qt/view/QtCodeView.cpp b/src/lib_gui/qt/view/QtCodeView.cpp index 7d8564bc..d85c0245 100644 --- a/src/lib_gui/qt/view/QtCodeView.cpp +++ b/src/lib_gui/qt/view/QtCodeView.cpp @@ -1,5 +1,6 @@ #include "QtCodeView.h" +#include "CodeController.h" #include "ResourcePaths.h" #include "tracing.h" @@ -31,6 +32,11 @@ void QtCodeView::initView() void QtCodeView::refreshView() { + if (getController()) + { + m_widget->setSchedulerId(getController()->getTabId()); + } + m_onQtThread([=]() { TRACE("refresh"); @@ -82,6 +88,11 @@ void QtCodeView::deactivateMatch(size_t matchIndex) void QtCodeView::clearMatches() { + if (!m_widget->hasScreenMatches()) + { + return; + } + m_onQtThread( [this]() { diff --git a/src/lib_gui/qt/view/QtDialogView.cpp b/src/lib_gui/qt/view/QtDialogView.cpp index 82d510fc..ee53a4ea 100644 --- a/src/lib_gui/qt/view/QtDialogView.cpp +++ b/src/lib_gui/qt/view/QtDialogView.cpp @@ -13,6 +13,7 @@ #include "QtWindow.h" #include "MessageIndexingStatus.h" #include "MessageStatus.h" +#include "TabId.h" #include "TaskLambda.h" #include "utility.h" #include "Project.h" @@ -168,7 +169,7 @@ void QtDialogView::startIndexingDialog( ); timer->start(200); - Task::dispatch(std::make_shared( + Task::dispatch(TabId::app(), std::make_shared( [=]() { RefreshInfo info = project->getRefreshInfo(refreshMode); @@ -194,7 +195,7 @@ void QtDialogView::startIndexingDialog( [=](RefreshMode refreshMode) { RefreshInfo info = m_refreshInfos.find(refreshMode)->second; - Task::dispatch(std::make_shared( + Task::dispatch(TabId::app(), std::make_shared( [=]() { onStartIndexing(info); @@ -208,7 +209,7 @@ void QtDialogView::startIndexingDialog( connect(window, &QtWindow::canceled, [=]() { - Task::dispatch(std::make_shared( + Task::dispatch(TabId::app(), std::make_shared( [=]() { onCancelIndexing(); diff --git a/src/lib_gui/qt/view/QtErrorView.cpp b/src/lib_gui/qt/view/QtErrorView.cpp index 4749e6b2..c1f2cf39 100644 --- a/src/lib_gui/qt/view/QtErrorView.cpp +++ b/src/lib_gui/qt/view/QtErrorView.cpp @@ -13,14 +13,15 @@ #include #include +#include "ColorScheme.h" +#include "MessageProjectEdit.h" #include "QtHelpButton.h" #include "QtIconButton.h" #include "QtTable.h" -#include "utilityQt.h" #include "QtViewWidgetWrapper.h" -#include "ColorScheme.h" -#include "MessageProjectEdit.h" #include "ResourcePaths.h" +#include "TabId.h" +#include "utilityQt.h" QIcon QtErrorView::s_errorIcon; @@ -54,8 +55,7 @@ QWidget* SelectableDelegate::createEditor( QtErrorView::QtErrorView(ViewLayout* viewLayout) : ErrorView(viewLayout) - , m_controllerProxy(this) - , m_ignoreRowSelection(false) + , m_controllerProxy(this, TabId::app()) { s_errorIcon = QIcon(QString::fromStdWString(ResourcePaths::getGuiPath().concatenate(L"indexing_dialog/error.png").wstr())); } @@ -78,8 +78,8 @@ void QtErrorView::initView() layout->setSpacing(0); widget->setLayout(layout); - m_table = new QtTable(this); - m_model = new QStandardItemModel(this); + m_table = new QtTable(widget); + m_model = new QStandardItemModel(widget); m_table->setSortingEnabled(true); m_table->setModel(m_model); m_table->setItemDelegate(new SelectableDelegate(m_table)); @@ -97,10 +97,10 @@ void QtErrorView::initView() headers << "ID" << "Type" << "Message" << "File" << "Line" << "Indexed" << "Translation Unit"; m_model->setHorizontalHeaderLabels(headers); - connect(m_table->selectionModel(), &QItemSelectionModel::currentRowChanged, - [=](const QModelIndex& index, const QModelIndex& previousIndex) + connect(m_table, &QTableView::clicked, + [=](const QModelIndex& index) { - if (index.isValid() && !m_ignoreRowSelection) + if (index.isValid()) { if (m_model->item(index.row(), Column::FILE) == nullptr) { @@ -267,9 +267,7 @@ void QtErrorView::setErrorId(Id errorId) if (items.size() == 1) { - m_ignoreRowSelection = true; m_table->selectRow(items.at(0)->row()); - m_ignoreRowSelection = false; } }); } diff --git a/src/lib_gui/qt/view/QtErrorView.h b/src/lib_gui/qt/view/QtErrorView.h index 1b33e617..e8d23e19 100644 --- a/src/lib_gui/qt/view/QtErrorView.h +++ b/src/lib_gui/qt/view/QtErrorView.h @@ -48,7 +48,7 @@ private slots: void errorFilterChanged(int i = 0); private: - enum Column + enum Column { ID = 0, TYPE = 1, @@ -88,8 +88,6 @@ private: QStandardItemModel* m_model; QtTable* m_table; - - bool m_ignoreRowSelection; }; #endif // QT_ERROR_VIEW_H diff --git a/src/lib_gui/qt/view/QtGraphView.cpp b/src/lib_gui/qt/view/QtGraphView.cpp index 197d15d9..2ac1f006 100644 --- a/src/lib_gui/qt/view/QtGraphView.cpp +++ b/src/lib_gui/qt/view/QtGraphView.cpp @@ -287,6 +287,11 @@ void QtGraphView::deactivateMatch(size_t matchIndex) void QtGraphView::clearMatches() { + if (m_matchedNodes.empty()) + { + return; + } + m_onQtThread( [this]() { @@ -384,7 +389,7 @@ void QtGraphView::rebuildGraph( m_scrollToTop = params.scrollToTop; m_isIndexedList = params.isIndexedList; - if (params.animatedTransition && ApplicationSettings::getInstance()->getUseAnimations()) + if (params.animatedTransition && ApplicationSettings::getInstance()->getUseAnimations() && view->isVisible()) { createTransition(); } @@ -755,7 +760,7 @@ void QtGraphView::groupingUpdated(QPushButton* button) void QtGraphView::performScroll(QScrollBar* scrollBar, int value) const { - if (ApplicationSettings::getInstance()->getUseAnimations()) + if (ApplicationSettings::getInstance()->getUseAnimations() && getView()->isVisible()) { QPropertyAnimation* anim = new QPropertyAnimation(scrollBar, "value"); anim->setDuration(300); diff --git a/src/lib_gui/qt/view/QtMainView.cpp b/src/lib_gui/qt/view/QtMainView.cpp index 8abb9696..a6d8d7c0 100644 --- a/src/lib_gui/qt/view/QtMainView.cpp +++ b/src/lib_gui/qt/view/QtMainView.cpp @@ -3,7 +3,8 @@ #include "QtViewWidgetWrapper.h" #include "QtMainWindow.h" -QtMainView::QtMainView() +QtMainView::QtMainView(const ViewFactory* viewFactory, StorageAccess* storageAccess) + : MainView(viewFactory, storageAccess) { m_window = std::make_shared(); m_window->show(); @@ -11,6 +12,8 @@ QtMainView::QtMainView() QtMainView::~QtMainView() { + // clear components to avoid double deletion of views when destroying m_window + m_componentManager.clear(); } QtMainWindow* QtMainView::getMainWindow() const @@ -24,6 +27,11 @@ void QtMainView::addView(View* view) m_window->addView(view); } +void QtMainView::overrideView(View* view) +{ + m_window->overrideView(view); +} + void QtMainView::removeView(View* view) { std::vector::iterator it = std::find(m_views.begin(), m_views.end(), view); @@ -72,6 +80,14 @@ View* QtMainView::findFloatingView(const std::string& name) const return m_window->findFloatingView(name); } +void QtMainView::showOriginalViews() +{ + for (View* view : m_views) + { + m_window->overrideView(view); + } +} + void QtMainView::loadLayout() { m_window->loadLayout(); @@ -157,12 +173,22 @@ void QtMainView::updateRecentProjectMenu() ); } -void QtMainView::updateHistoryMenu(const std::vector>& historyMenuItems) +void QtMainView::updateHistoryMenu(std::shared_ptr message) { m_onQtThread( [=]() { - m_window->updateHistoryMenu(historyMenuItems); + m_window->updateHistoryMenu(message); + } + ); +} + +void QtMainView::clearHistoryMenu() +{ + m_onQtThread( + [=]() + { + m_window->clearHistoryMenu(); } ); } @@ -177,6 +203,11 @@ void QtMainView::updateBookmarksMenu(const std::vector ); } +void QtMainView::clearBookmarksMenu() +{ + updateBookmarksMenu({}); +} + void QtMainView::handleMessage(MessageForceEnterLicense* message) { LicenseChecker::LicenseState state = message->state; diff --git a/src/lib_gui/qt/view/QtMainView.h b/src/lib_gui/qt/view/QtMainView.h index 337931a9..a42ce52b 100644 --- a/src/lib_gui/qt/view/QtMainView.h +++ b/src/lib_gui/qt/view/QtMainView.h @@ -24,45 +24,52 @@ class QtMainView , public MessageListener { public: - QtMainView(); + QtMainView(const ViewFactory* viewFactory, StorageAccess* storageAccess); virtual ~QtMainView(); QtMainWindow* getMainWindow() const; // ViewLayout implementation - virtual void addView(View* view); - virtual void removeView(View* view); + void addView(View* view) override; + void overrideView(View* view) override; + void removeView(View* view) override; - virtual void showView(View* view); - virtual void hideView(View* view); + void showView(View* view) override; + void hideView(View* view) override; - virtual void setViewEnabled(View* view, bool enabled); + void setViewEnabled(View* view, bool enabled) override; - virtual View* findFloatingView(const std::string& name) const; + View* findFloatingView(const std::string& name) const override; - virtual QStatusBar* getStatusBar(); - virtual void setStatusBar(QStatusBar* statusBar); + void showOriginalViews() override; + + QStatusBar* getStatusBar(); + void setStatusBar(QStatusBar* statusBar); // MainView implementation - virtual void loadLayout(); - virtual void saveLayout(); + void loadLayout() override; + void saveLayout() override; - virtual void loadWindow(bool showStartWindow); + void loadWindow(bool showStartWindow) override; - virtual void refreshView(); + void refreshView() override; - virtual void hideStartScreen(); - virtual void setTitle(const std::wstring& title); - virtual void activateWindow(); + void hideStartScreen() override; + void setTitle(const std::wstring& title) override; + void activateWindow() override; - virtual void updateRecentProjectMenu(); - virtual void updateHistoryMenu(const std::vector>& historyMenuItems); - virtual void updateBookmarksMenu(const std::vector>& bookmarks); + void updateRecentProjectMenu() override; + + void updateHistoryMenu(std::shared_ptr message) override; + void clearHistoryMenu() override; + + void updateBookmarksMenu(const std::vector>& bookmarks) override; + void clearBookmarksMenu() override; private: - void handleMessage(MessageForceEnterLicense* message); - void handleMessage(MessageProjectEdit* message); - void handleMessage(MessageProjectNew* message); + void handleMessage(MessageForceEnterLicense* message) override; + void handleMessage(MessageProjectEdit* message) override; + void handleMessage(MessageProjectNew* message) override; std::shared_ptr m_window; std::vector m_views; diff --git a/src/lib_gui/qt/view/QtScreenSearchView.cpp b/src/lib_gui/qt/view/QtScreenSearchView.cpp index 05ceab4c..c51c46f8 100644 --- a/src/lib_gui/qt/view/QtScreenSearchView.cpp +++ b/src/lib_gui/qt/view/QtScreenSearchView.cpp @@ -3,15 +3,16 @@ #include #include "QtScreenSearchBox.h" -#include "utilityQt.h" #include "QtMainView.h" #include "QtViewWidgetWrapper.h" #include "QtMainWindow.h" #include "ResourcePaths.h" +#include "TabId.h" +#include "utilityQt.h" QtScreenSearchView::QtScreenSearchView(ViewLayout* viewLayout) : ScreenSearchView(viewLayout) - , m_controllerProxy(this) + , m_controllerProxy(this, TabId::app()) { m_widget = new QtScreenSearchBox(&m_controllerProxy); diff --git a/src/lib_gui/qt/view/QtStatusBarView.cpp b/src/lib_gui/qt/view/QtStatusBarView.cpp index a366001f..ece7ad03 100644 --- a/src/lib_gui/qt/view/QtStatusBarView.cpp +++ b/src/lib_gui/qt/view/QtStatusBarView.cpp @@ -7,12 +7,10 @@ QtStatusBarView::QtStatusBarView(ViewLayout* viewLayout) : StatusBarView(viewLayout) { - m_widget = std::make_shared(); + m_widget = new QtStatusBar(); m_widget->show(); - QtMainView* mw = static_cast(viewLayout); - QStatusBar* sb = static_cast(m_widget.get()); - mw->setStatusBar(sb); + dynamic_cast(viewLayout)->setStatusBar(m_widget); } void QtStatusBarView::createWidgetWrapper() diff --git a/src/lib_gui/qt/view/QtStatusBarView.h b/src/lib_gui/qt/view/QtStatusBarView.h index 7b4b4165..486f133b 100644 --- a/src/lib_gui/qt/view/QtStatusBarView.h +++ b/src/lib_gui/qt/view/QtStatusBarView.h @@ -33,7 +33,7 @@ public: private: QtThreadedLambdaFunctor m_onQtThread; - std::shared_ptr m_widget; + QtStatusBar* m_widget; }; #endif // !QT_STATUS_BAR_VIEW_H diff --git a/src/lib_gui/qt/view/QtTabsView.cpp b/src/lib_gui/qt/view/QtTabsView.cpp new file mode 100644 index 00000000..90db9cb6 --- /dev/null +++ b/src/lib_gui/qt/view/QtTabsView.cpp @@ -0,0 +1,290 @@ +#include "QtTabsView.h" + +#include +#include +#include +#include + +#include "Application.h" +#include "ColorScheme.h" +#include "GraphViewStyle.h" +#include "QtIconButton.h" +#include "QtTabBar.h" +#include "QtViewWidgetWrapper.h" +#include "ResourcePaths.h" +#include "TabId.h" +#include "TabsController.h" +#include "utilityQt.h" + +QtTabsView::QtTabsView(ViewLayout* viewLayout) + : TabsView(viewLayout) + , m_widget(nullptr) + , m_insertedTabCount(0) +{ +} + +void QtTabsView::createWidgetWrapper() +{ + m_widget = new QWidget(); + setWidgetWrapper(std::make_shared(m_widget)); +} + +void QtTabsView::initView() +{ + QHBoxLayout* layout = new QHBoxLayout(m_widget); + layout->setContentsMargins(0, 0, 0, 0); + layout->setSpacing(0); + + QWidget* front = new QWidget(); + front->setMinimumWidth(5); + front->setObjectName("side_area"); + layout->addWidget(front); + + m_tabBar = new QtTabBar(); + m_tabBar->setDrawBase(false); + m_tabBar->setMinimumWidth(0); + m_tabBar->setMovable(true); + m_tabBar->setElideMode(Qt::ElideMiddle); + layout->addWidget(m_tabBar); + + connect(m_tabBar, &QTabBar::currentChanged, this, &QtTabsView::changedTab); + + QPushButton* addButton = new QtSelfRefreshIconButton( + "", ResourcePaths::getGuiPath().concatenate(L"tabs_view/images/add.png"), "tab/bar/button"); + addButton->setObjectName("add_button"); + addButton->setIconSize(QSize(14, 14)); + + QWidget* back = new QWidget(); + back->setObjectName("side_area"); + QHBoxLayout* backLayout = new QHBoxLayout(back); + backLayout->setContentsMargins(3, 0, 5, 0); + backLayout->setSpacing(0); + backLayout->addWidget(addButton); + backLayout->addStretch(); + layout->addWidget(back); + + connect(addButton, &QPushButton::clicked, this, &QtTabsView::addTab); +} + +void QtTabsView::refreshView() +{ + m_onQtThread([=]() + { + setStyleSheet(); + }); +} + +void QtTabsView::clear() +{ + m_onQtThread([=]() + { + getController()->onClearTabs(); + + m_tabBar->blockSignals(true); + + int c = m_tabBar->count(); + for (int i = c - 1; i >= 0; i--) + { + removeTab(i); + } + + m_tabBar->blockSignals(false); + }); +} + +void QtTabsView::openTab(bool showTab, SearchMatch match) +{ + m_onQtThread([=]() + { + insertTab(showTab, match); + }); +} + +void QtTabsView::closeTab() +{ + m_onQtThread([=]() + { + removeTab(m_tabBar->currentIndex()); + }); +} + +void QtTabsView::destroyTab(Id tabId) +{ + m_onQtThread([=]() + { + getController()->destroyTab(tabId); + }); +} + +void QtTabsView::selectTab(bool next) +{ + m_onQtThread([=]() + { + int idx = m_tabBar->currentIndex(); + if (idx != -1) + { + idx += next ? 1 : -1; + m_tabBar->setCurrentIndex((idx + m_tabBar->count()) % m_tabBar->count()); + } + }); +} + +void QtTabsView::updateTab(Id tabId, std::vector matches) +{ + m_onQtThread([=]() + { + for (int i = 0; i < m_tabBar->count(); i++) + { + if (m_tabBar->tabData(i).toInt() == int(tabId)) + { + setTabState(i, matches); + return; + } + } + }); +} + +void QtTabsView::addTab() +{ + if (Application::getInstance()->isProjectLoaded()) + { + insertTab(true, SearchMatch()); + } +} + +void QtTabsView::insertTab(bool showTab, SearchMatch match) +{ + int tabId = TabId::nextTab(); + + m_tabBar->blockSignals(true); + + m_insertedTabCount++; + int idx = match.isValid() ? m_tabBar->currentIndex() + m_insertedTabCount : m_tabBar->count() + 1; + idx = m_tabBar->insertTab(idx, " Empty Tab "); + m_tabBar->setTabData(idx, QVariant(tabId)); + + QPushButton* typeCircle = new QPushButton(); + typeCircle->setObjectName("type_circle"); + m_tabBar->setTabButton(idx, QTabBar::LeftSide, typeCircle); + + connect(typeCircle, &QPushButton::clicked, + [tabId, this]() + { + for (int i = 0; i < m_tabBar->count(); i++) + { + if (m_tabBar->tabData(i).toInt() == tabId) + { + m_tabBar->setCurrentIndex(i); + return; + } + } + } + ); + + QPushButton* closeButton = new QtSelfRefreshIconButton( + "", ResourcePaths::getGuiPath().concatenate(L"tabs_view/images/close.png"), "tab/bar/button"); + closeButton->setObjectName("close_button"); + closeButton->setIconSize(QSize(10, 10)); + m_tabBar->setTabButton(idx, QTabBar::RightSide, closeButton); + + connect(closeButton, &QPushButton::clicked, + [tabId, this]() + { + for (int i = 0; i < m_tabBar->count(); i++) + { + if (m_tabBar->tabData(i).toInt() == tabId) + { + removeTab(i); + return; + } + } + } + ); + + m_tabBar->blockSignals(false); + + getController()->addTab(tabId, match); + + if (m_tabBar->count() == 1) + { + changedTab(m_tabBar->currentIndex()); + } + else if (showTab) + { + m_tabBar->setCurrentIndex(idx); + } + + setTabState(idx, { }); +} + +void QtTabsView::changedTab(int index) +{ + m_insertedTabCount = 0; + + getController()->showTab(m_tabBar->tabData(index).toInt()); + + for (int i = 0; i < m_tabBar->count(); i++) + { + QWidget* circle = m_tabBar->tabButton(i, QTabBar::LeftSide); + bool selected = (i == index); + if (circle->property("selected").toBool() != selected) + { + circle->setProperty("selected", selected); + circle->style()->unpolish(circle); + circle->style()->polish(circle); + } + } +} + +void QtTabsView::removeTab(int index) +{ + m_insertedTabCount = 0; + + getController()->removeTab(m_tabBar->tabData(index).toInt()); + m_tabBar->removeTab(index); +} + +void QtTabsView::setTabState(int idx, const std::vector& matches) +{ + ColorScheme* scheme = ColorScheme::getInstance().get(); + std::wstring name; + std::string color; + std::string activeColor; + + if (matches.size()) + { + const SearchMatch& match = matches[0]; + name = match.getFullName(); + + if (match.searchType == SearchMatch::SEARCH_TOKEN) + { + color = GraphViewStyle::getNodeColor(match.nodeType.getUnderscoredTypeString(), false).fill; + activeColor = GraphViewStyle::getNodeColor(match.nodeType.getUnderscoredTypeString(), true).fill; + } + else + { + color = scheme->getSearchTypeColor(utility::encodeToUtf8(match.getSearchTypeName()), "fill"); + activeColor = scheme->getSearchTypeColor(utility::encodeToUtf8(match.getSearchTypeName()), "fill", "hover"); + } + } + else + { + name = L"Empty Tab"; + color = scheme->getColor("tab/bar/button/background/press"); + activeColor = color; + } + + m_tabBar->setTabText(idx, ' ' + QString::fromStdWString(name) + ' '); + m_tabBar->tabButton(idx, QTabBar::LeftSide)->setStyleSheet( + "#type_circle { background-color: " + QString::fromStdString(color) + "; } " + "#type_circle[selected=true] { background-color: " + QString::fromStdString(activeColor) + "; } " + ); +} + +void QtTabsView::setStyleSheet() +{ + const std::string css = utility::getStyleSheet(ResourcePaths::getGuiPath().concatenate(L"tabs_view/tabs_view.css")); + m_widget->setStyleSheet(css.c_str()); + + utility::setWidgetBackgroundColor(m_widget, ColorScheme::getInstance()->getColor("tab/bar/background")); +} diff --git a/src/lib_gui/qt/view/QtTabsView.h b/src/lib_gui/qt/view/QtTabsView.h new file mode 100644 index 00000000..5b55d714 --- /dev/null +++ b/src/lib_gui/qt/view/QtTabsView.h @@ -0,0 +1,54 @@ +#ifndef QT_TABS_VIEW_H +#define QT_TABS_VIEW_H + +#include + +#include "TabsController.h" +#include "TabsView.h" +#include "QtThreadedFunctor.h" + +class QtTabBar; + +class QtTabsView + : public QObject + , public TabsView +{ + Q_OBJECT + +public: + QtTabsView(ViewLayout* viewLayout); + virtual ~QtTabsView() = default; + + // View implementation + void createWidgetWrapper() override; + void initView() override; + void refreshView() override; + + // TabsView implementation + void clear() override; + void openTab(bool showTab, SearchMatch match) override; + void closeTab() override; + void destroyTab(Id tabId) override; + void selectTab(bool next) override; + void updateTab(Id tabId, std::vector matches) override; + +private slots: + void addTab(); + void insertTab(bool showTab, SearchMatch match); + void changedTab(int index); + void removeTab(int index); + +private: + void setTabState(int idx, const std::vector& matches); + + void setStyleSheet(); + + QtThreadedLambdaFunctor m_onQtThread; + + QWidget* m_widget; + QtTabBar* m_tabBar; + + size_t m_insertedTabCount; +}; + +#endif // QT_TABS_VIEW_H diff --git a/src/lib_gui/qt/view/QtViewFactory.cpp b/src/lib_gui/qt/view/QtViewFactory.cpp index 5a088e93..fc96f01d 100644 --- a/src/lib_gui/qt/view/QtViewFactory.cpp +++ b/src/lib_gui/qt/view/QtViewFactory.cpp @@ -1,6 +1,7 @@ #include "QtViewFactory.h" #include "GraphViewStyle.h" +#include "QtBookmarkButtonsView.h" #include "QtBookmarkView.h" #include "QtCodeView.h" #include "QtCompositeView.h" @@ -15,6 +16,7 @@ #include "QtStatusBarView.h" #include "QtStatusView.h" #include "QtTabbedView.h" +#include "QtTabsView.h" #include "QtTooltipView.h" #include "QtUndoRedoView.h" @@ -22,9 +24,9 @@ QtViewFactory::QtViewFactory() { } -std::shared_ptr QtViewFactory::createMainView() const +std::shared_ptr QtViewFactory::createMainView(StorageAccess* storageAccess) const { - return std::make_shared(); + return std::make_shared(this, storageAccess); } std::shared_ptr QtViewFactory::createCompositeView( @@ -44,9 +46,14 @@ std::shared_ptr QtViewFactory::createTabbedView(ViewLayout* viewLayo return ptr; } +std::shared_ptr QtViewFactory::createBookmarkButtonsView(ViewLayout* viewLayout) const +{ + return View::createInitAndAddToLayout(viewLayout); +} + std::shared_ptr QtViewFactory::createBookmarkView(ViewLayout* viewLayout) const { - return View::createInitAndAddToLayout(viewLayout); + return View::createAndInit(viewLayout); } std::shared_ptr QtViewFactory::createCodeView(ViewLayout* viewLayout) const @@ -66,7 +73,6 @@ std::shared_ptr QtViewFactory::createStatusView(ViewLayout* viewLayo std::shared_ptr QtViewFactory::createGraphView(ViewLayout* viewLayout) const { - GraphViewStyle::setImpl(std::make_shared()); return View::createInitAndAddToLayout(viewLayout); } @@ -90,6 +96,11 @@ std::shared_ptr QtViewFactory::createStatusBarView(ViewLayout* vi return View::createAndInit(viewLayout); } +std::shared_ptr QtViewFactory::createTabsView(ViewLayout* viewLayout) const +{ + return View::createInitAndAddToLayout(viewLayout); +} + std::shared_ptr QtViewFactory::createTooltipView(ViewLayout* viewLayout) const { return View::createAndInit(viewLayout); @@ -105,3 +116,8 @@ std::shared_ptr QtViewFactory::createDialogView( { return std::make_shared(dynamic_cast(viewLayout)->getMainWindow(), useCase, storageAccess); } + +std::shared_ptr QtViewFactory::createGraphStyleImpl() const +{ + return std::make_shared(); +} diff --git a/src/lib_gui/qt/view/QtViewFactory.h b/src/lib_gui/qt/view/QtViewFactory.h index 698c00f3..f42451b7 100644 --- a/src/lib_gui/qt/view/QtViewFactory.h +++ b/src/lib_gui/qt/view/QtViewFactory.h @@ -10,11 +10,12 @@ public: QtViewFactory(); virtual ~QtViewFactory() = default; - virtual std::shared_ptr createMainView() const; + virtual std::shared_ptr createMainView(StorageAccess* storageAccess) const; virtual std::shared_ptr createCompositeView( ViewLayout* viewLayout, CompositeView::CompositeDirection direction, const std::string& name) const; virtual std::shared_ptr createTabbedView(ViewLayout* viewLayout, const std::string& name) const; + virtual std::shared_ptr createBookmarkButtonsView(ViewLayout* viewLayout) const; virtual std::shared_ptr createBookmarkView(ViewLayout* viewLayout) const; virtual std::shared_ptr createCodeView(ViewLayout* viewLayout) const; virtual std::shared_ptr createErrorView(ViewLayout* viewLayout) const; @@ -24,11 +25,14 @@ public: virtual std::shared_ptr createSearchView(ViewLayout* viewLayout) const; virtual std::shared_ptr createStatusBarView(ViewLayout* viewLayout) const; virtual std::shared_ptr createStatusView(ViewLayout* viewLayout) const; + virtual std::shared_ptr createTabsView(ViewLayout* viewLayout) const; virtual std::shared_ptr createTooltipView(ViewLayout* viewLayout) const; virtual std::shared_ptr createUndoRedoView(ViewLayout* viewLayout) const; virtual std::shared_ptr createDialogView( ViewLayout* viewLayout, DialogView::UseCase useCase, StorageAccess* storageAccess) const; + + virtual std::shared_ptr createGraphStyleImpl() const; }; #endif // QT_VIEW_FACTORY_H diff --git a/src/lib_gui/qt/view/QtViewWidgetWrapper.cpp b/src/lib_gui/qt/view/QtViewWidgetWrapper.cpp index 9d014361..d8cfce29 100644 --- a/src/lib_gui/qt/view/QtViewWidgetWrapper.cpp +++ b/src/lib_gui/qt/view/QtViewWidgetWrapper.cpp @@ -29,6 +29,8 @@ QtViewWidgetWrapper::QtViewWidgetWrapper(QWidget* widget) QtViewWidgetWrapper::~QtViewWidgetWrapper() { + m_widget->hide(); + m_widget->deleteLater(); } QWidget* QtViewWidgetWrapper::getWidget() diff --git a/src/lib_gui/qt/view/graphElements/QtGraphNode.cpp b/src/lib_gui/qt/view/graphElements/QtGraphNode.cpp index feed8831..b5289d88 100644 --- a/src/lib_gui/qt/view/graphElements/QtGraphNode.cpp +++ b/src/lib_gui/qt/view/graphElements/QtGraphNode.cpp @@ -382,6 +382,10 @@ void QtGraphNode::onClick() { } +void QtGraphNode::onMiddleClick() +{ +} + void QtGraphNode::onHide() { Id tokenId = getTokenId(); @@ -431,11 +435,6 @@ void QtGraphNode::mousePressEvent(QGraphicsSceneMouseEvent* event) { event->ignore(); - if (event->button() != Qt::LeftButton) - { - return; - } - for (std::shared_ptr component : m_components) { component->nodeMousePressEvent(event); @@ -474,11 +473,6 @@ void QtGraphNode::mouseReleaseEvent(QGraphicsSceneMouseEvent* event) { event->ignore(); - if (event->button() != Qt::LeftButton) - { - return; - } - for (std::shared_ptr component : m_components) { component->nodeMouseReleaseEvent(event); diff --git a/src/lib_gui/qt/view/graphElements/QtGraphNode.h b/src/lib_gui/qt/view/graphElements/QtGraphNode.h index 38887fb0..8b6699f2 100644 --- a/src/lib_gui/qt/view/graphElements/QtGraphNode.h +++ b/src/lib_gui/qt/view/graphElements/QtGraphNode.h @@ -95,6 +95,7 @@ public: virtual void addSubNode(QtGraphNode* node); virtual void onClick(); + virtual void onMiddleClick(); void onHide(); void onCollapseExpand(); diff --git a/src/lib_gui/qt/view/graphElements/QtGraphNodeData.cpp b/src/lib_gui/qt/view/graphElements/QtGraphNodeData.cpp index ee5cabbc..bafa6ce6 100644 --- a/src/lib_gui/qt/view/graphElements/QtGraphNodeData.cpp +++ b/src/lib_gui/qt/view/graphElements/QtGraphNodeData.cpp @@ -5,6 +5,7 @@ #include "MessageDeactivateEdge.h" #include "MessageFocusIn.h" #include "MessageFocusOut.h" +#include "MessageTabOpenWith.h" #include "MessageTooltipShow.h" #include "ResourcePaths.h" @@ -61,6 +62,11 @@ void QtGraphNodeData::onClick() MessageActivateNodes(m_data->getId()).dispatch(); } +void QtGraphNodeData::onMiddleClick() +{ + MessageTabOpenWith(m_data->getId()).dispatch(); +} + void QtGraphNodeData::updateStyle() { GraphViewStyle::NodeStyle style = GraphViewStyle::getStyleForNodeType( diff --git a/src/lib_gui/qt/view/graphElements/QtGraphNodeData.h b/src/lib_gui/qt/view/graphElements/QtGraphNodeData.h index 124d1a6f..74fd1f5a 100644 --- a/src/lib_gui/qt/view/graphElements/QtGraphNodeData.h +++ b/src/lib_gui/qt/view/graphElements/QtGraphNodeData.h @@ -22,6 +22,7 @@ public: virtual Id getTokenId() const; virtual void onClick(); + virtual void onMiddleClick(); virtual void updateStyle(); protected: diff --git a/src/lib_gui/qt/view/graphElements/nodeComponents/QtGraphNodeComponentClickable.cpp b/src/lib_gui/qt/view/graphElements/nodeComponents/QtGraphNodeComponentClickable.cpp index a2d36367..daaefc38 100644 --- a/src/lib_gui/qt/view/graphElements/nodeComponents/QtGraphNodeComponentClickable.cpp +++ b/src/lib_gui/qt/view/graphElements/nodeComponents/QtGraphNodeComponentClickable.cpp @@ -17,8 +17,15 @@ QtGraphNodeComponentClickable::~QtGraphNodeComponentClickable() void QtGraphNodeComponentClickable::nodeMousePressEvent(QGraphicsSceneMouseEvent* event) { + if (event->button() != Qt::LeftButton && event->button() != Qt::MiddleButton) + { + return; + } + m_mousePos = Vec2i(event->scenePos().x(), event->scenePos().y()); m_mouseMoved = false; + + event->accept(); } void QtGraphNodeComponentClickable::nodeMouseMoveEvent(QGraphicsSceneMouseEvent* event) @@ -33,23 +40,35 @@ void QtGraphNodeComponentClickable::nodeMouseMoveEvent(QGraphicsSceneMouseEvent* void QtGraphNodeComponentClickable::nodeMouseReleaseEvent(QGraphicsSceneMouseEvent* event) { + if (event->button() != Qt::LeftButton && event->button() != Qt::MiddleButton) + { + return; + } + if (!m_mouseMoved) { - if (event->modifiers() & Qt::AltModifier) + if (event->modifiers() & Qt::AltModifier && event->button() == Qt::LeftButton) { m_graphNode->onHide(); } - else if (event->modifiers() & Qt::ShiftModifier) + else if (event->modifiers() & Qt::ShiftModifier && event->button() == Qt::LeftButton) { m_graphNode->onCollapseExpand(); } - else if (event->modifiers() & Qt::ControlModifier) + else if (event->modifiers() & Qt::ControlModifier && event->button() == Qt::LeftButton) { m_graphNode->onShowDefinition(); } else { - m_graphNode->onClick(); + if (event->button() == Qt::MiddleButton) + { + m_graphNode->onMiddleClick(); + } + else + { + m_graphNode->onClick(); + } } event->accept(); } diff --git a/src/lib_gui/qt/view/graphElements/nodeComponents/QtGraphNodeComponentMoveable.cpp b/src/lib_gui/qt/view/graphElements/nodeComponents/QtGraphNodeComponentMoveable.cpp index d93f8eb0..f401966f 100644 --- a/src/lib_gui/qt/view/graphElements/nodeComponents/QtGraphNodeComponentMoveable.cpp +++ b/src/lib_gui/qt/view/graphElements/nodeComponents/QtGraphNodeComponentMoveable.cpp @@ -16,6 +16,11 @@ QtGraphNodeComponentMoveable::~QtGraphNodeComponentMoveable() void QtGraphNodeComponentMoveable::nodeMousePressEvent(QGraphicsSceneMouseEvent* event) { + if (event->button() != Qt::LeftButton) + { + return; + } + m_oldPos = m_graphNode->getPosition(); m_mouseOffset.x = event->scenePos().x() - m_oldPos.x; m_mouseOffset.y = event->scenePos().y() - m_oldPos.y; @@ -25,12 +30,22 @@ void QtGraphNodeComponentMoveable::nodeMousePressEvent(QGraphicsSceneMouseEvent* void QtGraphNodeComponentMoveable::nodeMouseMoveEvent(QGraphicsSceneMouseEvent* event) { + if (event->button() != Qt::LeftButton) + { + return; + } + m_graphNode->setPosition(Vec2i(event->scenePos().x() - m_mouseOffset.x, event->scenePos().y() - m_mouseOffset.y)); event->accept(); } void QtGraphNodeComponentMoveable::nodeMouseReleaseEvent(QGraphicsSceneMouseEvent* event) { + if (event->button() != Qt::LeftButton) + { + return; + } + if (event->isAccepted()) { return; diff --git a/src/lib_gui/qt/window/QtMainWindow.cpp b/src/lib_gui/qt/window/QtMainWindow.cpp index a7333201..9a9881af 100644 --- a/src/lib_gui/qt/window/QtMainWindow.cpp +++ b/src/lib_gui/qt/window/QtMainWindow.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include "Application.h" #include "CompositeView.h" @@ -33,10 +34,10 @@ #include "MessageHistoryUndo.h" #include "MessageActivateAll.h" #include "MessageActivateBase.h" -#include "MessageActivateBookmark.h" +#include "MessageBookmarkActivate.h" +#include "MessageBookmarkBrowse.h" +#include "MessageBookmarkCreate.h" #include "MessageCodeReference.h" -#include "MessageDisplayBookmarkCreator.h" -#include "MessageDisplayBookmarks.h" #include "MessageEnteredLicense.h" #include "MessageFind.h" #include "MessageIndexingShowDialog.h" @@ -45,6 +46,9 @@ #include "MessageRefresh.h" #include "MessageRefreshUI.h" #include "MessageResetZoom.h" +#include "MessageTabClose.h" +#include "MessageTabOpen.h" +#include "MessageTabSelect.h" #include "MessageWindowClosed.h" #include "MessageZoom.h" #include "ResourcePaths.h" @@ -150,12 +154,30 @@ QtMainWindow::~QtMainWindow() void QtMainWindow::addView(View* view) { - QDockWidget* dock = new QDockWidget(tr(view->getName().c_str()), this); - dock->setWidget(QtViewWidgetWrapper::getWidgetOfView(view)); - dock->setObjectName(QString::fromStdString("Dock" + view->getName())); + const QString name = QString::fromStdString(view->getName()); + if (name == "Tabs") + { + QToolBar* toolBar = new QToolBar(); + toolBar->setObjectName("Tool" + name); + toolBar->setMovable(false); + toolBar->setFloatable(false); + toolBar->setStyleSheet("* { margin: 0; }"); + toolBar->addWidget(QtViewWidgetWrapper::getWidgetOfView(view)); + addToolBar(toolBar); + return; + } + + QDockWidget* dock = new QDockWidget(name, this); + dock->setObjectName("Dock" + name); + + dock->setWidget(new QWidget()); + QVBoxLayout* layout = new QVBoxLayout(dock->widget()); + layout->setContentsMargins(0, 0, 0, 0); + layout->setSpacing(0); + layout->addWidget(QtViewWidgetWrapper::getWidgetOfView(view)); // Disable un-intended vertical growth of search widget - if (view->getName() == "Search") + if (name == "Search") { dock->setSizePolicy(dock->sizePolicy().horizontalPolicy(), QSizePolicy::Fixed); } @@ -171,7 +193,7 @@ void QtMainWindow::addView(View* view) QtViewToggle* toggle = new QtViewToggle(view, this); connect(dock, &QDockWidget::visibilityChanged, toggle, &QtViewToggle::toggledByUI); - QAction* action = new QAction(tr((view->getName() + " Window").c_str()), this); + QAction* action = new QAction(name + " Window", this); action->setCheckable(true); connect(action, &QAction::triggered, toggle, &QtViewToggle::toggledByAction); m_viewMenu->insertAction(m_viewSeparator, action); @@ -185,6 +207,44 @@ void QtMainWindow::addView(View* view) m_dockWidgets.push_back(dockWidget); } +void QtMainWindow::overrideView(View* view) +{ + const QString name = QString::fromStdString(view->getName()); + if (name == "Tabs") + { + return; + } + + QDockWidget* dock = nullptr; + for (const DockWidget& dockWidget : m_dockWidgets) + { + if (dockWidget.widget->windowTitle() == name) + { + dock = dockWidget.widget; + break; + } + } + + if (!dock) + { + LOG_ERROR_STREAM(<< "Couldn't find view to override: " << name.toStdString()); + return; + } + + QWidget* oldWidget = dock->widget()->layout()->itemAt(0)->widget(); + QWidget* newWidget = QtViewWidgetWrapper::getWidgetOfView(view); + + if (oldWidget == newWidget) + { + return; + } + + oldWidget = dock->widget()->layout()->takeAt(0)->widget(); + oldWidget->hide(); + dock->widget()->layout()->addWidget(newWidget); + newWidget->show(); +} + void QtMainWindow::removeView(View* view) { for (size_t i = 0; i < m_dockWidgets.size(); i++) @@ -347,9 +407,41 @@ void QtMainWindow::forceEnterLicense(LicenseChecker::LicenseState state) connect(window, &QtWindow::canceled, dynamic_cast(QCoreApplication::instance()), &QApplication::quit); } -void QtMainWindow::updateHistoryMenu(const std::vector>& historyMenuItems) +void QtMainWindow::updateHistoryMenu(std::shared_ptr message) { - m_history = historyMenuItems; + const size_t historyMenuSize = 20; + + if (message && dynamic_cast(message.get())) + { + std::vector matches = dynamic_cast(message.get())->getSearchMatches(); + if (matches.size() && !matches[0].text.empty()) + { + std::vector> history = { message }; + std::set uniqueMatches = { matches[0] }; + + for (std::shared_ptr m : m_history) + { + if (uniqueMatches.insert(dynamic_cast(m.get())->getSearchMatches()[0]).second) + { + history.push_back(m); + + if (history.size() >= historyMenuSize) + { + break; + } + } + } + + m_history = history; + } + } + + setupHistoryMenu(); +} + +void QtMainWindow::clearHistoryMenu() +{ + m_history.clear(); setupHistoryMenu(); } @@ -426,6 +518,7 @@ void QtMainWindow::keyPressEvent(QKeyEvent* event) void QtMainWindow::contextMenuEvent(QContextMenuEvent* event) { QtContextMenu menu(event, this); + menu.addUndoActions(); menu.show(); } @@ -549,6 +642,26 @@ void QtMainWindow::showLogFolder() QDesktopServices::openUrl(QUrl(QString::fromStdWString(L"file:///" + UserPaths::getLogPath().makeCanonical().wstr()), QUrl::TolerantMode)); } +void QtMainWindow::openTab() +{ + MessageTabOpen().dispatch(); +} + +void QtMainWindow::closeTab() +{ + MessageTabClose().dispatch(); +} + +void QtMainWindow::nextTab() +{ + MessageTabSelect(true).dispatch(); +} + +void QtMainWindow::previousTab() +{ + MessageTabSelect(false).dispatch(); +} + void QtMainWindow::showStartScreen() { if (dynamic_cast(m_windowStack.getTopWindow())) @@ -757,12 +870,12 @@ void QtMainWindow::toggleShowDockWidgetTitleBars() void QtMainWindow::showBookmarkCreator() { - MessageDisplayBookmarkCreator().dispatch(); + MessageBookmarkCreate().dispatch(); } void QtMainWindow::showBookmarkBrowser() { - MessageDisplayBookmarks().dispatch(); + MessageBookmarkBrowse().dispatch(); } void QtMainWindow::openHistoryAction() @@ -771,6 +884,7 @@ void QtMainWindow::openHistoryAction() if (action) { std::shared_ptr m = m_history[action->data().toInt()]; + m->setSchedulerId(TabId::currentTab()); m->setIsReplayed(false); m->dispatch(); } @@ -782,7 +896,7 @@ void QtMainWindow::activateBookmarkAction() if (action) { std::shared_ptr bookmark = m_bookmarks[action->data().toInt()]; - MessageActivateBookmark(bookmark).dispatch(); + MessageBookmarkActivate(bookmark).dispatch(); } } @@ -845,9 +959,9 @@ void QtMainWindow::setupEditMenu() &QtMainWindow::codeReferencePrevious, QKeySequence(Qt::SHIFT + Qt::CTRL + Qt::Key_G)); menu->addAction(tr("Next Local Reference"), this, - &QtMainWindow::codeLocalReferenceNext, QKeySequence(Qt::CTRL + Qt::Key_T)); + &QtMainWindow::codeLocalReferenceNext, QKeySequence(Qt::CTRL + Qt::Key_E)); menu->addAction(tr("Previous Local Reference"), this, - &QtMainWindow::codeLocalReferencePrevious, QKeySequence(Qt::SHIFT + Qt::CTRL + Qt::Key_T)); + &QtMainWindow::codeLocalReferencePrevious, QKeySequence(Qt::SHIFT + Qt::CTRL + Qt::Key_E)); menu->addSeparator(); @@ -863,6 +977,22 @@ void QtMainWindow::setupViewMenu() QMenu *menu = new QMenu(tr("&View"), this); menuBar()->addMenu(menu); + menu->addAction(tr("New Tab"), this, &QtMainWindow::openTab, QKeySequence::AddTab); + menu->addAction(tr("Close Tab"), this, &QtMainWindow::closeTab, QKeySequence::Close); + + if (utility::getOsType() == OS_MAC) + { + menu->addAction(tr("Select Next Tab"), this, &QtMainWindow::nextTab, QKeySequence(Qt::META + Qt::Key_Tab)); + menu->addAction(tr("Select Previous Tab"), this, &QtMainWindow::previousTab, QKeySequence(Qt::SHIFT + Qt::META + Qt::Key_Tab)); + } + else + { + menu->addAction(tr("Select Next Tab"), this, &QtMainWindow::nextTab, QKeySequence(Qt::CTRL + Qt::Key_Tab)); + menu->addAction(tr("Select Previous Tab"), this, &QtMainWindow::previousTab, QKeySequence(Qt::SHIFT + Qt::CTRL + Qt::Key_Tab)); + } + + menu->addSeparator(); + menu->addAction(tr("Show Start Window"), this, &QtMainWindow::showStartScreen); m_showTitleBarsAction = new QAction("Show Title Bars", this); diff --git a/src/lib_gui/qt/window/QtMainWindow.h b/src/lib_gui/qt/window/QtMainWindow.h index 4a5b85b5..b402d45f 100644 --- a/src/lib_gui/qt/window/QtMainWindow.h +++ b/src/lib_gui/qt/window/QtMainWindow.h @@ -60,6 +60,7 @@ public: ~QtMainWindow(); void addView(View* view); + void overrideView(View* view); void removeView(View* view); void showView(View* view); @@ -75,7 +76,9 @@ public: void forceEnterLicense(LicenseChecker::LicenseState state); - void updateHistoryMenu(const std::vector>& historyMenuItems); + void updateHistoryMenu(std::shared_ptr message); + void clearHistoryMenu(); + void updateBookmarksMenu(const std::vector>& bookmarks); void setContentEnabled(bool enabled); @@ -111,6 +114,11 @@ public slots: void showDataFolder(); void showLogFolder(); + void openTab(); + void closeTab(); + void nextTab(); + void previousTab(); + void showStartScreen(); void hideStartScreen(); diff --git a/src/test/TaskSchedulerTestSuite.h b/src/test/TaskSchedulerTestSuite.h index ebf976c1..a3ecd53d 100644 --- a/src/test/TaskSchedulerTestSuite.h +++ b/src/test/TaskSchedulerTestSuite.h @@ -14,19 +14,20 @@ class TaskSchedulerTestSuite: public CxxTest::TestSuite public: void test_scheduler_loop_starts_and_stops(void) { - TS_ASSERT(!TaskScheduler::getInstance()->loopIsRunning()); + TaskScheduler scheduler(0); + TS_ASSERT(!scheduler.loopIsRunning()); - TaskScheduler::getInstance()->startSchedulerLoopThreaded(); + scheduler.startSchedulerLoopThreaded(); - waitForThread(); + waitForThread(scheduler); - TS_ASSERT(TaskScheduler::getInstance()->loopIsRunning()); + TS_ASSERT(scheduler.loopIsRunning()); - TaskScheduler::getInstance()->stopSchedulerLoop(); + scheduler.stopSchedulerLoop(); - waitForThread(); + waitForThread(scheduler); - TS_ASSERT(!TaskScheduler::getInstance()->loopIsRunning()); + TS_ASSERT(!scheduler.loopIsRunning()); } void test_tasks_get_executed_without_scheduling_in_correct_order(void) @@ -45,16 +46,17 @@ public: void test_scheduled_tasks_get_processed_with_callbacks_in_correct_order(void) { - TaskScheduler::getInstance()->startSchedulerLoopThreaded(); + TaskScheduler scheduler(0); + scheduler.startSchedulerLoopThreaded(); int order = 0; std::shared_ptr task = std::make_shared(&order, 1); - Task::dispatch(task); + scheduler.pushTask(task); - waitForThread(); + waitForThread(scheduler); - TaskScheduler::getInstance()->stopSchedulerLoop(); + scheduler.stopSchedulerLoop(); TS_ASSERT_EQUALS(3, order); @@ -65,7 +67,8 @@ public: void test_sequential_task_group_to_process_tasks_in_correct_order(void) { - TaskScheduler::getInstance()->startSchedulerLoopThreaded(); + TaskScheduler scheduler(0); + scheduler.startSchedulerLoopThreaded(); int order = 0; std::shared_ptr task1 = std::make_shared(&order, 1); @@ -75,11 +78,11 @@ public: taskGroup->addTask(task1); taskGroup->addTask(task2); - Task::dispatch(taskGroup); + scheduler.pushTask(taskGroup); - waitForThread(); + waitForThread(scheduler); - TaskScheduler::getInstance()->stopSchedulerLoop(); + scheduler.stopSchedulerLoop(); TS_ASSERT_EQUALS(6, order); @@ -94,7 +97,8 @@ public: void test_sequential_task_group_does_not_evaluate_tasks_after_failure(void) { - TaskScheduler::getInstance()->startSchedulerLoopThreaded(); + TaskScheduler scheduler(0); + scheduler.startSchedulerLoopThreaded(); int order = 0; std::shared_ptr task1 = std::make_shared(&order, 1, Task::STATE_FAILURE); @@ -104,11 +108,11 @@ public: taskGroup->addTask(task1); taskGroup->addTask(task2); - Task::dispatch(taskGroup); + scheduler.pushTask(taskGroup); - waitForThread(); + waitForThread(scheduler); - TaskScheduler::getInstance()->stopSchedulerLoop(); + scheduler.stopSchedulerLoop(); TS_ASSERT_EQUALS(1, task1->enterCallOrder); TS_ASSERT_EQUALS(2, task1->updateCallOrder); @@ -121,7 +125,8 @@ public: void test_sequential_task_group_does_not_evaluate_tasks_after_success(void) { - TaskScheduler::getInstance()->startSchedulerLoopThreaded(); + TaskScheduler scheduler(0); + scheduler.startSchedulerLoopThreaded(); int order = 0; std::shared_ptr task1 = std::make_shared(&order, 1, Task::STATE_FAILURE); @@ -133,11 +138,11 @@ public: taskGroup->addTask(task2); taskGroup->addTask(task3); - Task::dispatch(taskGroup); + scheduler.pushTask(taskGroup); - waitForThread(); + waitForThread(scheduler); - TaskScheduler::getInstance()->stopSchedulerLoop(); + scheduler.stopSchedulerLoop(); TS_ASSERT_EQUALS(1, task1->enterCallOrder); TS_ASSERT_EQUALS(2, task1->updateCallOrder); @@ -154,16 +159,17 @@ public: void test_task_scheduling_within_task_processing() { - TaskScheduler::getInstance()->startSchedulerLoopThreaded(); + TaskScheduler scheduler(0); + scheduler.startSchedulerLoopThreaded(); int order = 0; - std::shared_ptr task = std::make_shared(&order, 1); + std::shared_ptr task = std::make_shared(&order, 1, &scheduler); - Task::dispatch(task); + scheduler.pushTask(task); - waitForThread(); + waitForThread(scheduler); - TaskScheduler::getInstance()->stopSchedulerLoop(); + scheduler.stopSchedulerLoop(); TS_ASSERT_EQUALS(6, order); @@ -250,29 +256,31 @@ private: class TestTaskDispatch: public TestTask { public: - TestTaskDispatch(int* orderCountPtr, int updateCount) + TestTaskDispatch(int* orderCountPtr, int updateCount, TaskScheduler* scheduler) : TestTask(orderCountPtr, updateCount) + , scheduler(scheduler) { } virtual TaskState doUpdate(std::shared_ptr blakboard) { subTask = std::make_shared(&orderCount, 1); - Task::dispatch(subTask); + scheduler->pushTask(subTask); return TestTask::doUpdate(blakboard); } + TaskScheduler* scheduler; std::shared_ptr subTask; }; - void waitForThread() const + void waitForThread(TaskScheduler& scheduler) const { static const int THREAD_WAIT_TIME_MS = 20; do { std::this_thread::sleep_for(std::chrono::milliseconds(THREAD_WAIT_TIME_MS)); } - while (TaskScheduler::getInstance()->hasTasksQueued()); + while (scheduler.hasTasksQueued()); } };