2014-07-07 00:19:45 +08:00
/*
Copyright ( C ) 2014 by Project Tox < https : //tox.im>
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 .
*/
2014-06-25 04:11:11 +08:00
# include "widget.h"
2014-08-11 16:00:08 +08:00
# include "ui_mainwindow.h"
2014-09-11 21:44:34 +08:00
# include "core.h"
2014-09-30 02:28:59 +08:00
# include "misc/settings.h"
2014-06-25 04:11:11 +08:00
# include "friend.h"
# include "friendlist.h"
2014-06-27 06:42:45 +08:00
# include "widget/tool/friendrequestdialog.h"
# include "widget/friendwidget.h"
2014-06-25 04:11:11 +08:00
# include "grouplist.h"
# include "group.h"
2014-06-27 06:42:45 +08:00
# include "widget/groupwidget.h"
# include "widget/form/groupchatform.h"
2014-09-30 02:28:59 +08:00
# include "misc/style.h"
2014-09-11 21:44:34 +08:00
# include "widget/friendlistwidget.h"
# include "camera.h"
# include "widget/form/chatform.h"
2014-09-26 22:39:29 +08:00
# include "widget/maskablepixmapwidget.h"
2014-06-25 04:11:11 +08:00
# include <QMessageBox>
# include <QDebug>
2014-07-01 10:12:17 +08:00
# include <QFile>
# include <QString>
2014-09-24 22:51:16 +08:00
# include <QBuffer>
2014-07-01 10:12:17 +08:00
# include <QPainter>
# include <QMouseEvent>
2014-07-02 05:50:07 +08:00
# include <QClipboard>
2014-09-11 21:44:34 +08:00
# include <QThread>
2014-09-24 22:51:16 +08:00
# include <QFileDialog>
2014-10-02 03:03:10 +08:00
# include "historykeeper.h"
2014-09-11 21:44:34 +08:00
# include <tox/tox.h>
2014-06-25 04:11:11 +08:00
Widget * Widget : : instance { nullptr } ;
2014-08-11 16:00:08 +08:00
Widget : : Widget ( QWidget * parent )
: QMainWindow ( parent ) ,
ui ( new Ui : : MainWindow ) ,
2014-09-02 00:20:28 +08:00
activeChatroomWidget { nullptr }
2014-06-25 04:11:11 +08:00
{
ui - > setupUi ( this ) ;
2014-07-01 10:12:17 +08:00
2014-08-11 16:00:08 +08:00
ui - > statusbar - > hide ( ) ;
ui - > menubar - > hide ( ) ;
//restore window state
restoreGeometry ( Settings : : getInstance ( ) . getWindowGeometry ( ) ) ;
restoreState ( Settings : : getInstance ( ) . getWindowState ( ) ) ;
2014-08-11 20:07:27 +08:00
ui - > mainSplitter - > restoreState ( Settings : : getInstance ( ) . getSplitterState ( ) ) ;
2014-08-11 16:00:08 +08:00
2014-10-04 16:54:50 +08:00
layout ( ) - > setContentsMargins ( 0 , 0 , 0 , 0 ) ;
ui - > friendList - > setStyleSheet ( Style : : getStylesheet ( " :ui/friendList/friendList.css " ) ) ;
2014-07-01 10:12:17 +08:00
2014-09-26 22:39:29 +08:00
profilePicture = new MaskablePixmapWidget ( this , QSize ( 40 , 40 ) , " :/img/avatar_mask.png " ) ;
2014-09-27 23:58:56 +08:00
profilePicture - > setPixmap ( QPixmap ( " :/img/contact_dark.png " ) ) ;
2014-09-28 01:13:46 +08:00
profilePicture - > setClickable ( true ) ;
2014-09-26 22:39:29 +08:00
ui - > horizontalLayout_3 - > insertWidget ( 0 , profilePicture ) ;
2014-10-01 02:10:42 +08:00
ui - > horizontalLayout_3 - > insertSpacing ( 1 , 7 ) ;
2014-09-26 22:39:29 +08:00
2014-06-25 04:11:11 +08:00
ui - > mainContent - > setLayout ( new QVBoxLayout ( ) ) ;
ui - > mainHead - > setLayout ( new QVBoxLayout ( ) ) ;
2014-06-26 04:43:28 +08:00
ui - > mainHead - > layout ( ) - > setMargin ( 0 ) ;
ui - > mainHead - > layout ( ) - > setSpacing ( 0 ) ;
2014-10-07 17:50:36 +08:00
ui - > mainHead - > setStyleSheet ( Style : : getStylesheet ( " :ui/settings/mainHead.css " ) ) ;
ui - > mainContent - > setStyleSheet ( Style : : getStylesheet ( " :ui/settings/mainContent.css " ) ) ;
2014-08-11 16:00:08 +08:00
2014-08-22 23:19:16 +08:00
contactListWidget = new FriendListWidget ( ) ;
ui - > friendList - > setWidget ( contactListWidget ) ;
2014-08-12 01:46:14 +08:00
ui - > friendList - > setLayoutDirection ( Qt : : RightToLeft ) ;
2014-06-25 04:11:11 +08:00
2014-09-01 17:08:02 +08:00
ui - > nameLabel - > setEditable ( true ) ;
ui - > statusLabel - > setEditable ( true ) ;
2014-10-04 16:24:20 +08:00
ui - > statusPanel - > setStyleSheet ( Style : : getStylesheet ( " :/ui/window/statusPanel.css " ) ) ;
2014-07-06 03:30:00 +08:00
2014-07-06 04:54:27 +08:00
QMenu * statusButtonMenu = new QMenu ( ui - > statusButton ) ;
2014-08-29 17:56:42 +08:00
QAction * setStatusOnline = statusButtonMenu - > addAction ( Widget : : tr ( " Online " , " Button to set your status to 'Online' " ) ) ;
2014-07-06 04:54:27 +08:00
setStatusOnline - > setIcon ( QIcon ( " :ui/statusButton/dot_online.png " ) ) ;
2014-08-29 17:56:42 +08:00
QAction * setStatusAway = statusButtonMenu - > addAction ( Widget : : tr ( " Away " , " Button to set your status to 'Away' " ) ) ;
2014-07-06 04:54:27 +08:00
setStatusAway - > setIcon ( QIcon ( " :ui/statusButton/dot_idle.png " ) ) ;
2014-08-29 17:56:42 +08:00
QAction * setStatusBusy = statusButtonMenu - > addAction ( Widget : : tr ( " Busy " , " Button to set your status to 'Busy' " ) ) ;
2014-07-06 04:54:27 +08:00
setStatusBusy - > setIcon ( QIcon ( " :ui/statusButton/dot_busy.png " ) ) ;
ui - > statusButton - > setMenu ( statusButtonMenu ) ;
2014-08-11 19:56:52 +08:00
// disable proportional scaling
2014-08-11 20:07:27 +08:00
ui - > mainSplitter - > setStretchFactor ( 0 , 0 ) ;
ui - > mainSplitter - > setStretchFactor ( 1 , 1 ) ;
2014-06-25 04:11:11 +08:00
2014-10-04 16:24:20 +08:00
ui - > statusButton - > setProperty ( " status " , " offline " ) ;
Style : : repolish ( ui - > statusButton ) ;
2014-07-06 21:51:24 +08:00
2014-10-08 20:25:32 +08:00
settingsWidget = new SettingsWidget ( ) ;
2014-06-30 05:38:48 +08:00
2014-09-03 06:01:04 +08:00
// Disable some widgets until we're connected to the DHT
ui - > statusButton - > setEnabled ( false ) ;
2014-06-25 04:11:11 +08:00
qRegisterMetaType < Status > ( " Status " ) ;
2014-07-12 16:54:52 +08:00
qRegisterMetaType < vpx_image > ( " vpx_image " ) ;
2014-06-25 04:11:11 +08:00
qRegisterMetaType < uint8_t > ( " uint8_t " ) ;
2014-10-03 07:53:44 +08:00
qRegisterMetaType < uint16_t > ( " uint16_t " ) ;
2014-06-26 04:43:28 +08:00
qRegisterMetaType < int32_t > ( " int32_t " ) ;
2014-07-13 00:40:01 +08:00
qRegisterMetaType < int64_t > ( " int64_t " ) ;
2014-09-24 23:28:38 +08:00
qRegisterMetaType < QPixmap > ( " QPixmap " ) ;
2014-06-27 01:45:47 +08:00
qRegisterMetaType < ToxFile > ( " ToxFile " ) ;
qRegisterMetaType < ToxFile : : FileDirection > ( " ToxFile::FileDirection " ) ;
2014-06-25 04:11:11 +08:00
coreThread = new QThread ( this ) ;
2014-10-08 20:25:32 +08:00
core = new Core ( Camera : : getInstance ( ) , coreThread ) ;
2014-06-25 04:11:11 +08:00
core - > moveToThread ( coreThread ) ;
connect ( coreThread , & QThread : : started , core , & Core : : start ) ;
connect ( core , & Core : : connected , this , & Widget : : onConnected ) ;
connect ( core , & Core : : disconnected , this , & Widget : : onDisconnected ) ;
connect ( core , & Core : : failedToStart , this , & Widget : : onFailedToStartCore ) ;
2014-10-06 04:49:44 +08:00
connect ( core , & Core : : badProxy , this , & Widget : : onBadProxyCore ) ;
2014-06-25 04:11:11 +08:00
connect ( core , & Core : : statusSet , this , & Widget : : onStatusSet ) ;
connect ( core , & Core : : usernameSet , this , & Widget : : setUsername ) ;
connect ( core , & Core : : statusMessageSet , this , & Widget : : setStatusMessage ) ;
2014-09-24 22:51:16 +08:00
connect ( core , & Core : : selfAvatarChanged , this , & Widget : : onSelfAvatarLoaded ) ;
2014-07-12 01:14:56 +08:00
connect ( core , SIGNAL ( fileDownloadFinished ( const QString & ) ) , & filesForm , SLOT ( onFileDownloadComplete ( const QString & ) ) ) ;
connect ( core , SIGNAL ( fileUploadFinished ( const QString & ) ) , & filesForm , SLOT ( onFileUploadComplete ( const QString & ) ) ) ;
2014-06-25 04:11:11 +08:00
connect ( core , & Core : : friendAdded , this , & Widget : : addFriend ) ;
2014-06-27 01:45:47 +08:00
connect ( core , & Core : : failedToAddFriend , this , & Widget : : addFriendFailed ) ;
2014-06-25 04:11:11 +08:00
connect ( core , & Core : : friendStatusChanged , this , & Widget : : onFriendStatusChanged ) ;
connect ( core , & Core : : friendUsernameChanged , this , & Widget : : onFriendUsernameChanged ) ;
connect ( core , & Core : : friendStatusChanged , this , & Widget : : onFriendStatusChanged ) ;
connect ( core , & Core : : friendStatusMessageChanged , this , & Widget : : onFriendStatusMessageChanged ) ;
connect ( core , & Core : : friendRequestReceived , this , & Widget : : onFriendRequestReceived ) ;
connect ( core , & Core : : friendMessageReceived , this , & Widget : : onFriendMessageReceived ) ;
connect ( core , & Core : : groupInviteReceived , this , & Widget : : onGroupInviteReceived ) ;
connect ( core , & Core : : groupMessageReceived , this , & Widget : : onGroupMessageReceived ) ;
connect ( core , & Core : : groupNamelistChanged , this , & Widget : : onGroupNamelistChanged ) ;
2014-06-30 05:38:48 +08:00
connect ( core , & Core : : emptyGroupCreated , this , & Widget : : onEmptyGroupCreated ) ;
2014-10-08 10:20:38 +08:00
connect ( core , & Core : : avInvite , this , & Widget : : playRingtone ) ;
2014-06-25 04:11:11 +08:00
2014-09-24 00:35:06 +08:00
connect ( core , SIGNAL ( messageSentResult ( int , QString , int ) ) , this , SLOT ( onMessageSendResult ( int , QString , int ) ) ) ;
connect ( core , SIGNAL ( groupSentResult ( int , QString , int ) ) , this , SLOT ( onGroupSendResult ( int , QString , int ) ) ) ;
2014-06-25 04:11:11 +08:00
connect ( this , & Widget : : statusSet , core , & Core : : setStatus ) ;
connect ( this , & Widget : : friendRequested , core , & Core : : requestFriendship ) ;
connect ( this , & Widget : : friendRequestAccepted , core , & Core : : acceptFriendRequest ) ;
connect ( ui - > addButton , SIGNAL ( clicked ( ) ) , this , SLOT ( onAddClicked ( ) ) ) ;
connect ( ui - > groupButton , SIGNAL ( clicked ( ) ) , this , SLOT ( onGroupClicked ( ) ) ) ;
connect ( ui - > transferButton , SIGNAL ( clicked ( ) ) , this , SLOT ( onTransferClicked ( ) ) ) ;
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 ) ) ) ;
2014-09-26 22:39:29 +08:00
connect ( profilePicture , SIGNAL ( clicked ( ) ) , this , SLOT ( onAvatarClicked ( ) ) ) ;
2014-07-06 04:54:27 +08:00
connect ( setStatusOnline , SIGNAL ( triggered ( ) ) , this , SLOT ( setStatusOnline ( ) ) ) ;
2014-10-06 00:17:01 +08:00
// connect(settingsWidget->getIdentityForm(), &IdentityForm::userNameChanged, Core::getInstance(), &Core::setUsername);
// connect(settingsWidget->getIdentityForm(), &IdentityForm::statusMessageChanged, Core::getInstance(), &Core::setStatusMessage);
2014-07-06 04:54:27 +08:00
connect ( setStatusAway , SIGNAL ( triggered ( ) ) , this , SLOT ( setStatusAway ( ) ) ) ;
connect ( setStatusBusy , SIGNAL ( triggered ( ) ) , this , SLOT ( setStatusBusy ( ) ) ) ;
2014-06-25 04:11:11 +08:00
connect ( & friendForm , SIGNAL ( friendRequested ( QString , QString ) ) , this , SIGNAL ( friendRequested ( QString , QString ) ) ) ;
coreThread - > start ( ) ;
friendForm . show ( * ui ) ;
}
Widget : : ~ Widget ( )
{
2014-07-04 01:38:30 +08:00
core - > saveConfiguration ( ) ;
2014-06-25 04:11:11 +08:00
coreThread - > exit ( ) ;
2014-08-28 19:09:26 +08:00
coreThread - > wait ( 500 ) ; // In case of deadlock (can happen with QtAudio/PA bugs)
if ( ! coreThread - > isFinished ( ) )
coreThread - > terminate ( ) ;
2014-06-25 04:11:11 +08:00
delete core ;
2014-09-30 17:44:27 +08:00
delete settingsWidget ;
2014-06-25 04:11:11 +08:00
for ( Friend * f : FriendList : : friendList )
delete f ;
FriendList : : friendList . clear ( ) ;
for ( Group * g : GroupList : : groupList )
delete g ;
GroupList : : groupList . clear ( ) ;
delete ui ;
2014-09-30 17:44:27 +08:00
instance = nullptr ;
2014-06-25 04:11:11 +08:00
}
Widget * Widget : : getInstance ( )
{
if ( ! instance )
instance = new Widget ( ) ;
return instance ;
}
2014-07-07 06:03:37 +08:00
QThread * Widget : : getCoreThread ( )
{
return coreThread ;
}
2014-08-11 16:00:08 +08:00
void Widget : : closeEvent ( QCloseEvent * event )
2014-07-03 14:43:23 +08:00
{
2014-08-11 16:00:08 +08:00
Settings : : getInstance ( ) . setWindowGeometry ( saveGeometry ( ) ) ;
Settings : : getInstance ( ) . setWindowState ( saveState ( ) ) ;
2014-08-11 20:07:27 +08:00
Settings : : getInstance ( ) . setSplitterState ( ui - > mainSplitter - > saveState ( ) ) ;
2014-08-11 16:00:08 +08:00
QWidget : : closeEvent ( event ) ;
2014-07-03 14:43:23 +08:00
}
2014-07-01 10:12:17 +08:00
2014-06-25 04:11:11 +08:00
QString Widget : : getUsername ( )
{
2014-10-06 14:46:30 +08:00
return core - > getUsername ( ) ;
2014-06-25 04:11:11 +08:00
}
2014-09-24 22:51:16 +08:00
void Widget : : onAvatarClicked ( )
{
2014-09-28 16:59:49 +08:00
QString filename = QFileDialog : : getOpenFileName ( this , tr ( " Choose a profile picture " ) , QDir : : homePath ( ) ) ;
2014-09-25 23:16:36 +08:00
if ( filename = = " " )
return ;
2014-09-24 22:51:16 +08:00
QFile file ( filename ) ;
file . open ( QIODevice : : ReadOnly ) ;
if ( ! file . isOpen ( ) )
{
2014-09-25 23:16:36 +08:00
QMessageBox : : critical ( this , tr ( " Error " ) , tr ( " Unable to open this file " ) ) ;
2014-09-24 22:51:16 +08:00
return ;
}
QPixmap pic ;
if ( ! pic . loadFromData ( file . readAll ( ) ) )
{
2014-09-25 23:16:36 +08:00
QMessageBox : : critical ( this , tr ( " Error " ) , tr ( " Unable to read this image " ) ) ;
2014-09-24 22:51:16 +08:00
return ;
}
QByteArray bytes ;
QBuffer buffer ( & bytes ) ;
buffer . open ( QIODevice : : WriteOnly ) ;
pic . save ( & buffer , " PNG " ) ;
buffer . close ( ) ;
2014-09-25 22:55:36 +08:00
if ( bytes . size ( ) > = TOX_AVATAR_MAX_DATA_LENGTH )
2014-09-24 22:51:16 +08:00
{
2014-09-25 00:40:40 +08:00
pic = pic . scaled ( 64 , 64 , Qt : : KeepAspectRatio , Qt : : SmoothTransformation ) ;
2014-09-24 22:51:16 +08:00
bytes . clear ( ) ;
buffer . open ( QIODevice : : WriteOnly ) ;
pic . save ( & buffer , " PNG " ) ;
buffer . close ( ) ;
}
2014-09-25 22:55:36 +08:00
if ( bytes . size ( ) > = TOX_AVATAR_MAX_DATA_LENGTH )
2014-09-24 22:51:16 +08:00
{
2014-09-25 23:16:36 +08:00
QMessageBox : : critical ( this , tr ( " Error " ) , tr ( " This image is too big " ) ) ;
2014-09-24 22:51:16 +08:00
return ;
}
2014-09-25 22:55:36 +08:00
core - > setAvatar ( TOX_AVATAR_FORMAT_PNG , bytes ) ;
2014-09-24 22:51:16 +08:00
}
void Widget : : onSelfAvatarLoaded ( const QPixmap & pic )
{
2014-09-26 22:39:29 +08:00
profilePicture - > setPixmap ( pic ) ;
2014-09-24 22:51:16 +08:00
}
2014-06-25 04:11:11 +08:00
void Widget : : onConnected ( )
{
2014-09-03 06:01:04 +08:00
ui - > statusButton - > setEnabled ( true ) ;
2014-06-25 04:11:11 +08:00
emit statusSet ( Status : : Online ) ;
}
void Widget : : onDisconnected ( )
{
2014-09-03 06:01:04 +08:00
ui - > statusButton - > setEnabled ( false ) ;
2014-06-25 04:11:11 +08:00
emit statusSet ( Status : : Offline ) ;
}
void Widget : : onFailedToStartCore ( )
{
QMessageBox critical ( this ) ;
2014-10-06 04:49:44 +08:00
critical . setText ( tr ( " Toxcore failed to start, the application will terminate after you close this message. " ) ) ;
2014-06-25 04:11:11 +08:00
critical . setIcon ( QMessageBox : : Critical ) ;
critical . exec ( ) ;
qApp - > quit ( ) ;
}
2014-10-06 04:49:44 +08:00
void Widget : : onBadProxyCore ( )
{
QMessageBox critical ( this ) ;
critical . setText ( tr ( " toxcore failed to start with your proxy settings. qTox cannot run; please modify your "
" settings and restart. " , " popup text " ) ) ;
critical . setIcon ( QMessageBox : : Critical ) ;
critical . exec ( ) ;
onSettingsClicked ( ) ;
}
2014-06-25 04:11:11 +08:00
void Widget : : onStatusSet ( Status status )
{
2014-07-06 06:03:53 +08:00
//We have to use stylesheets here, there's no way to
//prevent the button icon from moving when pressed otherwise
2014-10-04 16:24:20 +08:00
switch ( status )
2014-07-06 06:03:53 +08:00
{
2014-10-04 16:24:20 +08:00
case Status : : Online :
ui - > statusButton - > setProperty ( " status " , " online " ) ;
break ;
case Status : : Away :
ui - > statusButton - > setProperty ( " status " , " away " ) ;
break ;
case Status : : Busy :
ui - > statusButton - > setProperty ( " status " , " busy " ) ;
break ;
case Status : : Offline :
ui - > statusButton - > setProperty ( " status " , " offline " ) ;
break ;
2014-07-06 06:03:53 +08:00
}
2014-10-04 16:24:20 +08:00
Style : : repolish ( ui - > statusButton ) ;
2014-06-25 04:11:11 +08:00
}
void Widget : : onAddClicked ( )
{
hideMainForms ( ) ;
friendForm . show ( * ui ) ;
}
void Widget : : onGroupClicked ( )
{
2014-06-30 05:38:48 +08:00
core - > createGroup ( ) ;
2014-06-25 04:11:11 +08:00
}
void Widget : : onTransferClicked ( )
{
2014-07-12 00:05:18 +08:00
hideMainForms ( ) ;
filesForm . show ( * ui ) ;
2014-09-02 00:20:28 +08:00
activeChatroomWidget = nullptr ;
2014-06-25 04:11:11 +08:00
}
2014-10-08 22:17:05 +08:00
void Widget : : onIconClick ( )
{
if ( this - > isHidden ( ) = = true )
this - > show ( ) ;
else
this - > hide ( ) ;
}
2014-06-25 04:11:11 +08:00
void Widget : : onSettingsClicked ( )
{
hideMainForms ( ) ;
2014-09-30 17:44:27 +08:00
settingsWidget - > show ( * ui ) ;
2014-09-02 00:20:28 +08:00
activeChatroomWidget = nullptr ;
2014-06-25 04:11:11 +08:00
}
void Widget : : hideMainForms ( )
{
QLayoutItem * item ;
while ( ( item = ui - > mainHead - > layout ( ) - > takeAt ( 0 ) ) ! = 0 )
item - > widget ( ) - > hide ( ) ;
while ( ( item = ui - > mainContent - > layout ( ) - > takeAt ( 0 ) ) ! = 0 )
item - > widget ( ) - > hide ( ) ;
2014-10-04 16:54:50 +08:00
2014-09-02 00:20:28 +08:00
if ( activeChatroomWidget ! = nullptr )
2014-06-27 09:47:16 +08:00
{
2014-09-02 00:20:28 +08:00
activeChatroomWidget - > setAsInactiveChatroom ( ) ;
2014-06-27 09:47:16 +08:00
}
2014-06-25 04:11:11 +08:00
}
void Widget : : onUsernameChanged ( const QString & newUsername , const QString & oldUsername )
{
ui - > nameLabel - > setText ( oldUsername ) ; // restore old username until Core tells us to set it
2014-07-16 00:04:26 +08:00
ui - > nameLabel - > setToolTip ( oldUsername ) ; // for overlength names
2014-06-25 04:11:11 +08:00
core - > setUsername ( newUsername ) ;
}
void Widget : : setUsername ( const QString & username )
{
ui - > nameLabel - > setText ( username ) ;
2014-07-16 00:04:26 +08:00
ui - > nameLabel - > setToolTip ( username ) ; // for overlength names
2014-10-06 00:17:01 +08:00
settingsWidget - > getIdentityForm ( ) - > setUserName ( username ) ;
2014-06-25 04:11:11 +08:00
}
void Widget : : onStatusMessageChanged ( const QString & newStatusMessage , const QString & oldStatusMessage )
{
ui - > statusLabel - > setText ( oldStatusMessage ) ; // restore old status message until Core tells us to set it
2014-07-16 00:04:26 +08:00
ui - > statusLabel - > setToolTip ( oldStatusMessage ) ; // for overlength messsages
2014-06-25 04:11:11 +08:00
core - > setStatusMessage ( newStatusMessage ) ;
}
void Widget : : setStatusMessage ( const QString & statusMessage )
{
ui - > statusLabel - > setText ( statusMessage ) ;
2014-07-16 00:04:26 +08:00
ui - > statusLabel - > setToolTip ( statusMessage ) ; // for overlength messsages
2014-10-06 00:17:01 +08:00
settingsWidget - > getIdentityForm ( ) - > setStatusMessage ( statusMessage ) ;
2014-06-25 04:11:11 +08:00
}
void Widget : : addFriend ( int friendId , const QString & userId )
{
2014-09-28 05:44:08 +08:00
qDebug ( ) < < " Widget: Adding friend with id " < < userId ;
2014-06-25 04:11:11 +08:00
Friend * newfriend = FriendList : : addFriend ( friendId , userId ) ;
2014-08-22 23:19:16 +08:00
QLayout * layout = contactListWidget - > getFriendLayout ( Status : : Offline ) ;
2014-06-25 04:11:11 +08:00
layout - > addWidget ( newfriend - > widget ) ;
2014-09-02 00:20:28 +08:00
connect ( newfriend - > widget , SIGNAL ( chatroomWidgetClicked ( GenericChatroomWidget * ) ) , this , SLOT ( onChatroomWidgetClicked ( GenericChatroomWidget * ) ) ) ;
2014-06-25 04:11:11 +08:00
connect ( newfriend - > widget , SIGNAL ( removeFriend ( int ) ) , this , SLOT ( removeFriend ( int ) ) ) ;
2014-07-02 05:50:07 +08:00
connect ( newfriend - > widget , SIGNAL ( copyFriendIdToClipboard ( int ) ) , this , SLOT ( copyFriendIdToClipboard ( int ) ) ) ;
2014-09-11 04:53:02 +08:00
connect ( newfriend - > widget , SIGNAL ( chatroomWidgetClicked ( GenericChatroomWidget * ) ) , newfriend - > chatForm , SLOT ( focusInput ( ) ) ) ;
2014-06-25 04:11:11 +08:00
connect ( newfriend - > chatForm , SIGNAL ( sendMessage ( int , QString ) ) , core , SLOT ( sendMessage ( int , QString ) ) ) ;
2014-10-02 15:00:06 +08:00
connect ( newfriend - > chatForm , & GenericChatForm : : sendAction , core , & Core : : sendAction ) ;
2014-07-13 00:40:01 +08:00
connect ( newfriend - > chatForm , SIGNAL ( sendFile ( int32_t , QString , QString , long long ) ) , core , SLOT ( sendFile ( int32_t , QString , QString , long long ) ) ) ;
2014-06-27 08:08:33 +08:00
connect ( newfriend - > chatForm , SIGNAL ( answerCall ( int ) ) , core , SLOT ( answerCall ( int ) ) ) ;
connect ( newfriend - > chatForm , SIGNAL ( hangupCall ( int ) ) , core , SLOT ( hangupCall ( int ) ) ) ;
2014-06-27 09:06:56 +08:00
connect ( newfriend - > chatForm , SIGNAL ( startCall ( int ) ) , core , SLOT ( startCall ( int ) ) ) ;
2014-06-30 10:39:43 +08:00
connect ( newfriend - > chatForm , SIGNAL ( startVideoCall ( int , bool ) ) , core , SLOT ( startCall ( int , bool ) ) ) ;
2014-06-27 09:06:56 +08:00
connect ( newfriend - > chatForm , SIGNAL ( cancelCall ( int , int ) ) , core , SLOT ( cancelCall ( int , int ) ) ) ;
2014-08-19 23:20:20 +08:00
connect ( newfriend - > chatForm , SIGNAL ( micMuteToggle ( int ) ) , core , SLOT ( micMuteToggle ( int ) ) ) ;
2014-06-27 01:45:47 +08:00
connect ( core , & Core : : fileReceiveRequested , newfriend - > chatForm , & ChatForm : : onFileRecvRequest ) ;
2014-06-27 08:08:33 +08:00
connect ( core , & Core : : avInvite , newfriend - > chatForm , & ChatForm : : onAvInvite ) ;
connect ( core , & Core : : avStart , newfriend - > chatForm , & ChatForm : : onAvStart ) ;
connect ( core , & Core : : avCancel , newfriend - > chatForm , & ChatForm : : onAvCancel ) ;
connect ( core , & Core : : avEnd , newfriend - > chatForm , & ChatForm : : onAvEnd ) ;
2014-06-27 09:06:56 +08:00
connect ( core , & Core : : avRinging , newfriend - > chatForm , & ChatForm : : onAvRinging ) ;
connect ( core , & Core : : avStarting , newfriend - > chatForm , & ChatForm : : onAvStarting ) ;
2014-06-27 08:08:33 +08:00
connect ( core , & Core : : avEnding , newfriend - > chatForm , & ChatForm : : onAvEnding ) ;
2014-06-27 09:06:56 +08:00
connect ( core , & Core : : avRequestTimeout , newfriend - > chatForm , & ChatForm : : onAvRequestTimeout ) ;
2014-06-28 03:59:25 +08:00
connect ( core , & Core : : avPeerTimeout , newfriend - > chatForm , & ChatForm : : onAvPeerTimeout ) ;
2014-08-30 01:20:34 +08:00
connect ( core , & Core : : avMediaChange , newfriend - > chatForm , & ChatForm : : onAvMediaChange ) ;
2014-09-24 23:28:38 +08:00
connect ( core , & Core : : friendAvatarChanged , newfriend - > chatForm , & ChatForm : : onAvatarChange ) ;
connect ( core , & Core : : friendAvatarChanged , newfriend - > widget , & FriendWidget : : onAvatarChange ) ;
2014-09-27 03:23:20 +08:00
connect ( core , & Core : : friendAvatarRemoved , newfriend - > chatForm , & ChatForm : : onAvatarRemoved ) ;
connect ( core , & Core : : friendAvatarRemoved , newfriend - > widget , & FriendWidget : : onAvatarRemoved ) ;
2014-09-24 23:55:54 +08:00
// Try to get the avatar from the cache
2014-09-28 06:19:30 +08:00
QPixmap avatar = Settings : : getInstance ( ) . getSavedAvatar ( userId ) ;
2014-09-24 23:55:54 +08:00
if ( ! avatar . isNull ( ) )
{
2014-09-28 05:44:08 +08:00
qWarning ( ) < < " Widget: loadded avatar for id " < < userId ;
2014-09-24 23:55:54 +08:00
newfriend - > chatForm - > onAvatarChange ( friendId , avatar ) ;
newfriend - > widget - > onAvatarChange ( friendId , avatar ) ;
}
2014-06-27 01:45:47 +08:00
}
void Widget : : addFriendFailed ( const QString & )
{
QMessageBox : : critical ( 0 , " Error " , " Couldn't request friendship " ) ;
2014-06-25 04:11:11 +08:00
}
void Widget : : onFriendStatusChanged ( int friendId , Status status )
{
Friend * f = FriendList : : findFriend ( friendId ) ;
if ( ! f )
return ;
2014-08-22 23:19:16 +08:00
contactListWidget - > moveWidget ( f - > widget , status ) ;
2014-06-28 00:12:43 +08:00
f - > friendStatus = status ;
2014-08-31 22:19:16 +08:00
f - > widget - > updateStatusLight ( ) ;
2014-06-25 04:11:11 +08:00
}
void Widget : : onFriendStatusMessageChanged ( int friendId , const QString & message )
{
Friend * f = FriendList : : findFriend ( friendId ) ;
if ( ! f )
return ;
2014-09-29 02:09:10 +08:00
QString str = message ; str . replace ( ' \n ' , ' ' ) ;
str . remove ( ' \r ' ) ; str . remove ( QChar ( ( char ) 0 ) ) ; // null terminator...
f - > setStatusMessage ( str ) ;
2014-06-25 04:11:11 +08:00
}
void Widget : : onFriendUsernameChanged ( int friendId , const QString & username )
{
Friend * f = FriendList : : findFriend ( friendId ) ;
if ( ! f )
return ;
2014-09-29 02:09:10 +08:00
QString str = username ; str . replace ( ' \n ' , ' ' ) ;
str . remove ( ' \r ' ) ; str . remove ( QChar ( ( char ) 0 ) ) ; // null terminator...
f - > setName ( str ) ;
2014-06-25 04:11:11 +08:00
}
2014-09-02 00:20:28 +08:00
void Widget : : onChatroomWidgetClicked ( GenericChatroomWidget * widget )
2014-06-25 04:11:11 +08:00
{
hideMainForms ( ) ;
2014-09-02 00:20:28 +08:00
widget - > setChatForm ( * ui ) ;
if ( activeChatroomWidget ! = nullptr )
2014-06-27 09:47:16 +08:00
{
2014-09-02 00:20:28 +08:00
activeChatroomWidget - > setAsInactiveChatroom ( ) ;
2014-06-27 09:47:16 +08:00
}
2014-09-02 00:20:28 +08:00
activeChatroomWidget = widget ;
2014-06-27 09:47:16 +08:00
widget - > setAsActiveChatroom ( ) ;
2014-09-02 00:20:28 +08:00
widget - > resetEventFlags ( ) ;
widget - > updateStatusLight ( ) ;
2014-06-25 04:11:11 +08:00
}
2014-10-02 14:01:23 +08:00
void Widget : : onFriendMessageReceived ( int friendId , const QString & message , bool isAction )
2014-06-25 04:11:11 +08:00
{
Friend * f = FriendList : : findFriend ( friendId ) ;
if ( ! f )
return ;
2014-10-02 14:01:23 +08:00
f - > chatForm - > addMessage ( f - > getName ( ) , message , isAction ) ;
2014-10-02 03:03:10 +08:00
HistoryKeeper : : getInstance ( ) - > addChatEntry ( f - > userId , message , f - > userId ) ;
2014-06-28 00:12:43 +08:00
2014-09-02 00:20:28 +08:00
if ( activeChatroomWidget ! = nullptr )
2014-06-28 00:12:43 +08:00
{
2014-10-04 16:54:50 +08:00
if ( ( static_cast < GenericChatroomWidget * > ( f - > widget ) ! = activeChatroomWidget ) | | isMinimized ( ) | | ! isActiveWindow ( ) )
2014-06-28 05:36:44 +08:00
{
2014-08-31 22:48:15 +08:00
f - > hasNewEvents = 1 ;
2014-06-28 09:35:39 +08:00
newMessageAlert ( ) ;
2014-06-28 05:36:44 +08:00
}
2014-06-28 00:12:43 +08:00
}
else
2014-06-28 05:36:44 +08:00
{
2014-08-31 22:48:15 +08:00
f - > hasNewEvents = 1 ;
2014-06-28 09:35:39 +08:00
newMessageAlert ( ) ;
2014-06-28 05:36:44 +08:00
}
2014-06-28 00:12:43 +08:00
2014-08-31 22:19:16 +08:00
f - > widget - > updateStatusLight ( ) ;
2014-06-25 04:11:11 +08:00
}
2014-06-28 09:35:39 +08:00
void Widget : : newMessageAlert ( )
2014-06-28 05:36:44 +08:00
{
2014-07-01 10:25:00 +08:00
QApplication : : alert ( this ) ;
2014-08-30 21:15:23 +08:00
2014-09-11 03:53:18 +08:00
static QFile sndFile ( " :audio/notification.pcm " ) ;
2014-08-30 21:15:23 +08:00
static QByteArray sndData ;
if ( sndData . isEmpty ( ) )
{
sndFile . open ( QIODevice : : ReadOnly ) ;
sndData = sndFile . readAll ( ) ;
sndFile . close ( ) ;
}
ALuint buffer ;
alGenBuffers ( 1 , & buffer ) ;
2014-09-11 03:53:18 +08:00
alBufferData ( buffer , AL_FORMAT_MONO16 , sndData . data ( ) , sndData . size ( ) , 44100 ) ;
2014-08-30 21:15:23 +08:00
alSourcei ( core - > alMainSource , AL_BUFFER , buffer ) ;
alSourcePlay ( core - > alMainSource ) ;
2014-06-28 05:36:44 +08:00
}
2014-10-08 10:20:38 +08:00
void Widget : : playRingtone ( )
{
QApplication : : alert ( this ) ;
static QFile sndFile1 ( " :audio/ToxicIncomingCall.pcm " ) ; // for whatever reason this plays slower/downshifted from what any other program plays the file as... but whatever
static QByteArray sndData1 ;
if ( sndData1 . isEmpty ( ) )
{
sndFile1 . open ( QIODevice : : ReadOnly ) ;
sndData1 = sndFile1 . readAll ( ) ;
sndFile1 . close ( ) ;
}
ALuint buffer ;
alGenBuffers ( 1 , & buffer ) ;
alBufferData ( buffer , AL_FORMAT_MONO16 , sndData1 . data ( ) , sndData1 . size ( ) , 44100 ) ;
alSourcei ( core - > alMainSource , AL_BUFFER , buffer ) ;
alSourcePlay ( core - > alMainSource ) ;
}
2014-06-25 04:11:11 +08:00
void Widget : : onFriendRequestReceived ( const QString & userId , const QString & message )
{
FriendRequestDialog dialog ( this , userId , message ) ;
if ( dialog . exec ( ) = = QDialog : : Accepted )
emit friendRequestAccepted ( userId ) ;
}
void Widget : : removeFriend ( int friendId )
{
Friend * f = FriendList : : findFriend ( friendId ) ;
2014-07-03 14:43:23 +08:00
f - > widget - > setAsInactiveChatroom ( ) ;
2014-09-02 00:20:28 +08:00
if ( static_cast < GenericChatroomWidget * > ( f - > widget ) = = activeChatroomWidget )
activeChatroomWidget = nullptr ;
2014-06-25 04:11:11 +08:00
FriendList : : removeFriend ( friendId ) ;
core - > removeFriend ( friendId ) ;
delete f ;
if ( ui - > mainHead - > layout ( ) - > isEmpty ( ) )
onAddClicked ( ) ;
}
2014-07-02 05:50:07 +08:00
void Widget : : copyFriendIdToClipboard ( int friendId )
{
Friend * f = FriendList : : findFriend ( friendId ) ;
if ( f ! = nullptr )
{
QClipboard * clipboard = QApplication : : clipboard ( ) ;
2014-09-01 04:26:45 +08:00
clipboard - > setText ( core - > getFriendAddress ( f - > friendId ) , QClipboard : : Clipboard ) ;
2014-07-02 05:50:07 +08:00
}
}
2014-09-28 16:56:02 +08:00
void Widget : : onGroupInviteReceived ( int32_t friendId , const uint8_t * publicKey , uint16_t length )
2014-06-25 04:11:11 +08:00
{
2014-09-28 16:56:02 +08:00
int groupId = core - > joinGroupchat ( friendId , publicKey , length ) ;
2014-06-25 04:11:11 +08:00
if ( groupId = = - 1 )
{
qWarning ( ) < < " Widget::onGroupInviteReceived: Unable to accept invitation " ;
return ;
}
}
2014-10-06 14:46:30 +08:00
void Widget : : onGroupMessageReceived ( int groupnumber , const QString & message , const QString & author )
2014-06-25 04:11:11 +08:00
{
Group * g = GroupList : : findGroup ( groupnumber ) ;
if ( ! g )
return ;
2014-10-06 14:46:30 +08:00
g - > chatForm - > addMessage ( author , message ) ;
2014-06-28 07:10:02 +08:00
2014-10-04 16:54:50 +08:00
if ( ( static_cast < GenericChatroomWidget * > ( g - > widget ) ! = activeChatroomWidget ) | | isMinimized ( ) | | ! isActiveWindow ( ) )
2014-06-28 07:10:02 +08:00
{
2014-09-02 00:20:28 +08:00
g - > hasNewMessages = 1 ;
2014-10-06 14:46:30 +08:00
newMessageAlert ( ) ; // sound alert on any message, not just naming user
2014-07-12 04:38:39 +08:00
if ( message . contains ( core - > getUsername ( ) , Qt : : CaseInsensitive ) )
2014-06-28 07:10:02 +08:00
{
2014-10-06 14:46:30 +08:00
g - > userWasMentioned = 1 ; // useful for highlighting line or desktop notifications
2014-06-28 07:10:02 +08:00
}
2014-09-02 00:20:28 +08:00
g - > widget - > updateStatusLight ( ) ;
2014-06-28 07:10:02 +08:00
}
2014-06-25 04:11:11 +08:00
}
void Widget : : onGroupNamelistChanged ( int groupnumber , int peernumber , uint8_t Change )
{
Group * g = GroupList : : findGroup ( groupnumber ) ;
if ( ! g )
{
qDebug ( ) < < " Widget::onGroupNamelistChanged: Group not found, creating it " ;
g = createGroup ( groupnumber ) ;
}
TOX_CHAT_CHANGE change = static_cast < TOX_CHAT_CHANGE > ( Change ) ;
if ( change = = TOX_CHAT_CHANGE_PEER_ADD )
2014-09-12 00:05:02 +08:00
{
QString name = core - > getGroupPeerName ( groupnumber , peernumber ) ;
if ( name . isEmpty ( ) )
name = tr ( " <Unknown> " , " Placeholder when we don't know someone's name in a group chat " ) ;
g - > addPeer ( peernumber , name ) ;
}
2014-06-25 04:11:11 +08:00
else if ( change = = TOX_CHAT_CHANGE_PEER_DEL )
g - > removePeer ( peernumber ) ;
else if ( change = = TOX_CHAT_CHANGE_PEER_NAME )
g - > updatePeer ( peernumber , core - > getGroupPeerName ( groupnumber , peernumber ) ) ;
}
void Widget : : removeGroup ( int groupId )
{
Group * g = GroupList : : findGroup ( groupId ) ;
2014-07-03 14:43:23 +08:00
g - > widget - > setAsInactiveChatroom ( ) ;
2014-09-02 00:20:28 +08:00
if ( static_cast < GenericChatroomWidget * > ( g - > widget ) = = activeChatroomWidget )
activeChatroomWidget = nullptr ;
2014-06-25 04:11:11 +08:00
GroupList : : removeGroup ( groupId ) ;
core - > removeGroup ( groupId ) ;
delete g ;
if ( ui - > mainHead - > layout ( ) - > isEmpty ( ) )
onAddClicked ( ) ;
}
2014-06-26 07:48:20 +08:00
Core * Widget : : getCore ( )
2014-06-25 04:11:11 +08:00
{
return core ;
}
Group * Widget : : createGroup ( int groupId )
{
Group * g = GroupList : : findGroup ( groupId ) ;
if ( g )
{
qWarning ( ) < < " Widget::createGroup: Group already exists " ;
return g ;
}
QString groupName = QString ( " Groupchat #%1 " ) . arg ( groupId ) ;
Group * newgroup = GroupList : : addGroup ( groupId , groupName ) ;
2014-08-22 23:19:16 +08:00
QLayout * layout = contactListWidget - > getGroupLayout ( ) ;
2014-06-25 04:11:11 +08:00
layout - > addWidget ( newgroup - > widget ) ;
2014-09-02 00:20:28 +08:00
newgroup - > widget - > updateStatusLight ( ) ;
2014-08-11 16:00:08 +08:00
2014-09-02 00:20:28 +08:00
connect ( newgroup - > widget , SIGNAL ( chatroomWidgetClicked ( GenericChatroomWidget * ) ) , this , SLOT ( onChatroomWidgetClicked ( GenericChatroomWidget * ) ) ) ;
2014-06-25 04:11:11 +08:00
connect ( newgroup - > widget , SIGNAL ( removeGroup ( int ) ) , this , SLOT ( removeGroup ( int ) ) ) ;
2014-09-11 05:00:45 +08:00
connect ( newgroup - > widget , SIGNAL ( chatroomWidgetClicked ( GenericChatroomWidget * ) ) , newgroup - > chatForm , SLOT ( focusInput ( ) ) ) ;
2014-06-25 04:11:11 +08:00
connect ( newgroup - > chatForm , SIGNAL ( sendMessage ( int , QString ) ) , core , SLOT ( sendGroupMessage ( int , QString ) ) ) ;
return newgroup ;
}
2014-06-30 05:38:48 +08:00
void Widget : : onEmptyGroupCreated ( int groupId )
{
createGroup ( groupId ) ;
}
2014-07-01 03:14:51 +08:00
bool Widget : : isFriendWidgetCurActiveWidget ( Friend * f )
{
if ( ! f )
return false ;
2014-09-02 00:20:28 +08:00
if ( activeChatroomWidget = = static_cast < GenericChatroomWidget * > ( f - > widget ) )
return true ;
2014-07-01 03:14:51 +08:00
else
return false ;
}
2014-07-01 10:12:17 +08:00
2014-07-03 06:27:30 +08:00
bool Widget : : event ( QEvent * e )
2014-07-01 10:12:17 +08:00
{
2014-10-04 16:54:50 +08:00
if ( e - > type ( ) = = QEvent : : WindowActivate )
2014-07-03 06:27:30 +08:00
{
2014-09-02 00:20:28 +08:00
if ( activeChatroomWidget ! = nullptr )
2014-07-03 06:27:30 +08:00
{
2014-09-02 00:20:28 +08:00
activeChatroomWidget - > resetEventFlags ( ) ;
activeChatroomWidget - > updateStatusLight ( ) ;
2014-07-03 06:27:30 +08:00
}
}
2014-07-01 10:12:17 +08:00
return QWidget : : event ( e ) ;
}
2014-07-06 04:54:27 +08:00
void Widget : : setStatusOnline ( )
{
core - > setStatus ( Status : : Online ) ;
}
void Widget : : setStatusAway ( )
{
core - > setStatus ( Status : : Away ) ;
}
void Widget : : setStatusBusy ( )
2014-07-04 01:33:08 +08:00
{
2014-07-06 04:54:27 +08:00
core - > setStatus ( Status : : Busy ) ;
2014-07-04 01:33:08 +08:00
}
2014-07-21 02:17:06 +08:00
2014-09-24 00:35:06 +08:00
void Widget : : onMessageSendResult ( int friendId , const QString & message , int messageId )
{
Q_UNUSED ( message )
Friend * f = FriendList : : findFriend ( friendId ) ;
if ( ! f )
return ;
if ( ! messageId )
f - > chatForm - > addSystemInfoMessage ( " Message failed to send " , " red " ) ;
}
void Widget : : onGroupSendResult ( int groupId , const QString & message , int result )
{
Q_UNUSED ( message )
Group * g = GroupList : : findGroup ( groupId ) ;
if ( ! g )
return ;
if ( result = = - 1 )
g - > chatForm - > addSystemInfoMessage ( " Message failed to send " , " red " ) ;
}