2018-11-11 16:57:05 +01:00
/*******************************************************************************
* gui / common / MimeTextEdit . cpp *
* *
* Copyright ( C ) 2012 , Retroshare Team < retroshare . project @ gmail . com > *
* *
* This program is free software : you can redistribute it and / or modify *
* it under the terms of the GNU Affero 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 *
* GNU Affero General Public License for more details . *
* *
* You should have received a copy of the GNU Affero General Public License *
* along with this program . If not , see < https : //www.gnu.org/licenses/>. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2012-09-26 23:32:53 +00:00
2020-08-15 22:17:52 +02:00
# include "gui/common/FilesDefs.h"
2015-09-03 00:27:14 +02:00
# include <QApplication>
# include <QClipboard>
2012-09-26 23:32:53 +00:00
# include <QMimeData>
# include <QTextDocumentFragment>
2013-07-04 19:36:12 +00:00
# include <QCompleter>
# include <QAbstractItemView>
# include <QKeyEvent>
# include <QScrollBar>
2013-12-30 19:12:16 +00:00
# include <QMenu>
# include "MimeTextEdit.h"
# include "util/HandleRichText.h"
# include "gui/RetroShareLink.h"
# include <retroshare/rspeers.h>
2012-09-26 23:32:53 +00:00
MimeTextEdit : : MimeTextEdit ( QWidget * parent )
2014-12-25 02:39:40 +00:00
: RSTextEdit ( parent ) , mCompleter ( 0 )
2012-09-26 23:32:53 +00:00
{
2013-12-30 19:12:16 +00:00
mCompleterKeyModifiers = Qt : : ControlModifier ;
mCompleterKey = Qt : : Key_Space ;
mForceCompleterShowNextKeyEvent = false ;
2015-12-13 02:01:06 +01:00
highliter = new RsSyntaxHighlighter ( this ) ;
2017-07-21 10:58:19 +02:00
mOnlyPlainText = false ;
2012-09-26 23:32:53 +00:00
}
bool MimeTextEdit : : canInsertFromMimeData ( const QMimeData * source ) const
{
# if QT_VERSION >= 0x040700
// embedded images are not supported before QT 4.7.0
2013-01-22 00:14:10 +00:00
if ( source ! = NULL ) {
if ( source - > hasImage ( ) ) {
return true ;
}
}
2012-09-26 23:32:53 +00:00
# endif
2014-12-25 02:39:40 +00:00
return RSTextEdit : : canInsertFromMimeData ( source ) ;
2012-09-26 23:32:53 +00:00
}
void MimeTextEdit : : insertFromMimeData ( const QMimeData * source )
{
# if QT_VERSION >= 0x040700
// embedded images are not supported before QT 4.7.0
2013-01-22 00:14:10 +00:00
if ( source ! = NULL ) {
if ( source - > hasImage ( ) ) {
// insert as embedded image
QImage image = qvariant_cast < QImage > ( source - > imageData ( ) ) ;
if ( image . isNull ( ) = = false ) {
QString encodedImage ;
2017-10-23 17:04:20 +02:00
if ( RsHtml : : makeEmbeddedImage ( image , encodedImage , 640 * 480 , mMaxBytes ) ) {
2013-01-22 00:14:10 +00:00
QTextDocumentFragment fragment = QTextDocumentFragment : : fromHtml ( encodedImage ) ;
2013-12-30 19:12:16 +00:00
textCursor ( ) . insertFragment ( fragment ) ;
2013-01-22 00:14:10 +00:00
return ;
}
}
}
}
2012-09-26 23:32:53 +00:00
# endif
2017-04-19 14:15:34 +02:00
if ( source = = NULL ) return ;
2012-09-26 23:32:53 +00:00
2016-10-31 00:23:39 +01:00
//insert retroshare links
QList < RetroShareLink > links ;
RSLinkClipboard : : parseText ( source - > text ( ) , links ) ;
if ( links . size ( ) > 0 )
{
for ( int i = 0 ; i < links . size ( ) ; + + i )
2017-07-21 10:58:19 +02:00
if ( mOnlyPlainText )
insertPlainText ( links [ i ] . toString ( ) ) ;
else
insertHtml ( links [ i ] . toHtml ( ) + " <br> " ) ;
2016-10-31 00:23:39 +01:00
return ;
}
2014-12-25 02:39:40 +00:00
return RSTextEdit : : insertFromMimeData ( source ) ;
2012-09-26 23:32:53 +00:00
}
2013-07-04 19:36:12 +00:00
void MimeTextEdit : : setCompleter ( QCompleter * completer )
{
2013-12-30 19:12:16 +00:00
if ( mCompleter )
QObject : : disconnect ( mCompleter , 0 , this , 0 ) ;
2013-07-04 19:36:12 +00:00
2013-12-30 19:12:16 +00:00
mCompleter = completer ;
2013-07-04 19:36:12 +00:00
2013-12-30 19:12:16 +00:00
if ( ! mCompleter )
return ;
2013-07-04 19:36:12 +00:00
2013-12-30 19:12:16 +00:00
mCompleter - > setWidget ( this ) ;
mCompleter - > setCompletionMode ( QCompleter : : PopupCompletion ) ;
mCompleter - > setCaseSensitivity ( Qt : : CaseInsensitive ) ;
QObject : : connect ( mCompleter , SIGNAL ( activated ( QString ) ) , this , SLOT ( insertCompletion ( QString ) ) ) ;
2013-07-04 19:36:12 +00:00
}
QCompleter * MimeTextEdit : : completer ( ) const
{
2013-12-30 19:12:16 +00:00
return mCompleter ;
2013-07-04 19:36:12 +00:00
}
void MimeTextEdit : : insertCompletion ( const QString & completion )
{
2013-12-30 19:12:16 +00:00
if ( mCompleter - > widget ( ) ! = this )
return ;
QTextCursor tc = textCursor ( ) ;
if ( mCompleter - > completionPrefix ( ) . length ( ) > 0 ) {
tc . movePosition ( QTextCursor : : PreviousWord , QTextCursor : : KeepAnchor ) ;
}
tc . removeSelectedText ( ) ;
tc . insertText ( mCompleterStartString + completion ) ;
mCompleterStartString . clear ( ) ;
setTextCursor ( tc ) ;
2013-07-04 19:36:12 +00:00
}
QString MimeTextEdit : : textUnderCursor ( ) const
{
2013-12-30 19:12:16 +00:00
QTextCursor tc = textCursor ( ) ;
tc . select ( QTextCursor : : WordUnderCursor ) ;
return tc . selectedText ( ) ;
2013-07-04 19:36:12 +00:00
}
void MimeTextEdit : : focusInEvent ( QFocusEvent * e )
{
2013-12-30 19:12:16 +00:00
if ( mCompleter )
mCompleter - > setWidget ( this ) ;
2014-12-25 02:39:40 +00:00
RSTextEdit : : focusInEvent ( e ) ;
2013-07-04 19:36:12 +00:00
}
void MimeTextEdit : : keyPressEvent ( QKeyEvent * e )
{
2013-12-30 19:12:16 +00:00
if ( mCompleter & & mCompleter - > popup ( ) - > isVisible ( ) ) {
// The following keys are forwarded by the completer to the widget
switch ( e - > key ( ) ) {
case Qt : : Key_Enter :
case Qt : : Key_Return :
case Qt : : Key_Escape :
case Qt : : Key_Tab :
case Qt : : Key_Backtab :
mCompleter - > popup ( ) - > hide ( ) ;
mForceCompleterShowNextKeyEvent = false ;
e - > ignore ( ) ;
return ; // let the completer do default behavior
default :
break ;
}
}
bool isShortcut = ( ( e - > modifiers ( ) & mCompleterKeyModifiers ) & & e - > key ( ) = = mCompleterKey ) ;
if ( isShortcut & & ! mForceCompleterShowNextKeyEvent ) {
mCompleterStartString . clear ( ) ;
}
isShortcut | = mForceCompleterShowNextKeyEvent ;
if ( ! mCompleter | | ! isShortcut ) // do not process the shortcut when we have a completer
2014-12-25 02:39:40 +00:00
RSTextEdit : : keyPressEvent ( e ) ;
2013-12-30 19:12:16 +00:00
if ( ! mCompleter ) return ; //Nothing else to do if not mCompleter initialized
if ( ! isShortcut & & ( mCompleter & & ! mCompleter - > popup ( ) - > isVisible ( ) ) ) {
return ;
}
if ( ! mForceCompleterShowNextKeyEvent ) {
static QString eow ( " ~!@#$%^&*() _ + { } | : \ " <>?,./;'[] \\ -= " ) ; // end of word
if ( ! isShortcut & & ! e - > text ( ) . isEmpty ( ) & & eow . contains ( e - > text ( ) ) ) {
mCompleter - > popup ( ) - > hide ( ) ;
return ;
}
}
QString completionPrefix = textUnderCursor ( ) ;
if ( completionPrefix ! = mCompleter - > completionPrefix ( ) ) {
mCompleter - > setCompletionPrefix ( completionPrefix ) ;
mCompleter - > popup ( ) - > setCurrentIndex ( mCompleter - > completionModel ( ) - > index ( 0 , 0 ) ) ;
}
2013-07-04 19:36:12 +00:00
2013-12-30 19:12:16 +00:00
QRect cr = cursorRect ( ) ;
cr . setWidth ( mCompleter - > popup ( ) - > sizeHintForColumn ( 0 ) + mCompleter - > popup ( ) - > verticalScrollBar ( ) - > sizeHint ( ) . width ( ) ) ;
mCompleter - > complete ( cr ) ; // popup it up!
if ( mCompleter - > completionCount ( ) = = 0 & & isShortcut ) {
2014-12-25 02:39:40 +00:00
RSTextEdit : : keyPressEvent ( e ) ; // Process the key if no match
2013-12-30 19:12:16 +00:00
}
mForceCompleterShowNextKeyEvent = false ;
2013-07-04 19:36:12 +00:00
}
void MimeTextEdit : : setCompleterKeyModifiers ( Qt : : KeyboardModifier modifiers )
{
2013-12-30 19:12:16 +00:00
mCompleterKeyModifiers = modifiers ;
2013-07-04 19:36:12 +00:00
}
2013-12-30 19:12:16 +00:00
2013-07-04 19:36:12 +00:00
Qt : : KeyboardModifier MimeTextEdit : : getCompleterKeyModifiers ( ) const
{
2013-12-30 19:12:16 +00:00
return mCompleterKeyModifiers ;
2013-07-04 19:36:12 +00:00
}
void MimeTextEdit : : setCompleterKey ( Qt : : Key key )
{
2013-12-30 19:12:16 +00:00
mCompleterKey = key ;
2013-07-04 19:36:12 +00:00
}
2013-12-30 19:12:16 +00:00
2013-07-04 19:36:12 +00:00
Qt : : Key MimeTextEdit : : getCompleterKey ( ) const
{
2013-12-30 19:12:16 +00:00
return mCompleterKey ;
}
void MimeTextEdit : : forceCompleterShowNextKeyEvent ( QString startString )
{
if ( ! mCompleter ) return ; //Nothing else to do if not mCompleter initialized
if ( ! mCompleter - > popup ( ) - > isVisible ( ) ) {
mForceCompleterShowNextKeyEvent = true ;
mCompleterStartString = startString ;
}
}
void MimeTextEdit : : addContextMenuAction ( QAction * action )
{
mContextMenuActions . push_back ( action ) ;
2013-07-04 19:36:12 +00:00
}
2013-12-30 19:12:16 +00:00
void MimeTextEdit : : contextMenuEvent ( QContextMenuEvent * e )
2013-07-04 19:36:12 +00:00
{
2013-12-30 19:12:16 +00:00
emit calculateContextMenuActions ( ) ;
QMenu * contextMenu = createStandardContextMenu ( e - > pos ( ) ) ;
/* Add actions for pasting links */
2015-09-03 00:27:14 +02:00
contextMenu - > addAction ( tr ( " Paste as plain text " ) , this , SLOT ( pastePlainText ( ) ) ) ;
2015-12-07 02:28:27 +01:00
QAction * spoilerAction = contextMenu - > addAction ( tr ( " Spoiler " ) , this , SLOT ( spoiler ( ) ) ) ;
spoilerAction - > setToolTip ( tr ( " Select text to hide, then push this button " ) ) ;
2013-12-30 19:12:16 +00:00
contextMenu - > addSeparator ( ) ;
2020-08-15 22:17:52 +02:00
QAction * pasteLinkAction = contextMenu - > addAction ( FilesDefs : : getIconFromQtResourcePath ( " :/images/pasterslink.png " ) , tr ( " Paste RetroShare Link " ) , this , SLOT ( pasteLink ( ) ) ) ;
contextMenu - > addAction ( FilesDefs : : getIconFromQtResourcePath ( " :/images/pasterslink.png " ) , tr ( " Paste my certificate link " ) , this , SLOT ( pasteOwnCertificateLink ( ) ) ) ;
2013-07-18 21:50:32 +00:00
2013-12-30 19:12:16 +00:00
if ( RSLinkClipboard : : empty ( ) ) {
pasteLinkAction - > setDisabled ( true ) ;
}
QList < QAction * > : : iterator it ;
for ( it = mContextMenuActions . begin ( ) ; it ! = mContextMenuActions . end ( ) ; + + it ) {
contextMenu - > addAction ( * it ) ;
}
contextMenu - > exec ( QCursor : : pos ( ) ) ;
delete ( contextMenu ) ;
}
void MimeTextEdit : : pasteLink ( )
{
insertHtml ( RSLinkClipboard : : toHtml ( ) ) ;
2013-07-04 19:36:12 +00:00
}
2013-12-30 19:12:16 +00:00
void MimeTextEdit : : pasteOwnCertificateLink ( )
{
2014-03-17 20:56:06 +00:00
RsPeerId ownId = rsPeers - > getOwnId ( ) ;
2017-07-16 13:11:47 +02:00
RetroShareLink link = RetroShareLink : : createCertificate ( ownId ) ;
2013-12-30 19:12:16 +00:00
2017-07-16 13:11:47 +02:00
if ( link . valid ( ) ) {
2013-12-30 19:12:16 +00:00
insertHtml ( link . toHtml ( ) + " " ) ;
}
2013-07-18 21:50:32 +00:00
}
2015-09-03 00:27:14 +02:00
void MimeTextEdit : : pastePlainText ( )
{
2016-01-23 18:17:49 +01:00
insertPlainText ( QApplication : : clipboard ( ) - > text ( ) . remove ( QChar ( - 4 ) ) ) ; //Char used when image on text.
2015-09-03 00:27:14 +02:00
}
2015-12-07 02:28:27 +01:00
void MimeTextEdit : : spoiler ( )
{
RsHtml : : insertSpoilerText ( this - > textCursor ( ) ) ;
}