KUserFeedback

notificationpopup.cpp
1/*
2 SPDX-FileCopyrightText: 2017 Volker Krause <vkrause@kde.org>
3
4 SPDX-License-Identifier: MIT
5*/
6
7#include "notificationpopup.h"
8#include "ui_notificationpopup.h"
9#include "feedbackconfigdialog.h"
10
11#include <provider.h>
12#include <surveyinfo.h>
13
14#include <QApplication>
15#include <QDebug>
16#include <QDesktopServices>
17#include <QKeyEvent>
18#include <QPropertyAnimation>
19#include <QStyle>
20
21using namespace KUserFeedback;
22
23namespace KUserFeedback {
24namespace Ui
25{
27}
28
29class NotificationPopupPrivate {
30public:
31 NotificationPopupPrivate(QWidget *qq);
32 void showEncouragement();
33 void surveyAvailable(const SurveyInfo &info);
34
35 void showPopup();
36 void hidePopup();
37 void action();
38 void reposition();
39 int xPosition() const;
40
41 static QString appName();
42
43 Provider *provider;
44 SurveyInfo survey;
45 QPropertyAnimation *animation;
46 std::unique_ptr<Ui::NotificationPopup> ui;
47 QWidget *q;
48};
49
50}
51
52NotificationPopupPrivate::NotificationPopupPrivate(QWidget *qq) :
53 provider(nullptr),
54 animation(nullptr),
55 q(qq)
56{
57}
58
59void NotificationPopupPrivate::showEncouragement()
60{
61 if (q->isVisible())
62 return;
63
64 survey = SurveyInfo();
65 const auto name = appName();
66 if (name.isEmpty()) {
67 ui->title->setText(NotificationPopup::tr("Help us make this application better!"));
68 ui->message->setText(NotificationPopup::tr("You can help us improving this application by sharing statistics and participate in surveys."));
69 } else {
70 ui->title->setText(NotificationPopup::tr("Help us make %1 better!").arg(name));
71 ui->message->setText(NotificationPopup::tr("You can help us improving %1 by sharing statistics and participate in surveys.").arg(name));
72 }
73 ui->actionButton->setText(NotificationPopup::tr("Contribute…", "@action:button"));
74 showPopup();
75}
76
77void NotificationPopupPrivate::surveyAvailable(const SurveyInfo &info)
78{
79 if (q->isVisible())
80 return;
81
82 survey = info;
83 const auto name = appName();
84 ui->title->setText(NotificationPopup::tr("We are looking for your feedback!"));
85 if (name.isEmpty())
86 ui->message->setText(NotificationPopup::tr("We would like a few minutes of your time to provide feedback about this application in a survey."));
87 else
88 ui->message->setText(NotificationPopup::tr("We would like a few minutes of your time to provide feedback about %1 in a survey.").arg(name));
89 ui->actionButton->setText(NotificationPopup::tr("Participate"));
90 showPopup();
91}
92
93void NotificationPopupPrivate::showPopup()
94{
95 q->show();
96
97 q->resize(q->sizeHint());
98 const auto startPos = QPoint(xPosition(), q->parentWidget()->height());
99 q->move(startPos);
100
101 if (!animation)
102 animation = new QPropertyAnimation(q, "pos", q);
103 animation->setStartValue(startPos);
104 animation->setEndValue(QPoint(xPosition(), q->parentWidget()->height() - q->height()));
105 animation->setDuration(100);
107 animation->start();
108
109 ui->actionButton->setFocus();
110}
111
112void NotificationPopupPrivate::hidePopup()
113{
114 if (animation)
115 animation->stop();
116 q->hide();
117}
118
119void NotificationPopupPrivate::action()
120{
121 if (survey.isValid()) {
122 QDesktopServices::openUrl(survey.url());
123 provider->surveyCompleted(survey);
124 } else {
126 dlg.setFeedbackProvider(provider);
127 dlg.exec();
128 }
129
130 hidePopup();
131}
132
133void NotificationPopupPrivate::reposition()
134{
135 const auto pos = QPoint(xPosition(), q->parentWidget()->height() - q->height());
136 if (animation->state() == QAbstractAnimation::Running)
137 animation->setEndValue(pos);
138 else
139 q->move(pos);
140}
141
142int NotificationPopupPrivate::xPosition() const
143{
145 return q->parentWidget()->width() - q->width();
146 }
147 return 0;
148}
149
150QString NotificationPopupPrivate::appName()
151{
153}
154
155
157 : QWidget(parent)
158 , d(new NotificationPopupPrivate(this))
159{
160 Q_ASSERT(parent);
161
162 d->ui.reset(new Ui::NotificationPopup);
163 d->ui->setupUi(this);
164
165 d->ui->frame->setAutoFillBackground(true);
166 d->ui->closeButton->setIcon(style()->standardIcon(QStyle::SP_DialogCloseButton));
167 connect(d->ui->actionButton, &QPushButton::clicked, this, [this]() { d->action(); });
168 connect(d->ui->closeButton, &QPushButton::clicked, this, [this]() { d->hidePopup(); });
169
171 setVisible(false);
172}
173
174NotificationPopup::~NotificationPopup()
175{
176}
177
179{
180 Q_ASSERT(provider);
181 d->provider = provider;
182 connect(provider, &Provider::showEncouragementMessage, this, [this]() { d->showEncouragement(); });
183 connect(provider, &Provider::surveyAvailable, this, [this](const SurveyInfo &info) { d->surveyAvailable(info); });
184}
185
187{
188 if (isVisible() && event->key() == Qt::Key_Escape)
189 d->hidePopup();
190}
191
192bool NotificationPopup::eventFilter(QObject* receiver, QEvent* event)
193{
194 if (receiver == parentWidget() && isVisible()) {
195 d->reposition();
196 }
197 return QWidget::eventFilter(receiver, event);
198}
199
200#include "moc_notificationpopup.cpp"
Configure which feedback a user wants to provide.
Notification popup that overlays a small part of the application for encouraging contributions or inf...
NotificationPopup(QWidget *parent)
Create a new notification popup.
void setFeedbackProvider(Provider *provider)
Set the feedback provider that is going to drive this notification popup.
The central object managing data sources and transmitting feedback to the server.
Definition provider.h:32
void surveyCompleted(const KUserFeedback::SurveyInfo &info)
Marks the given survey as completed.
Definition provider.cpp:611
void showEncouragementMessage()
Indicate that the encouragement notice should be shown.
void surveyAvailable(const KUserFeedback::SurveyInfo &survey)
Emitted whenever there is a new survey available that can be presented to the user.
Information about a survey request.
Definition surveyinfo.h:31
QString name(StandardAction id)
Classes for integrating telemetry collection, survey targeting, and contribution encouragenemt and co...
void start(QAbstractAnimation::DeletionPolicy policy)
void clicked(bool checked)
bool openUrl(const QUrl &url)
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
virtual bool eventFilter(QObject *watched, QEvent *event)
void installEventFilter(QObject *filterObj)
QObject * parent() const const
QString tr(const char *sourceText, const char *disambiguation, int n)
bool isEmpty() const const
SP_DialogCloseButton
Key_Escape
LeftToRight
void setDuration(int msecs)
void setEasingCurve(const QEasingCurve &easing)
void setEndValue(const QVariant &value)
void setStartValue(const QVariant &value)
virtual bool event(QEvent *event) override
void hide()
virtual void keyReleaseEvent(QKeyEvent *event)
QWidget * parentWidget() const const
void move(const QPoint &)
void show()
void resize(const QSize &)
QStyle * style() const const
bool isVisible() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Sat Dec 21 2024 16:57:44 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.