diff --git a/src/config/geneneralconf.cpp b/src/config/geneneralconf.cpp index ec480793..d25b17ee 100644 --- a/src/config/geneneralconf.cpp +++ b/src/config/geneneralconf.cpp @@ -36,6 +36,7 @@ GeneneralConf::GeneneralConf(QWidget* parent) m_layout = new QVBoxLayout(this); m_layout->setAlignment(Qt::AlignTop); initShowHelp(); + initShowSidePanelButton(); initShowDesktopNotification(); initShowTrayIcon(); initAutostart(); @@ -53,6 +54,7 @@ GeneneralConf::updateComponents() { ConfigHandler config; m_helpMessage->setChecked(config.showHelpValue()); + m_sidePanelButton->setChecked(config.showSidePanelButtonValue()); m_sysNotifications->setChecked(config.desktopNotificationValue()); m_autostart->setChecked(config.startupLaunchValue()); m_closeAfterCapture->setChecked(config.closeAfterScreenshotValue()); @@ -78,6 +80,12 @@ GeneneralConf::showHelpChanged(bool checked) ConfigHandler().setShowHelp(checked); } +void +GeneneralConf::showSidePanelButtonChanged(bool checked) +{ + ConfigHandler().setShowSidePanelButton(checked); +} + void GeneneralConf::showDesktopNotificationChanged(bool checked) { @@ -182,6 +190,20 @@ GeneneralConf::initShowHelp() m_helpMessage, &QCheckBox::clicked, this, &GeneneralConf::showHelpChanged); } +void +GeneneralConf::initShowSidePanelButton() +{ + m_sidePanelButton = new QCheckBox(tr("Show the side panel button"), this); + m_sidePanelButton->setChecked(ConfigHandler().showSidePanelButtonValue()); + m_sidePanelButton->setToolTip( + tr("Show the side panel toggle button in the capture mode.")); + m_layout->addWidget(m_sidePanelButton); + + connect(m_sidePanelButton, + &QCheckBox::clicked, + this, + &GeneneralConf::showSidePanelButtonChanged); +} void GeneneralConf::initShowDesktopNotification() { diff --git a/src/config/geneneralconf.h b/src/config/geneneralconf.h index 7dfe47a1..527d03af 100644 --- a/src/config/geneneralconf.h +++ b/src/config/geneneralconf.h @@ -36,6 +36,7 @@ public slots: private slots: void showHelpChanged(bool checked); + void showSidePanelButtonChanged(bool checked); void showDesktopNotificationChanged(bool checked); void showTrayIconChanged(bool checked); void autostartChanged(bool checked); @@ -51,6 +52,7 @@ private: QCheckBox* m_sysNotifications; QCheckBox* m_showTray; QCheckBox* m_helpMessage; + QCheckBox* m_sidePanelButton; QCheckBox* m_autostart; QCheckBox* m_closeAfterCapture; QCheckBox* m_copyAndCloseAfterUpload; @@ -62,6 +64,7 @@ private: QPushButton* m_changeSaveButton; void initShowHelp(); + void initShowSidePanelButton(); void initShowDesktopNotification(); void initShowTrayIcon(); void initConfingButtons(); diff --git a/src/utils/confighandler.cpp b/src/utils/confighandler.cpp index cc33fdd6..a77efe7b 100644 --- a/src/utils/confighandler.cpp +++ b/src/utils/confighandler.cpp @@ -208,6 +208,19 @@ ConfigHandler::setShowHelp(const bool showHelp) m_settings.setValue(QStringLiteral("showHelp"), showHelp); } +bool +ConfigHandler::showSidePanelButtonValue() +{ + return m_settings.value(QStringLiteral("showSidePanelButton"), true).toBool(); +} + +void +ConfigHandler::setShowSidePanelButton(const bool showSidePanelButton) +{ + m_settings.setValue(QStringLiteral("showSidePanelButton"), + showSidePanelButton); +} + bool ConfigHandler::desktopNotificationValue() { diff --git a/src/utils/confighandler.h b/src/utils/confighandler.h index 1e58b0f4..81951f47 100644 --- a/src/utils/confighandler.h +++ b/src/utils/confighandler.h @@ -47,6 +47,9 @@ public: bool showHelpValue(); void setShowHelp(const bool); + bool showSidePanelButtonValue(); + void setShowSidePanelButton(const bool); + bool desktopNotificationValue(); void setDesktopNotification(const bool); diff --git a/src/widgets/CMakeLists.txt b/src/widgets/CMakeLists.txt index 3226b2ee..219b981a 100644 --- a/src/widgets/CMakeLists.txt +++ b/src/widgets/CMakeLists.txt @@ -5,15 +5,19 @@ add_subdirectory(capture) target_sources( flameshot PRIVATE capturelauncher.h + draggablewidgetmaker.h imagelabel.h infowindow.h loadspinner.h - notificationwidget.h) + notificationwidget.h + orientablepushbutton.h) target_sources( flameshot PRIVATE capturelauncher.cpp + draggablewidgetmaker.cpp imagelabel.cpp infowindow.cpp loadspinner.cpp - notificationwidget.cpp) + notificationwidget.cpp + orientablepushbutton.cpp) diff --git a/src/widgets/capture/capturewidget.cpp b/src/widgets/capture/capturewidget.cpp index 52fd2207..76307d85 100644 --- a/src/widgets/capture/capturewidget.cpp +++ b/src/widgets/capture/capturewidget.cpp @@ -34,6 +34,7 @@ #include "src/widgets/capture/hovereventfilter.h" #include "src/widgets/capture/modificationcommand.h" #include "src/widgets/capture/notifierbox.h" +#include "src/widgets/orientablepushbutton.h" #include "src/widgets/panel/sidepanelwidget.h" #include #include @@ -45,6 +46,7 @@ #include #include #include +#include // CaptureWidget is the main component used to capture the screen. It contains // an are of selection with its respective buttons. @@ -602,12 +604,42 @@ CaptureWidget::initContext(const QString& savePath, bool fullscreen) void CaptureWidget::initPanel() { - m_panel = new UtilityPanel(this); - makeChild(m_panel); QRect panelRect = rect(); if (m_context.fullscreen) { panelRect = QGuiApplication::primaryScreen()->geometry(); } + + ConfigHandler config; + + if (config.showSidePanelButtonValue()) { + auto* panelToggleButton = + new OrientablePushButton(tr("Tool Settings"), this); + makeChild(panelToggleButton); + panelToggleButton->setOrientation( + OrientablePushButton::VerticalBottomToTop); + panelToggleButton->move(panelRect.x(), + panelRect.y() + panelRect.height() / 2 - + panelToggleButton->width() / 2); + panelToggleButton->setCursor(Qt::ArrowCursor); + (new DraggableWidgetMaker(this))->makeDraggable(panelToggleButton); + connect(panelToggleButton, + &QPushButton::clicked, + this, + &CaptureWidget::togglePanel); + + QColor mainColor = config.uiMainColorValue(); + QColor textColor = + ColorUtils::colorIsDark(mainColor) ? Qt::white : Qt::black; + QPalette palette = panelToggleButton->palette(); + palette.setColor(QPalette::Button, mainColor); + palette.setColor(QPalette::ButtonText, textColor); + panelToggleButton->setAutoFillBackground(true); + panelToggleButton->setPalette(palette); + panelToggleButton->update(); + } + + m_panel = new UtilityPanel(this); + makeChild(m_panel); panelRect.moveTo(mapFromGlobal(panelRect.topLeft())); panelRect.setWidth(m_colorPicker->width() * 3); m_panel->setGeometry(panelRect); diff --git a/src/widgets/draggablewidgetmaker.cpp b/src/widgets/draggablewidgetmaker.cpp new file mode 100644 index 00000000..617fb668 --- /dev/null +++ b/src/widgets/draggablewidgetmaker.cpp @@ -0,0 +1,81 @@ +// Copyright(c) 2017-2019 Alejandro Sirgo Rica & Contributors +// +// This file is part of Flameshot. +// +// Flameshot is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Flameshot 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 Flameshot. If not, see . + +#include "draggablewidgetmaker.h" +#include + +DraggableWidgetMaker::DraggableWidgetMaker(QObject* parent) + : QObject(parent) +{} + +void +DraggableWidgetMaker::makeDraggable(QWidget* widget) +{ + widget->installEventFilter(this); +} + +bool +DraggableWidgetMaker::eventFilter(QObject* obj, QEvent* event) +{ + auto widget = static_cast(obj); + + // based on https://stackoverflow.com/a/12221360/964478 + switch (event->type()) { + case QEvent::MouseButtonPress: { + auto mouseEvent = static_cast(event); + + m_isPressing = false; + m_isDragging = false; + if (mouseEvent->button() == Qt::LeftButton) { + m_isPressing = true; + m_mousePressPos = mouseEvent->globalPos(); + m_mouseMovePos = m_mousePressPos; + } + } break; + case QEvent::MouseMove: { + auto mouseEvent = static_cast(event); + + if (m_isPressing) { + QPoint widgetPos = widget->mapToGlobal(widget->pos()); + QPoint eventPos = mouseEvent->globalPos(); + QPoint diff = eventPos - m_mouseMovePos; + QPoint newPos = widgetPos + diff; + + widget->move(widget->mapFromGlobal(newPos)); + + if (!m_isDragging) { + QPoint totalMovedDiff = eventPos - m_mousePressPos; + if (totalMovedDiff.manhattanLength() > 3) { + m_isDragging = true; + } + } + + m_mouseMovePos = eventPos; + } + } break; + case QEvent::MouseButtonRelease: { + if (m_isDragging) { + m_isPressing = false; + m_isDragging = false; + event->ignore(); + return true; + } + } break; + } + + return QObject::eventFilter(obj, event); +} diff --git a/src/widgets/draggablewidgetmaker.h b/src/widgets/draggablewidgetmaker.h new file mode 100644 index 00000000..62f7f17b --- /dev/null +++ b/src/widgets/draggablewidgetmaker.h @@ -0,0 +1,41 @@ +// Copyright(c) 2017-2019 Alejandro Sirgo Rica & Contributors +// +// This file is part of Flameshot. +// +// Flameshot is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Flameshot 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 Flameshot. If not, see . + +#pragma once + +#include +#include +#include +#include + +class DraggableWidgetMaker : public QObject +{ + Q_OBJECT +public: + DraggableWidgetMaker(QObject* parent = nullptr); + + void makeDraggable(QWidget* widget); + +protected: + bool eventFilter(QObject* obj, QEvent* event) override; + +private: + bool m_isPressing = false; + bool m_isDragging = false; + QPoint m_mouseMovePos; + QPoint m_mousePressPos; +}; diff --git a/src/widgets/orientablepushbutton.cpp b/src/widgets/orientablepushbutton.cpp new file mode 100644 index 00000000..dd37d1bf --- /dev/null +++ b/src/widgets/orientablepushbutton.cpp @@ -0,0 +1,87 @@ +// Copyright(c) 2017-2019 Alejandro Sirgo Rica & Contributors +// +// This file is part of Flameshot. +// +// Flameshot is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Flameshot 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 Flameshot. If not, see . + +// Based on https://stackoverflow.com/a/53135675/964478 + +#include "orientablepushbutton.h" +#include +#include +#include +#include + +OrientablePushButton::OrientablePushButton(QWidget* parent) + : QPushButton(parent) +{} + +OrientablePushButton::OrientablePushButton(const QString& text, QWidget* parent) + : QPushButton(text, parent) +{} + +OrientablePushButton::OrientablePushButton(const QIcon& icon, + const QString& text, + QWidget* parent) + : QPushButton(icon, text, parent) +{} + +QSize +OrientablePushButton::sizeHint() const +{ + QSize sh = QPushButton::sizeHint(); + + if (m_orientation != OrientablePushButton::Horizontal) { + sh.transpose(); + } + + return sh; +} + +void +OrientablePushButton::paintEvent(QPaintEvent* event) +{ + Q_UNUSED(event) + + QStylePainter painter(this); + QStyleOptionButton option; + initStyleOption(&option); + + if (m_orientation == OrientablePushButton::VerticalTopToBottom) { + painter.rotate(90); + painter.translate(0, -1 * width()); + option.rect = option.rect.transposed(); + } + + else if (m_orientation == OrientablePushButton::VerticalBottomToTop) { + painter.rotate(-90); + painter.translate(-1 * height(), 0); + option.rect = option.rect.transposed(); + } + + painter.drawControl(QStyle::CE_PushButton, option); +} + +OrientablePushButton::Orientation +OrientablePushButton::orientation() const +{ + return m_orientation; +} + +void +OrientablePushButton::setOrientation( + const OrientablePushButton::Orientation& orientation) +{ + m_orientation = orientation; +} diff --git a/src/widgets/orientablepushbutton.h b/src/widgets/orientablepushbutton.h new file mode 100644 index 00000000..2dbe9fcd --- /dev/null +++ b/src/widgets/orientablepushbutton.h @@ -0,0 +1,51 @@ +// Copyright(c) 2017-2019 Alejandro Sirgo Rica & Contributors +// +// This file is part of Flameshot. +// +// Flameshot is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Flameshot 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 Flameshot. If not, see . + +// Based on https://stackoverflow.com/a/53135675/964478 + +#pragma once + +#include + +class OrientablePushButton : public QPushButton +{ + Q_OBJECT +public: + enum Orientation + { + Horizontal, + VerticalTopToBottom, + VerticalBottomToTop + }; + + OrientablePushButton(QWidget* parent = nullptr); + OrientablePushButton(const QString& text, QWidget* parent = nullptr); + OrientablePushButton(const QIcon& icon, + const QString& text, + QWidget* parent = nullptr); + + QSize sizeHint() const; + + OrientablePushButton::Orientation orientation() const; + void setOrientation(const OrientablePushButton::Orientation& orientation); + +protected: + void paintEvent(QPaintEvent* event); + +private: + Orientation m_orientation = Horizontal; +}; diff --git a/src/widgets/panel/utilitypanel.cpp b/src/widgets/panel/utilitypanel.cpp index dbfd0fb4..2e9799ee 100644 --- a/src/widgets/panel/utilitypanel.cpp +++ b/src/widgets/panel/utilitypanel.cpp @@ -17,6 +17,7 @@ #include "utilitypanel.h" #include +#include #include #include #include @@ -72,7 +73,7 @@ UtilityPanel::clearToolWidget() void UtilityPanel::pushWidget(QWidget* w) { - m_layout->addWidget(w); + m_layout->insertWidget(m_layout->count() - 1, w); } void @@ -103,9 +104,16 @@ UtilityPanel::initInternalPanel() m_layout = new QVBoxLayout(); m_upLayout = new QVBoxLayout(); + m_bottomLayout = new QVBoxLayout(); m_layout->addLayout(m_upLayout); + m_layout->addLayout(m_bottomLayout); widget->setLayout(m_layout); + QPushButton* closeButton = new QPushButton(this); + closeButton->setText(tr("Close")); + connect(closeButton, &QPushButton::clicked, this, &UtilityPanel::toggle); + m_bottomLayout->addWidget(closeButton); + QColor bgColor = palette().window().color(); bgColor.setAlphaF(0.0); m_internalPanel->setStyleSheet( diff --git a/src/widgets/panel/utilitypanel.h b/src/widgets/panel/utilitypanel.h index 630ed078..ce143193 100644 --- a/src/widgets/panel/utilitypanel.h +++ b/src/widgets/panel/utilitypanel.h @@ -48,6 +48,7 @@ private: QPointer m_toolWidget; QScrollArea* m_internalPanel; QVBoxLayout* m_upLayout; + QVBoxLayout* m_bottomLayout; QVBoxLayout* m_layout; QPropertyAnimation* m_showAnimation; QPropertyAnimation* m_hideAnimation;