diff --git a/sublime/idealbuttonbarwidget.h b/sublime/idealbuttonbarwidget.h --- a/sublime/idealbuttonbarwidget.h +++ b/sublime/idealbuttonbarwidget.h @@ -36,6 +36,8 @@ class View; class Area; +class LockButton; + class IdealButtonBarWidget: public QWidget { Q_OBJECT @@ -59,6 +61,11 @@ void showWidget(QAction *widgetAction, bool checked); bool isEmpty(); + bool isShown(); + + bool isLocked(); + void setLocked(bool); + private Q_SLOTS: void showWidget(bool checked); void buttonPressed(bool state); @@ -75,6 +82,8 @@ QHash _buttons; QHash _widgets; QWidget *_corner; + bool _isLocked; + LockButton* _lockButton; }; } diff --git a/sublime/idealbuttonbarwidget.cpp b/sublime/idealbuttonbarwidget.cpp --- a/sublime/idealbuttonbarwidget.cpp +++ b/sublime/idealbuttonbarwidget.cpp @@ -37,12 +37,79 @@ using namespace Sublime; +class Sublime::LockButton : public IdealToolButton +{ +public: + LockButton(IdealButtonBarWidget* barWidget) + : IdealToolButton(barWidget->area(), barWidget) + , _barWidget(barWidget) + { + QAction* lockAction = new QAction(this); + lockAction->setCheckable(true); + lockAction->setToolTip(i18nc("@info:tooltip", "Lock/Unlock the Panel")); + setDefaultAction(lockAction); + + setLocked(barWidget->isLocked()); + setEnabled(barWidget->isShown()); + + connect(lockAction, &QAction::toggled, this, &LockButton::setLocked); + } + + bool isLocked() + { + return defaultAction()->isChecked(); + } + + void setLocked(bool lockValue) + { + defaultAction()->setIcon(lockIcon(lockValue)); + + + if (isLocked() != lockValue) + defaultAction()->setChecked(lockValue); + + if (_barWidget->isLocked() != lockValue) + _barWidget->setLocked(lockValue); + } + + QSize sizeHint() const override + { + QSize size = IdealToolButton::sizeHint(); + + size.setHeight(std::min(size.height(), size.width())); + size.setWidth(size.height()); + + return size; + } + +private: + QIcon lockIcon(bool lockValue) + { + if (lockValue) + return QIcon::fromTheme("lock"); + else + return QIcon::fromTheme("unlock"); + } + + QString nextActionName(bool currrentLockValue) + { + if (currrentLockValue) + return QStringLiteral("Unlock"); + else + return QStringLiteral("Lock"); + } + + IdealButtonBarWidget* _barWidget; +}; + IdealButtonBarWidget::IdealButtonBarWidget(Qt::DockWidgetArea area, IdealController *controller, Sublime::MainWindow *parent) : QWidget(parent) , _area(area) , _controller(controller) - , _corner(0) + , _corner(nullptr) + , _isLocked(false) + , _lockButton(nullptr) { setContextMenuPolicy(Qt::CustomContextMenu); setToolTip(i18nc("@info:tooltip", "Right click to add new tool views.")); @@ -50,6 +117,7 @@ if (area == Qt::BottomDockWidgetArea) { QBoxLayout *statusLayout = new QBoxLayout(QBoxLayout::RightToLeft, this); + statusLayout->setMargin(0); statusLayout->setSpacing(IDEAL_LAYOUT_SPACING); statusLayout->setContentsMargins(0, IDEAL_LAYOUT_MARGIN, 0, IDEAL_LAYOUT_MARGIN); @@ -66,6 +134,15 @@ } else (void) new IdealButtonBarLayout(orientation(), this); + + if (_area != Qt::TopDockWidgetArea) { + KConfigGroup config = KSharedConfig::openConfig()->group("UI"); + bool defaultLockValue = (_area == Qt::LeftDockWidgetArea) ? true : false; + setLocked(config.readEntry(QStringLiteral("Toolview Bar (%1) Is Locked").arg(_area), defaultLockValue)); + + _lockButton = new LockButton(this); + layout()->addWidget(_lockButton); + } } QAction* IdealButtonBarWidget::addWidget(const QString& title, IdealDockWidget *dock, @@ -117,6 +194,30 @@ return actions().isEmpty(); } +bool IdealButtonBarWidget::isShown() +{ + return std::any_of(actions().cbegin(), actions().cend(), + [](const QAction* action){ return action->isChecked(); }); +} + +bool IdealButtonBarWidget::isLocked() +{ + return _isLocked; +} + +void IdealButtonBarWidget::setLocked(bool lockValue) +{ + _isLocked = lockValue; + + if (_lockButton) { + KConfigGroup config = KSharedConfig::openConfig()->group("UI"); + config.writeEntry(QStringLiteral("Toolview Bar (%1) Is Locked").arg(_area), _isLocked); + + if (_lockButton->isLocked() != lockValue) + _lockButton->setLocked(lockValue); + } +} + Qt::Orientation IdealButtonBarWidget::orientation() const { if (_area == Qt::LeftDockWidgetArea || _area == Qt::RightDockWidgetArea) @@ -167,8 +268,10 @@ _controller->showDockWidget(widget, checked); widgetAction->setChecked(checked); button->setChecked(checked); -} + if (_lockButton) + _lockButton->setEnabled(isShown()); +} void IdealButtonBarWidget::actionEvent(QActionEvent *event) { @@ -198,7 +301,12 @@ Q_ASSERT(_widgets.contains(action)); _widgets[action]->setWindowTitle(action->text()); - layout()->addWidget(button); + if (_area == Qt::BottomDockWidgetArea) { + layout()->replaceWidget(_lockButton, button); + layout()->addWidget(_lockButton); + } else + layout()->addWidget(button); + connect(action, &QAction::toggled, this, static_cast(&IdealButtonBarWidget::showWidget)); connect(button, &IdealToolButton::clicked, this, &IdealButtonBarWidget::buttonPressed); connect(button, &IdealToolButton::customContextMenuRequested, diff --git a/sublime/mainwindow_p.h b/sublime/mainwindow_p.h --- a/sublime/mainwindow_p.h +++ b/sublime/mainwindow_p.h @@ -82,10 +82,10 @@ /**Reconstructs the mainwindow according to the current area.*/ void reconstruct(); /**Reconstructs the views according to the current area index.*/ - void reconstructViews(QList topViews = QList()); + void reconstructViews(QList topViews = QList()); /**Clears the area leaving mainwindow empty.*/ void clearArea(); - + /** Sets a @p w widget that will be shown when there are no documents on the area */ void setBackgroundCentralWidget(QWidget* w); @@ -135,11 +135,13 @@ void showRightDock(bool b); void showBottomDock(bool b); void focusEditor(); + void focusEditorOrHideUnlockedDocks(); void selectNextDock(); void selectPreviousDock(); private: void restoreConcentrationMode(); + void hideUnlockedDocks(); void setBackgroundVisible(bool v); Qt::DockWidgetArea positionToDockArea(Position position); diff --git a/sublime/mainwindow_p.cpp b/sublime/mainwindow_p.cpp --- a/sublime/mainwindow_p.cpp +++ b/sublime/mainwindow_p.cpp @@ -114,6 +114,11 @@ connect(action, &QAction::triggered, this, &MainWindowPrivate::focusEditor); ac->addAction(QStringLiteral("focus_editor"), action); + action = new QAction(i18nc("@action", "Focus Editor or Hide Unlocked Docks"), this); + ac->setDefaultShortcut(action, Qt::Key_Escape); + connect(action, &QAction::triggered, this, &MainWindowPrivate::focusEditorOrHideUnlockedDocks); + ac->addAction(QStringLiteral("focus_editor_or_hide_unlocked_docks"), action); + action = new QAction(i18n("Hide/Restore Docks"), this); ac->setDefaultShortcut(action, Qt::META | Qt::CTRL | Qt::Key_Up); connect(action, &QAction::triggered, this, &MainWindowPrivate::toggleDocksShown); @@ -282,6 +287,43 @@ view->widget()->setFocus(Qt::ShortcutFocusReason); } +void MainWindowPrivate::focusEditorOrHideUnlockedDocks() +{ + View* view = m_mainWindow->activeView(); + + if (!view || (view && !view->hasWidget())) { + hideUnlockedDocks(); + return; + } + + if (view->widget()->hasFocus()) + hideUnlockedDocks(); + else + focusEditor(); +} + +void MainWindowPrivate::hideUnlockedDocks() +{ + // Due IdealController::showBottomDock() logic, + // first call focuses Dock, second - hide it + // TODO: add 'force' param to showXXXDock() ? + + if (!idealController->leftBarWidget->isLocked()) { + idealController->showLeftDock(false); + idealController->showLeftDock(false); + } + + if (!idealController->bottomBarWidget->isLocked()) { + idealController->showBottomDock(false); + idealController->showBottomDock(false); + } + + if (!idealController->rightBarWidget->isLocked()) { + idealController->showRightDock(false); + idealController->showRightDock(false); + } +} + void MainWindowPrivate::toggleDocksShown() { idealController->toggleDocksShown();