SimplePanels Example

#include <QApplication>
#include <QScreen>
#include <QPainter>
#include <QAction>
#include <QFrame>
#include <QMessageBox>
#include <QResizeEvent>
#include <QStyleOption>

#include "mainwindow.h"

/* CustomWidget */
class CustomWidget : public QFrame
{
public:
    CustomWidget(const QString& strTitle, QFrame::Shape shape = QFrame::NoFrame);
    virtual ~CustomWidget();
protected:
    virtual void paintEvent(QPaintEvent* event);
protected:
    QString m_strTitle;
};

CustomWidget::CustomWidget(const QString& strTitle, QFrame::Shape shape)
    : m_strTitle(strTitle)
{
    setFocusPolicy(Qt::StrongFocus);
    setLineWidth(0);
    if (shape != QFrame::NoFrame)
    {
        setFrameShape(shape);
        setFrameShadow(QFrame::Sunken);
    }
}

CustomWidget::~CustomWidget()
{
}

void CustomWidget::paintEvent(QPaintEvent* event)
{
    QFrame::paintEvent(event);
    if (!m_strTitle.isEmpty())
    {
        QPainter painter(this);
        QStyleOption opt;
        opt.initFrom(this);
        painter.fillRect(opt.rect.adjusted(lineWidth(), lineWidth(), -lineWidth(), -lineWidth()), opt.palette.color(QPalette::Base));
        style()->drawItemText(&painter, opt.rect, Qt::TextShowMnemonic | Qt::AlignCenter, opt.palette, true, m_strTitle, QPalette::Text);
    }
}

/* MainWindow */
MainWindow::MainWindow(QWidget* parent)
    : DemoDockWindow(parent)
    , m_panel_1(Q_NULL)
    , m_panel_2(Q_NULL)
    , m_panel_3(Q_NULL)
{
    dockPanelManager()->setCentralWidget(new CustomWidget(tr("Central Widget")));
    createMenus();

    m_panel_1 = dockPanelManager()->addDockPanel(tr("Panel 1"), Qtitan::LeftDockPanelArea);
    m_panel_1->setObjectName("_qtn_widget_panel_id_1");
    m_panel_1->setWidget(new CustomWidget(tr("Custom Widget")));
    m_panel_1->setIcon(QIcon(QStringLiteral(":/res/resource_view.ico")));
    connect(m_panel_1, SIGNAL(featuresChanged(DockWidgetPanel::DockPanelFeatures)),
        this, SLOT(updateFeaturesActions(DockWidgetPanel::DockPanelFeatures)));

    m_panel_2 = dockPanelManager()->addDockPanel(tr("Panel 2"), Qtitan::RightDockPanelArea);
    m_panel_2->setObjectName("_qtn_widget_panel_id_2");
    m_panel_2->setIcon(QIcon(QStringLiteral(":/res/web.ico")));

    m_panel_3 = dockPanelManager()->addDockPanel(tr("Panel 3"), Qtitan::BottomDockPanelArea);
    m_panel_3->setObjectName("_qtn_widget_panel_id_3");
    m_panel_3->setIcon(QIcon(QStringLiteral(":/res/xml.ico")));

    connect(dockPanelManager(), SIGNAL(dockPanelActivated(DockWidgetPanel*)), this, SLOT(activationPanel(DockWidgetPanel*)));
    connect(dockPanelManager(), SIGNAL(dockPanelDeactivated(DockWidgetPanel*)), this, SLOT(deactivationPanel(DockWidgetPanel*)));
    connect(dockPanelManager(), SIGNAL(aboutToClose(DockPanelBase*, bool&)), this, SLOT(aboutToClosePanel(DockPanelBase*, bool&)));

    if (centralWidget() != Q_NULL)
        centralWidget()->setFocus();

#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
    const QRect availableGeometry = screen()->availableGeometry();
#else
    const QRect availableGeometry = QGuiApplication::primaryScreen()->availableGeometry();
#endif
    resize(availableGeometry.width() / 2, availableGeometry.height() / 2);
    move((availableGeometry.width() - width()) / 2, (availableGeometry.height() - height()) / 2);

    if (m_panel_1 != Q_NULL)
        initFeaturesActions(m_panel_1->features());

    readSettings();
}

MainWindow::~MainWindow()
{
    writeSettings();
}

void MainWindow::createMenus()
{
    QMenu* panelsMenu = menuBar()->addMenu(tr("&Panels"));
    QMenu* subPanelMenu_1 = panelsMenu->addMenu(tr("Panel 1"));
    QMenu* subPanelMenu_2 = panelsMenu->addMenu(tr("Panel 2"));
    QMenu* subPanelMenu_3 = panelsMenu->addMenu(tr("Panel 3"));
    panelsMenu->addSeparator();
    QAction* subActionDragging = panelsMenu->addAction(tr("Shown Dragging Contents"));
    subActionDragging->setCheckable(true);
    subActionDragging->setChecked(false);
    connect(subActionDragging, SIGNAL(toggled(bool)), this, SLOT(draggingFrameActions(bool)));

    if (QWidget* centralWidget = this->centralWidget())
    {
        panelsMenu->addSeparator();
        QAction* actCentralWidget = panelsMenu->addAction(tr("Show central widget"));
        actCentralWidget->setCheckable(true);
        actCentralWidget->setChecked(!centralWidget->isHidden());
        connect(actCentralWidget, SIGNAL(toggled(bool)), this, SLOT(showCentralWidget(bool)));
    }
    connect(panelsMenu, SIGNAL(aboutToShow()), this, SLOT(enableActions()));

    m_panelFloatAction_1 = new QAction(tr("Float"), this);
    subPanelMenu_1->addAction(m_panelFloatAction_1);
    connect(m_panelFloatAction_1, SIGNAL(triggered()), this, SLOT(triggeredPanelFloat_1()));

    m_panelDockAction_1 = new QAction(tr("Dock"), this);
    subPanelMenu_1->addAction(m_panelDockAction_1);
    connect(m_panelDockAction_1, SIGNAL(triggered()), this, SLOT(triggeredPanelDock_1()));

    m_panelAutoHideAction_1 = new QAction(tr("Auto Hide"), this);
    subPanelMenu_1->addAction(m_panelAutoHideAction_1);
    connect(m_panelAutoHideAction_1, SIGNAL(triggered()), this, SLOT(triggeredPanelAutoHide_1()));

    m_panelHideAction_1 = new QAction(tr("Hide"), this);
    subPanelMenu_1->addAction(m_panelHideAction_1);
    connect(m_panelHideAction_1, SIGNAL(triggered()), this, SLOT(triggeredPanelHide_1()));

    m_panelShowAction_1 = new QAction(tr("Show"), this);
    subPanelMenu_1->addAction(m_panelShowAction_1);
    connect(m_panelShowAction_1, SIGNAL(triggered()), this, SLOT(triggeredPanelShow_1()));

    //////////////////////////////////////////////////////////////////////////////////

    m_panelFloatAction_2 = new QAction(tr("Float"), this);
    subPanelMenu_2->addAction(m_panelFloatAction_2);
    connect(m_panelFloatAction_2, SIGNAL(triggered()), this, SLOT(triggeredPanelFloat_2()));

    m_panelDockAction_2 = new QAction(tr("Dock"), this);
    subPanelMenu_2->addAction(m_panelDockAction_2);
    connect(m_panelDockAction_2, SIGNAL(triggered()), this, SLOT(triggeredPanelDock_2()));

    m_panelAutoHideAction_2 = new QAction(tr("Auto Hide"), this);
    subPanelMenu_2->addAction(m_panelAutoHideAction_2);
    connect(m_panelAutoHideAction_2, SIGNAL(triggered()), this, SLOT(triggeredPanelAutoHide_2()));

    m_panelHideAction_2 = new QAction(tr("Hide"), this);
    subPanelMenu_2->addAction(m_panelHideAction_2);
    connect(m_panelHideAction_2, SIGNAL(triggered()), this, SLOT(triggeredPanelHide_2()));

    m_panelShowAction_2 = new QAction(tr("Show"), this);
    subPanelMenu_2->addAction(m_panelShowAction_2);
    connect(m_panelShowAction_2, SIGNAL(triggered()), this, SLOT(triggeredPanelShow_2()));

    //////////////////////////////////////////////////////////////////////////////////
    m_panelFloatableAction_1 = new QAction(QStringLiteral("DockPanelFloatable"), this); m_panelFloatableAction_1->setCheckable(true);
    connect(m_panelFloatableAction_1, SIGNAL(triggered(bool)), this, SLOT(triggeredPanelFeature_1(bool)));
    m_panelClosableAction_1 = new QAction(QStringLiteral("DockPanelClosable"), this); m_panelClosableAction_1->setCheckable(true);
    connect(m_panelClosableAction_1, SIGNAL(triggered(bool)), this, SLOT(triggeredPanelFeature_1(bool)));
    m_panelHideableAction_1 = new QAction(QStringLiteral("DockPanelHideable"), this); m_panelHideableAction_1->setCheckable(true);
    connect(m_panelHideableAction_1, SIGNAL(triggered(bool)), this, SLOT(triggeredPanelFeature_1(bool)));
    m_panelMenuButtonAction_1 = new QAction(QStringLiteral("DockPanelMenuButton"), this); m_panelMenuButtonAction_1->setCheckable(true);
    connect(m_panelMenuButtonAction_1, SIGNAL(triggered(bool)), this, SLOT(triggeredPanelFeature_1(bool)));
    m_panelNoCaptionAction_1 = new QAction(QStringLiteral("DockPanelNoCaption"), this); m_panelNoCaptionAction_1->setCheckable(true);
    connect(m_panelNoCaptionAction_1, SIGNAL(triggered(bool)), this, SLOT(triggeredPanelFeature_1(bool)));
    //////////////////////////////////////////////////////////////////////////////////

    m_panelFloatAction_3 = new QAction(tr("Float"), this);
    subPanelMenu_3->addAction(m_panelFloatAction_3);
    connect(m_panelFloatAction_3, SIGNAL(triggered()), this, SLOT(triggeredPanelFloat_3()));

    m_panelDockAction_3 = new QAction(tr("Dock"), this);
    subPanelMenu_3->addAction(m_panelDockAction_3);
    connect(m_panelDockAction_3, SIGNAL(triggered()), this, SLOT(triggeredPanelDock_3()));

    m_panelAutoHideAction_3 = new QAction(tr("Auto Hide"), this);
    subPanelMenu_3->addAction(m_panelAutoHideAction_3);
    connect(m_panelAutoHideAction_3, SIGNAL(triggered()), this, SLOT(triggeredPanelAutoHide_3()));

    m_panelHideAction_3 = new QAction(tr("Hide"), this);
    subPanelMenu_3->addAction(m_panelHideAction_3);
    connect(m_panelHideAction_3, SIGNAL(triggered()), this, SLOT(triggeredPanelHide_3()));

    m_panelShowAction_3 = new QAction(tr("Show"), this);
    subPanelMenu_3->addAction(m_panelShowAction_3);
    connect(m_panelShowAction_3, SIGNAL(triggered()), this, SLOT(triggeredPanelShow_3()));

    m_panelHoverShow = new QAction(tr("DockPanelHoverShow"), this); m_panelHoverShow->setCheckable(true);
    connect(m_panelHoverShow, SIGNAL(triggered(bool)), this, SLOT(triggeredPanelHoverShow(bool)));

    QMenu* featureMenu = menuBar()->addMenu(tr("&Feature"));
    connect(featureMenu, SIGNAL(aboutToShow()), this, SLOT(enableFeatures()));
    QMenu* subFeatureMenu_1 = featureMenu->addMenu(tr("Panel 1"));
    subFeatureMenu_1->addAction(m_panelFloatableAction_1);
    subFeatureMenu_1->addAction(m_panelMenuButtonAction_1);
    subFeatureMenu_1->addAction(m_panelHideableAction_1);
    subFeatureMenu_1->addAction(m_panelClosableAction_1);
    subFeatureMenu_1->addSeparator();
    subFeatureMenu_1->addAction(m_panelNoCaptionAction_1);
    featureMenu->addSeparator();
    featureMenu->addAction(m_panelHoverShow);

    QMenu* menu = menuBar()->addMenu(tr("&View"));
    addSaveLoadMenu(menu);
    menu->addSeparator();
    addStyleMenu(menu);

    QMenu* helpMenu = menuBar()->addMenu(tr("&Help"));
    helpMenu->addAction(m_aboutAction);
}

void MainWindow::enableActions()
{
    DockPanelManager* panelManager = dockPanelManager();
    Q_ASSERT(panelManager != Q_NULL);
    if (m_panel_1 != Q_NULL)
    {
        m_panelFloatAction_1->setEnabled(!panelManager->isDockPanelFloat(m_panel_1) && !panelManager->isDockPanelAutoHide(m_panel_1) &&
            !m_panel_1->isClosed() && m_panel_1->features().testFlag(DockWidgetPanel::DockPanelFloatable));
        m_panelDockAction_1->setEnabled((panelManager->isDockPanelFloat(m_panel_1) || panelManager->isDockPanelAutoHide(m_panel_1)) && !m_panel_1->isClosed());
        m_panelAutoHideAction_1->setEnabled((!panelManager->isDockPanelAutoHide(m_panel_1) && !panelManager->isDockPanelFloat(m_panel_1)) &&
            !m_panel_1->isClosed() && m_panel_1->features().testFlag(DockWidgetPanel::DockPanelHideable));
        m_panelHideAction_1->setEnabled(!m_panel_1->isClosed() && m_panel_1->features().testFlag(DockWidgetPanel::DockPanelClosable));
        m_panelShowAction_1->setEnabled(m_panel_1->isClosed() && m_panel_1->features().testFlag(DockWidgetPanel::DockPanelClosable));
    }
    else
    {
        m_panelFloatAction_1->setEnabled(false);
        m_panelDockAction_1->setEnabled(false);
        m_panelAutoHideAction_1->setEnabled(false);
        m_panelHideAction_1->setEnabled(false);
        m_panelShowAction_1->setEnabled(false);
    }
    if (m_panel_2 != Q_NULL)
    {
        m_panelFloatAction_2->setEnabled(!panelManager->isDockPanelFloat(m_panel_2) && !panelManager->isDockPanelAutoHide(m_panel_2) &&
            !m_panel_2->isClosed() && m_panel_2->features().testFlag(DockWidgetPanel::DockPanelFloatable));
        m_panelDockAction_2->setEnabled((panelManager->isDockPanelFloat(m_panel_2) || dockPanelManager()->isDockPanelAutoHide(m_panel_2)) && !m_panel_2->isClosed());
        m_panelAutoHideAction_2->setEnabled((!panelManager->isDockPanelAutoHide(m_panel_2) && !panelManager->isDockPanelFloat(m_panel_2)) &&
            !m_panel_2->isClosed() && m_panel_2->features().testFlag(DockWidgetPanel::DockPanelHideable));
        m_panelHideAction_2->setEnabled(!m_panel_2->isClosed() && m_panel_2->features().testFlag(DockWidgetPanel::DockPanelClosable));
        m_panelShowAction_2->setEnabled(m_panel_2->isClosed() && m_panel_2->features().testFlag(DockWidgetPanel::DockPanelClosable));
    }
    else
    {
        m_panelFloatAction_2->setEnabled(false);
        m_panelDockAction_2->setEnabled(false);
        m_panelAutoHideAction_2->setEnabled(false);
        m_panelHideAction_2->setEnabled(false);
        m_panelShowAction_2->setEnabled(false);
    }
    if (m_panel_3 != Q_NULL)
    {
        m_panelFloatAction_3->setEnabled(!panelManager->isDockPanelFloat(m_panel_3) && !panelManager->isDockPanelAutoHide(m_panel_3) &&
            !m_panel_3->isClosed() && m_panel_3->features().testFlag(DockWidgetPanel::DockPanelFloatable));
        m_panelDockAction_3->setEnabled((panelManager->isDockPanelFloat(m_panel_3) || panelManager->isDockPanelAutoHide(m_panel_3)) && !m_panel_3->isClosed());
        m_panelAutoHideAction_3->setEnabled((!panelManager->isDockPanelAutoHide(m_panel_3) && !panelManager->isDockPanelFloat(m_panel_3)) &&
            !m_panel_3->isClosed() && m_panel_3->features().testFlag(DockWidgetPanel::DockPanelHideable));
        m_panelHideAction_3->setEnabled(!m_panel_3->isClosed() && m_panel_3->features().testFlag(DockWidgetPanel::DockPanelClosable));
        m_panelShowAction_3->setEnabled(m_panel_3->isClosed() && m_panel_3->features().testFlag(DockWidgetPanel::DockPanelClosable));
    }
    else
    {
        m_panelFloatAction_3->setEnabled(false);
        m_panelDockAction_3->setEnabled(false);
        m_panelAutoHideAction_3->setEnabled(false);
        m_panelHideAction_3->setEnabled(false);
        m_panelShowAction_3->setEnabled(false);
    }
}

void MainWindow::enableFeatures()
{
    m_panelHoverShow->setChecked(dockPanelManager()->options().features().testFlag(DockWidgetPanel::DockPanelHoverShow));
}

void MainWindow::updateFeaturesActions(DockWidgetPanel::DockPanelFeatures features)
{
    initFeaturesActions(features);
}

void MainWindow::triggeredPanelFloat_1()
{
    dockPanelManager()->setDockPanelFloat(m_panel_1, true);
}

void MainWindow::triggeredPanelDock_1()
{
    if (m_panel_1 != nullptr)
        dockPanelManager()->setDockPanelFloat(m_panel_1, false);
}

void MainWindow::triggeredPanelAutoHide_1()
{
    if (m_panel_1 != nullptr)
        dockPanelManager()->setDockPanelAutoHide(m_panel_1, true);
}

void MainWindow::triggeredPanelHide_1()
{
    if (!m_panel_1->isClosed())
        m_panel_1->closePanel();
}

void MainWindow::triggeredPanelShow_1()
{
    if (m_panel_1->isClosed())
        dockPanelManager()->showDockPanel(m_panel_1);
}

void MainWindow::triggeredPanelFeature_1(bool checked)
{
    QAction* actionSender = qobject_cast<QAction*>(sender());
    if (actionSender == Q_NULL)
        return;
    DockWidgetPanel::DockPanelFeatures flags = m_panel_1->features();
    if (actionSender == m_panelFloatableAction_1)
    {
        if (checked)
            flags |= DockWidgetPanel::DockPanelFloatable;
        else
            flags &= ~DockWidgetPanel::DockPanelFloatable;
    }
    else if (actionSender == m_panelClosableAction_1)
    {
        if (checked)
            flags |= DockWidgetPanel::DockPanelClosable;
        else
            flags &= ~DockWidgetPanel::DockPanelClosable;
    }
    else if (actionSender == m_panelHideableAction_1)
    {
        if (checked)
            flags |= DockWidgetPanel::DockPanelHideable;
        else
            flags &= ~DockWidgetPanel::DockPanelHideable;
    }
    else if (actionSender == m_panelMenuButtonAction_1)
    {
        if (checked)
            flags |= DockWidgetPanel::DockPanelMenuButton;
        else
            flags &= ~DockWidgetPanel::DockPanelMenuButton;
    }
    else if (actionSender == m_panelNoCaptionAction_1)
    {
        if (checked)
            flags |= DockWidgetPanel::DockPanelNoCaption;
        else
            flags &= ~DockWidgetPanel::DockPanelNoCaption;
    }
    m_panel_1->setFeatures(flags);
}

// 2
void MainWindow::triggeredPanelFloat_2()
{
    dockPanelManager()->setDockPanelFloat(m_panel_2, true);
}

void MainWindow::triggeredPanelDock_2()
{
    dockPanelManager()->setDockPanelFloat(m_panel_2, false);
}

void MainWindow::triggeredPanelAutoHide_2()
{
    dockPanelManager()->setDockPanelAutoHide(m_panel_2, true);
}

void MainWindow::triggeredPanelHide_2()
{
    if (!m_panel_2->isClosed())
        m_panel_2->closePanel();
}

void MainWindow::triggeredPanelShow_2()
{
    if (m_panel_2->isClosed())
        dockPanelManager()->showDockPanel(m_panel_2);
}
// 3
void MainWindow::triggeredPanelFloat_3()
{
    dockPanelManager()->setDockPanelFloat(m_panel_3, true);
}

void MainWindow::triggeredPanelDock_3()
{
    dockPanelManager()->setDockPanelFloat(m_panel_3, false);
}

void MainWindow::triggeredPanelAutoHide_3()
{
    dockPanelManager()->setDockPanelAutoHide(m_panel_3, true);
}

void MainWindow::triggeredPanelHide_3()
{
    if (!m_panel_3->isClosed())
        m_panel_3->closePanel();
}

void MainWindow::triggeredPanelShow_3()
{
    if (m_panel_3->isClosed())
        dockPanelManager()->showDockPanel(m_panel_3);
}

void MainWindow::triggeredPanelHoverShow(bool checked)
{
    DockWidgetPanel::DockPanelFeatures flags = dockPanelManager()->options().features();
    if (checked)
        flags |= DockWidgetPanel::DockPanelHoverShow;
    else
        flags &= ~DockWidgetPanel::DockPanelHoverShow;
    dockPanelManager()->options().setFeatures(flags);
}

void MainWindow::activationPanel(DockWidgetPanel* dockWidget)
{
    QString titleText = QCoreApplication::applicationName();
    titleText += QStringLiteral(" - ");
    titleText += dockWidget->windowTitle();
    setWindowTitle(titleText);
}

void MainWindow::deactivationPanel(DockWidgetPanel* dockWidget)
{
    Q_UNUSED(dockWidget);
    QString titleText = QCoreApplication::applicationName();
    setWindowTitle(titleText);
}

void MainWindow::draggingFrameActions(bool dragging)
{
    dockPanelManager()->options().setDockPanelTransparentWhileDragging(!dragging);
    dockPanelManager()->options().setArrowMarkersShown(!dragging);
    dockPanelManager()->options().setDockPanelFullContentsWhileDraggingShown(!dragging);
}

void MainWindow::showCentralWidget(bool visible)
{
#if 0
    if (QWidget* widget = centralWidget())
        widget->setVisible(visible);
#else
    QWidget* widget = centralWidget();
    dockPanelManager()->setCentralWidget(visible ? new CustomWidget(tr("Central Widget")) : Q_NULL);
    delete widget;
#endif
}

void MainWindow::aboutToClosePanel(DockPanelBase* panel, bool& handled)
{
    if (panel == m_panel_1)
    {
        QMessageBox messageBox(QMessageBox::Information, windowTitle(), QStringLiteral("Warning"), QMessageBox::Yes | QMessageBox::No, this);
        messageBox.setInformativeText(QStringLiteral("Are you sure you want to close this panel?"));
        handled = messageBox.exec() == QMessageBox::Yes;
    }
}

void MainWindow::initFeaturesActions(DockWidgetPanel::DockPanelFeatures features)
{
    m_panelFloatableAction_1->setChecked(features.testFlag(DockWidgetPanel::DockPanelFloatable));
    m_panelClosableAction_1->setChecked(features.testFlag(DockWidgetPanel::DockPanelClosable));
    m_panelHideableAction_1->setChecked(features.testFlag(DockWidgetPanel::DockPanelHideable));
    m_panelMenuButtonAction_1->setChecked(features.testFlag(DockWidgetPanel::DockPanelMenuButton));
    m_panelNoCaptionAction_1->setChecked(features.testFlag(DockWidgetPanel::DockPanelNoCaption));
}

void MainWindow::closeEvent(QCloseEvent* event)
{
    event->accept();
}