From 32bf56c7d94e56a32ce9a0959d9e6ed2c3b267da Mon Sep 17 00:00:00 2001 From: "Tux3 / Mlkj / !Lev.uXFMLA" Date: Sun, 25 Jan 2015 04:57:20 +0100 Subject: [PATCH 1/6] Implement new call confirm widget logic Works, but does not have any styling at the moment --- qtox.pro | 6 +- src/core.h | 1 + src/coreav.cpp | 9 ++- src/widget/callconfirmwidget.cpp | 33 +++++++++++ src/widget/callconfirmwidget.h | 19 ++++++ src/widget/form/chatform.cpp | 99 +++++++++++++++++++++++++++----- src/widget/form/chatform.h | 9 +++ src/widget/widget.cpp | 1 + 8 files changed, 159 insertions(+), 18 deletions(-) create mode 100644 src/widget/callconfirmwidget.cpp create mode 100644 src/widget/callconfirmwidget.h diff --git a/qtox.pro b/qtox.pro index 541de4d65..215237c00 100644 --- a/qtox.pro +++ b/qtox.pro @@ -188,7 +188,8 @@ HEADERS += src/widget/form/addfriendform.h \ src/autoupdate.h \ src/misc/serialize.h \ src/widget/form/settings/advancedform.h \ - src/audio.h + src/audio.h \ + src/widget/callconfirmwidget.h SOURCES += \ src/widget/form/addfriendform.cpp \ @@ -255,7 +256,8 @@ SOURCES += \ src/autoupdate.cpp \ src/misc/serialize.cpp \ src/widget/form/settings/advancedform.cpp \ - src/audio.cpp + src/audio.cpp \ + src/widget/callconfirmwidget.cpp contains(DEFINES, QTOX_FILTER_AUDIO) { HEADERS += src/audiofilterer.h diff --git a/src/core.h b/src/core.h index 14d42a12f..de9b62215 100644 --- a/src/core.h +++ b/src/core.h @@ -117,6 +117,7 @@ public slots: void pauseResumeFileRecv(int friendId, int fileNum); void answerCall(int callId); + void rejectCall(int callId); void hangupCall(int callId); void startCall(int friendId, bool video=false); void cancelCall(int callId, int friendId); diff --git a/src/coreav.cpp b/src/coreav.cpp index b26be579c..b615661cd 100644 --- a/src/coreav.cpp +++ b/src/coreav.cpp @@ -159,6 +159,13 @@ void Core::hangupCall(int callId) toxav_hangup(toxav, callId); } +void Core::rejectCall(int callId) +{ + qDebug() << QString("Core: rejecting call %1").arg(callId); + calls[callId].active = false; + toxav_reject(toxav, callId, nullptr); +} + void Core::startCall(int friendId, bool video) { int callId; @@ -201,7 +208,7 @@ void Core::cancelCall(int callId, int friendId) { qDebug() << QString("Core: Cancelling call with %1").arg(friendId); calls[callId].active = false; - toxav_cancel(toxav, callId, friendId, 0); + toxav_cancel(toxav, callId, friendId, nullptr); } void Core::cleanupCall(int callId) diff --git a/src/widget/callconfirmwidget.cpp b/src/widget/callconfirmwidget.cpp new file mode 100644 index 000000000..07ad5b224 --- /dev/null +++ b/src/widget/callconfirmwidget.cpp @@ -0,0 +1,33 @@ +#include "callconfirmwidget.h" +#include "widget.h" +#include +#include +#include +#include +#include + +CallConfirmWidget::CallConfirmWidget(QWidget *anchor) : + QWidget(Widget::getInstance()) +{ + Widget* w = Widget::getInstance(); + + setWindowFlags(Qt::SubWindow); + setAutoFillBackground(true); + + QVBoxLayout *layout = new QVBoxLayout(this); + QLabel *callLabel = new QLabel(tr("Incoming call..."), this); + QDialogButtonBox *buttonBox = new QDialogButtonBox(Qt::Horizontal, this); + QPushButton *accept = new QPushButton("Y", this), *reject = new QPushButton("N", this); + + buttonBox->addButton(accept, QDialogButtonBox::AcceptRole); + buttonBox->addButton(reject, QDialogButtonBox::RejectRole); + + connect(buttonBox, &QDialogButtonBox::accepted, this, &CallConfirmWidget::accepted); + connect(buttonBox, &QDialogButtonBox::rejected, this, &CallConfirmWidget::rejected); + + layout->addWidget(callLabel); + layout->addWidget(buttonBox); + + setFixedSize(150,90); + move(anchor->mapToGlobal({(anchor->width()-width())/2,anchor->height()})-w->mapToGlobal({0,0})); +} diff --git a/src/widget/callconfirmwidget.h b/src/widget/callconfirmwidget.h new file mode 100644 index 000000000..cea51ad56 --- /dev/null +++ b/src/widget/callconfirmwidget.h @@ -0,0 +1,19 @@ +#ifndef CALLCONFIRMWIDGET_H +#define CALLCONFIRMWIDGET_H + +#include + +class QMoveEvent; + +class CallConfirmWidget : public QWidget +{ + Q_OBJECT +public: + explicit CallConfirmWidget(QWidget *anchor); + +signals: + void accepted(); + void rejected(); +}; + +#endif // CALLCONFIRMWIDGET_H diff --git a/src/widget/form/chatform.cpp b/src/widget/form/chatform.cpp index 12de13fbb..02b61dc98 100644 --- a/src/widget/form/chatform.cpp +++ b/src/widget/form/chatform.cpp @@ -24,22 +24,23 @@ #include #include #include "chatform.h" -#include "src/historykeeper.h" -#include "src/widget/form/loadhistorydialog.h" -#include "src/friend.h" -#include "src/widget/friendwidget.h" -#include "src/filetransferinstance.h" -#include "src/widget/tool/chatactions/filetransferaction.h" -#include "src/widget/netcamview.h" -#include "src/widget/chatareawidget.h" -#include "src/widget/tool/chattextedit.h" #include "src/core.h" -#include "src/widget/widget.h" -#include "src/widget/maskablepixmapwidget.h" -#include "src/widget/croppinglabel.h" +#include "src/friend.h" +#include "src/filetransferinstance.h" +#include "src/historykeeper.h" #include "src/misc/style.h" #include "src/misc/settings.h" #include "src/misc/cstring.h" +#include "src/widget/callconfirmwidget.h" +#include "src/widget/friendwidget.h" +#include "src/widget/netcamview.h" +#include "src/widget/chatareawidget.h" +#include "src/widget/form/loadhistorydialog.h" +#include "src/widget/tool/chattextedit.h" +#include "src/widget/tool/chatactions/filetransferaction.h" +#include "src/widget/widget.h" +#include "src/widget/maskablepixmapwidget.h" +#include "src/widget/croppinglabel.h" ChatForm::ChatForm(Friend* chatFriend) : f(chatFriend) @@ -54,6 +55,8 @@ ChatForm::ChatForm(Friend* chatFriend) statusMessageLabel->setFont(Style::getFont(Style::Medium)); statusMessageLabel->setMinimumHeight(Style::getFont(Style::Medium).pixelSize()); + callConfirm = nullptr; + isTypingLabel = new QLabel(); QFont font = isTypingLabel->font(); font.setItalic(true); @@ -97,6 +100,7 @@ ChatForm::ChatForm(Friend* chatFriend) ChatForm::~ChatForm() { delete netcam; + delete callConfirm; } void ChatForm::setStatusMessage(QString newMessage) @@ -261,6 +265,12 @@ void ChatForm::onAvInvite(int FriendId, int CallId, bool video) qDebug() << "onAvInvite"; + callConfirm = new CallConfirmWidget(callButton); + if (isVisible()) + callConfirm->show(); + connect(callConfirm, SIGNAL(accepted()), this, SLOT(onAnswerCallTriggered())); + connect(callConfirm, SIGNAL(rejected()), this, SLOT(onRejectCallTriggered())); + callId = CallId; callButton->disconnect(); videoButton->disconnect(); @@ -329,12 +339,14 @@ void ChatForm::onAvStart(int FriendId, int CallId, bool video) void ChatForm::onAvCancel(int FriendId, int) { - if (FriendId != f->getFriendID()) return; qDebug() << "onAvCancel"; + delete callConfirm; + callConfirm = nullptr; + stopCounter(); audioInputFlag = false; @@ -364,6 +376,9 @@ void ChatForm::onAvEnd(int FriendId, int) qDebug() << "onAvEnd"; + delete callConfirm; + callConfirm = nullptr; + audioInputFlag = false; audioOutputFlag = false; micButton->setObjectName("green"); @@ -452,6 +467,9 @@ void ChatForm::onAvEnding(int FriendId, int) qDebug() << "onAvEnding"; + delete callConfirm; + callConfirm = nullptr; + audioInputFlag = false; audioOutputFlag = false; micButton->setObjectName("green"); @@ -481,6 +499,9 @@ void ChatForm::onAvRequestTimeout(int FriendId, int) qDebug() << "onAvRequestTimeout"; + delete callConfirm; + callConfirm = nullptr; + audioInputFlag = false; audioOutputFlag = false; micButton->setObjectName("green"); @@ -508,6 +529,9 @@ void ChatForm::onAvPeerTimeout(int FriendId, int) qDebug() << "onAvPeerTimeout"; + delete callConfirm; + callConfirm = nullptr; + audioInputFlag = false; audioOutputFlag = false; micButton->setObjectName("green"); @@ -535,6 +559,9 @@ void ChatForm::onAvRejected(int FriendId, int) qDebug() << "onAvRejected"; + delete callConfirm; + callConfirm = nullptr; + audioInputFlag = false; audioOutputFlag = false; micButton->setObjectName("green"); @@ -577,7 +604,13 @@ void ChatForm::onAvMediaChange(int FriendId, int CallId, bool video) void ChatForm::onAnswerCallTriggered() { qDebug() << "onAnswerCallTriggered"; - + + if (callConfirm) + { + delete callConfirm; + callConfirm = nullptr; + } + audioInputFlag = true; audioOutputFlag = true; emit answerCall(callId); @@ -596,10 +629,29 @@ void ChatForm::onHangupCallTriggered() volButton->style()->polish(volButton); } +void ChatForm::onRejectCallTriggered() +{ + qDebug() << "onRejectCallTriggered"; + + if (callConfirm) + { + delete callConfirm; + callConfirm = nullptr; + } + + audioInputFlag = false; + audioOutputFlag = false; + emit rejectCall(callId); + micButton->setObjectName("green"); + micButton->style()->polish(micButton); + volButton->setObjectName("green"); + volButton->style()->polish(volButton); +} + void ChatForm::onCallTriggered() { qDebug() << "onCallTriggered"; - + audioInputFlag = true; audioOutputFlag = true; callButton->disconnect(); @@ -625,6 +677,9 @@ void ChatForm::onAvCallFailed(int FriendId) qDebug() << "onAvCallFailed"; + delete callConfirm; + callConfirm = nullptr; + audioInputFlag = false; audioOutputFlag = false; callButton->disconnect(); @@ -947,3 +1002,17 @@ void ChatForm::deliverOfflineMsgs() registerReceipt(rec, iter.key(), iter.value()); } } + +void ChatForm::show(Ui::MainWindow &ui) +{ + GenericChatForm::show(ui); + + if (callConfirm) + callConfirm->show(); +} + +void ChatForm::hideEvent(QHideEvent*) +{ + if (callConfirm) + callConfirm->hide(); +} diff --git a/src/widget/form/chatform.h b/src/widget/form/chatform.h index 21e97078d..7dfbd1f74 100644 --- a/src/widget/form/chatform.h +++ b/src/widget/form/chatform.h @@ -28,6 +28,9 @@ struct Friend; class FileTransferInstance; class NetCamView; class QPixmap; +class CallConfirmWidget; +class QHideEvent; +class QMoveEvent; class ChatForm : public GenericChatForm { @@ -41,6 +44,8 @@ public: void dischargeReceipt(int receipt); void setFriendTyping(bool isTyping); + virtual void show(Ui::MainWindow &ui); + signals: void sendFile(int32_t friendId, QString, QString, long long); void startCall(int friendId); @@ -48,6 +53,7 @@ signals: void answerCall(int callId); void hangupCall(int callId); void cancelCall(int callId, int friendId); + void rejectCall(int callId); void micMuteToggle(int callId); void volMuteToggle(int callId); void aliasChanged(const QString& alias); @@ -83,6 +89,7 @@ private slots: void onAnswerCallTriggered(); void onHangupCallTriggered(); void onCancelCallTriggered(); + void onRejectCallTriggered(); void onFileTansBtnClicked(QString widgetName, QString buttonName); void onFileSendFailed(int FriendId, const QString &fname); void onLoadHistory(); @@ -92,6 +99,7 @@ protected: // drag & drop void dragEnterEvent(QDragEnterEvent* ev); void dropEvent(QDropEvent* ev); + virtual void hideEvent(QHideEvent* event); void registerReceipt(int receipt, int messageID, MessageActionPtr msg); private: @@ -111,6 +119,7 @@ private: QString secondsToDHMS(quint32 duration); QHash receipts; QMap undeliveredMsgs; + CallConfirmWidget *callConfirm; }; #endif // CHATFORM_H diff --git a/src/widget/widget.cpp b/src/widget/widget.cpp index 89f148a81..11cdf17b6 100644 --- a/src/widget/widget.cpp +++ b/src/widget/widget.cpp @@ -679,6 +679,7 @@ void Widget::addFriend(int friendId, const QString &userId) connect(newfriend->getChatForm(), SIGNAL(sendFile(int32_t, QString, QString, long long)), core, SLOT(sendFile(int32_t, QString, QString, long long))); connect(newfriend->getChatForm(), SIGNAL(answerCall(int)), core, SLOT(answerCall(int))); connect(newfriend->getChatForm(), SIGNAL(hangupCall(int)), core, SLOT(hangupCall(int))); + connect(newfriend->getChatForm(), SIGNAL(rejectCall(int)), core, SLOT(rejectCall(int))); connect(newfriend->getChatForm(), SIGNAL(startCall(int)), core, SLOT(startCall(int))); connect(newfriend->getChatForm(), SIGNAL(startVideoCall(int,bool)), core, SLOT(startCall(int,bool))); connect(newfriend->getChatForm(), SIGNAL(cancelCall(int,int)), core, SLOT(cancelCall(int,int))); From b13c27202adf5bec926ee8fd552f572087e3bd1a Mon Sep 17 00:00:00 2001 From: "Tux3 / Mlkj / !Lev.uXFMLA" Date: Sun, 25 Jan 2015 16:46:33 +0100 Subject: [PATCH 2/6] Stylized CallConfirmedWidget, placeholder buttons --- src/widget/callconfirmwidget.cpp | 36 ++++++++++++++++++++++++++++---- src/widget/callconfirmwidget.h | 17 ++++++++++++++- 2 files changed, 48 insertions(+), 5 deletions(-) diff --git a/src/widget/callconfirmwidget.cpp b/src/widget/callconfirmwidget.cpp index 07ad5b224..94c6c4b41 100644 --- a/src/widget/callconfirmwidget.cpp +++ b/src/widget/callconfirmwidget.cpp @@ -5,19 +5,30 @@ #include #include #include +#include +#include +#include +#include CallConfirmWidget::CallConfirmWidget(QWidget *anchor) : - QWidget(Widget::getInstance()) + QWidget(Widget::getInstance()), + rectW{130}, rectH{90}, + spikeW{30}, spikeH{15}, + roundedFactor{15} { Widget* w = Widget::getInstance(); setWindowFlags(Qt::SubWindow); - setAutoFillBackground(true); + + QPalette palette; + palette.setColor(QPalette::WindowText, Qt::white); + setPalette(palette); QVBoxLayout *layout = new QVBoxLayout(this); QLabel *callLabel = new QLabel(tr("Incoming call..."), this); + callLabel->setAlignment(Qt::AlignHCenter); QDialogButtonBox *buttonBox = new QDialogButtonBox(Qt::Horizontal, this); - QPushButton *accept = new QPushButton("Y", this), *reject = new QPushButton("N", this); + QPushButton *accept = new QPushButton("Accept", this), *reject = new QPushButton("Reject", this); buttonBox->addButton(accept, QDialogButtonBox::AcceptRole); buttonBox->addButton(reject, QDialogButtonBox::RejectRole); @@ -25,9 +36,26 @@ CallConfirmWidget::CallConfirmWidget(QWidget *anchor) : connect(buttonBox, &QDialogButtonBox::accepted, this, &CallConfirmWidget::accepted); connect(buttonBox, &QDialogButtonBox::rejected, this, &CallConfirmWidget::rejected); + layout->setMargin(12); + layout->addSpacing(spikeH); layout->addWidget(callLabel); layout->addWidget(buttonBox); - setFixedSize(150,90); + mainRect = {0,spikeH,rectW,rectH}; + brush = QBrush(QColor(65,65,65)); + spikePoly = QPolygon({{(rectW-spikeW)/2,spikeH},{rectW/2,0},{(rectW+spikeW)/2,spikeH}}); + + setFixedSize(rectW,rectH+spikeH); move(anchor->mapToGlobal({(anchor->width()-width())/2,anchor->height()})-w->mapToGlobal({0,0})); } + +void CallConfirmWidget::paintEvent(QPaintEvent*) +{ + QPainter painter(this); + painter.setRenderHint(QPainter::Antialiasing); + painter.setBrush(brush); + painter.setPen(Qt::NoPen); + + painter.drawRoundRect(mainRect, roundedFactor, roundedFactor); + painter.drawPolygon(spikePoly); +} diff --git a/src/widget/callconfirmwidget.h b/src/widget/callconfirmwidget.h index cea51ad56..350486bb6 100644 --- a/src/widget/callconfirmwidget.h +++ b/src/widget/callconfirmwidget.h @@ -2,8 +2,11 @@ #define CALLCONFIRMWIDGET_H #include +#include +#include +#include -class QMoveEvent; +class QPaintEvent; class CallConfirmWidget : public QWidget { @@ -14,6 +17,18 @@ public: signals: void accepted(); void rejected(); + +protected: + virtual void paintEvent(QPaintEvent* event) override; + +private: + QRect mainRect; + QPolygon spikePoly; + QBrush brush; + + const int rectW, rectH; + const int spikeW, spikeH; + const int roundedFactor; }; #endif // CALLCONFIRMWIDGET_H From 40478d6bac3554e03be6ef0961bc8e49e90dbedb Mon Sep 17 00:00:00 2001 From: "Tux3 / Mlkj / !Lev.uXFMLA" Date: Sun, 25 Jan 2015 17:39:20 +0100 Subject: [PATCH 3/6] Show call confirm under video if appropriate --- src/widget/form/chatform.cpp | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/widget/form/chatform.cpp b/src/widget/form/chatform.cpp index 02b61dc98..806cb2225 100644 --- a/src/widget/form/chatform.cpp +++ b/src/widget/form/chatform.cpp @@ -265,17 +265,17 @@ void ChatForm::onAvInvite(int FriendId, int CallId, bool video) qDebug() << "onAvInvite"; - callConfirm = new CallConfirmWidget(callButton); - if (isVisible()) - callConfirm->show(); - connect(callConfirm, SIGNAL(accepted()), this, SLOT(onAnswerCallTriggered())); - connect(callConfirm, SIGNAL(rejected()), this, SLOT(onRejectCallTriggered())); - callId = CallId; callButton->disconnect(); videoButton->disconnect(); if (video) { + callConfirm = new CallConfirmWidget(videoButton); + if (isVisible()) + callConfirm->show(); + connect(callConfirm, SIGNAL(accepted()), this, SLOT(onAnswerCallTriggered())); + connect(callConfirm, SIGNAL(rejected()), this, SLOT(onRejectCallTriggered())); + callButton->setObjectName("grey"); callButton->style()->polish(callButton); videoButton->setObjectName("yellow"); @@ -284,6 +284,12 @@ void ChatForm::onAvInvite(int FriendId, int CallId, bool video) } else { + callConfirm = new CallConfirmWidget(callButton); + if (isVisible()) + callConfirm->show(); + connect(callConfirm, SIGNAL(accepted()), this, SLOT(onAnswerCallTriggered())); + connect(callConfirm, SIGNAL(rejected()), this, SLOT(onRejectCallTriggered())); + callButton->setObjectName("yellow"); callButton->style()->polish(callButton); videoButton->setObjectName("grey"); From b10edb9baf1cfce57805289ea2c1467ca6f00b2e Mon Sep 17 00:00:00 2001 From: "Tux3 / Mlkj / !Lev.uXFMLA" Date: Sun, 25 Jan 2015 17:53:37 +0100 Subject: [PATCH 4/6] CallConfirmWidget: don't overflow to the right --- src/widget/callconfirmwidget.cpp | 12 ++++++++++-- src/widget/form/chatform.cpp | 2 +- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/widget/callconfirmwidget.cpp b/src/widget/callconfirmwidget.cpp index 94c6c4b41..07aa31553 100644 --- a/src/widget/callconfirmwidget.cpp +++ b/src/widget/callconfirmwidget.cpp @@ -41,12 +41,20 @@ CallConfirmWidget::CallConfirmWidget(QWidget *anchor) : layout->addWidget(callLabel); layout->addWidget(buttonBox); + QPoint pos = anchor->mapToGlobal({(anchor->width()-width())/2,anchor->height()})-w->mapToGlobal({0,0}); + int xOverflow=0; + if (pos.x() + rectW > w->width()) + xOverflow = pos.x() + rectW - w->width(); + pos.rx() -= xOverflow; + mainRect = {0,spikeH,rectW,rectH}; brush = QBrush(QColor(65,65,65)); - spikePoly = QPolygon({{(rectW-spikeW)/2,spikeH},{rectW/2,0},{(rectW+spikeW)/2,spikeH}}); + spikePoly = QPolygon({{(rectW-spikeW+xOverflow)/2,spikeH}, + {(rectW+xOverflow)/2,0}, + {(rectW+spikeW+xOverflow)/2,spikeH}}); setFixedSize(rectW,rectH+spikeH); - move(anchor->mapToGlobal({(anchor->width()-width())/2,anchor->height()})-w->mapToGlobal({0,0})); + move(pos); } void CallConfirmWidget::paintEvent(QPaintEvent*) diff --git a/src/widget/form/chatform.cpp b/src/widget/form/chatform.cpp index 806cb2225..809518dc1 100644 --- a/src/widget/form/chatform.cpp +++ b/src/widget/form/chatform.cpp @@ -668,7 +668,7 @@ void ChatForm::onCallTriggered() void ChatForm::onVideoCallTriggered() { qDebug() << "onVideoCallTriggered"; - + audioInputFlag = true; audioOutputFlag = true; callButton->disconnect(); From 279debdab9b77f94ff3e2e374fe5d3f3b53ee1cf Mon Sep 17 00:00:00 2001 From: "Tux3 / Mlkj / !Lev.uXFMLA" Date: Sun, 25 Jan 2015 18:43:30 +0100 Subject: [PATCH 5/6] CallConfirmWidget: track anchor's position --- src/widget/callconfirmwidget.cpp | 33 +++++++++++++++++++++++--------- src/widget/callconfirmwidget.h | 14 ++++++++++++-- src/widget/widget.cpp | 2 ++ src/widget/widget.h | 1 + 4 files changed, 39 insertions(+), 11 deletions(-) diff --git a/src/widget/callconfirmwidget.cpp b/src/widget/callconfirmwidget.cpp index 07aa31553..c1b7bcff2 100644 --- a/src/widget/callconfirmwidget.cpp +++ b/src/widget/callconfirmwidget.cpp @@ -10,14 +10,12 @@ #include #include -CallConfirmWidget::CallConfirmWidget(QWidget *anchor) : - QWidget(Widget::getInstance()), +CallConfirmWidget::CallConfirmWidget(const QWidget *Anchor) : + QWidget(Widget::getInstance()), anchor(Anchor), rectW{130}, rectH{90}, spikeW{30}, spikeH{15}, roundedFactor{15} { - Widget* w = Widget::getInstance(); - setWindowFlags(Qt::SubWindow); QPalette palette; @@ -36,12 +34,23 @@ CallConfirmWidget::CallConfirmWidget(QWidget *anchor) : connect(buttonBox, &QDialogButtonBox::accepted, this, &CallConfirmWidget::accepted); connect(buttonBox, &QDialogButtonBox::rejected, this, &CallConfirmWidget::rejected); + connect(Widget::getInstance(), &Widget::resized, this, &CallConfirmWidget::reposition); + layout->setMargin(12); layout->addSpacing(spikeH); layout->addWidget(callLabel); layout->addWidget(buttonBox); - QPoint pos = anchor->mapToGlobal({(anchor->width()-width())/2,anchor->height()})-w->mapToGlobal({0,0}); + setFixedSize(rectW,rectH+spikeH); + reposition(); +} + +void CallConfirmWidget::reposition() +{ + Widget* w = Widget::getInstance(); + QPoint pos = anchor->mapToGlobal({(anchor->width()-rectW)/2,anchor->height()})-w->mapToGlobal({0,0}); + + // We don't want the widget to overflow past the right of the screen int xOverflow=0; if (pos.x() + rectW > w->width()) xOverflow = pos.x() + rectW - w->width(); @@ -49,12 +58,12 @@ CallConfirmWidget::CallConfirmWidget(QWidget *anchor) : mainRect = {0,spikeH,rectW,rectH}; brush = QBrush(QColor(65,65,65)); - spikePoly = QPolygon({{(rectW-spikeW+xOverflow)/2,spikeH}, - {(rectW+xOverflow)/2,0}, - {(rectW+spikeW+xOverflow)/2,spikeH}}); + spikePoly = QPolygon({{(rectW-spikeW)/2+xOverflow,spikeH}, + {rectW/2+xOverflow,0}, + {(rectW+spikeW)/2+xOverflow,spikeH}}); - setFixedSize(rectW,rectH+spikeH); move(pos); + update(); } void CallConfirmWidget::paintEvent(QPaintEvent*) @@ -67,3 +76,9 @@ void CallConfirmWidget::paintEvent(QPaintEvent*) painter.drawRoundRect(mainRect, roundedFactor, roundedFactor); painter.drawPolygon(spikePoly); } + +void CallConfirmWidget::showEvent(QShowEvent*) +{ + reposition(); + update(); +} diff --git a/src/widget/callconfirmwidget.h b/src/widget/callconfirmwidget.h index 350486bb6..eb64fdac1 100644 --- a/src/widget/callconfirmwidget.h +++ b/src/widget/callconfirmwidget.h @@ -7,12 +7,16 @@ #include class QPaintEvent; +class QShowEvent; +/// This is a widget with dialog buttons to accept/reject a call +/// It tracks the position of another widget called the anchor +/// and looks like a bubble at the bottom of that widget. class CallConfirmWidget : public QWidget { Q_OBJECT public: - explicit CallConfirmWidget(QWidget *anchor); + explicit CallConfirmWidget(const QWidget *Anchor); signals: void accepted(); @@ -20,15 +24,21 @@ signals: protected: virtual void paintEvent(QPaintEvent* event) override; + virtual void showEvent(QShowEvent * event) override; + +protected slots: + void reposition(); ///< Recalculate our positions to track the anchor private: + const QWidget* anchor; ///< The widget we're going to be tracking + QRect mainRect; QPolygon spikePoly; QBrush brush; const int rectW, rectH; const int spikeW, spikeH; - const int roundedFactor; + const int roundedFactor; ///< By how much are the corners of the main rect rounded }; #endif // CALLCONFIRMWIDGET_H diff --git a/src/widget/widget.cpp b/src/widget/widget.cpp index 11cdf17b6..367502ab9 100644 --- a/src/widget/widget.cpp +++ b/src/widget/widget.cpp @@ -377,6 +377,8 @@ void Widget::resizeEvent(QResizeEvent *event) { Q_UNUSED(event); saveWindowGeometry(); + + emit resized(); } QString Widget::detectProfile() diff --git a/src/widget/widget.h b/src/widget/widget.h index 4cad2c83c..e1a39f89e 100644 --- a/src/widget/widget.h +++ b/src/widget/widget.h @@ -90,6 +90,7 @@ signals: void usernameChanged(const QString& username); void statusMessageChanged(const QString& statusMessage); void changeProfile(const QString& profile); + void resized(); private slots: void onConnected(); From 328f75ac6db3b793de6ea0a43f5ec43785b42bc8 Mon Sep 17 00:00:00 2001 From: "Tux3 / Mlkj / !Lev.uXFMLA" Date: Sun, 25 Jan 2015 19:12:36 +0100 Subject: [PATCH 6/6] Add real buttons for CallConfirmWidget Still sort of placeholders, those are just upscaled buttons extracted from a screeshot, but those will work in the meantime --- res.qrc | 2 ++ src/widget/callconfirmwidget.cpp | 12 ++++++++++-- ui/acceptCall/acceptCall.png | Bin 0 -> 2708 bytes ui/rejectCall/rejectCall.png | Bin 0 -> 2717 bytes 4 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 ui/acceptCall/acceptCall.png create mode 100644 ui/rejectCall/rejectCall.png diff --git a/res.qrc b/res.qrc index a62fa5697..196a3b2e2 100644 --- a/res.qrc +++ b/res.qrc @@ -227,5 +227,7 @@ ui/window/applicationIcon.png ui/window/statusPanel.css ui/window/window.css + ui/acceptCall/acceptCall.png + ui/rejectCall/rejectCall.png diff --git a/src/widget/callconfirmwidget.cpp b/src/widget/callconfirmwidget.cpp index c1b7bcff2..2953cd30b 100644 --- a/src/widget/callconfirmwidget.cpp +++ b/src/widget/callconfirmwidget.cpp @@ -12,7 +12,7 @@ CallConfirmWidget::CallConfirmWidget(const QWidget *Anchor) : QWidget(Widget::getInstance()), anchor(Anchor), - rectW{130}, rectH{90}, + rectW{120}, rectH{85}, spikeW{30}, spikeH{15}, roundedFactor{15} { @@ -26,7 +26,15 @@ CallConfirmWidget::CallConfirmWidget(const QWidget *Anchor) : QLabel *callLabel = new QLabel(tr("Incoming call..."), this); callLabel->setAlignment(Qt::AlignHCenter); QDialogButtonBox *buttonBox = new QDialogButtonBox(Qt::Horizontal, this); - QPushButton *accept = new QPushButton("Accept", this), *reject = new QPushButton("Reject", this); + QPushButton *accept = new QPushButton(this), *reject = new QPushButton(this); + accept->setFlat(true); + reject->setFlat(true); + accept->setStyleSheet("QPushButton{border:none;}"); + reject->setStyleSheet("QPushButton{border:none;}"); + accept->setIcon(QIcon(":/ui/acceptCall/acceptCall.png")); + reject->setIcon(QIcon(":/ui/rejectCall/rejectCall.png")); + accept->setIconSize(accept->size()); + reject->setIconSize(reject->size()); buttonBox->addButton(accept, QDialogButtonBox::AcceptRole); buttonBox->addButton(reject, QDialogButtonBox::RejectRole); diff --git a/ui/acceptCall/acceptCall.png b/ui/acceptCall/acceptCall.png new file mode 100644 index 0000000000000000000000000000000000000000..c892aba9b58a0ab958e89a631d0cc06be75f173d GIT binary patch literal 2708 zcmV;F3TyR=P)(edpZ0clYjYvdQK_2m~kw#1sTnkcV0c(Z*`+_&~90bW~=nqcfcj z`j69&j-6KMjIH80Q>iV|DPVn#T9K-0bx=VO93G+aHX?>3o9AZl?%sRO=^wj$vw1-_ zguwU5&d%<6e6Qd4edjxekOM7WeG@jUe0`|D`OnwfTI(zKK4*}BvQGwJ2cocjF_0pF z04PB80K&qN`1kR9*FUuB;}PyPfM_^_R=iaQ0QBddu2Y%cZvXu)Wr0d_q2{LoZo(0k z@Jkz2q_Jh1(!(BQKo|)~Jqf7ZZDbNqHd+S28q_fZ8m;c9$DM1T@FmS{@;;>#5W|MOMXj`#?c z7`|!m+f+A;8TchLRET*{3`L8G1EdXDNdbzoEs?dOazFddP)ex(0*H`CQ4pSa{)%vW4(KDc?;N5`<=8H(2-nW?T_VwNlkRfT5z zpI}~AJ7OS@0!drF*|9VF*k>#EAITPG7_JraOunbIIyBq=1k>5#e%cximEc!{bC$lcj$;caGH?s=2}L_y52<$v?%o15cwZn|I0v z&3&8dW@$m(tOc+V1RvCpp>eFKmj^-|3adbPEt6-KufC}-gAcq}_gALj9_~*kIfe6? z{`UNp>+T%@_UrGj2{S{5m=7T4hS>9sT%MGp0<-fj^|}>nrT`313tX*-`PJM@73Tpi zPM`NAPL?bQo%mt(jP~9CYOpi_2vnL2iD4BKRjBjZoq8qW^dn=OKE)WP{|dnC8USd1 zDgaPHd~Ct3prDk3P$CsVNdplLZz_R^VKRWQ8-BS7r_Ycv^AiFQfe{;-i>18B&IrPV zCH&mvW0t!W6dY;8;9e9MVN4IrfQRY$qWLqlC)%KM9W+dR%7pX)0Kaq1vY&YJ_#$So z%f`YMnP8|h1Esz)Ob=CIe(54qxT(C zn=ZwPW4u|8nc+FOtat(Pjgb3)Tf7w?pQy)y&ITk!VmQ&O&j3xSGXXe3C}vf2jnSisI~EwR)8iw}Gt*P$l*Y77e$QRQ zQVDpu7p4(LLd1~}i9VH0=DU}BT}#X?oQ-0$)Wyq5s|jB;e~O(gpTm)M?yB^pOvAKb zs*#XO=p_)OlCYc@%FJ@qOt=n}`Kb_^5>UE~a^jc}n1s2-^Rck>Dir%l-F1$19m3nk zUd8_Qy(u9GBgrW#*OE@ENTeLB;wT$F&BV0O49qUN6jcQmqtIJ~pq`ICZMzVOw}2GE z$9*XGSKyMOd8jJ9*u{i`!okk3@ny?)9P0cUF{cLv0z>XXC_B{%(L@wr29QgW%@#I_ zyg^(!z8V*Xs^HfGDE5_Ng1-V?$xg)V9th=Nyng~_hUZ{j=^_L@dG7r7cm(ywx46I_ z7A6LRx=M8}Wuo_lm{a&=j3X%%INW&@tf)@Y)3XDS3OuP;k`aWS|gA6nTZi4RX4xr zis^?vc`TVri9*DnkOF&`-G$C%dkQ0I_u<45@C0FSugmChs}Wn8-p0|`LBxfXvh2vM z;ff(Gu`c#);#t1?-F=5ItD7~6>Fm1P3qJ>OVIgXFgEI{QPY^**9*78>I0%Heh~seA z0qkhmhK7#ah}zv}E<`pTLalr0jtv_%0D}8?Pp(OkK+u>5p#&oF7HmJc6;Znj*G{~_ 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