From 8c174deb53268c1ecfdd818339ac0fb1614d3312 Mon Sep 17 00:00:00 2001 From: sbh Date: Fri, 8 Aug 2014 10:37:13 +0400 Subject: [PATCH] Issue #20 main menu size processing --- src/XGUI/XGUI_Command.cpp | 39 +++++++--- src/XGUI/XGUI_Command.h | 13 ++++ src/XGUI/XGUI_MainMenu.cpp | 119 +++++++++++++++++++++---------- src/XGUI/XGUI_MainMenu.h | 32 +++++++-- src/XGUI/XGUI_MainWindow.cpp | 82 +++++++++++++++++---- src/XGUI/XGUI_MainWindow.h | 19 +++++ src/XGUI/XGUI_MenuGroupPanel.cpp | 9 ++- src/XGUI/XGUI_MenuGroupPanel.h | 10 +-- src/XGUI/XGUI_Workshop.cpp | 20 +++--- 9 files changed, 257 insertions(+), 86 deletions(-) diff --git a/src/XGUI/XGUI_Command.cpp b/src/XGUI/XGUI_Command.cpp index b289f8014..f260a1691 100644 --- a/src/XGUI/XGUI_Command.cpp +++ b/src/XGUI/XGUI_Command.cpp @@ -1,6 +1,33 @@ #include "XGUI_Command.h" +#include -#include + +XGUI_MenuButton::XGUI_MenuButton(const QIcon& theIcon, + const QString& theText, + QWidget * theParent) + : QPushButton(theIcon, theText, theParent) + +{ + setFlat(true); + setMinimumSize(MIN_BUTTON_WIDTH, MIN_BUTTON_HEIGHT); + setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); + QString aStyleSheet = "QPushButton { text-align: left; }"; + //aStyleSheet += "QPushButton:hover { border: 1px solid gray; border-radius: 3px; }"; + setStyleSheet(aStyleSheet); + installEventFilter(this); +} + +//void XGUI_MenuButton::enterEvent(QEvent * event) +//{ +// if(isEnabled()) { +// setFlat(false); +// } +//} + +//void XGUI_MenuButton::leaveEvent(QEvent * event) +//{ +// setFlat(true); +//} XGUI_Command::XGUI_Command(const QString& theId, QObject * parent, bool isCheckable) : QWidgetAction(parent), myCheckable(isCheckable) @@ -24,16 +51,8 @@ XGUI_Command::~XGUI_Command() QWidget* XGUI_Command::createWidget(QWidget* theParent) { if (theParent->inherits("XGUI_MenuGroupPanel")) { - QToolButton* aButton = new QToolButton(theParent); - aButton->setIcon(icon()); - aButton->setText(text()); - aButton->setStyleSheet("QToolButton::menu-indicator { image: none; }"); - aButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); - aButton->setAutoRaise(true); - aButton->setArrowType(Qt::NoArrow); + XGUI_MenuButton* aButton = new XGUI_MenuButton(icon(), text(), theParent); aButton->setCheckable(myCheckable); - aButton->setMinimumSize(MIN_BUTTON_WIDTH, MIN_BUTTON_HEIGHT); - aButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); QKeySequence aKeys = shortcut(); QString aToolTip = toolTip(); if (!aKeys.isEmpty()) diff --git a/src/XGUI/XGUI_Command.h b/src/XGUI/XGUI_Command.h index 4247a7ca4..fcd99b3c8 100644 --- a/src/XGUI/XGUI_Command.h +++ b/src/XGUI/XGUI_Command.h @@ -3,10 +3,23 @@ #include "XGUI.h" #include +#include #define MIN_BUTTON_HEIGHT 25 #define MIN_BUTTON_WIDTH 60 +class XGUI_EXPORT XGUI_MenuButton: public QPushButton +{ + Q_OBJECT + public: + XGUI_MenuButton(const QIcon & icon, const QString & text, QWidget * parent = 0); + +// protected: +// virtual void enterEvent(QEvent * event); +// virtual void leaveEvent(QEvent * event); + +}; + /**\class XGUI_Command * \ingroup GUI * \brief Represents a command item in the application menu (Workbench) diff --git a/src/XGUI/XGUI_MainMenu.cpp b/src/XGUI/XGUI_MainMenu.cpp index 9f79a1db8..a16076e54 100644 --- a/src/XGUI/XGUI_MainMenu.cpp +++ b/src/XGUI/XGUI_MainMenu.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -8,17 +9,27 @@ #include #include #include +#include +#include XGUI_MainMenu::XGUI_MainMenu(XGUI_MainWindow *parent) - : QObject(parent), myDesktop(parent) + : QWidget(parent), myDesktop(parent) { - parent->setTabPosition(Qt::TopDockWidgetArea, QTabWidget::North); - myDesktop->setStyleSheet("QTabBar::tab {height: 24px;}"); - myGeneralPage = addWorkbench(tr("General")); + myGeneralPage = new XGUI_MenuGroupPanel(this); + myGeneralPage->setObjectName("Default"); myGeneralPage->parentWidget()->setMaximumWidth(200); myGeneralPage->installEventFilter(this); -// QString aStyle = myDesktop->styleSheet(); -// aStyle += " QTabBar::tab {min-height: 24px;}"; + myGeneralPage->setFrameStyle(QFrame::StyledPanel); + + myMenuTabs = new QTabWidget(this); + myMenuTabs->setStyleSheet("QTabBar::tab {height: 24px;} QTabWidget:pane {border: 0px;}"); + QHBoxLayout* aMainLayout = new QHBoxLayout(this); + aMainLayout->addWidget(myGeneralPage); + aMainLayout->addWidget(myMenuTabs); + aMainLayout->setContentsMargins(0, 2, 2, 0); + aMainLayout->setSpacing(2); + setLayout(aMainLayout); + setFixedHeight(menuHeight()); } XGUI_MainMenu::~XGUI_MainMenu(void) @@ -27,27 +38,13 @@ XGUI_MainMenu::~XGUI_MainMenu(void) XGUI_Workbench* XGUI_MainMenu::addWorkbench(const QString& theId, const QString& theTitle) { - QDockWidget* aDock = new QDockWidget(myDesktop); - aDock->setFeatures(QDockWidget::DockWidgetVerticalTitleBar); - aDock->setAllowedAreas(Qt::TopDockWidgetArea); QString aTitle = theTitle; if (aTitle.isEmpty()) { aTitle = tr(theId.toLatin1().constData()); } - aDock->setWindowTitle(aTitle); - aDock->setMinimumHeight(30); - aDock->setContentsMargins(0, 0, 0, 0); - - XGUI_Workbench* aPage = new XGUI_Workbench(aDock); + XGUI_Workbench* aPage = new XGUI_Workbench(myMenuTabs); aPage->setObjectName(theId); - aDock->setWidget(aPage); - - myDesktop->addDockWidget(Qt::TopDockWidgetArea, aDock); - if (myMenuTabs.length() > 1) { - myDesktop->tabifyDockWidget(myMenuTabs.last(), aDock); - } - - myMenuTabs.append(aDock); + myMenuTabs->addTab(aPage, aTitle); return aPage; } @@ -71,24 +68,48 @@ bool XGUI_MainMenu::eventFilter(QObject *theWatched, QEvent *theEvent) return QObject::eventFilter(theWatched, theEvent); } +void XGUI_MainMenu::insertConsole(QWidget* theConsole) +{ + int aConsoleTabId = myMenuTabs->addTab(theConsole, "Console"); + + QTabBar* aTabBar = myMenuTabs->findChild(); + QPushButton* aCloseTabButton = new QPushButton(); + aCloseTabButton->setFixedSize(16, 16); + aCloseTabButton->setIcon(QIcon(":pictures/wnd_close.png")); + aCloseTabButton->setFlat(true); + aTabBar->setTabButton(aConsoleTabId, + QTabBar::RightSide, + aCloseTabButton); + + connect(aCloseTabButton, SIGNAL(clicked()), + myDesktop, SLOT(dockPythonConsole())); +} + +void XGUI_MainMenu::removeConsole() +{ + const int kLastTab = myMenuTabs->count() - 1; + myMenuTabs->removeTab(kLastTab); +} + XGUI_Command* XGUI_MainMenu::feature(const QString& theId) const { - QList::const_iterator aIt; - for (aIt = myMenuTabs.constBegin(); aIt != myMenuTabs.constEnd(); ++aIt) { - XGUI_Workbench* aWbn = static_cast((*aIt)->widget()); - XGUI_Command* aCmd = aWbn->feature(theId); - if (aCmd) - return aCmd; + XGUI_Command* result; + result = myGeneralPage->feature(theId); + if (!result) { + for (int aTabIdx = 0; aTabIdx < myMenuTabs->count(); ++aTabIdx) { + XGUI_Workbench* aWbn = static_cast(myMenuTabs->widget(aTabIdx)); + result = aWbn->feature(theId); + if (result) break; + } } - return 0; + return result; } QList XGUI_MainMenu::features() const { - QList aList; - QList::const_iterator aIt; - for (aIt = myMenuTabs.constBegin(); aIt != myMenuTabs.constEnd(); ++aIt) { - XGUI_Workbench* aWbn = static_cast((*aIt)->widget()); + QList aList = myGeneralPage->features(); + for (int aTabIdx = 0; aTabIdx < myMenuTabs->count(); ++aTabIdx) { + XGUI_Workbench* aWbn = static_cast(myMenuTabs->widget(aTabIdx)); aList.append(aWbn->features()); } return aList; @@ -97,11 +118,33 @@ QList XGUI_MainMenu::features() const QList XGUI_MainMenu::workbenches() const { QList aList; - aList.append(myGeneralPage); - foreach(QDockWidget* aDoc, myMenuTabs) { - XGUI_Workbench* aWb = dynamic_cast(aDoc->widget()); - if (aWb) + for (int aTabIdx = 0; aTabIdx < myMenuTabs->count(); ++aTabIdx) { + XGUI_Workbench* aWb = dynamic_cast(myMenuTabs->widget(aTabIdx)); + if (aWb) { aList.append(aWb); + } } return aList; -} \ No newline at end of file +} + +int XGUI_MainMenu::menuItemSize() const +{ + //TODO(sbh, vsv): get this value from the preferences + static const ItemSize DEFAULT_ITEM_SIZE = Medium; + return (int) DEFAULT_ITEM_SIZE; +} + +int XGUI_MainMenu::menuHeight() const +{ + // Default group has no tabs above --> one extra row + int rows = menuItemRowsCount() + 1; + const int kMarginsSpacings = 4; + return rows * menuItemSize() + kMarginsSpacings; +} + +int XGUI_MainMenu::menuItemRowsCount() const +{ + //TODO(sbh, vsv): get this value from the preferences + static const int DEFAULT_ITEM_ROWS_COUNT = 3; + return DEFAULT_ITEM_ROWS_COUNT; +} diff --git a/src/XGUI/XGUI_MainMenu.h b/src/XGUI/XGUI_MainMenu.h index 945ddcb8d..3be908792 100644 --- a/src/XGUI/XGUI_MainMenu.h +++ b/src/XGUI/XGUI_MainMenu.h @@ -5,6 +5,7 @@ #include #include #include +#include class XGUI_Command; class XGUI_MainWindow; @@ -17,14 +18,22 @@ class QAction; class QDockWidget; class QEvent; - /**\class XGUI_MainMenu * \ingroup GUI * \brief Class for creation of main menu (set of workbenches) */ -class XGUI_EXPORT XGUI_MainMenu: public QObject +class XGUI_EXPORT XGUI_MainMenu: public QWidget { -Q_OBJECT + Q_OBJECT + + //! Size of menu item + //TODO(sbh, vsv): Move to the settings + enum ItemSize { + Small = 20, + Medium = 25, + Large = 30 + }; + public: XGUI_MainMenu(XGUI_MainWindow *parent); virtual ~XGUI_MainMenu(); @@ -36,10 +45,10 @@ public: XGUI_Workbench* findWorkbench(const QString& theId) const; //! Returns General page (predefined workbench) - XGUI_Workbench* generalPage() const { return myGeneralPage; } + XGUI_MenuGroupPanel* generalPage() const { return myGeneralPage; } //! Rerturns last created workbench in dock widget container - QDockWidget* getLastDockWindow() const { return myMenuTabs.last(); } + //QDockWidget* getLastDockWindow() const; //! Returns already created command by its ID XGUI_Command* feature(const QString& theId) const; @@ -51,10 +60,19 @@ public: virtual bool eventFilter(QObject *theWatched, QEvent *theEvent); + //! Displays given console as a tab in the workbench + void insertConsole(QWidget*); + //! Removes already created tab with python console + void removeConsole(); + + int menuItemSize() const; + int menuItemRowsCount() const; + int menuHeight() const; + private: XGUI_MainWindow* myDesktop; - QList myMenuTabs; - XGUI_Workbench* myGeneralPage; + QTabWidget* myMenuTabs; + XGUI_MenuGroupPanel* myGeneralPage; QMap myCommandState; }; diff --git a/src/XGUI/XGUI_MainWindow.cpp b/src/XGUI/XGUI_MainWindow.cpp index 1400fc0cc..b989488c6 100644 --- a/src/XGUI/XGUI_MainWindow.cpp +++ b/src/XGUI/XGUI_MainWindow.cpp @@ -18,11 +18,11 @@ XGUI_MainWindow::XGUI_MainWindow(QWidget* parent) : QMainWindow(parent), - myPythonConsole(0) + myPythonConsole(0), + myIsConsoleDocked(false) { setWindowTitle(tr("New Geom")); - myMenuBar = new XGUI_MainMenu(this); - + createMainMenu(); QMdiArea* aMdiArea = new QMdiArea(this); aMdiArea->setContextMenuPolicy(Qt::ActionsContextMenu); setCentralWidget(aMdiArea); @@ -67,15 +67,8 @@ QMdiArea* XGUI_MainWindow::mdiArea() const void XGUI_MainWindow::showPythonConsole() { if (!myPythonConsole) { - - QDockWidget* aDoc = new QDockWidget(this); - aDoc->setFeatures(QDockWidget::AllDockWidgetFeatures | QDockWidget::DockWidgetVerticalTitleBar); - aDoc->setMinimumHeight(0); - aDoc->setWindowTitle("Console"); - myPythonConsole = new PyConsole_EnhConsole( aDoc, new PyConsole_EnhInterp()); - aDoc->setWidget(myPythonConsole); - addDockWidget(Qt::TopDockWidgetArea, aDoc); - tabifyDockWidget(myMenuBar->getLastDockWindow(), aDoc); + myPythonConsole = new PyConsole_EnhConsole(this, new PyConsole_EnhInterp()); + undockPythonConsole(); } myPythonConsole->parentWidget()->show(); } @@ -87,6 +80,44 @@ void XGUI_MainWindow::hidePythonConsole() myPythonConsole->parentWidget()->hide(); } +//****************************************************** +void XGUI_MainWindow::dockPythonConsole() +{ + if (!myPythonConsole) + return; + myMenuBar->removeConsole(); + QDockWidget* aDock = new QDockWidget(this); + aDock->setFeatures(QDockWidget::AllDockWidgetFeatures | + QDockWidget::DockWidgetVerticalTitleBar); + aDock->setAllowedAreas(Qt::LeftDockWidgetArea | + Qt::RightDockWidgetArea | + Qt::BottomDockWidgetArea); + aDock->setMinimumHeight(0); + aDock->setWindowTitle("Console"); + aDock->setWidget(myPythonConsole); + addDockWidget(Qt::BottomDockWidgetArea, aDock); + // Undock python console if widget is closed... + CloseEventWatcher* aWatcher = new CloseEventWatcher(aDock); + connect(aWatcher, SIGNAL(widgetClosed()), + this, SLOT(undockPythonConsole())); + aDock->installEventFilter(aWatcher); +} + +void XGUI_MainWindow::undockPythonConsole() +{ + if (!myPythonConsole) + return; + QDockWidget* aDock = qobject_cast(myPythonConsole->parentWidget()); + //When the application starts console will be displayed as + //a wokbench tab, so there is no dock yet + if(aDock) { + aDock->hide(); + aDock->setWidget(NULL); + aDock->deleteLater(); + } + myMenuBar->insertConsole(myPythonConsole); +} + //****************************************************** void XGUI_MainWindow::createSubWindow() { @@ -205,3 +236,30 @@ void XGUI_MainWindow::closeEvent(QCloseEvent * event) emit exitKeySequence(); event->ignore(); } + +void XGUI_MainWindow::createMainMenu() +{ + myMenuBar = new XGUI_MainMenu(this); + QDockWidget* aMenuDock = new QDockWidget(this); + aMenuDock->setWidget(myMenuBar); + aMenuDock->setAllowedAreas(Qt::TopDockWidgetArea); + aMenuDock->setFeatures(QDockWidget::DockWidgetVerticalTitleBar); + aMenuDock->setWindowTitle(tr("General")); + addDockWidget(Qt::TopDockWidgetArea, aMenuDock); +} + +CloseEventWatcher::CloseEventWatcher(QObject* theParent) + : QObject(theParent) +{} + +bool CloseEventWatcher::eventFilter(QObject *obj, QEvent *event) { + if (event->type() == QEvent::Close) { + emit widgetClosed(); + event->ignore(); + return true; + } else { + // standard event processing + return QObject::eventFilter(obj, event); + } +} + diff --git a/src/XGUI/XGUI_MainWindow.h b/src/XGUI/XGUI_MainWindow.h index 010f9e309..2126834aa 100644 --- a/src/XGUI/XGUI_MainWindow.h +++ b/src/XGUI/XGUI_MainWindow.h @@ -44,6 +44,8 @@ public: public slots: void showPythonConsole(); void hidePythonConsole(); + void dockPythonConsole(); + void undockPythonConsole(); void createSubWindow(); @@ -59,12 +61,29 @@ signals: protected: void closeEvent(QCloseEvent* event); + void createMainMenu(); private: XGUI_MainMenu* myMenuBar; XGUI_Viewer* myViewer; PyConsole_EnhConsole* myPythonConsole; + //! Python console can be a dock widget if true, else as the tab. + bool myIsConsoleDocked; +}; + +class XGUI_EXPORT CloseEventWatcher: public QObject { + Q_OBJECT + + public: + CloseEventWatcher(QObject* theParent); + + signals: + void widgetClosed(); + + protected: + bool eventFilter(QObject *obj, QEvent *); + }; #endif diff --git a/src/XGUI/XGUI_MenuGroupPanel.cpp b/src/XGUI/XGUI_MenuGroupPanel.cpp index 8d5d24b21..f268c3691 100644 --- a/src/XGUI/XGUI_MenuGroupPanel.cpp +++ b/src/XGUI/XGUI_MenuGroupPanel.cpp @@ -10,14 +10,17 @@ #include XGUI_MenuGroupPanel::XGUI_MenuGroupPanel(QWidget *parent) - : QWidget(parent), myNewRow(0), myNewCol(0), myMaxRow(1) + : QFrame(parent), myNewRow(0), myNewCol(0), myMaxRow(1) { myLayout = new QGridLayout(this); myLayout->setSpacing(0); myLayout->setMargin(0); myLayout->setContentsMargins(0, 0, 0, 0); + setFrameShape(QFrame::NoFrame); } + + void XGUI_MenuGroupPanel::addCommand(XGUI_Command* theAction) { myActions.append(theAction); @@ -68,9 +71,9 @@ XGUI_Command* XGUI_MenuGroupPanel::addFeature(const QString& theId, const QStrin { XGUI_Command* aCommand = new XGUI_Command(theId, theIcon, theTitle, this, isCheckable); aCommand->setToolTip(theTip); - if (!theKeys.isEmpty()) + if (!theKeys.isEmpty()) { aCommand->setShortcut(theKeys); - + } addCommand(aCommand); return aCommand; } diff --git a/src/XGUI/XGUI_MenuGroupPanel.h b/src/XGUI/XGUI_MenuGroupPanel.h index b43ef75c6..07f51ed1e 100644 --- a/src/XGUI/XGUI_MenuGroupPanel.h +++ b/src/XGUI/XGUI_MenuGroupPanel.h @@ -2,20 +2,22 @@ #define XGUI_MenuGroupPanel_H #include "XGUI.h" -#include +#include #include class XGUI_Command; class QGridLayout; + /**\class XGUI_MenuGroupPanel * \ingroup GUI * \brief Represents a one group in a page of main menu (workbench) */ -class XGUI_EXPORT XGUI_MenuGroupPanel: public QWidget +class XGUI_EXPORT XGUI_MenuGroupPanel: public QFrame { -Q_OBJECT -public: + Q_OBJECT + + public: explicit XGUI_MenuGroupPanel(QWidget *parent = 0); //! Adding a new feature (Command) in the group diff --git a/src/XGUI/XGUI_Workshop.cpp b/src/XGUI/XGUI_Workshop.cpp index 8577da961..db0ab95fd 100644 --- a/src/XGUI/XGUI_Workshop.cpp +++ b/src/XGUI/XGUI_Workshop.cpp @@ -168,10 +168,8 @@ void XGUI_Workshop::initMenu() salomeConnector()->addEditMenuSeparator(); return; } - XGUI_Workbench* aPage = myMainWindow->menuObject()->generalPage(); - // File commands group - XGUI_MenuGroupPanel* aGroup = aPage->addGroup("Default"); + XGUI_MenuGroupPanel* aGroup = myMainWindow->menuObject()->generalPage(); XGUI_Command* aCommand; @@ -208,11 +206,11 @@ void XGUI_Workshop::initMenu() QIcon(":pictures/close.png"), QKeySequence::Close); aCommand->connectTo(this, SLOT(onExit())); //FIXME: SBH's test action. Can be used for some GUI tests. - //#ifdef _DEBUG - // aCommand = aGroup->addFeature("TEST_CMD", "Test!", "Private debug button", - // QIcon(":pictures/close.png")); - // aCommand->connectTo(myActionsMgr, SLOT(update())); - //#endif +// #ifdef _DEBUG +// aCommand = aGroup->addFeature("TEST_CMD", "Test!", "Private debug button", +// QIcon(":pictures/close.png"), QKeySequence(), true); +// aCommand->connectTo(myMainWindow, SLOT(dockPythonConsole())); +// #endif } //****************************************************** @@ -775,10 +773,8 @@ QList XGUI_Workshop::getModuleCommands() const } else { XGUI_MainMenu* aMenuBar = myMainWindow->menuObject(); foreach (XGUI_Workbench* aWb, aMenuBar->workbenches()) { - if (aWb != aMenuBar->generalPage()) { - foreach(XGUI_Command* aCmd, aWb->features()) - aCommands.append(aCmd); - } + foreach(XGUI_Command* aCmd, aWb->features()) + aCommands.append(aCmd); } } return aCommands; -- 2.39.2