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