qTox  Version: nightly | Commit: bc751c8e1cac455f9690654fcfe0f560d2d7dfdd
callconfirmwidget.cpp
Go to the documentation of this file.
1 /*
2  Copyright © 2015-2019 by The qTox Project Contributors
3 
4  This file is part of qTox, a Qt-based graphical interface for Tox.
5 
6  qTox is libre software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  qTox is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with qTox. If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 
21 #include "callconfirmwidget.h"
22 #include "src/widget/style.h"
23 #include "src/widget/widget.h"
24 #include <QDialogButtonBox>
25 #include <QFontMetrics>
26 #include <QHBoxLayout>
27 #include <QLabel>
28 #include <QPaintEvent>
29 #include <QPainter>
30 #include <QPalette>
31 #include <QPushButton>
32 #include <QRect>
33 #include <QVBoxLayout>
34 #include <assert.h>
35 
54  : QWidget()
55  , anchor(anchor)
56  , rectW{120}
57  , rectH{85}
58  , spikeW{30}
59  , spikeH{15}
60  , roundedFactor{20}
61  , rectRatio(static_cast<qreal>(rectH) / static_cast<qreal>(rectW))
62 {
63  setWindowFlags(Qt::SubWindow);
64  setAttribute(Qt::WA_DeleteOnClose);
65 
66  QPalette palette;
67  palette.setColor(QPalette::WindowText, Qt::white);
68  setPalette(palette);
69 
70  QVBoxLayout* layout = new QVBoxLayout(this);
71  QLabel* callLabel = new QLabel(QObject::tr("Incoming call..."), this);
72  callLabel->setStyleSheet("QLabel{color: white;} QToolTip{color: black;}");
73  callLabel->setAlignment(Qt::AlignHCenter);
74  callLabel->setToolTip(callLabel->text());
75 
76  // Note: At the moment this may not work properly. For languages written
77  // from right to left, there is no translation for the phrase "Incoming call...".
78  // In this situation, the phrase "Incoming call..." looks as "...oming call..."
79  Qt::TextElideMode elideMode =
80  (QGuiApplication::layoutDirection() == Qt::LeftToRight) ? Qt::ElideRight : Qt::ElideLeft;
81  int marginSize = 12;
82  QFontMetrics fontMetrics(callLabel->font());
83  QString elidedText =
84  fontMetrics.elidedText(callLabel->text(), elideMode, rectW - marginSize * 2 - 4);
85  callLabel->setText(elidedText);
86 
87  QDialogButtonBox* buttonBox = new QDialogButtonBox(Qt::Horizontal, this);
88  QPushButton *accept = new QPushButton(this), *reject = new QPushButton(this);
89  accept->setFlat(true);
90  reject->setFlat(true);
91  accept->setStyleSheet("QPushButton{border:none;}");
92  reject->setStyleSheet("QPushButton{border:none;}");
93  accept->setIcon(QIcon(Style::getImagePath("acceptCall/acceptCall.svg")));
94  reject->setIcon(QIcon(Style::getImagePath("rejectCall/rejectCall.svg")));
95  accept->setIconSize(accept->size());
96  reject->setIconSize(reject->size());
97 
98  buttonBox->addButton(accept, QDialogButtonBox::AcceptRole);
99  buttonBox->addButton(reject, QDialogButtonBox::RejectRole);
100 
101  connect(buttonBox, &QDialogButtonBox::accepted, this, &CallConfirmWidget::accepted);
102  connect(buttonBox, &QDialogButtonBox::rejected, this, &CallConfirmWidget::rejected);
103 
104  layout->setMargin(marginSize);
105  layout->addSpacing(spikeH);
106  layout->addWidget(callLabel);
107  layout->addWidget(buttonBox);
108 
109  setFixedSize(rectW, rectH + spikeH);
110  reposition();
111 }
112 
117 {
118  if (parentWidget())
119  parentWidget()->removeEventFilter(this);
120 
121  setParent(anchor->window());
122  parentWidget()->installEventFilter(this);
123 
124  QWidget* w = anchor->window();
125  QPoint pos = anchor->mapToGlobal({(anchor->width() - rectW) / 2, anchor->height()})
126  - w->mapToGlobal({0, 0});
127 
128  // We don't want the widget to overflow past the right of the screen
129  int xOverflow = 0;
130  if (pos.x() + rectW > w->width())
131  xOverflow = pos.x() + rectW - w->width();
132  pos.rx() -= xOverflow;
133 
134  mainRect = {0, spikeH, rectW, rectH};
135  brush = QBrush(QColor(65, 65, 65));
136  spikePoly = QPolygon({{(rectW - spikeW) / 2 + xOverflow, spikeH},
137  {rectW / 2 + xOverflow, 0},
138  {(rectW + spikeW) / 2 + xOverflow, spikeH}});
139 
140  move(pos);
141  update();
142 }
143 
145 {
146  QPainter painter(this);
147  painter.setRenderHint(QPainter::Antialiasing);
148  painter.setBrush(brush);
149  painter.setPen(Qt::NoPen);
150 
151  painter.drawRoundedRect(mainRect, roundedFactor * rectRatio, roundedFactor, Qt::RelativeSize);
152  painter.drawPolygon(spikePoly);
153 }
154 
156 {
157  // Kriby: Legacy comment, is this still true?
158  // If someone does show() from Widget or lower, the event will reach us
159  // because it's our parent, and we could show up in the wrong form.
160  // So check here if our friend's form is actually the active one.
161 
162  reposition();
163  update();
164 }
165 
167 {
168  if (parentWidget())
169  parentWidget()->removeEventFilter(this);
170 
171  setParent(nullptr);
172 }
173 
174 bool CallConfirmWidget::eventFilter(QObject*, QEvent* event)
175 {
176  if (event->type() == QEvent::Resize)
177  reposition();
178 
179  return false;
180 }
style.h
CallConfirmWidget::rejected
void rejected()
CallConfirmWidget::rectRatio
const qreal rectRatio
Used to correct the rounding factors on non-square rects.
Definition: callconfirmwidget.h:60
CallConfirmWidget::accepted
void accepted()
CallConfirmWidget::paintEvent
void paintEvent(QPaintEvent *event) final
Definition: callconfirmwidget.cpp:144
CallConfirmWidget::showEvent
void showEvent(QShowEvent *event) final
Definition: callconfirmwidget.cpp:155
callconfirmwidget.h
CallConfirmWidget::CallConfirmWidget
CallConfirmWidget(const QWidget *anchor)
Definition: callconfirmwidget.cpp:53
Style::getImagePath
static const QString getImagePath(const QString &filename)
Definition: style.cpp:182
CallConfirmWidget::reposition
void reposition()
Recalculate our positions to track the anchor.
Definition: callconfirmwidget.cpp:116
CallConfirmWidget::spikePoly
QPolygon spikePoly
Definition: callconfirmwidget.h:54
CallConfirmWidget::mainRect
QRect mainRect
Definition: callconfirmwidget.h:53
widget.h
CallConfirmWidget::anchor
const QWidget * anchor
The widget we're going to be tracking.
Definition: callconfirmwidget.h:51
CallConfirmWidget::rectW
const int rectW
Definition: callconfirmwidget.h:57
CallConfirmWidget::brush
QBrush brush
Definition: callconfirmwidget.h:55
CallConfirmWidget::roundedFactor
const int roundedFactor
By how much are the corners of the main rect rounded.
Definition: callconfirmwidget.h:59
CallConfirmWidget::hideEvent
void hideEvent(QHideEvent *event) final
Definition: callconfirmwidget.cpp:166
CallConfirmWidget::eventFilter
bool eventFilter(QObject *, QEvent *event) final
Definition: callconfirmwidget.cpp:174