Skip to content

Commit

Permalink
Added a tab widget at the bottom of MainWindow (#11627)
Browse files Browse the repository at this point in the history
* Added a tab widget at the bottom of MainWindow

The tab widget mimics the Messages Browser. It is a shorter version of it.
Only shown when Messages Browser is hidden.
Messages Browser can now only be docked at the bottom.

Scroll to bottom when a new simulation output is added.

Fixes #9889

* Set the index to 0
  • Loading branch information
adeas31 committed Nov 22, 2023
1 parent 2c9c736 commit ddbb85b
Show file tree
Hide file tree
Showing 10 changed files with 328 additions and 28 deletions.
184 changes: 180 additions & 4 deletions OMEdit/OMEditLIB/MainWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
#include "Util/Helper.h"
#include "Simulation/ArchivedSimulationsWidget.h"
#include "Simulation/SimulationOutputWidget.h"
#include "OMS/OMSSimulationOutputWidget.h"
#include "TLM/FetchInterfaceDataDialog.h"
#include "TLM/TLMCoSimulationOutputWidget.h"
#include "OMS/OMSSimulationDialog.h"
Expand Down Expand Up @@ -185,11 +186,11 @@ void MainWindow::setUpMainWindow(threadData_t *threadData)
// Create MessagesDockWidget dock
mpMessagesDockWidget = new QDockWidget(tr("Messages Browser"), this);
mpMessagesDockWidget->setObjectName("Messages");
mpMessagesDockWidget->setAllowedAreas(Qt::TopDockWidgetArea | Qt::BottomDockWidgetArea);
mpMessagesDockWidget->setAllowedAreas(Qt::BottomDockWidgetArea);
mpMessagesDockWidget->setWidget(MessagesWidget::instance());
addDockWidget(Qt::BottomDockWidgetArea, mpMessagesDockWidget);
mpMessagesDockWidget->hide();
connect(MessagesWidget::instance(), SIGNAL(MessageAdded()), SLOT(showMessagesBrowser()));
connect(MessagesWidget::instance(), SIGNAL(messageAdded()), SLOT(showMessagesBrowser()));
// Create the OMCProxy object.
mpOMCProxy = new OMCProxy(threadData, this);
if (getExitApplicationStatus()) {
Expand Down Expand Up @@ -381,8 +382,25 @@ void MainWindow::setUpMainWindow(threadData_t *threadData)
mpCentralStackedWidget->addWidget(mpWelcomePageWidget);
mpCentralStackedWidget->addWidget(mpModelWidgetContainer);
mpCentralStackedWidget->addWidget(mpPlotWindowContainer);
// central widget layout
QVBoxLayout *pCentralWidgetLayout = new QVBoxLayout;
pCentralWidgetLayout->setSpacing(0);
pCentralWidgetLayout->setContentsMargins(0, 0, 0, 0);
QWidget *pCentralWidget = new QWidget;
pCentralWidgetLayout->addWidget(mpCentralStackedWidget, 1);
// Create a QTabWidget that mimicks the Messages Browser
mpMessagesTabWidget = new QTabWidget(this);
mpMessagesTabWidget->setTabsClosable(true);
mpMessagesTabWidget->setDocumentMode(true);
connect(mpMessagesTabWidget, SIGNAL(tabBarClicked(int)), SLOT(messagesTabBarClicked(int)));
connect(mpMessagesDockWidget, SIGNAL(visibilityChanged(bool)), SLOT(messagesDockWidgetVisibilityChanged(bool)));
connect(MessagesWidget::instance(), SIGNAL(messageTabAdded(QWidget*,QString)), SLOT(messageTabAdded(QWidget*,QString)));
connect(MessagesWidget::instance(), SIGNAL(messageTabClosed(int)), SLOT(messageTabClosed(int)));
connect(mpMessagesTabWidget, SIGNAL(tabCloseRequested(int)), MessagesWidget::instance(), SLOT(closeTab(int)));
pCentralWidgetLayout->addWidget(mpMessagesTabWidget, 0);
pCentralWidget->setLayout(pCentralWidgetLayout);
//Set the centralwidget
setCentralWidget(mpCentralStackedWidget);
setCentralWidget(pCentralWidget);
// Load and add user defined Modelica libraries into the Library Widget.
if (!isTestsuiteRunning()) {
mpLibraryWidget->getLibraryTreeModel()->addModelicaLibraries();
Expand Down Expand Up @@ -429,6 +447,20 @@ void MainWindow::setUpMainWindow(threadData_t *threadData)
if (OptionsDialog::instance()->getGeneralSettingsPage()->getEnableAutoSaveGroupBox()->isChecked()) {
mpAutoSaveTimer->start();
}
// create tabs from MessagesWidget
QTabBar::ButtonPosition closeSide = (QTabBar::ButtonPosition)style()->styleHint(QStyle::SH_TabBar_CloseButtonPosition, 0, mpMessagesTabWidget);
MessagesTabWidget *pMessagesTabWidget = MessagesWidget::instance()->getMessagesTabWidget();
for (int i = 0; i < pMessagesTabWidget->count(); ++i) {
createMessageTab(pMessagesTabWidget->tabText(i), true);
QWidget *pTabButtonWidget = mpMessagesTabWidget->tabBar()->tabButton(i, closeSide);
if (pTabButtonWidget) {
pTabButtonWidget->deleteLater();
}
mpMessagesTabWidget->tabBar()->setTabButton(i, closeSide, 0);
}
// since createMessageTab() changes the index so switch it back to 0.
mpMessagesTabWidget->setCurrentIndex(0);
mpMessagesTabWidget->setVisible(!mpMessagesDockWidget->isVisible());
}

/*!
Expand Down Expand Up @@ -1785,7 +1817,7 @@ void MainWindow::writeNewApiProfiling(const QString &str)

/*!
* \brief MainWindow::showMessagesBrowser
* Slot activated when MessagesWidget::MessageAdded signal is raised.\n
* Slot activated when MessagesWidget::messageAdded signal is raised.\n
* Shows the Messages Browser.
*/
void MainWindow::showMessagesBrowser()
Expand Down Expand Up @@ -3574,6 +3606,62 @@ void MainWindow::threeDViewerDockWidgetVisibilityChanged(bool visible)
#endif
}

/*!
* \brief MainWindow::messagesTabBarClicked
* Shows the MessagesWidget when tab is clicked.
* \param index
*/
void MainWindow::messagesTabBarClicked(int index)
{
showMessagesBrowser();
MessagesWidget::instance()->getMessagesTabWidget()->setCurrentIndex(index);
}

/*!
* \brief MainWindow::messagesDockWidgetVisibilityChanged
* Handles the VisibilityChanged signal of MessagesBrowser Dock Widget.
* \param visible
*/
void MainWindow::messagesDockWidgetVisibilityChanged(bool visible)
{
mpMessagesTabWidget->setVisible(!visible);
if (!visible && MessagesWidget::instance()) {
mpMessagesTabWidget->setCurrentIndex(MessagesWidget::instance()->getMessagesTabWidget()->currentIndex());
}
}

/*!
* \brief MainWindow::messageTabAdded
* Handles the messageTabAdded signal of MessagesWidget.
* \param pSimulationOutputTab
* \param name
*/
void MainWindow::messageTabAdded(QWidget *pSimulationOutputTab, const QString &name)
{
MessageTab *pMessageTab = createMessageTab(name, false);
SimulationOutputWidget *pSimulationOutputWidget = qobject_cast<SimulationOutputWidget*>(pSimulationOutputTab);
if (pSimulationOutputWidget) {
connect(pSimulationOutputWidget, SIGNAL(updateText(QString)), pMessageTab, SLOT(updateText(QString)));
connect(pSimulationOutputWidget, SIGNAL(updateProgressBar(QProgressBar*)), pMessageTab, SLOT(updateProgress(QProgressBar*)));
} else {
OMSSimulationOutputWidget *pOMSSimulationOutputWidget = qobject_cast<OMSSimulationOutputWidget*>(pSimulationOutputTab);
if (pOMSSimulationOutputWidget) {
connect(pOMSSimulationOutputWidget, SIGNAL(updateText(QString)), pMessageTab, SLOT(updateText(QString)));
connect(pOMSSimulationOutputWidget, SIGNAL(updateProgressBar(QProgressBar*)), pMessageTab, SLOT(updateProgress(QProgressBar*)));
}
}
}

/*!
* \brief MainWindow::messageTabClosed
* Handles the messageTabClosed signal of MessagesWidget.
* \param name
*/
void MainWindow::messageTabClosed(int index)
{
mpMessagesTabWidget->removeTab(index);
}

/*!
* \brief MainWindow::autoSave
* Slot activated when mpAutoSaveTimer timeout SIGNAL is raised.\n
Expand Down Expand Up @@ -5016,6 +5104,23 @@ void MainWindow::toolBarVisibilityChanged(const QString &toolbar, bool visible)
pSettings->endGroup();
}

/*!
* \brief MainWindow::createMessageTab
* Creates the MessageTab.
* \param name
* \param fixedTab
* \return
*/
MessageTab *MainWindow::createMessageTab(const QString &name, bool fixedTab)
{
MessageTab *pMessageTab = new MessageTab(fixedTab);
int index = mpMessagesTabWidget->addTab(pMessageTab, name);
pMessageTab->setIndex(index);
mpMessagesTabWidget->setCurrentIndex(index);
connect(pMessageTab, SIGNAL(clicked(int)), mpMessagesTabWidget, SIGNAL(tabBarClicked(int)));
return pMessageTab;
}

//! when the dragged object enters the main window
//! @param event contains information of the drag operation.
void MainWindow::dragEnterEvent(QDragEnterEvent *event)
Expand Down Expand Up @@ -5184,3 +5289,74 @@ void AboutOMEditDialog::showReportIssue()
CrashReportDialog *pCrashReportDialog = new CrashReportDialog("", true);
pCrashReportDialog->exec();
}

/*!
* \class MessageTab
* \brief Creates a tab that mimicks the tab of Messages Browser.
*/
/*!
* \brief MessageTab::MessageTab
* \param fixedTab
*/
MessageTab::MessageTab(bool fixedTab)
: QWidget()
{
mpProgressLabel = new Label;
mpProgressLabel->setElideMode(Qt::ElideMiddle);
mpProgressLabel->installEventFilter(this);
if (fixedTab) {
mpProgressLabel->setText(tr("Click to open Messages Browser."));
}
mpProgressBar = new QProgressBar;
mpProgressBar->setAlignment(Qt::AlignHCenter);
mpProgressBar->installEventFilter(this);
// layout
QGridLayout *pMainLayout = new QGridLayout;
pMainLayout->setContentsMargins(5, 5, 5, 5);
pMainLayout->addWidget(mpProgressLabel, 0, 0);
if (!fixedTab) {
pMainLayout->addWidget(mpProgressBar, 0, 1);
}
setLayout(pMainLayout);
}

/*!
* \brief MessageTab::updateText
* Updates the text label.
* \param text
*/
void MessageTab::updateText(const QString &text)
{
mpProgressLabel->setText(text);
}

/*!
* \brief MessageTab::updateProgress
* Updates the progressBar
* \param pProgressBar
*/
void MessageTab::updateProgress(QProgressBar *pProgressBar)
{
mpProgressBar->setRange(pProgressBar->minimum(), pProgressBar->maximum());
mpProgressBar->setValue(pProgressBar->value());
mpProgressBar->setTextVisible(pProgressBar->isTextVisible());
}

/*!
* \brief MessageTab::eventFilter
* Emits the clicked signal on left mouse press.
* \param pObject
* \param pEvent
* \return
*/
bool MessageTab::eventFilter(QObject *pObject, QEvent *pEvent)
{
if (pEvent->type() == QEvent::MouseButtonPress) {
QMouseEvent *pMouseEvent = static_cast<QMouseEvent*>(pEvent);
if (pMouseEvent && pMouseEvent->button() == Qt::LeftButton) {
emit clicked(mIndex);
return true;
}
}
return QObject::eventFilter(pObject, pEvent);
}
28 changes: 28 additions & 0 deletions OMEdit/OMEditLIB/MainWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ class TraceabilityInformationURI;
class StatusBar;
class TraceabilityGraphViewWidget;
class SearchWidget;
class MessageTab;

class MainWindow : public QMainWindow
{
Expand All @@ -117,6 +118,7 @@ class MainWindow : public QMainWindow
void setExitApplicationStatus(bool status) {mExitApplicationStatus = status;}
bool getExitApplicationStatus() {return mExitApplicationStatus;}
int getNumberOfProcessors() {return mNumberOfProcessors;}
QDockWidget* getMessagesDockWidget() {return mpMessagesDockWidget;}
LibraryWidget* getLibraryWidget() {return mpLibraryWidget;}
StackFramesWidget* getStackFramesWidget() {return mpStackFramesWidget;}
BreakpointsWidget* getBreakpointsWidget() {return mpBreakpointsWidget;}
Expand Down Expand Up @@ -314,6 +316,7 @@ class MainWindow : public QMainWindow
CommitChangesDialog *mpCommitChangesDialog;
TraceabilityInformationURI *mpTraceabilityInformationURI;
QStackedWidget *mpCentralStackedWidget;
QTabWidget *mpMessagesTabWidget;
QProgressBar *mpProgressBar;
Label *mpPositionLabel;
QTabBar *mpPerspectiveTabbar;
Expand Down Expand Up @@ -589,6 +592,10 @@ private slots:
void perspectiveTabChanged(int tabIndex);
void documentationDockWidgetVisibilityChanged(bool visible);
void threeDViewerDockWidgetVisibilityChanged(bool visible);
void messagesTabBarClicked(int index);
void messagesDockWidgetVisibilityChanged(bool visible);
void messageTabAdded(QWidget *pSimulationOutputTab, const QString &name);
void messageTabClosed(int index);
void autoSave();
void showDataReconciliationDialog();
void showDebugConfigurationsDialog();
Expand All @@ -613,6 +620,7 @@ private slots:
void tileSubWindows(QMdiArea *pMdiArea, bool horizontally);
void fetchInterfaceDataHelper(LibraryTreeItem *pLibraryTreeItem, QString singleModel = QString());
void toolBarVisibilityChanged(const QString &toolbar, bool visible);
MessageTab* createMessageTab(const QString &name, bool fixedTab);
protected:
virtual void dragEnterEvent(QDragEnterEvent *event) override;
virtual void dragMoveEvent(QDragMoveEvent *event) override;
Expand All @@ -633,4 +641,24 @@ private slots:
void readOMContributors(QNetworkReply *pNetworkReply);
};

class MessageTab : public QWidget
{
Q_OBJECT
public:
MessageTab(bool fixedTab);
void setIndex(int index) {mIndex = index;}
private:
int mIndex = -1;
Label *mpProgressLabel;
QProgressBar *mpProgressBar;
public slots:
void updateText(const QString &text);
void updateProgress(QProgressBar *pProgressBar);
signals:
void clicked(int index);
// QObject interface
public:
virtual bool eventFilter(QObject *pObject, QEvent *pEvent) override;
};

#endif // MAINWINDOW_H
7 changes: 5 additions & 2 deletions OMEdit/OMEditLIB/Modeling/MessagesWidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,7 @@ void MessageWidget::clearAllTabsMessages()
MessagesTabWidget::MessagesTabWidget(QWidget *pParent)
: QTabWidget(pParent)
{
setDocumentMode(true);
setTabsClosable(true);
}

Expand Down Expand Up @@ -523,8 +524,8 @@ void MessagesWidget::addSimulationOutputTab(QWidget *pSimulationOutputTab, const
// add the tab if it doesn't already exist
if (!tabFound) {
mpMessagesTabWidget->setCurrentIndex(mpMessagesTabWidget->addTab(pSimulationOutputTab, name));
emit messageTabAdded(pSimulationOutputTab, name);
}
emit MessageAdded();
}

/*!
Expand Down Expand Up @@ -568,11 +569,13 @@ bool MessagesWidget::closeTab(int index)
if (pSimulationOutputWidget->getSimulationOptions().isInteractiveSimulation()) {
MainWindow::instance()->getSimulationDialog()->removeSimulationOutputWidget(pSimulationOutputWidget);
}
emit messageTabClosed(index);
return true;
}
OMSSimulationOutputWidget *pOMSSimulationOutputWidget = qobject_cast<OMSSimulationOutputWidget*>(mpMessagesTabWidget->widget(index));
if (pOMSSimulationOutputWidget && !pOMSSimulationOutputWidget->isSimulationProcessRunning()) {
mpMessagesTabWidget->removeTab(index);
emit messageTabClosed(index);
return true;
}
return false;
Expand Down Expand Up @@ -616,7 +619,7 @@ void MessagesWidget::addGUIMessage(MessageItem messageItem)
break;
}
mpMessagesTabWidget->setCurrentWidget(mpAllMessageWidget);
emit MessageAdded();
emit messageAdded();
}

/*!
Expand Down
5 changes: 4 additions & 1 deletion OMEdit/OMEditLIB/Modeling/MessagesWidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ class MessagesWidget : public QWidget
bool mShowingPendingMessages;
public:
static MessagesWidget* instance() {return mpInstance;}
MessagesTabWidget* getMessagesTabWidget() const {return mpMessagesTabWidget;}
MessageWidget* getAllMessageWidget() {return mpAllMessageWidget;}
MessageWidget* getNotificationMessageWidget() {return mpNotificationMessageWidget;}
MessageWidget* getWarningMessageWidget() {return mpWarningMessageWidget;}
Expand All @@ -146,7 +147,9 @@ class MessagesWidget : public QWidget
int getSimulationOutputTabsSize();
SimulationOutputWidget* getSimulationOutputWidget(const QString &className);
signals:
void MessageAdded();
void messageAdded();
void messageTabAdded(QWidget *pSimulationOutputTab, const QString &name);
void messageTabClosed(int index);
private slots:
bool closeTab(int index);
public slots:
Expand Down

0 comments on commit ddbb85b

Please sign in to comment.