diff --git a/img/avatar_mask.png b/img/avatar_mask.png new file mode 100644 index 000000000..2527e3365 Binary files /dev/null and b/img/avatar_mask.png differ diff --git a/mainwindow.ui b/mainwindow.ui index 845a0c728..a197594bd 100644 --- a/mainwindow.ui +++ b/mainwindow.ui @@ -6,8 +6,8 @@ 0 0 - 716 - 543 + 714 + 541 @@ -1452,32 +1452,20 @@ QSplitter:handle{ 0 - - + + + Qt::Horizontal + + + QSizePolicy::Maximum + + - 40 - 40 + 5 + 20 - - - 40 - 40 - - - - - - - :/img/contact.png - - - false - - - true - - + @@ -2095,8 +2083,8 @@ QSplitter:handle{ 0 0 - 263 - 378 + 262 + 375 @@ -3230,8 +3218,8 @@ QSplitter:handle{ 0 0 - 716 - 19 + 714 + 25 @@ -3257,11 +3245,6 @@ QSplitter:handle{ QLabel
widget/croppinglabel.h
- - ClickableLabel - QLabel -
widget/tool/clickablelabel.h
-
diff --git a/qtox.pro b/qtox.pro index 6b63a9835..c5bf81c1b 100644 --- a/qtox.pro +++ b/qtox.pro @@ -117,7 +117,7 @@ HEADERS += widget/form/addfriendform.h \ widget/tool/chatactions/messageaction.h \ widget/tool/chatactions/filetransferaction.h \ widget/tool/chatactions/systemmessageaction.h \ - widget/tool/clickablelabel.h + widget/maskablepixmapwidget.h SOURCES += \ widget/form/addfriendform.cpp \ @@ -157,4 +157,5 @@ SOURCES += \ widget/settingsdialog.cpp \ widget/tool/chatactions/messageaction.cpp \ widget/tool/chatactions/filetransferaction.cpp \ - widget/tool/chatactions/systemmessageaction.cpp + widget/tool/chatactions/systemmessageaction.cpp \ + widget/maskablepixmapwidget.cpp diff --git a/res.qrc b/res.qrc index b1b50df58..603fc8ba2 100644 --- a/res.qrc +++ b/res.qrc @@ -142,5 +142,6 @@ translations/pl.qm translations/fi.qm translations/mannol.qm + img/avatar_mask.png diff --git a/widget/chatareawidget.cpp b/widget/chatareawidget.cpp index 524039d20..765d9e96c 100644 --- a/widget/chatareawidget.cpp +++ b/widget/chatareawidget.cpp @@ -34,6 +34,7 @@ ChatAreaWidget::ChatAreaWidget(QWidget *parent) : setOpenExternalLinks(false); setOpenLinks(false); setAcceptRichText(false); + setFrameStyle(QFrame::NoFrame); chatTextTable = textCursor().insertTable(1,3); @@ -117,7 +118,7 @@ void ChatAreaWidget::insertMessage(ChatAction *msgAction) chatTextTable->cellAt(row,1).firstCursorPosition().insertHtml(msgAction->getMessage()); chatTextTable->cellAt(row,2).firstCursorPosition().insertText(msgAction->getDate()); - msgAction->setTextCursor(cur); + msgAction->setup(cur, this); messages.append(msgAction); } diff --git a/widget/form/chatform.cpp b/widget/form/chatform.cpp index 8d29c9b2d..dc8b7bf05 100644 --- a/widget/form/chatform.cpp +++ b/widget/form/chatform.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include "chatform.h" #include "friend.h" #include "widget/friendwidget.h" @@ -32,12 +33,13 @@ #include "widget/tool/chattextedit.h" #include "core.h" #include "widget/widget.h" +#include "widget/maskablepixmapwidget.h" ChatForm::ChatForm(Friend* chatFriend) : f(chatFriend) { nameLabel->setText(f->getName()); - avatarLabel->setPixmap(QPixmap(":/img/contact_dark.png")); + avatar->setPixmap(QPixmap(":/img/contact_dark.png")); statusMessageLabel = new CroppingLabel(); netcam = new NetCamView(); @@ -475,8 +477,7 @@ void ChatForm::onAvatarChange(int FriendId, const QPixmap &pic) if (FriendId != f->friendId) return; - QPixmap scaled = pic.scaled(40,40,Qt::KeepAspectRatio,Qt::SmoothTransformation); - avatarLabel->setPixmap(scaled); + avatar->setPixmap(pic); } void ChatForm::dragEnterEvent(QDragEnterEvent *ev) diff --git a/widget/form/genericchatform.cpp b/widget/form/genericchatform.cpp index cff9e3b50..a10fe0c83 100644 --- a/widget/form/genericchatform.cpp +++ b/widget/form/genericchatform.cpp @@ -26,6 +26,7 @@ #include "widget/tool/chatactions/systemmessageaction.h" #include "widget/chatareawidget.h" #include "widget/tool/chattextedit.h" +#include "widget/maskablepixmapwidget.h" GenericChatForm::GenericChatForm(QWidget *parent) : QWidget(parent) @@ -35,7 +36,7 @@ GenericChatForm::GenericChatForm(QWidget *parent) : headWidget = new QWidget(); nameLabel = new CroppingLabel(); - avatarLabel = new QLabel(); + avatar = new MaskablePixmapWidget(this, QSize(40,40), ":/img/avatar_mask.png"); QHBoxLayout *headLayout = new QHBoxLayout(), *mainFootLayout = new QHBoxLayout(); headTextLayout = new QVBoxLayout(); QVBoxLayout *mainLayout = new QVBoxLayout(); @@ -99,7 +100,7 @@ GenericChatForm::GenericChatForm(QWidget *parent) : mainFootLayout->setSpacing(0); headWidget->setLayout(headLayout); - headLayout->addWidget(avatarLabel); + headLayout->addWidget(avatar); headLayout->addLayout(headTextLayout); headLayout->addLayout(volMicLayout); headLayout->addWidget(callButton); diff --git a/widget/form/genericchatform.h b/widget/form/genericchatform.h index c824d5e85..d45bf1072 100644 --- a/widget/form/genericchatform.h +++ b/widget/form/genericchatform.h @@ -30,6 +30,7 @@ class QPushButton; class CroppingLabel; class ChatTextEdit; class ChatAreaWidget; +class MaskablePixmapWidget; namespace Ui { class MainWindow; @@ -60,7 +61,7 @@ protected slots: protected: CroppingLabel *nameLabel; - QLabel *avatarLabel; + MaskablePixmapWidget *avatar; QWidget *headWidget; QPushButton *fileButton, *emoteButton, *callButton, *videoButton, *volButton, *micButton; QVBoxLayout *headTextLayout; diff --git a/widget/form/groupchatform.cpp b/widget/form/groupchatform.cpp index 4dc6c7e0d..7622f2cf0 100644 --- a/widget/form/groupchatform.cpp +++ b/widget/form/groupchatform.cpp @@ -19,6 +19,7 @@ #include "widget/groupwidget.h" #include "widget/tool/chattextedit.h" #include "widget/croppinglabel.h" +#include "widget/maskablepixmapwidget.h" #include "core.h" #include #include @@ -42,7 +43,7 @@ GroupChatForm::GroupChatForm(Group* chatGroup) nameLabel->setText(group->widget->name.text()); nusersLabel->setFont(small); nusersLabel->setText(GroupChatForm::tr("%1 users in chat","Number of users in chat").arg(group->peers.size())); - avatarLabel->setPixmap(QPixmap(":/img/group_dark.png")); + avatar->setPixmap(QPixmap(":/img/group_dark.png")); QString names; for (QString& s : group->peers) diff --git a/widget/friendwidget.cpp b/widget/friendwidget.cpp index b4ddc2c93..7b09c2b95 100644 --- a/widget/friendwidget.cpp +++ b/widget/friendwidget.cpp @@ -22,11 +22,13 @@ #include "friend.h" #include "core.h" #include "widget/form/chatform.h" +#include "widget/maskablepixmapwidget.h" #include #include #include #include #include +#include FriendWidget::FriendWidget(int FriendId, QString id) : friendId(FriendId), isDefaultAvatar{true} @@ -42,7 +44,8 @@ FriendWidget::FriendWidget(int FriendId, QString id) textLayout.setMargin(0); setLayoutDirection(Qt::LeftToRight); // parent might have set Qt::RightToLeft - avatar.setPixmap(QPixmap(":img/contact.png")); + avatar = new MaskablePixmapWidget(this, QSize(40,40), ":/img/avatar_mask.png"); + avatar->setPixmap(QPixmap(":img/contact_dark.png")); name.setText(id); //statusPic.setAlignment(Qt::AlignHCenter); statusPic.setPixmap(QPixmap(":img/status/dot_away.png")); @@ -65,7 +68,7 @@ FriendWidget::FriendWidget(int FriendId, QString id) textLayout.addStretch(); layout.addSpacing(20); - layout.addWidget(&avatar); + layout.addWidget(avatar); layout.addSpacing(5); layout.addLayout(&textLayout); layout.addSpacing(5); @@ -137,8 +140,6 @@ void FriendWidget::setAsActiveChatroom() QPalette pal3; pal3.setColor(QPalette::Background, Qt::white); this->setPalette(pal3); - if (isDefaultAvatar) - avatar.setPixmap(QPixmap(":img/contact_dark.png")); } void FriendWidget::setAsInactiveChatroom() @@ -157,9 +158,6 @@ void FriendWidget::setAsInactiveChatroom() QPalette pal3; pal3.setColor(QPalette::Background, QColor(65,65,65,255)); this->setPalette(pal3); - - if (isDefaultAvatar) - avatar.setPixmap(QPixmap(":img/contact.png")); } void FriendWidget::updateStatusLight() @@ -203,8 +201,7 @@ void FriendWidget::onAvatarChange(int FriendId, const QPixmap& pic) return; isDefaultAvatar = false; - QPixmap scaled = pic.scaled(40,40,Qt::KeepAspectRatio,Qt::SmoothTransformation); - avatar.setPixmap(scaled); + avatar->setPixmap(pic); } void FriendWidget::onAvatarRemoved(int FriendId) @@ -234,8 +231,7 @@ void FriendWidget::mouseMoveEvent(QMouseEvent *ev) mdata->setData("friend", QString::number(friendId).toLatin1()); drag->setMimeData(mdata); - if (avatar.pixmap()) - drag->setPixmap(*avatar.pixmap()); + drag->setPixmap(avatar->getPixmap()); drag->exec(Qt::CopyAction | Qt::MoveAction); } diff --git a/widget/friendwidget.h b/widget/friendwidget.h index 2f94229ee..cc29c0385 100644 --- a/widget/friendwidget.h +++ b/widget/friendwidget.h @@ -23,6 +23,7 @@ #include "croppinglabel.h" class QPixmap; +class MaskablePixmapWidget; struct FriendWidget : public GenericChatroomWidget { @@ -51,7 +52,8 @@ protected: public: int friendId; - QLabel avatar, statusPic; + MaskablePixmapWidget* avatar; + QLabel statusPic; CroppingLabel name, statusMessage; bool isDefaultAvatar; QPoint dragStartPos; diff --git a/widget/maskablepixmapwidget.cpp b/widget/maskablepixmapwidget.cpp new file mode 100644 index 000000000..305eb015c --- /dev/null +++ b/widget/maskablepixmapwidget.cpp @@ -0,0 +1,72 @@ +/* + Copyright (C) 2014 by Project Tox + + This file is part of qTox, a Qt-based graphical interface for Tox. + + This program is libre 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 "maskablepixmapwidget.h" +#include + +MaskablePixmapWidget::MaskablePixmapWidget(QWidget *parent, QSize size, QString maskName, QColor background) + : QWidget(parent) + , backgroundColor(background) + , clickable(false) +{ + setFixedSize(size); + mask = QPixmap(maskName).scaled(size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); +} + +void MaskablePixmapWidget::setClickable(bool clickable) +{ + this->clickable = clickable; + + if (clickable) + setCursor(Qt::PointingHandCursor); + else + unsetCursor(); +} + +void MaskablePixmapWidget::setPixmap(const QPixmap &pmap) +{ + pixmap = pmap.scaled(width(), height(), Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation); +} + +QPixmap MaskablePixmapWidget::getPixmap() const +{ + return pixmap; +} + +void MaskablePixmapWidget::paintEvent(QPaintEvent *) +{ + QPixmap tmp(width(), height()); + tmp.fill(Qt::transparent); + + QPoint offset((width() - pixmap.size().width())/2,(height() - pixmap.size().height())/2); // centering the pixmap + + QPainter painter(&tmp); + painter.setCompositionMode(QPainter::CompositionMode_SourceOver); + painter.fillRect(0,0,width(),height(),backgroundColor); + painter.drawPixmap(offset,pixmap); + painter.setCompositionMode(QPainter::CompositionMode_DestinationIn); + painter.drawPixmap(0,0,mask); + painter.end(); + + painter.begin(this); + painter.drawPixmap(0,0,tmp); +} + +void MaskablePixmapWidget::mousePressEvent(QMouseEvent*) +{ + if(clickable) + emit clicked(); +} diff --git a/widget/maskablepixmapwidget.h b/widget/maskablepixmapwidget.h new file mode 100644 index 000000000..c4601d227 --- /dev/null +++ b/widget/maskablepixmapwidget.h @@ -0,0 +1,48 @@ +/* + Copyright (C) 2014 by Project Tox + + This file is part of qTox, a Qt-based graphical interface for Tox. + + This program is libre 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 MASKABLEPIXMAPWIDGET_H +#define MASKABLEPIXMAPWIDGET_H + +#include + +class MaskablePixmapWidget : public QWidget +{ + Q_OBJECT +public: + MaskablePixmapWidget(QWidget *parent, QSize size, QString maskName, QColor background = Qt::white); + + void setClickable(bool clickable); + void setPixmap(const QPixmap &pmap); + QPixmap getPixmap() const; + +signals: + void clicked(); + +protected: + virtual void paintEvent(QPaintEvent *); + virtual void mousePressEvent(QMouseEvent *); + +private: + QPixmap pixmap; + QPixmap mask; + QSize size; + QString maskName; + QColor backgroundColor; + bool clickable; +}; + +#endif // MASKABLEPIXMAPWIDGET_H diff --git a/widget/tool/chatactions/chataction.h b/widget/tool/chatactions/chataction.h index 16c9f179b..5c3eed650 100644 --- a/widget/tool/chatactions/chataction.h +++ b/widget/tool/chatactions/chataction.h @@ -21,13 +21,14 @@ #include class FileTransferInstance; +class QTextEdit; class ChatAction : public QObject { public: ChatAction(const bool &me, const QString &author, const QString &date) : isMe(me), name(author), date(date) {;} virtual ~ChatAction(){;} - virtual void setTextCursor(QTextCursor cursor){(void)cursor;} ///< Call once, and then you MUST let the object update itself + virtual void setup(QTextCursor cursor, QTextEdit* textEdit) = 0; ///< Call once, and then you MUST let the object update itself virtual QString getName(); virtual QString getMessage() = 0; diff --git a/widget/tool/chatactions/filetransferaction.cpp b/widget/tool/chatactions/filetransferaction.cpp index 12e2a1ac6..59f2c9250 100644 --- a/widget/tool/chatactions/filetransferaction.cpp +++ b/widget/tool/chatactions/filetransferaction.cpp @@ -17,8 +17,12 @@ #include "filetransferaction.h" #include "filetransferinstance.h" -FileTransferAction::FileTransferAction(FileTransferInstance *widget, const QString &author, const QString &date, const bool &me) : - ChatAction(me, author, date) +#include +#include + +FileTransferAction::FileTransferAction(FileTransferInstance *widget, const QString &author, const QString &date, const bool &me) + : ChatAction(me, author, date) + , edit(nullptr) { w = widget; @@ -39,20 +43,26 @@ QString FileTransferAction::getMessage() return widgetHtml; } -void FileTransferAction::setTextCursor(QTextCursor cursor) +void FileTransferAction::setup(QTextCursor cursor, QTextEdit *textEdit) { cur = cursor; cur.setKeepPositionOnInsert(true); int end=cur.selectionEnd(); cur.setPosition(cur.position()); cur.setPosition(end, QTextCursor::KeepAnchor); + + edit = textEdit; } void FileTransferAction::updateHtml() { - if (cur.isNull()) + if (cur.isNull() || !edit) return; + // save old slider value + int vSliderVal = edit->verticalScrollBar()->value(); + + // update content int pos = cur.selectionStart(); cur.removeSelectedText(); cur.setKeepPositionOnInsert(false); @@ -62,6 +72,9 @@ void FileTransferAction::updateHtml() cur.setPosition(pos); cur.setPosition(end, QTextCursor::KeepAnchor); + // restore old slider value + edit->verticalScrollBar()->setValue(vSliderVal); + // Free our ressources if we'll never need to update again if (w->getState() == FileTransferInstance::TransfState::tsCanceled || w->getState() == FileTransferInstance::TransfState::tsFinished) diff --git a/widget/tool/chatactions/filetransferaction.h b/widget/tool/chatactions/filetransferaction.h index ee6d0e11c..31982cd45 100644 --- a/widget/tool/chatactions/filetransferaction.h +++ b/widget/tool/chatactions/filetransferaction.h @@ -26,7 +26,7 @@ public: FileTransferAction(FileTransferInstance *widget, const QString &author, const QString &date, const bool &me); virtual ~FileTransferAction(); virtual QString getMessage(); - virtual void setTextCursor(QTextCursor cursor) final; + virtual void setup(QTextCursor cursor, QTextEdit* textEdit) override; private slots: void updateHtml(); @@ -34,6 +34,7 @@ private slots: private: FileTransferInstance *w; QTextCursor cur; + QTextEdit* edit; }; #endif // FILETRANSFERACTION_H diff --git a/widget/tool/chatactions/messageaction.cpp b/widget/tool/chatactions/messageaction.cpp index fa396468c..84ce86194 100644 --- a/widget/tool/chatactions/messageaction.cpp +++ b/widget/tool/chatactions/messageaction.cpp @@ -23,7 +23,7 @@ MessageAction::MessageAction(const QString &author, const QString &message, cons { } -void MessageAction::setTextCursor(QTextCursor cursor) +void MessageAction::setup(QTextCursor cursor, QTextEdit *) { // When this function is called, we're supposed to only update ourselve when needed // Nobody should ask us to do anything with our content, we're on our own diff --git a/widget/tool/chatactions/messageaction.h b/widget/tool/chatactions/messageaction.h index baa68898a..65f8e6465 100644 --- a/widget/tool/chatactions/messageaction.h +++ b/widget/tool/chatactions/messageaction.h @@ -25,7 +25,7 @@ public: MessageAction(const QString &author, const QString &message, const QString &date, const bool &me); virtual ~MessageAction(){;} virtual QString getMessage(); - virtual void setTextCursor(QTextCursor cursor) final; + virtual void setup(QTextCursor cursor, QTextEdit*) override; private: QString message; diff --git a/widget/tool/chatactions/systemmessageaction.cpp b/widget/tool/chatactions/systemmessageaction.cpp index 32457c6ed..a50f55e47 100644 --- a/widget/tool/chatactions/systemmessageaction.cpp +++ b/widget/tool/chatactions/systemmessageaction.cpp @@ -28,7 +28,7 @@ QString SystemMessageAction::getMessage() return QString("
" + message + "
"); } -void SystemMessageAction::setTextCursor(QTextCursor cursor) +void SystemMessageAction::setup(QTextCursor cursor, QTextEdit *) { // When this function is called, we're supposed to only update ourselve when needed // Nobody should ask us to do anything with our content, we're on our own diff --git a/widget/tool/chatactions/systemmessageaction.h b/widget/tool/chatactions/systemmessageaction.h index b628f7e04..6767a3f73 100644 --- a/widget/tool/chatactions/systemmessageaction.h +++ b/widget/tool/chatactions/systemmessageaction.h @@ -24,7 +24,7 @@ class SystemMessageAction : public ChatAction public: SystemMessageAction(const QString &message, const QString& type, const QString &date); virtual ~SystemMessageAction(){;} - virtual void setTextCursor(QTextCursor cursor) final; + virtual void setup(QTextCursor cursor, QTextEdit*) override; virtual QString getName() {return QString();} virtual QString getMessage(); diff --git a/widget/tool/clickablelabel.h b/widget/tool/clickablelabel.h deleted file mode 100644 index 99e523b20..000000000 --- a/widget/tool/clickablelabel.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef CLICKABLELABEL_H -#define CLICKABLELABEL_H - -#include - -class QMouseEvent; -class QWidget; - -class ClickableLabel : public QLabel -{ -Q_OBJECT - -public: - explicit ClickableLabel(QWidget* parent = 0) : QLabel(parent) {} -signals: - void clicked(); -protected: - void mousePressEvent (QMouseEvent*) {emit clicked();} -}; - - -#endif // CLICKABLELABEL_H diff --git a/widget/widget.cpp b/widget/widget.cpp index 3f3137717..a8f2ab683 100644 --- a/widget/widget.cpp +++ b/widget/widget.cpp @@ -32,6 +32,7 @@ #include "camera.h" #include "widget/form/chatform.h" #include "widget/settingsdialog.h" +#include "widget/maskablepixmapwidget.h" #include #include #include @@ -111,6 +112,11 @@ Widget::Widget(QWidget *parent) isWindowMinimized = 0; + profilePicture = new MaskablePixmapWidget(this, QSize(40,40), ":/img/avatar_mask.png"); + profilePicture->setPixmap(QPixmap(":/img/contact_dark.png")); + profilePicture->setClickable(true); + ui->horizontalLayout_3->insertWidget(0,profilePicture); + ui->mainContent->setLayout(new QVBoxLayout()); ui->mainHead->setLayout(new QVBoxLayout()); ui->mainHead->layout()->setMargin(0); @@ -214,7 +220,7 @@ Widget::Widget(QWidget *parent) connect(ui->settingsButton, SIGNAL(clicked()), this, SLOT(onSettingsClicked())); connect(ui->nameLabel, SIGNAL(textChanged(QString,QString)), this, SLOT(onUsernameChanged(QString,QString))); connect(ui->statusLabel, SIGNAL(textChanged(QString,QString)), this, SLOT(onStatusMessageChanged(QString,QString))); - connect(ui->profilePicture, SIGNAL(clicked()), this, SLOT(onAvatarClicked())); + connect(profilePicture, SIGNAL(clicked()), this, SLOT(onAvatarClicked())); connect(setStatusOnline, SIGNAL(triggered()), this, SLOT(setStatusOnline())); connect(setStatusAway, SIGNAL(triggered()), this, SLOT(setStatusAway())); connect(setStatusBusy, SIGNAL(triggered()), this, SLOT(setStatusBusy())); @@ -322,8 +328,7 @@ void Widget::onAvatarClicked() void Widget::onSelfAvatarLoaded(const QPixmap& pic) { - QPixmap scaled = pic.scaled(40,40, Qt::KeepAspectRatio,Qt::SmoothTransformation); - ui->profilePicture->setPixmap(scaled); + profilePicture->setPixmap(pic); } void Widget::onConnected() diff --git a/widget/widget.h b/widget/widget.h index 352e12cfa..dd6c8180e 100644 --- a/widget/widget.h +++ b/widget/widget.h @@ -38,6 +38,7 @@ class Core; class Camera; class FriendListWidget; class SettingsDialog; +class MaskablePixmapWidget; class Widget : public QMainWindow { @@ -144,6 +145,7 @@ private: GenericChatroomWidget* activeChatroomWidget; FriendListWidget* contactListWidget; Camera* camera; + MaskablePixmapWidget* profilePicture; bool notify(QObject *receiver, QEvent *event); bool eventFilter(QObject *, QEvent *event); };