ui: Added tabs UI to top of main window (issue #215)

* Added tab bar to top of main window with UI/shortcuts similar to web browsers
* ComponentManager offers components for 2 use-cases: application and tab
* Application components: log view (status/errors), bookmarks, screen search, status bar, tabs, tooltips, dialogs and all tab views disabled
* Tab components: graph, code, history and search
* When a project is loaded there is always at least one tab, otherwise there is none
* Each tab replaces the application views of the same name in the main layout when activated
* Each tab has it's own TaskScheduler, to process tasks independent from other tabs
* The application has a global TaskScheduler for application wide tasks
* The singloton class TaskManager is responsible for managing the TaskSchedulers
* MessageListeners and Messages hold an optional schedulerId, both must be set to only send to a specific TaskScheduler
* Bookmark buttons where split off into a separate view per tab, bookmark managemement is done in the application
* History menu processing is done by the QtMainWindow now
* Screen search is an application component, the responders are always changed to the active tab
* Plugin messages are opened in a new tab
* Symbols can be opened in a new tab via middle click/context menu in graph, code, history dropdown
* Full text index creation is mutexed now in PersistenStorage to make it fully thread-safe
* All tabs are closed when switching projects
* Tab contents are only animated when visible

fortune cookie message = Catch your lucky star!
This commit is contained in:
Eberhard Graether
2018-11-05 01:28:12 +01:00
parent bd4a554b27
commit f13aec70dd
170 changed files with 2972 additions and 823 deletions
@@ -0,0 +1,134 @@
#include "QtBookmarkButtonsView.h"
#include <QFrame>
#include <QHBoxLayout>
#include <QMessageBox>
#include <QPushButton>
#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<QtViewWidgetWrapper>(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();
}
@@ -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
+3 -128
View File
@@ -1,109 +1,28 @@
#include "QtBookmarkView.h"
#include <QFrame>
#include <QHBoxLayout>
#include <QMessageBox>
#include <QPushButton>
#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<QtViewWidgetWrapper>(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::vector<std::shared_ptr<Bookmark
);
}
void QtBookmarkView::enableDisplayBookmarks(bool enable)
{
m_onQtThread(
[=]()
{
m_showBookmarksButton->setEnabled(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);
}
+3 -23
View File
@@ -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<std::wstring>& names, const std::vector<BookmarkCategory>& categories, Id nodeId);
virtual void displayBookmarkEditor(
std::shared_ptr<Bookmark> bookmark, const std::vector<BookmarkCategory>& categories);
virtual void displayBookmarks(const std::vector<std::shared_ptr<Bookmark>>& bookmarks);
virtual void enableDisplayBookmarks(bool enable);
virtual bool bookmarkBrowserIsVisible() const;
private slots:
void createBookmarkClicked();
void showBookmarksClicked();
private:
ControllerProxy<BookmarkController> 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
+11
View File
@@ -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]()
{
+4 -3
View File
@@ -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<TaskLambda>(
Task::dispatch(TabId::app(), std::make_shared<TaskLambda>(
[=]()
{
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<TaskLambda>(
Task::dispatch(TabId::app(), std::make_shared<TaskLambda>(
[=]()
{
onStartIndexing(info);
@@ -208,7 +209,7 @@ void QtDialogView::startIndexingDialog(
connect(window, &QtWindow::canceled,
[=]()
{
Task::dispatch(std::make_shared<TaskLambda>(
Task::dispatch(TabId::app(), std::make_shared<TaskLambda>(
[=]()
{
onCancelIndexing();
+10 -12
View File
@@ -13,14 +13,15 @@
#include <QStandardItem>
#include <QStyledItemDelegate>
#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;
}
});
}
+1 -3
View File
@@ -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
+7 -2
View File
@@ -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);
+34 -3
View File
@@ -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<QtMainWindow>();
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<View*>::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<std::shared_ptr<MessageBase>>& historyMenuItems)
void QtMainView::updateHistoryMenu(std::shared_ptr<MessageBase> 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<std::shared_ptr<Bookmark>
);
}
void QtMainView::clearBookmarksMenu()
{
updateBookmarksMenu({});
}
void QtMainView::handleMessage(MessageForceEnterLicense* message)
{
LicenseChecker::LicenseState state = message->state;
+29 -22
View File
@@ -24,45 +24,52 @@ class QtMainView
, public MessageListener<MessageProjectNew>
{
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<std::shared_ptr<MessageBase>>& historyMenuItems);
virtual void updateBookmarksMenu(const std::vector<std::shared_ptr<Bookmark>>& bookmarks);
void updateRecentProjectMenu() override;
void updateHistoryMenu(std::shared_ptr<MessageBase> message) override;
void clearHistoryMenu() override;
void updateBookmarksMenu(const std::vector<std::shared_ptr<Bookmark>>& 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<QtMainWindow> m_window;
std::vector<View*> m_views;
+3 -2
View File
@@ -3,15 +3,16 @@
#include <QToolBar>
#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);
+2 -4
View File
@@ -7,12 +7,10 @@
QtStatusBarView::QtStatusBarView(ViewLayout* viewLayout)
: StatusBarView(viewLayout)
{
m_widget = std::make_shared<QtStatusBar>();
m_widget = new QtStatusBar();
m_widget->show();
QtMainView* mw = static_cast<QtMainView*>(viewLayout);
QStatusBar* sb = static_cast<QStatusBar*>(m_widget.get());
mw->setStatusBar(sb);
dynamic_cast<QtMainView*>(viewLayout)->setStatusBar(m_widget);
}
void QtStatusBarView::createWidgetWrapper()
+1 -1
View File
@@ -33,7 +33,7 @@ public:
private:
QtThreadedLambdaFunctor m_onQtThread;
std::shared_ptr<QtStatusBar> m_widget;
QtStatusBar* m_widget;
};
#endif // !QT_STATUS_BAR_VIEW_H
+290
View File
@@ -0,0 +1,290 @@
#include "QtTabsView.h"
#include <QHBoxLayout>
#include <QPushButton>
#include <QStyle>
#include <QVariant>
#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<QtViewWidgetWrapper>(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<TabsController>()->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<TabsController>()->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<SearchMatch> 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<TabsController>()->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<TabsController>()->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<TabsController>()->removeTab(m_tabBar->tabData(index).toInt());
m_tabBar->removeTab(index);
}
void QtTabsView::setTabState(int idx, const std::vector<SearchMatch>& 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"));
}
+54
View File
@@ -0,0 +1,54 @@
#ifndef QT_TABS_VIEW_H
#define QT_TABS_VIEW_H
#include <QObject>
#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<SearchMatch> 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<SearchMatch>& matches);
void setStyleSheet();
QtThreadedLambdaFunctor m_onQtThread;
QWidget* m_widget;
QtTabBar* m_tabBar;
size_t m_insertedTabCount;
};
#endif // QT_TABS_VIEW_H
+20 -4
View File
@@ -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<MainView> QtViewFactory::createMainView() const
std::shared_ptr<MainView> QtViewFactory::createMainView(StorageAccess* storageAccess) const
{
return std::make_shared<QtMainView>();
return std::make_shared<QtMainView>(this, storageAccess);
}
std::shared_ptr<CompositeView> QtViewFactory::createCompositeView(
@@ -44,9 +46,14 @@ std::shared_ptr<TabbedView> QtViewFactory::createTabbedView(ViewLayout* viewLayo
return ptr;
}
std::shared_ptr<BookmarkButtonsView> QtViewFactory::createBookmarkButtonsView(ViewLayout* viewLayout) const
{
return View::createInitAndAddToLayout<QtBookmarkButtonsView>(viewLayout);
}
std::shared_ptr<BookmarkView> QtViewFactory::createBookmarkView(ViewLayout* viewLayout) const
{
return View::createInitAndAddToLayout<QtBookmarkView>(viewLayout);
return View::createAndInit<QtBookmarkView>(viewLayout);
}
std::shared_ptr<CodeView> QtViewFactory::createCodeView(ViewLayout* viewLayout) const
@@ -66,7 +73,6 @@ std::shared_ptr<StatusView> QtViewFactory::createStatusView(ViewLayout* viewLayo
std::shared_ptr<GraphView> QtViewFactory::createGraphView(ViewLayout* viewLayout) const
{
GraphViewStyle::setImpl(std::make_shared<QtGraphViewStyleImpl>());
return View::createInitAndAddToLayout<QtGraphView>(viewLayout);
}
@@ -90,6 +96,11 @@ std::shared_ptr<StatusBarView> QtViewFactory::createStatusBarView(ViewLayout* vi
return View::createAndInit<QtStatusBarView>(viewLayout);
}
std::shared_ptr<TabsView> QtViewFactory::createTabsView(ViewLayout* viewLayout) const
{
return View::createInitAndAddToLayout<QtTabsView>(viewLayout);
}
std::shared_ptr<TooltipView> QtViewFactory::createTooltipView(ViewLayout* viewLayout) const
{
return View::createAndInit<QtTooltipView>(viewLayout);
@@ -105,3 +116,8 @@ std::shared_ptr<DialogView> QtViewFactory::createDialogView(
{
return std::make_shared<QtDialogView>(dynamic_cast<QtMainView*>(viewLayout)->getMainWindow(), useCase, storageAccess);
}
std::shared_ptr<GraphViewStyleImpl> QtViewFactory::createGraphStyleImpl() const
{
return std::make_shared<QtGraphViewStyleImpl>();
}
+5 -1
View File
@@ -10,11 +10,12 @@ public:
QtViewFactory();
virtual ~QtViewFactory() = default;
virtual std::shared_ptr<MainView> createMainView() const;
virtual std::shared_ptr<MainView> createMainView(StorageAccess* storageAccess) const;
virtual std::shared_ptr<CompositeView> createCompositeView(
ViewLayout* viewLayout, CompositeView::CompositeDirection direction, const std::string& name) const;
virtual std::shared_ptr<TabbedView> createTabbedView(ViewLayout* viewLayout, const std::string& name) const;
virtual std::shared_ptr<BookmarkButtonsView> createBookmarkButtonsView(ViewLayout* viewLayout) const;
virtual std::shared_ptr<BookmarkView> createBookmarkView(ViewLayout* viewLayout) const;
virtual std::shared_ptr<CodeView> createCodeView(ViewLayout* viewLayout) const;
virtual std::shared_ptr<ErrorView> createErrorView(ViewLayout* viewLayout) const;
@@ -24,11 +25,14 @@ public:
virtual std::shared_ptr<SearchView> createSearchView(ViewLayout* viewLayout) const;
virtual std::shared_ptr<StatusBarView> createStatusBarView(ViewLayout* viewLayout) const;
virtual std::shared_ptr<StatusView> createStatusView(ViewLayout* viewLayout) const;
virtual std::shared_ptr<TabsView> createTabsView(ViewLayout* viewLayout) const;
virtual std::shared_ptr<TooltipView> createTooltipView(ViewLayout* viewLayout) const;
virtual std::shared_ptr<UndoRedoView> createUndoRedoView(ViewLayout* viewLayout) const;
virtual std::shared_ptr<DialogView> createDialogView(
ViewLayout* viewLayout, DialogView::UseCase useCase, StorageAccess* storageAccess) const;
virtual std::shared_ptr<GraphViewStyleImpl> createGraphStyleImpl() const;
};
#endif // QT_VIEW_FACTORY_H
@@ -29,6 +29,8 @@ QtViewWidgetWrapper::QtViewWidgetWrapper(QWidget* widget)
QtViewWidgetWrapper::~QtViewWidgetWrapper()
{
m_widget->hide();
m_widget->deleteLater();
}
QWidget* QtViewWidgetWrapper::getWidget()
@@ -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<QtGraphNodeComponent> 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<QtGraphNodeComponent> component : m_components)
{
component->nodeMouseReleaseEvent(event);
@@ -95,6 +95,7 @@ public:
virtual void addSubNode(QtGraphNode* node);
virtual void onClick();
virtual void onMiddleClick();
void onHide();
void onCollapseExpand();
@@ -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(
@@ -22,6 +22,7 @@ public:
virtual Id getTokenId() const;
virtual void onClick();
virtual void onMiddleClick();
virtual void updateStyle();
protected:
@@ -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();
}
@@ -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;