File indexing completed on 2024-04-28 04:37:32
0001 /* 0002 SPDX-FileCopyrightText: 2007 Roberto Raggi <roberto@kdevelop.org> 0003 SPDX-FileCopyrightText: 2007 Hamish Rodda <rodda@kde.org> 0004 SPDX-FileCopyrightText: 2011 Alexander Dymo <adymo@kdevelop.org> 0005 0006 SPDX-License-Identifier: LicenseRef-MIT-KDevelop-Ideal 0007 */ 0008 0009 #include "idealdockwidget.h" 0010 #include "mainwindow.h" 0011 #include "area.h" 0012 #include "document.h" 0013 #include "view.h" 0014 0015 #include <util/scopeddialog.h> 0016 0017 #include <KConfigGroup> 0018 #include <KLocalizedString> 0019 #include <KSharedConfig> 0020 #include <KShortcutWidget> 0021 0022 #include <QAbstractButton> 0023 #include <QDialog> 0024 #include <QDialogButtonBox> 0025 #include <QToolBar> 0026 #include <QVBoxLayout> 0027 #include <QActionGroup> 0028 0029 using namespace Sublime; 0030 0031 IdealDockWidget::IdealDockWidget(IdealController *controller, Sublime::MainWindow *parent) 0032 : QDockWidget(parent), 0033 m_area(nullptr), 0034 m_view(nullptr), 0035 m_docking_area(Qt::NoDockWidgetArea), 0036 m_controller(controller) 0037 { 0038 setAutoFillBackground(true); 0039 setContextMenuPolicy(Qt::CustomContextMenu); 0040 connect(this, &IdealDockWidget::customContextMenuRequested, 0041 this, &IdealDockWidget::contextMenuRequested); 0042 0043 auto *closeButton = findChild<QAbstractButton *>(QStringLiteral("qt_dockwidget_closebutton")); 0044 if (closeButton) { 0045 disconnect(closeButton, &QAbstractButton::clicked, nullptr, nullptr); 0046 0047 connect(closeButton, &QAbstractButton::clicked, this, &IdealDockWidget::closeRequested); 0048 } 0049 0050 setFeatures(QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable); 0051 // do not allow to move docks to the top dock area (no buttonbar there in our current UI) 0052 setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea | Qt::BottomDockWidgetArea); 0053 } 0054 0055 IdealDockWidget::~IdealDockWidget() 0056 { 0057 } 0058 0059 Area *IdealDockWidget::area() const 0060 { return m_area; } 0061 0062 void IdealDockWidget::setArea(Area *area) 0063 { m_area = area; } 0064 0065 View *IdealDockWidget::view() const 0066 { return m_view; } 0067 0068 void IdealDockWidget::setView(View *view) 0069 { m_view = view; } 0070 0071 Qt::DockWidgetArea IdealDockWidget::dockWidgetArea() const 0072 { return m_docking_area; } 0073 0074 void IdealDockWidget::setDockWidgetArea(Qt::DockWidgetArea dockingArea) 0075 { m_docking_area = dockingArea; } 0076 0077 void IdealDockWidget::slotRemove() 0078 { 0079 m_area->removeToolView(m_view); 0080 } 0081 0082 void IdealDockWidget::contextMenuRequested(const QPoint &point) 0083 { 0084 QWidget* senderWidget = qobject_cast<QWidget*>(sender()); 0085 Q_ASSERT(senderWidget); 0086 0087 KDevelop::ScopedDialog<QMenu> menu(senderWidget); 0088 menu->addSection(windowIcon(), m_view->document()->title()); 0089 0090 const QList<QAction*> viewActions = m_view->contextMenuActions(); 0091 if(!viewActions.isEmpty()) { 0092 // add the view's actions to the context menu, 0093 // checking each if it can be represented 0094 for (const auto action : viewActions) { 0095 if (!action->text().isEmpty() && !action->iconText().isEmpty()) { 0096 // avoid adding empty menu items 0097 menu->addAction(action); 0098 } 0099 } 0100 menu->addSeparator(); 0101 } 0102 0103 ///TODO: can this be cleaned up? 0104 if(auto* toolBar = widget()->findChild<QToolBar*>()) { 0105 menu->addAction(toolBar->toggleViewAction()); 0106 menu->addSeparator(); 0107 } 0108 0109 /// start position menu 0110 QMenu* positionMenu = menu->addMenu(i18nc("@title:menu", "Tool View Position")); 0111 0112 auto* g = new QActionGroup(positionMenu); 0113 0114 auto* left = new QAction(i18nc("@option:radio tool view position", "Left"), g); 0115 auto* bottom = new QAction(i18nc("@option:radio tool view position", "Bottom"), g); 0116 auto* right = new QAction(i18nc("@option:radio tool view position", "Right"), g); 0117 auto* detach = new QAction(i18nc("@option:radio tool view position", "Detached"), g); 0118 0119 for (auto action : {left, bottom, right, detach}) { 0120 positionMenu->addAction(action); 0121 action->setCheckable(true); 0122 } 0123 if (isFloating()) { 0124 detach->setChecked(true); 0125 } else if (m_docking_area == Qt::BottomDockWidgetArea) 0126 bottom->setChecked(true); 0127 else if (m_docking_area == Qt::LeftDockWidgetArea) 0128 left->setChecked(true); 0129 else if (m_docking_area == Qt::RightDockWidgetArea) 0130 right->setChecked(true); 0131 /// end position menu 0132 0133 menu->addSeparator(); 0134 0135 QAction *setShortcut = menu->addAction(QIcon::fromTheme(QStringLiteral("configure-shortcuts")), i18nc("@action:inmenu", "Assign Shortcut...")); 0136 setShortcut->setToolTip(i18nc("@info:tooltip", "Use this shortcut to trigger visibility of the tool view.")); 0137 0138 menu->addSeparator(); 0139 QAction* remove = menu->addAction(QIcon::fromTheme(QStringLiteral("dialog-close")), i18nc("@action:inmenu", "Remove Tool View")); 0140 0141 QAction* triggered = menu->exec(senderWidget->mapToGlobal(point)); 0142 0143 if (triggered) 0144 { 0145 if ( triggered == remove ) { 0146 slotRemove(); 0147 return; 0148 } else if ( triggered == setShortcut ) { 0149 auto* dialog = new QDialog(this); 0150 dialog->setWindowTitle(i18nc("@title:window", "Assign Shortcut For '%1' Tool View", m_view->document()->title())); 0151 auto *w = new KShortcutWidget(dialog); 0152 w->setShortcut(m_controller->actionForView(m_view)->shortcuts()); 0153 auto* dialogLayout = new QVBoxLayout(dialog); 0154 dialogLayout->addWidget(w); 0155 auto* buttonBox = new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel ); 0156 dialogLayout->addWidget(buttonBox); 0157 connect(buttonBox, &QDialogButtonBox::accepted, dialog, &QDialog::accept); 0158 connect(buttonBox, &QDialogButtonBox::rejected, dialog, &QDialog::reject); 0159 0160 if (dialog->exec() == QDialog::Accepted) { 0161 m_controller->actionForView(m_view)->setShortcuts(w->shortcut()); 0162 0163 //save shortcut config 0164 KConfigGroup config = KSharedConfig::openConfig()->group("UI"); 0165 const QStringList shortcuts{ 0166 w->shortcut().value(0).toString(), 0167 w->shortcut().value(1).toString(), 0168 }; 0169 config.writeEntry(QStringLiteral("Shortcut for %1").arg(m_view->document()->title()), shortcuts); 0170 config.sync(); 0171 } 0172 delete dialog; 0173 0174 return; 0175 } else if ( triggered == detach ) { 0176 setFloating(true); 0177 m_area->raiseToolView(m_view); 0178 return; 0179 } 0180 0181 if (isFloating()) { 0182 setFloating(false); 0183 } 0184 0185 Sublime::Position pos; 0186 if (triggered == left) 0187 pos = Sublime::Left; 0188 else if (triggered == bottom) 0189 pos = Sublime::Bottom; 0190 else if (triggered == right) 0191 pos = Sublime::Right; 0192 else 0193 return; 0194 0195 Area *area = m_area; 0196 View *view = m_view; 0197 /* This call will delete *this, so we no longer 0198 can access member variables. */ 0199 m_area->moveToolView(m_view, pos); 0200 area->raiseToolView(view); 0201 } 0202 } 0203 0204 #include "moc_idealdockwidget.cpp"