From 04dc650596b62e57b2324049d49e2e94961df2b8 Mon Sep 17 00:00:00 2001 From: Stefan Merettig Date: Wed, 25 Mar 2015 02:48:26 +0100 Subject: [PATCH] Screen grabber: Flyout menu for the screenshot button When hovering over the "attach file" button in the chat form, an additional button for the screenshot functionality will 'fly out' to the left, showing a computer monitor as icon. Leaving the attach file or the take screenshot button will collapse the fly out again. Bug: Moving the mouse over the fly out and then back again to the attach button collapses the fly out. Will sort this out later. Also used the opportunity to rename headers from hpp -> h extension I added earlier. --- qtox.pro | 11 +- res.qrc | 2 + src/widget/form/chatform.cpp | 14 +-- src/widget/form/chatform.h | 2 +- src/widget/form/genericchatform.cpp | 66 +++++++++++- src/widget/form/genericchatform.h | 8 +- src/widget/tool/flyoutoverlaywidget.cpp | 100 ++++++++++++++++++ src/widget/tool/flyoutoverlaywidget.h | 57 ++++++++++ .../tool/screengrabberchooserrectitem.cpp | 2 +- ...tem.hpp => screengrabberchooserrectitem.h} | 0 src/widget/tool/screengrabberoverlayitem.cpp | 2 +- ...layitem.hpp => screengrabberoverlayitem.h} | 0 src/widget/tool/screenshotgrabber.cpp | 6 +- src/widget/tool/toolboxgraphicsitem.cpp | 2 +- ...graphicsitem.hpp => toolboxgraphicsitem.h} | 0 ui/screenshotButton/screenshotButton.css | 31 ++++++ ui/screenshotButton/screenshotButton.svg | 8 ++ 17 files changed, 282 insertions(+), 29 deletions(-) create mode 100644 src/widget/tool/flyoutoverlaywidget.cpp create mode 100644 src/widget/tool/flyoutoverlaywidget.h rename src/widget/tool/{screengrabberchooserrectitem.hpp => screengrabberchooserrectitem.h} (100%) rename src/widget/tool/{screengrabberoverlayitem.hpp => screengrabberoverlayitem.h} (100%) rename src/widget/tool/{toolboxgraphicsitem.hpp => toolboxgraphicsitem.h} (100%) create mode 100644 ui/screenshotButton/screenshotButton.css create mode 100644 ui/screenshotButton/screenshotButton.svg diff --git a/qtox.pro b/qtox.pro index 41e1a28a2..d15539a9d 100644 --- a/qtox.pro +++ b/qtox.pro @@ -436,7 +436,8 @@ SOURCES += \ src/widget/tool/screenshotgrabber.cpp \ src/widget/tool/screengrabberchooserrectitem.cpp \ src/widget/tool/screengrabberoverlayitem.cpp \ - src/widget/tool/toolboxgraphicsitem.cpp + src/widget/tool/toolboxgraphicsitem.cpp \ + src/widget/tool/flyoutoverlaywidget.cpp HEADERS += \ @@ -464,7 +465,7 @@ HEADERS += \ src/profilelocker.h \ src/avatarbroadcaster.h \ src/widget/tool/screenshotgrabber.h \ - src/widget/tool/screengrabberchooserrectitem.hpp \ - src/widget/tool/screengrabberoverlayitem.hpp \ - src/widget/tool/toolboxgraphicsitem.hpp - + src/widget/tool/screengrabberchooserrectitem.h \ + src/widget/tool/screengrabberoverlayitem.h \ + src/widget/tool/toolboxgraphicsitem.h \ + src/widget/tool/flyoutoverlaywidget.h diff --git a/res.qrc b/res.qrc index dc28b6285..f43db5b73 100644 --- a/res.qrc +++ b/res.qrc @@ -80,6 +80,8 @@ ui/emoticonWidget/emoticonWidget.css ui/fileButton/fileButton.css ui/fileButton/fileButton.svg + ui/screenshotButton/screenshotButton.css + ui/screenshotButton/screenshotButton.svg ui/fileTransferWidget/fileTransferWidget.css ui/friendList/friendList.css ui/micButton/micButton.css diff --git a/src/widget/form/chatform.cpp b/src/widget/form/chatform.cpp index 6fcece8b9..0a4975c2d 100644 --- a/src/widget/form/chatform.cpp +++ b/src/widget/form/chatform.cpp @@ -85,9 +85,7 @@ ChatForm::ChatForm(Friend* chatFriend) connect(Core::getInstance(), &Core::fileSendStarted, this, &ChatForm::startFileSend); connect(sendButton, &QPushButton::clicked, this, &ChatForm::onSendTriggered); connect(fileButton, &QPushButton::clicked, this, &ChatForm::onAttachClicked); - fileButton->setContextMenuPolicy(Qt::CustomContextMenu); - connect(fileButton, &QPushButton::customContextMenuRequested, this, &ChatForm::onAttachContext); - connect(screenshotAction, &QAction::triggered, this, &ChatForm::onScreenshotCreate); + connect(screenshotButton, &QPushButton::clicked, this, &ChatForm::onScreenshotClicked); connect(callButton, &QPushButton::clicked, this, &ChatForm::onCallTriggered); connect(videoButton, &QPushButton::clicked, this, &ChatForm::onVideoCallTriggered); connect(msgEdit, &ChatTextEdit::enterPressed, this, &ChatForm::onSendTriggered); @@ -865,7 +863,7 @@ void ChatForm::loadHistory(QDateTime since, bool processUndelivered) chatWidget->verticalScrollBar()->setValue(savedSliderPos); } -void ChatForm::onScreenshotCreate() +void ChatForm::onScreenshotClicked() { ScreenshotGrabber *screenshotGrabber = new ScreenshotGrabber (this); connect(screenshotGrabber, &ScreenshotGrabber::screenshotTaken, this, &ChatForm::onScreenshotTaken); @@ -896,14 +894,6 @@ void ChatForm::onScreenshotTaken (const QPixmap &pixmap) { } -void ChatForm::onAttachContext(const QPoint &pos) -{ - QMenu* context = new QMenu(fileButton); - context->addAction(screenshotAction); - - context->exec(fileButton->mapToGlobal(pos)); -} - void ChatForm::onLoadHistory() { LoadHistoryDialog dlg; diff --git a/src/widget/form/chatform.h b/src/widget/form/chatform.h index 1e282000d..cc3835aa1 100644 --- a/src/widget/form/chatform.h +++ b/src/widget/form/chatform.h @@ -95,7 +95,7 @@ private slots: void onLoadHistory(); void onUpdateTime(); void onEnableCallButtons(); - void onScreenshotCreate(); + void onScreenshotClicked(); void onScreenshotTaken(const QPixmap &pixmap); protected: diff --git a/src/widget/form/genericchatform.cpp b/src/widget/form/genericchatform.cpp index 2a9b2b174..3f31b27ad 100644 --- a/src/widget/form/genericchatform.cpp +++ b/src/widget/form/genericchatform.cpp @@ -36,6 +36,7 @@ #include "src/friend.h" #include "src/chatlog/chatlog.h" #include "src/chatlog/content/timestamp.h" +#include "src/widget/tool/flyoutoverlaywidget.h" GenericChatForm::GenericChatForm(QWidget *parent) : QWidget(parent) @@ -77,6 +78,8 @@ GenericChatForm::GenericChatForm(QWidget *parent) // Setting the sizes in the CSS doesn't work (glitch with high DPIs) fileButton = new QPushButton(); fileButton->setToolTip(tr("Send file(s)")); + screenshotButton = new QPushButton; + screenshotButton->setToolTip(tr("Send a screenshot")); callButton = new QPushButton(); callButton->setFixedSize(50,40); callButton->setToolTip(tr("Start an audio call")); @@ -89,10 +92,15 @@ GenericChatForm::GenericChatForm(QWidget *parent) micButton = new QPushButton(); // micButton->setFixedSize(25,20); micButton->setToolTip(""); - - screenshotAction = new QAction(tr("Send screenshot"), nullptr); + + fileFlyout = new FlyoutOverlayWidget; + QHBoxLayout *fileLayout = new QHBoxLayout(fileFlyout); + fileLayout->addWidget(screenshotButton); + fileLayout->setContentsMargins(0, 0, 0, 0); footButtonsSmall->setSpacing(2); + fileLayout->setSpacing(0); + fileLayout->setMargin(0); msgEdit->setStyleSheet(Style::getStylesheet(":/ui/msgEdit/msgEdit.css")); msgEdit->setFixedHeight(50); @@ -100,6 +108,7 @@ GenericChatForm::GenericChatForm(QWidget *parent) sendButton->setStyleSheet(Style::getStylesheet(":/ui/sendButton/sendButton.css")); fileButton->setStyleSheet(Style::getStylesheet(":/ui/fileButton/fileButton.css")); + screenshotButton->setStyleSheet(Style::getStylesheet(":/ui/screenshotButton/screenshotButton.css")); emoteButton->setStyleSheet(Style::getStylesheet(":/ui/emoteButton/emoteButton.css")); callButton->setObjectName("green"); @@ -156,6 +165,7 @@ GenericChatForm::GenericChatForm(QWidget *parent) //https://bugreports.qt-project.org/browse/QTBUG-14591 sendButton->setAttribute(Qt::WA_LayoutUsesWidgetRect); fileButton->setAttribute(Qt::WA_LayoutUsesWidgetRect); + screenshotButton->setAttribute(Qt::WA_LayoutUsesWidgetRect); emoteButton->setAttribute(Qt::WA_LayoutUsesWidgetRect); micButton->setAttribute(Qt::WA_LayoutUsesWidgetRect); volButton->setAttribute(Qt::WA_LayoutUsesWidgetRect); @@ -175,6 +185,28 @@ GenericChatForm::GenericChatForm(QWidget *parent) chatWidget->setStyleSheet(Style::getStylesheet(":/ui/chatArea/chatArea.css")); headWidget->setStyleSheet(Style::getStylesheet(":/ui/chatArea/chatHead.css")); + + fileFlyout->setFixedSize(24, 24); + fileFlyout->setParent(this); + fileButton->installEventFilter(this); +} + +void GenericChatForm::showFileMenu() +{ + if (!fileFlyout->isShown()) { + QPoint pos = fileButton->pos(); + QSize size = fileFlyout->size(); + fileFlyout->move(pos.x() - size.width(), pos.y()); + fileFlyout->animateShow(); + } + +} + +void GenericChatForm::hideFileMenu() +{ + if(fileFlyout->isShown()) + fileFlyout->animateHide(); + } bool GenericChatForm::isEmpty() @@ -377,4 +409,32 @@ void GenericChatForm::insertChatMessage(ChatMessage::Ptr msg) chatWidget->insertChatlineAtBottom(std::dynamic_pointer_cast(msg)); } - +bool GenericChatForm::eventFilter(QObject* object, QEvent* event) +{ + if (object != this->fileButton) + return false; + + switch(event->type()) + { + case QEvent::Enter: + showFileMenu(); + break; + + case QEvent::Leave: { + QPoint pos = mapFromGlobal(QCursor::pos()); + QRect rect (fileFlyout->pos(), fileFlyout->size()); + + if (!rect.contains(pos)) + hideFileMenu(); + } break; + + case QEvent::MouseButtonPress: + hideFileMenu(); + break; + + default: + break; + } + + return false; +} diff --git a/src/widget/form/genericchatform.h b/src/widget/form/genericchatform.h index 33702f42e..21246c83d 100644 --- a/src/widget/form/genericchatform.h +++ b/src/widget/form/genericchatform.h @@ -36,6 +36,7 @@ class ChatLog; class MaskablePixmapWidget; class Widget; struct ToxID; +class FlyoutOverlayWidget; namespace Ui { class MainWindow; @@ -59,6 +60,7 @@ public: ChatLog* getChatLog() const; + bool eventFilter(QObject* object, QEvent* event); signals: void sendMessage(uint32_t, QString); void sendAction(uint32_t, QString); @@ -76,6 +78,8 @@ protected slots: void clearChatArea(bool); void clearChatArea(); void onSelectAllClicked(); + void showFileMenu(); + void hideFileMenu(); protected: QString resolveToxID(const ToxID &id); @@ -89,8 +93,8 @@ protected: CroppingLabel *nameLabel; MaskablePixmapWidget *avatar; QWidget *headWidget; - QPushButton *fileButton, *emoteButton, *callButton, *videoButton, *volButton, *micButton; - QAction *screenshotAction; + QPushButton *fileButton, *screenshotButton, *emoteButton, *callButton, *videoButton, *volButton, *micButton; + FlyoutOverlayWidget *fileFlyout; QVBoxLayout *headTextLayout; ChatTextEdit *msgEdit; QPushButton *sendButton; diff --git a/src/widget/tool/flyoutoverlaywidget.cpp b/src/widget/tool/flyoutoverlaywidget.cpp new file mode 100644 index 000000000..154bc9699 --- /dev/null +++ b/src/widget/tool/flyoutoverlaywidget.cpp @@ -0,0 +1,100 @@ +/* + Copyright (C) 2013 by Maxim Biro + + This file is part of Tox Qt GUI. + + This program 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. + 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 COPYING file for more details. +*/ + +#include "flyoutoverlaywidget.h" + +#include +#include +#include +#include + +FlyoutOverlayWidget::FlyoutOverlayWidget(QWidget *parent) + : QWidget(parent) +{ + setContentsMargins(0, 0, 0, 0); + + animation = new QPropertyAnimation(this, QByteArrayLiteral("flyoutPercent"), this); + animation->setKeyValueAt(0, 0.0f); + animation->setKeyValueAt(1, 1.0f); + animation->setDuration(200); + + connect(animation, &QAbstractAnimation::finished, this, &FlyoutOverlayWidget::finishedAnimation); + setFlyoutPercent(0); + show(); + +} + +FlyoutOverlayWidget::~FlyoutOverlayWidget() +{ + +} + +int FlyoutOverlayWidget::animationDuration() const +{ + return animation->duration(); +} + +void FlyoutOverlayWidget::setAnimationDuration(int timeMs) +{ + animation->setDuration(timeMs); +} + +qreal FlyoutOverlayWidget::flyoutPercent() const +{ + return percent; +} + +void FlyoutOverlayWidget::setFlyoutPercent(qreal progress) +{ + percent = progress; + + QSize self = size(); + setMask(QRegion(0, 0, self.width() * progress + 1, self.height())); + move(startPos.x() + self.width() - self.width() * percent, startPos.y()); + setVisible (progress != 0); + +} + +bool FlyoutOverlayWidget::isShown() const +{ + return (percent == 1); +} + +void FlyoutOverlayWidget::animateShow() +{ + this->startPos = pos(); + animation->setDirection(QAbstractAnimation::Forward); + animation->start(); +} + +void FlyoutOverlayWidget::animateHide() +{ + this->startPos = pos(); + animation->setDirection(QAbstractAnimation::Backward); + animation->start(); +} + +void FlyoutOverlayWidget::leaveEvent(QEvent* event) +{ + Q_UNUSED(event); + animateHide(); +} + +void FlyoutOverlayWidget::finishedAnimation() +{ + bool hide = (animation->direction() == QAbstractAnimation::Backward); + setAttribute(Qt::WA_TransparentForMouseEvents, hide); +} diff --git a/src/widget/tool/flyoutoverlaywidget.h b/src/widget/tool/flyoutoverlaywidget.h new file mode 100644 index 000000000..2c2fa5842 --- /dev/null +++ b/src/widget/tool/flyoutoverlaywidget.h @@ -0,0 +1,57 @@ +/* + Copyright (C) 2013 by Maxim Biro + + This file is part of Tox Qt GUI. + + This program 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. + 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 COPYING file for more details. +*/ + +#ifndef FLYOUTOVERLAYWIDGET_HPP +#define FLYOUTOVERLAYWIDGET_HPP + +#include + +class QPropertyAnimation; + +class FlyoutOverlayWidget : public QWidget +{ + Q_OBJECT + Q_PROPERTY(qreal flyoutPercent READ flyoutPercent WRITE setFlyoutPercent) +public: + explicit FlyoutOverlayWidget(QWidget *parent = 0); + ~FlyoutOverlayWidget(); + + int animationDuration() const; + void setAnimationDuration(int timeMs); + + qreal flyoutPercent() const; + void setFlyoutPercent(qreal progress); + + bool isShown() const; + + void animateShow(); + void animateHide(); + +protected: + void leaveEvent(QEvent* event); + +private: + + void finishedAnimation(); + + QWidget *container; + QPropertyAnimation *animation; + qreal percent = 1.0f; + QPoint startPos; + +}; + +#endif // FLYOUTOVERLAYWIDGET_HPP diff --git a/src/widget/tool/screengrabberchooserrectitem.cpp b/src/widget/tool/screengrabberchooserrectitem.cpp index 818574f65..8a176d4b2 100644 --- a/src/widget/tool/screengrabberchooserrectitem.cpp +++ b/src/widget/tool/screengrabberchooserrectitem.cpp @@ -14,7 +14,7 @@ See the COPYING file for more details. */ -#include "screengrabberchooserrectitem.hpp" +#include "screengrabberchooserrectitem.h" #include #include diff --git a/src/widget/tool/screengrabberchooserrectitem.hpp b/src/widget/tool/screengrabberchooserrectitem.h similarity index 100% rename from src/widget/tool/screengrabberchooserrectitem.hpp rename to src/widget/tool/screengrabberchooserrectitem.h diff --git a/src/widget/tool/screengrabberoverlayitem.cpp b/src/widget/tool/screengrabberoverlayitem.cpp index 37219b4a1..9641d0863 100644 --- a/src/widget/tool/screengrabberoverlayitem.cpp +++ b/src/widget/tool/screengrabberoverlayitem.cpp @@ -14,7 +14,7 @@ See the COPYING file for more details. */ -#include "screengrabberoverlayitem.hpp" +#include "screengrabberoverlayitem.h" #include #include diff --git a/src/widget/tool/screengrabberoverlayitem.hpp b/src/widget/tool/screengrabberoverlayitem.h similarity index 100% rename from src/widget/tool/screengrabberoverlayitem.hpp rename to src/widget/tool/screengrabberoverlayitem.h diff --git a/src/widget/tool/screenshotgrabber.cpp b/src/widget/tool/screenshotgrabber.cpp index b97bd405d..354cdc0e2 100644 --- a/src/widget/tool/screenshotgrabber.cpp +++ b/src/widget/tool/screenshotgrabber.cpp @@ -26,9 +26,9 @@ #include #include -#include "screengrabberchooserrectitem.hpp" -#include "screengrabberoverlayitem.hpp" -#include "toolboxgraphicsitem.hpp" +#include "screengrabberchooserrectitem.h" +#include "screengrabberoverlayitem.h" +#include "toolboxgraphicsitem.h" ScreenshotGrabber::ScreenshotGrabber(QWidget* parent) : QWidget(parent) diff --git a/src/widget/tool/toolboxgraphicsitem.cpp b/src/widget/tool/toolboxgraphicsitem.cpp index 77e096502..badaf4008 100644 --- a/src/widget/tool/toolboxgraphicsitem.cpp +++ b/src/widget/tool/toolboxgraphicsitem.cpp @@ -14,7 +14,7 @@ See the COPYING file for more details. */ -#include "toolboxgraphicsitem.hpp" +#include "toolboxgraphicsitem.h" #include diff --git a/src/widget/tool/toolboxgraphicsitem.hpp b/src/widget/tool/toolboxgraphicsitem.h similarity index 100% rename from src/widget/tool/toolboxgraphicsitem.hpp rename to src/widget/tool/toolboxgraphicsitem.h diff --git a/ui/screenshotButton/screenshotButton.css b/ui/screenshotButton/screenshotButton.css new file mode 100644 index 000000000..82d523193 --- /dev/null +++ b/ui/screenshotButton/screenshotButton.css @@ -0,0 +1,31 @@ +QPushButton +{ + background-color: #6bc260; + background-image: url(":/ui/screenshotButton/screenshotButton.svg"); + background-repeat: none; + background-position: center; + border-top-left-radius: 5px; + border: none; + width: 24px; + height: 24px; +} + +QPushButton:hover +{ + background-color: #79c76f; +} + +QPushButton:pressed +{ + background-color: #51b244; +} + +QPushButton[enabled="false"] +{ + background-color: #919191; +} + +QPushButton:focus +{ + outline: none; +} diff --git a/ui/screenshotButton/screenshotButton.svg b/ui/screenshotButton/screenshotButton.svg new file mode 100644 index 000000000..25a250ce3 --- /dev/null +++ b/ui/screenshotButton/screenshotButton.svg @@ -0,0 +1,8 @@ + + image/svg+xml + + Layer 1 + + + + \ No newline at end of file