2014-09-15 18:45:59 +08:00
/*
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 .
*/
2015-04-24 08:32:09 +08:00
# include "src/core/core.h"
2015-03-04 04:29:01 +08:00
# include "src/nexus.h"
2015-03-11 23:15:53 +08:00
# include "ui_profileform.h"
2015-03-04 04:29:01 +08:00
# include "profileform.h"
2015-03-05 03:35:34 +08:00
# include "ui_mainwindow.h"
2014-10-08 12:26:25 +08:00
# include "src/widget/form/settingswidget.h"
2015-03-04 04:29:01 +08:00
# include "src/widget/maskablepixmapwidget.h"
2014-10-12 17:58:56 +08:00
# include "src/misc/settings.h"
2014-10-08 12:26:25 +08:00
# include "src/widget/croppinglabel.h"
2014-10-12 17:58:56 +08:00
# include "src/widget/widget.h"
2015-02-07 04:01:30 +08:00
# include "src/widget/gui.h"
2014-10-19 01:38:47 +08:00
# include "src/historykeeper.h"
2014-10-15 23:45:41 +08:00
# include "src/misc/style.h"
2015-04-25 01:19:01 +08:00
# include "src/profilelocker.h"
2015-06-04 17:37:54 +08:00
# include "src/profile.h"
2014-09-15 18:45:59 +08:00
# include <QLabel>
# include <QLineEdit>
2015-03-04 04:29:01 +08:00
# include <QGroupBox>
2014-09-30 17:44:27 +08:00
# include <QApplication>
# include <QClipboard>
2014-10-09 16:07:26 +08:00
# include <QInputDialog>
# include <QFileDialog>
2015-03-04 04:29:01 +08:00
# include <QBuffer>
2014-09-15 18:45:59 +08:00
2015-03-04 04:29:01 +08:00
ProfileForm : : ProfileForm ( QWidget * parent ) :
2015-05-10 04:35:58 +08:00
QWidget { parent } , qr { nullptr }
2014-09-15 18:45:59 +08:00
{
2014-10-06 00:17:01 +08:00
bodyUI = new Ui : : IdentitySettings ;
bodyUI - > setupUi ( this ) ;
2014-10-23 20:41:47 +08:00
core = Core : : getInstance ( ) ;
2014-09-30 17:44:27 +08:00
2015-03-11 10:01:13 +08:00
head = new QWidget ( this ) ;
QHBoxLayout * headLayout = new QHBoxLayout ( ) ;
head - > setLayout ( headLayout ) ;
QLabel * imgLabel = new QLabel ( ) ;
headLayout - > addWidget ( imgLabel ) ;
QLabel * nameLabel = new QLabel ( ) ;
2015-03-05 03:35:34 +08:00
QFont bold ;
bold . setBold ( true ) ;
2015-03-11 10:01:13 +08:00
nameLabel - > setFont ( bold ) ;
headLayout - > addWidget ( nameLabel ) ;
headLayout - > addStretch ( 1 ) ;
2015-05-18 20:43:18 +08:00
nameLabel - > setText ( QObject : : tr ( " User Profile " ) ) ;
2015-03-11 10:01:13 +08:00
imgLabel - > setPixmap ( QPixmap ( " :/img/settings/identity.png " ) . scaledToHeight ( 40 , Qt : : SmoothTransformation ) ) ;
2015-03-05 03:35:34 +08:00
2014-09-30 17:44:27 +08:00
// tox
toxId = new ClickableTE ( ) ;
toxId - > setReadOnly ( true ) ;
2014-10-09 16:59:35 +08:00
toxId - > setFrame ( false ) ;
2014-10-15 23:45:41 +08:00
toxId - > setFont ( Style : : getFont ( Style : : Small ) ) ;
2015-03-17 05:15:34 +08:00
toxId - > setToolTip ( bodyUI - > toxId - > toolTip ( ) ) ;
2015-03-17 03:53:35 +08:00
2015-03-15 23:45:28 +08:00
QVBoxLayout * toxIdGroup = qobject_cast < QVBoxLayout * > ( bodyUI - > toxGroup - > layout ( ) ) ;
toxIdGroup - > replaceWidget ( bodyUI - > toxId , toxId ) ;
bodyUI - > toxId - > hide ( ) ;
2015-03-17 03:53:35 +08:00
2015-03-18 00:14:16 +08:00
bodyUI - > qrLabel - > setWordWrap ( true ) ;
2015-02-12 20:18:04 +08:00
profilePicture = new MaskablePixmapWidget ( this , QSize ( 64 , 64 ) , " :/img/avatar_mask.svg " ) ;
2015-03-18 23:51:58 +08:00
profilePicture - > setPixmap ( QPixmap ( " :/img/contact_dark.svg " ) ) ;
2015-03-04 04:29:01 +08:00
profilePicture - > setClickable ( true ) ;
connect ( profilePicture , SIGNAL ( clicked ( ) ) , this , SLOT ( onAvatarClicked ( ) ) ) ;
QHBoxLayout * publicGrouplayout = qobject_cast < QHBoxLayout * > ( bodyUI - > publicGroup - > layout ( ) ) ;
publicGrouplayout - > insertWidget ( 0 , profilePicture ) ;
publicGrouplayout - > insertSpacing ( 1 , 7 ) ;
2015-01-20 16:07:56 +08:00
timer . setInterval ( 750 ) ;
2014-11-11 07:20:10 +08:00
timer . setSingleShot ( true ) ;
2015-01-20 16:07:56 +08:00
connect ( & timer , & QTimer : : timeout , this , [ = ] ( ) { bodyUI - > toxIdLabel - > setText ( bodyUI - > toxIdLabel - > text ( ) . replace ( " ✔ " , " " ) ) ; hasCheck = false ; } ) ;
2015-03-17 03:53:35 +08:00
2014-10-06 00:17:01 +08:00
connect ( bodyUI - > toxIdLabel , SIGNAL ( clicked ( ) ) , this , SLOT ( copyIdClicked ( ) ) ) ;
2014-09-30 17:44:27 +08:00
connect ( toxId , SIGNAL ( clicked ( ) ) , this , SLOT ( copyIdClicked ( ) ) ) ;
2015-03-04 04:29:01 +08:00
connect ( core , & Core : : idSet , this , & ProfileForm : : setToxId ) ;
2014-10-06 00:17:01 +08:00
connect ( bodyUI - > userName , SIGNAL ( editingFinished ( ) ) , this , SLOT ( onUserNameEdited ( ) ) ) ;
connect ( bodyUI - > statusMessage , SIGNAL ( editingFinished ( ) ) , this , SLOT ( onStatusMessageEdited ( ) ) ) ;
2015-03-04 04:29:01 +08:00
connect ( bodyUI - > renameButton , & QPushButton : : clicked , this , & ProfileForm : : onRenameClicked ) ;
connect ( bodyUI - > exportButton , & QPushButton : : clicked , this , & ProfileForm : : onExportClicked ) ;
connect ( bodyUI - > deleteButton , & QPushButton : : clicked , this , & ProfileForm : : onDeleteClicked ) ;
2015-06-04 17:37:54 +08:00
connect ( bodyUI - > logoutButton , & QPushButton : : clicked , this , & ProfileForm : : onLogoutClicked ) ;
2014-10-23 20:41:47 +08:00
2014-11-11 07:20:10 +08:00
connect ( core , & Core : : usernameSet , this , [ = ] ( const QString & val ) { bodyUI - > userName - > setText ( val ) ; } ) ;
connect ( core , & Core : : statusMessageSet , this , [ = ] ( const QString & val ) { bodyUI - > statusMessage - > setText ( val ) ; } ) ;
2015-03-18 02:18:47 +08:00
for ( QComboBox * cb : findChildren < QComboBox * > ( ) )
{
2015-03-16 04:29:23 +08:00
cb - > installEventFilter ( this ) ;
cb - > setFocusPolicy ( Qt : : StrongFocus ) ;
}
2014-09-15 18:45:59 +08:00
}
2015-03-04 04:29:01 +08:00
ProfileForm : : ~ ProfileForm ( )
2014-09-15 18:45:59 +08:00
{
2015-05-10 04:35:58 +08:00
delete qr ;
2014-10-28 06:56:21 +08:00
delete bodyUI ;
2015-03-06 02:09:58 +08:00
head - > deleteLater ( ) ;
2015-03-05 03:35:34 +08:00
}
void ProfileForm : : show ( Ui : : MainWindow & ui )
{
ui . mainHead - > layout ( ) - > addWidget ( head ) ;
2015-03-11 10:01:13 +08:00
ui . mainContent - > layout ( ) - > addWidget ( this ) ;
2015-03-05 03:35:34 +08:00
head - > show ( ) ;
QWidget : : show ( ) ;
2015-03-28 04:01:42 +08:00
bodyUI - > userName - > setFocus ( ) ;
2015-03-12 11:00:54 +08:00
bodyUI - > userName - > selectAll ( ) ;
2014-09-15 18:45:59 +08:00
}
2014-09-30 17:44:27 +08:00
2015-03-04 04:29:01 +08:00
void ProfileForm : : copyIdClicked ( )
2014-09-30 17:44:27 +08:00
{
toxId - > selectAll ( ) ;
2014-10-06 02:02:12 +08:00
QString txt = toxId - > text ( ) ;
2014-09-30 17:44:27 +08:00
txt . replace ( ' \n ' , " " ) ;
2015-05-18 01:57:55 +08:00
QApplication : : clipboard ( ) - > setText ( txt , QClipboard : : Clipboard ) ;
if ( QApplication : : clipboard ( ) - > supportsSelection ( ) )
QApplication : : clipboard ( ) - > setText ( txt , QClipboard : : Selection ) ;
2014-10-09 16:59:35 +08:00
toxId - > setCursorPosition ( 0 ) ;
2014-11-11 07:20:10 +08:00
2015-01-20 16:07:56 +08:00
if ( ! hasCheck )
{
bodyUI - > toxIdLabel - > setText ( bodyUI - > toxIdLabel - > text ( ) + " ✔ " ) ;
hasCheck = true ;
}
2014-11-11 07:20:10 +08:00
timer . start ( ) ;
2014-09-30 17:44:27 +08:00
}
2015-03-04 04:29:01 +08:00
void ProfileForm : : onUserNameEdited ( )
2014-09-30 17:44:27 +08:00
{
2014-10-06 00:30:31 +08:00
Core : : getInstance ( ) - > setUsername ( bodyUI - > userName - > text ( ) ) ;
2014-09-30 17:44:27 +08:00
}
2015-03-04 04:29:01 +08:00
void ProfileForm : : onStatusMessageEdited ( )
2014-09-30 17:44:27 +08:00
{
2014-10-06 00:30:31 +08:00
Core : : getInstance ( ) - > setStatusMessage ( bodyUI - > statusMessage - > text ( ) ) ;
2014-09-30 17:44:27 +08:00
}
2015-03-04 04:29:01 +08:00
void ProfileForm : : onSelfAvatarLoaded ( const QPixmap & pic )
2014-09-30 17:44:27 +08:00
{
2015-03-04 04:29:01 +08:00
profilePicture - > setPixmap ( pic ) ;
2014-10-06 00:17:01 +08:00
}
2015-03-04 04:29:01 +08:00
void ProfileForm : : setToxId ( const QString & id )
2014-10-06 00:17:01 +08:00
{
2014-10-18 09:15:26 +08:00
toxId - > setText ( id ) ;
toxId - > setCursorPosition ( 0 ) ;
2015-03-17 03:53:35 +08:00
2015-05-10 04:35:58 +08:00
delete qr ;
2015-03-17 03:53:35 +08:00
qr = new QRWidget ( ) ;
qr - > setQRData ( " tox: " + id ) ;
2015-03-15 23:45:28 +08:00
bodyUI - > qrCode - > setPixmap ( QPixmap : : fromImage ( qr - > getImage ( ) - > scaledToWidth ( 150 ) ) ) ;
2014-10-06 00:17:01 +08:00
}
2014-10-09 16:07:26 +08:00
2015-03-04 04:29:01 +08:00
void ProfileForm : : onAvatarClicked ( )
{
2015-05-10 06:56:41 +08:00
auto picToPng = [ ] ( QPixmap pic )
{
QByteArray bytes ;
QBuffer buffer ( & bytes ) ;
buffer . open ( QIODevice : : WriteOnly ) ;
pic . save ( & buffer , " PNG " ) ;
buffer . close ( ) ;
return bytes ;
} ;
2015-03-15 04:15:56 +08:00
QString filename = QFileDialog : : getOpenFileName ( 0 ,
2015-03-04 04:29:01 +08:00
tr ( " Choose a profile picture " ) ,
QDir : : homePath ( ) ,
Nexus : : getSupportedImageFilter ( ) ) ;
if ( filename . isEmpty ( ) )
return ;
2015-04-24 19:01:50 +08:00
2015-03-04 04:29:01 +08:00
QFile file ( filename ) ;
file . open ( QIODevice : : ReadOnly ) ;
if ( ! file . isOpen ( ) )
{
2015-05-20 05:25:26 +08:00
GUI : : showError ( tr ( " Error " ) , tr ( " Unable to open this file. " ) ) ;
2015-03-04 04:29:01 +08:00
return ;
}
QPixmap pic ;
if ( ! pic . loadFromData ( file . readAll ( ) ) )
{
2015-05-20 05:25:26 +08:00
GUI : : showError ( tr ( " Error " ) , tr ( " Unable to read this image. " ) ) ;
2015-03-04 04:29:01 +08:00
return ;
}
2015-05-10 06:56:41 +08:00
// Limit the avatar size to 64kB
// We do a first rescale to 256x256 in case the image was huge, then keep tryng from here
QByteArray bytes { picToPng ( pic ) } ;
if ( bytes . size ( ) > 65535 )
{
pic = pic . scaled ( 256 , 256 , Qt : : KeepAspectRatio , Qt : : SmoothTransformation ) ;
bytes = picToPng ( pic ) ;
}
if ( bytes . size ( ) > 65535 )
bytes = picToPng ( pic . scaled ( 128 , 128 , Qt : : KeepAspectRatio , Qt : : SmoothTransformation ) ) ;
if ( bytes . size ( ) > 65535 )
bytes = picToPng ( pic . scaled ( 64 , 64 , Qt : : KeepAspectRatio , Qt : : SmoothTransformation ) ) ;
if ( bytes . size ( ) > 65535 )
bytes = picToPng ( pic . scaled ( 32 , 32 , Qt : : KeepAspectRatio , Qt : : SmoothTransformation ) ) ;
// If this happens, you're really doing it on purpose.
if ( bytes . size ( ) > 65535 )
{
2015-05-20 05:25:26 +08:00
QMessageBox : : critical ( this , tr ( " Error " ) ,
2015-05-25 07:25:00 +08:00
tr ( " The supplied image is too large. \n Please use another image. " ) ) ;
2015-05-10 06:56:41 +08:00
return ;
}
2015-03-04 04:29:01 +08:00
2015-04-20 05:12:44 +08:00
Nexus : : getCore ( ) - > setAvatar ( bytes ) ;
2015-03-04 04:29:01 +08:00
}
void ProfileForm : : onRenameClicked ( )
2014-10-09 16:07:26 +08:00
{
2015-06-04 17:37:54 +08:00
/** TODO: Create a rename (low level) function in Profile, use it
2014-10-09 16:07:26 +08:00
QString title = tr ( " Rename \" %1 \" " , " renaming a profile " ) . arg ( cur ) ;
2014-10-20 11:36:39 +08:00
do
2014-10-09 16:07:26 +08:00
{
2014-10-20 11:36:39 +08:00
QString name = QInputDialog : : getText ( this , title , title + " : " ) ;
if ( name . isEmpty ( ) ) break ;
2014-10-09 16:07:26 +08:00
name = Core : : sanitize ( name ) ;
QDir dir ( Settings : : getSettingsDirPath ( ) ) ;
2014-10-20 11:36:39 +08:00
QString file = dir . filePath ( name + Core : : TOX_EXT ) ;
2015-02-07 04:01:30 +08:00
if ( ! QFile : : exists ( file ) | | GUI : : askQuestion ( tr ( " Profile already exists " , " rename confirm title " ) ,
2014-10-20 11:36:39 +08:00
tr ( " A profile named \" %1 \" already exists. Do you want to erase it? " , " rename confirm text " ) . arg ( cur ) ) )
{
2015-04-25 01:19:01 +08:00
if ( ! ProfileLocker : : lock ( name ) )
{
GUI : : showWarning ( tr ( " Profile already exists " , " rename failed title " ) ,
tr ( " A profile named \" %1 \" already exists and is in use. " ) . arg ( cur ) ) ;
break ;
}
2014-10-20 11:36:39 +08:00
QFile : : rename ( dir . filePath ( cur + Core : : TOX_EXT ) , file ) ;
2015-01-23 22:31:13 +08:00
QFile : : rename ( dir . filePath ( cur + " .ini " ) , dir . filePath ( name + " .ini " ) ) ;
2014-10-20 11:36:39 +08:00
bodyUI - > profiles - > setItemText ( bodyUI - > profiles - > currentIndex ( ) , name ) ;
2014-10-22 22:05:04 +08:00
HistoryKeeper : : renameHistory ( cur , name ) ;
2014-12-17 21:44:23 +08:00
bool resetAutorun = Settings : : getInstance ( ) . getAutorun ( ) ;
Settings : : getInstance ( ) . setAutorun ( false ) ;
2014-10-20 11:36:39 +08:00
Settings : : getInstance ( ) . setCurrentProfile ( name ) ;
2014-12-17 21:44:23 +08:00
if ( resetAutorun )
2015-02-15 07:26:21 +08:00
Settings : : getInstance ( ) . setAutorun ( true ) ; // fixes -p flag in autostart command line
2015-04-24 19:01:50 +08:00
2014-10-20 11:36:39 +08:00
break ;
}
} while ( true ) ;
2015-06-04 17:37:54 +08:00
*/
2014-10-09 16:07:26 +08:00
}
2015-03-04 04:29:01 +08:00
void ProfileForm : : onExportClicked ( )
2014-10-09 16:07:26 +08:00
{
2015-06-04 17:37:54 +08:00
QString current = Nexus : : getProfile ( ) - > getName ( ) + Core : : TOX_EXT ;
2015-03-15 01:01:59 +08:00
QString path = QFileDialog : : getSaveFileName ( 0 , tr ( " Export profile " , " save dialog title " ) ,
2015-03-17 05:15:34 +08:00
QDir : : home ( ) . filePath ( current ) ,
2014-10-09 16:07:26 +08:00
tr ( " Tox save file (*.tox) " , " save dialog filter " ) ) ;
2014-10-14 05:17:42 +08:00
if ( ! path . isEmpty ( ) )
2014-11-12 06:06:15 +08:00
{
2015-04-26 23:39:39 +08:00
if ( ! Nexus : : tryRemoveFile ( path ) )
2014-11-12 06:06:15 +08:00
{
2015-03-17 05:41:59 +08:00
GUI : : showWarning ( tr ( " Location not writable " , " Title of permissions popup " ) , tr ( " You do not have permission to write that location. Choose another, or cancel the save dialog. " , " text of permissions popup " ) ) ;
return ;
2014-11-12 06:06:15 +08:00
}
2015-03-17 05:41:59 +08:00
if ( ! QFile : : copy ( QDir ( Settings : : getSettingsDirPath ( ) ) . filePath ( current ) , path ) )
GUI : : showWarning ( tr ( " Failed to copy file " ) , tr ( " The file you chose could not be written to. " ) ) ;
2014-11-12 06:06:15 +08:00
}
2014-10-09 16:07:26 +08:00
}
2015-03-04 04:29:01 +08:00
void ProfileForm : : onDeleteClicked ( )
2014-10-09 16:07:26 +08:00
{
2015-06-04 17:37:54 +08:00
/** Add a delete function in profile
2014-10-09 16:07:26 +08:00
if ( Settings : : getInstance ( ) . getCurrentProfile ( ) = = bodyUI - > profiles - > currentText ( ) )
{
2015-03-17 05:41:59 +08:00
GUI : : showWarning ( tr ( " Profile currently loaded " , " current profile deletion warning title " ) , tr ( " This profile is currently in use. Please load a different profile before deleting this one. " , " current profile deletion warning text " ) ) ;
2014-10-09 16:07:26 +08:00
}
else
2015-03-17 05:15:34 +08:00
{
2015-02-07 04:01:30 +08:00
if ( GUI : : askQuestion ( tr ( " Deletion imminent! " , " deletion confirmation title " ) ,
2014-12-06 09:17:02 +08:00
tr ( " Are you sure you want to delete this profile? " , " deletion confirmation text " ) ) )
2014-10-09 16:07:26 +08:00
{
2014-12-03 08:48:50 +08:00
QString profile = bodyUI - > profiles - > currentText ( ) ;
QDir dir ( Settings : : getSettingsDirPath ( ) ) ;
QFile : : remove ( dir . filePath ( profile + Core : : TOX_EXT ) ) ;
QFile : : remove ( dir . filePath ( profile + " .ini " ) ) ;
QFile : : remove ( HistoryKeeper : : getHistoryPath ( profile , 0 ) ) ;
QFile : : remove ( HistoryKeeper : : getHistoryPath ( profile , 1 ) ) ;
2014-10-09 16:07:26 +08:00
bodyUI - > profiles - > removeItem ( bodyUI - > profiles - > currentIndex ( ) ) ;
bodyUI - > profiles - > setCurrentText ( Settings : : getInstance ( ) . getCurrentProfile ( ) ) ;
}
}
2015-06-04 17:37:54 +08:00
*/
2014-10-09 16:07:26 +08:00
}
2015-06-04 17:37:54 +08:00
void ProfileForm : : onLogoutClicked ( )
2014-10-09 16:07:26 +08:00
{
2015-06-04 17:56:19 +08:00
Nexus & nexus = Nexus : : getInstance ( ) ;
Settings : : getInstance ( ) . save ( ) ;
nexus . showLogin ( ) ;
2014-10-09 16:07:26 +08:00
}
2014-10-20 11:07:51 +08:00
2015-06-04 17:37:54 +08:00
void ProfileForm : : onCopyQrClicked ( )
2015-03-15 23:45:28 +08:00
{
2015-03-16 02:53:10 +08:00
QApplication : : clipboard ( ) - > setImage ( * qr - > getImage ( ) ) ;
2015-03-15 23:45:28 +08:00
}
2015-06-04 17:37:54 +08:00
void ProfileForm : : onSaveQrClicked ( )
2015-03-15 23:45:28 +08:00
{
2015-06-04 17:37:54 +08:00
QString current = Nexus : : getProfile ( ) - > getName ( ) + " .png " ;
2015-03-15 23:45:28 +08:00
QString path = QFileDialog : : getSaveFileName ( 0 , tr ( " Save " , " save qr image " ) ,
2015-03-17 05:41:59 +08:00
QDir : : home ( ) . filePath ( current ) ,
2015-03-15 23:45:28 +08:00
tr ( " Save QrCode (*.png) " , " save dialog filter " ) ) ;
if ( ! path . isEmpty ( ) )
{
2015-04-26 23:39:39 +08:00
if ( ! Nexus : : tryRemoveFile ( path ) )
2015-03-15 23:45:28 +08:00
{
2015-03-17 05:41:59 +08:00
GUI : : showWarning ( tr ( " Location not writable " , " Title of permissions popup " ) , tr ( " You do not have permission to write that location. Choose another, or cancel the save dialog. " , " text of permissions popup " ) ) ;
return ;
2015-03-15 23:45:28 +08:00
}
2015-03-17 05:41:59 +08:00
if ( ! qr - > saveImage ( path ) )
GUI : : showWarning ( tr ( " Failed to copy file " ) , tr ( " The file you chose could not be written to. " ) ) ;
2015-03-15 23:45:28 +08:00
}
}