MuseScore/src/appshell/view/dockwindow/dockpanelview.cpp

284 lines
6.9 KiB
C++

/*
* SPDX-License-Identifier: GPL-3.0-only
* MuseScore-CLA-applies
*
* MuseScore
* Music Composition & Notation
*
* Copyright (C) 2021 MuseScore BVBA and others
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "dockpanelview.h"
#include "thirdparty/KDDockWidgets/src/DockWidgetQuick.h"
#include "thirdparty/KDDockWidgets/src/private/Frame_p.h"
#include "log.h"
#include "translation.h"
#include "ui/uitypes.h"
#include "uicomponents/view/abstractmenumodel.h"
using namespace mu::dock;
using namespace mu::ui;
using namespace mu::uicomponents;
using namespace mu::actions;
static const QString SET_DOCK_OPEN_ACTION_CODE = "dock-set-open";
static const QString TOGGLE_FLOATING_ACTION_CODE = "dock-toggle-floating";
class DockPanelView::DockPanelMenuModel : public uicomponents::AbstractMenuModel
{
public:
DockPanelMenuModel(DockPanelView* panel)
: AbstractMenuModel(panel), m_panel(panel)
{
listenFloatingChanged();
}
void load() override
{
TRACEFUNC;
MenuItemList items;
if (m_customMenuModel && m_customMenuModel->rowCount() > 0) {
items << m_customMenuModel->items();
items << makeSeparator();
}
MenuItem* closeDockItem = makeMenuItem(SET_DOCK_OPEN_ACTION_CODE, mu::qtrc("dock", "Close"));
closeDockItem->setArgs(ActionData::make_arg2<QString, bool>(m_panel->objectName(), false));
items << closeDockItem;
MenuItem* toggleFloatingItem = makeMenuItem(TOGGLE_FLOATING_ACTION_CODE, toggleFloatingActionTitle());
toggleFloatingItem->setArgs(ActionData::make_arg1<QString>(m_panel->objectName()));
items << toggleFloatingItem;
setItems(items);
}
AbstractMenuModel* customMenuModel() const
{
return m_customMenuModel;
}
void setCustomMenuModel(AbstractMenuModel* model)
{
m_customMenuModel = model;
if (!model) {
return;
}
connect(model, &AbstractMenuModel::itemsChanged, this, [this]() {
load();
});
connect(model, &AbstractMenuModel::itemChanged, this, [this](MenuItem* item) {
updateItem(item);
});
}
private:
MenuItem* makeMenuItem(const QString& actionCode, const QString& title)
{
MenuItem* item = new MenuItem(this);
item->setId(actionCode);
UiAction action;
action.code = codeFromQString(actionCode);
action.title = title;
item->setAction(action);
UiActionState state;
state.enabled = true;
item->setState(state);
return item;
}
QString toggleFloatingActionTitle() const
{
return m_panel->floating() ? mu::qtrc("dock", "Dock") : mu::qtrc("dock", "Undock");
}
void listenFloatingChanged()
{
connect(m_panel, &DockPanelView::floatingChanged, this, [this]() {
int index = itemIndex(TOGGLE_FLOATING_ACTION_CODE);
if (index == INVALID_ITEM_INDEX) {
return;
}
MenuItem& item = this->item(index);
UiAction action = item.action();
action.title = toggleFloatingActionTitle();
item.setAction(action);
});
}
void updateItem(MenuItem* newItem)
{
int index = itemIndex(newItem->id());
if (index == INVALID_ITEM_INDEX) {
return;
}
setItem(index, newItem);
}
AbstractMenuModel* m_customMenuModel = nullptr;
DockPanelView* m_panel = nullptr;
};
DockPanelView::DockPanelView(QQuickItem* parent)
: DockBase(DockType::Panel, parent), m_menuModel(new DockPanelMenuModel(this))
{
setLocation(Location::Left);
}
DockPanelView::~DockPanelView()
{
KDDockWidgets::DockWidgetQuick* dockWidget = this->dockWidget();
IF_ASSERT_FAILED(dockWidget) {
return;
}
dockWidget->setProperty(DOCK_PANEL_PROPERTY, QVariant::fromValue(nullptr));
dockWidget->setProperty(CONTEXT_MENU_MODEL_PROPERTY, QVariant::fromValue(nullptr));
}
QString DockPanelView::groupName() const
{
return m_groupName;
}
void DockPanelView::setGroupName(const QString& name)
{
if (m_groupName == name) {
return;
}
m_groupName = name;
emit groupNameChanged();
}
void DockPanelView::componentComplete()
{
DockBase::componentComplete();
KDDockWidgets::DockWidgetQuick* dockWidget = this->dockWidget();
IF_ASSERT_FAILED(dockWidget) {
return;
}
m_menuModel->load();
dockWidget->setProperty(DOCK_PANEL_PROPERTY, QVariant::fromValue(this));
dockWidget->setProperty(CONTEXT_MENU_MODEL_PROPERTY, QVariant::fromValue(m_menuModel));
connect(m_menuModel, &AbstractMenuModel::itemsChanged, [dockWidget, this]() {
if (dockWidget) {
dockWidget->setProperty(CONTEXT_MENU_MODEL_PROPERTY, QVariant::fromValue(m_menuModel));
}
});
}
QObject* DockPanelView::navigationSection() const
{
return m_navigationSection;
}
void DockPanelView::setNavigationSection(QObject* newNavigation)
{
if (m_navigationSection == newNavigation) {
return;
}
m_navigationSection = newNavigation;
emit navigationSectionChanged();
}
AbstractMenuModel* DockPanelView::contextMenuModel() const
{
return m_menuModel->customMenuModel();
}
void DockPanelView::setContextMenuModel(AbstractMenuModel* model)
{
if (m_menuModel->customMenuModel() == model) {
return;
}
m_menuModel->setCustomMenuModel(model);
m_menuModel->load();
emit contextMenuModelChanged();
}
bool DockPanelView::isTabAllowed(const DockPanelView* tab) const
{
IF_ASSERT_FAILED(tab) {
return false;
}
if (tab == this) {
return false;
}
if (!isOpen()) {
return false;
}
if (floating()) {
return false;
}
if (m_groupName.isEmpty() || tab->m_groupName.isEmpty()) {
return false;
}
return m_groupName == tab->m_groupName;
}
void DockPanelView::addPanelAsTab(DockPanelView* tab)
{
IF_ASSERT_FAILED(tab && dockWidget()) {
return;
}
if (!isTabAllowed(tab)) {
return;
}
dockWidget()->addDockWidgetAsTab(tab->dockWidget());
tab->setVisible(true);
}
void DockPanelView::setCurrentTabIndex(int index)
{
IF_ASSERT_FAILED(dockWidget()) {
return;
}
KDDockWidgets::Frame* frame = dockWidget()->frame();
if (frame) {
frame->setCurrentTabIndex(index);
}
}