~ubuntu-branches/ubuntu/lucid/kmess/lucid

« back to all changes in this revision

Viewing changes to src/chat/chatwindow.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Mark Purcell
  • Date: 2009-12-05 21:19:26 UTC
  • mfrom: (1.1.7 upstream) (0.1.8 sid)
  • Revision ID: james.westby@ubuntu.com-20091205211926-r26u8j38kysf6o2p
Tags: 2.0.2-1
* New upstream release 
  - Fixes friendly names (LP: #485640)
* Update Homepage: http://kmess.org
* Add Build-Depends: libphonon-dev | libqt4-phonon-dev (ubuntu friendly)
* kmess.1 fix lintian:hyphen-used-as-minus-sign

Show diffs side-by-side

added added

removed removed

Lines of Context:
34
34
#include "config-kmess.h"
35
35
#include "contactswidget.h"
36
36
#include "emoticonswidget.h"
37
 
#include "inkedit.h"
38
37
#include "winkswidget.h"
39
38
 
 
39
#include <IsfQt>
 
40
#include <IsfQtDrawing>
 
41
 
 
42
#include <QBuffer>
 
43
#include <QDir>
40
44
#include <QDockWidget>
41
45
#include <QShortcut>
42
46
#include <QTextDocumentFragment>
86
90
  setCentralWidget( mainWidget );
87
91
 
88
92
#if KMESS_ENABLE_INK == 0
89
 
  // Only enable the Ink button if GIFLib is available
 
93
  // Only enable the Ink button if Ink sending support is available
90
94
  inkButton_->hide();
91
 
  inkEdit_->setEnabled( false );
 
95
  inkCanvas_->setEnabled( false );
92
96
#endif
93
97
 
94
98
  // Connect the UI signals
98
102
           this,                     SLOT  ( slotNewLineButtonClicked() ) );
99
103
  connect( messageEdit_,             SIGNAL(              textChanged() ),
100
104
           this,                     SLOT  (       slotMessageChanged() ) );
101
 
  connect( inkEdit_,                 SIGNAL(               inkChanged() ),
 
105
  connect( inkCanvas_,               SIGNAL(               inkChanged() ),
102
106
           this,                     SLOT  (       slotMessageChanged() ) );
103
107
  connect( textButton_,              SIGNAL(                  clicked() ),
104
108
           this,                     SLOT  (         slotSwitchEditor() ) );
110
114
           this,                     SLOT  (         slotSwitchEditor() ) );
111
115
  connect( customEmoticonButton_,    SIGNAL(                  clicked() ),
112
116
           this,                     SLOT  (         slotSwitchEditor() ) );
 
117
  connect( fontButton_,              SIGNAL(                  clicked() ),
 
118
           this,                     SLOT  (                 editFont() ) );
 
119
  connect( fontColorButton_,         SIGNAL(                  clicked() ),
 
120
           this,                     SLOT  (            editFontColor() ) );
113
121
 
114
122
  // Create the contacts dock
115
123
  contactsDock_ = new QDockWidget( i18n( "Contacts" ), this );
142
150
 
143
151
  //Install the event filters to catch events
144
152
  installEventFilter( this );
145
 
  inkEdit_    ->installEventFilter( this );
 
153
  inkCanvas_  ->installEventFilter( this );
146
154
  messageEdit_->installEventFilter( this );
147
155
  winksWidget_->installEventFilter( this );
148
156
  messageEdit_->viewport()->installEventFilter( this );
153
161
  inkButton_             ->setIcon( KIcon( "draw-brush" ) );
154
162
  winksButton_           ->setIcon( KIcon( "applications-toys" ) );
155
163
  textButton_            ->setIcon( KIcon( "draw-text" ) );
 
164
  fontButton_            ->setIcon( KIcon( "preferences-desktop-font" ) );
 
165
  fontColorButton_       ->setIcon( KIcon( "format-stroke-color" ) );
 
166
 
 
167
  // Set up the buttons for setting ink colour/stroke size/etc.
 
168
  inkCanvas_->setPenSize( inkPenSize_->value() );
 
169
 
 
170
  inkColorButton_->setIcon( KIcon( "format-stroke-color" ) );
 
171
  inkEraseButton_->setIcon( KIcon( "draw-eraser"         ) );
 
172
  inkClearButton_->setIcon( KIcon( "edit-clear"          ) );
 
173
 
 
174
  connect( inkColorButton_,        SIGNAL(            clicked()    ),
 
175
           this,                   SLOT  ( slotChangeInkColor()    ) );
 
176
  connect( inkEraseButton_,        SIGNAL(            clicked()    ),
 
177
           this,                   SLOT  ( slotChangeInkBrush()    ) );
 
178
  connect( inkClearButton_,        SIGNAL(            clicked()    ),
 
179
           inkCanvas_,             SLOT  (              clear()    ) );
 
180
  connect( inkPenSize_,            SIGNAL(       valueChanged(int) ),
 
181
           inkCanvas_,             SLOT  (         setPenSize(int) ) );
156
182
 
157
183
  // Connect the message edit so that if its displayed color changes,
158
184
  // it's checked to match the user's chosen color.
205
231
  statusTimer_.setSingleShot( true );
206
232
  connect( &statusTimer_,  SIGNAL(           timeout() ),
207
233
           this,           SLOT  ( showStatusMessage() ) );
 
234
 
 
235
  inkCtlFrame_->setVisible( false );
208
236
}
209
237
 
210
238
 
333
361
// The chat window is closing
334
362
bool ChatWindow::closeAllTabs()
335
363
{
336
 
  // Do not ask if there only is one tab, or if the user has
337
 
  // explicitly requested all the tabs to be closed
338
 
  if( chatTabs_->count() > 1 && sender() != closeAllAction_ )
 
364
  // Ask the user for confirmation
 
365
  if( chatTabs_->count() > 1       // Do not ask if there only is one tab
 
366
  &&  sender() != closeAllAction_  // Do not ask if the user chose the "close all tabs" action
 
367
  &&  ! kapp->sessionSaving() )    // Do not ask if the KDE session is closing
339
368
  {
340
369
    int res = KMessageBox::questionYesNoCancel( this,
341
 
                                                i18n( "<html>There are multiple tabs open in this chat window. Do you want to close the "
342
 
                                                "current tab only, or all tabs?<br /><br />"
343
 
                                                "<i>Note: You can close all tabs at once by pressing Alt+F4.</i></html>" ),
344
 
                                                i18nc( "Dialog box caption: closing a chatwindow with a single tab", "Closing a Chat Tab" ),
 
370
                                                i18n( "<html>There are multiple tabs open in this chat window. "
 
371
                                                      "Do you want to close the current tab only, or all tabs?<br /><br />"
 
372
                                                      "<i>Note: You can close all tabs at once by pressing Alt+F4.</i></html>" ),
 
373
                                                i18nc( "Dialog box caption: closing a chatwindow with a single tab",
 
374
                                                       "Closing a Chat Tab" ),
345
375
                                                KGuiItem( i18n( "Close All Tabs" ), "window-close" ), // Yes option
346
376
                                                KGuiItem( i18n( "Close Current Tab" ), "tab-close" ), // No option
347
377
                                                KStandardGuiItem::cancel(),
461
491
 
462
492
  // Enable some default action shortcuts (preserve the original ones where needed)
463
493
  nudgeAction_->setShortcut( QKeySequence( "Alt+Z" ) );
464
 
  closeAction->setShortcuts( QList<QKeySequence>() << QKeySequence( "Ctrl+W" ) << QKeySequence( "Esc" ) << closeAction->shortcut()  );
 
494
  closeAction->setShortcuts( QList<QKeySequence>() << QKeySequence( "Ctrl+W" ) << closeAction->shortcut()  );
465
495
  closeAllAction_->setShortcuts( QList<QKeySequence>() << QKeySequence( "Ctrl+Q" ) << closeAllAction_->shortcut()  );
466
496
  prevTabAction_->setShortcuts( QList<QKeySequence>() << QKeySequence( QKeySequence::PreviousChild ) << prevTabAction_->shortcut() );
467
497
  nextTabAction_->setShortcuts( QList<QKeySequence>() << QKeySequence( QKeySequence::NextChild ) << nextTabAction_->shortcut() );
505
535
 
506
536
  // Connect slots to signals for "Chat" menu
507
537
  connect( inviteButton_,       SIGNAL(           triggered(bool) ),
508
 
           this,                SLOT  (       slotInviteContact() ) );
 
538
           this,                SLOT  (   slotInviteContact()     ) );
509
539
  connect( sendAction_,         SIGNAL(           triggered(bool) ),
510
540
           this,                SLOT  (   startFileTransfer()     ) );
511
541
  connect( nudgeAction_,        SIGNAL(           triggered(bool) ),
660
690
    messageEdit_->setTextColor( QColor( currentAccount_->getFontColor() ) );
661
691
    messageEdit_->setFont( QFont ( currentAccount_->getFont() ) );
662
692
  }
 
693
 
 
694
  // Adjust the message editor's minimum height to match the current font size
 
695
  QFontMetrics metrics( messageEdit_->currentFont() );
 
696
  messageEdit_->setMinimumSize( 100, metrics.height() + metrics.lineSpacing() );
663
697
}
664
698
 
665
699
 
692
726
    {
693
727
      messageEdit_->setFocus();
694
728
    }
695
 
    else if( inkEdit_->isVisible() )
 
729
    else if( inkCanvas_->isVisible() )
696
730
    {
697
 
      inkEdit_->inkFrame_->setFocus();
 
731
      inkCanvas_->setFocus();
698
732
    }
699
733
 
700
734
    return false;
701
735
  }
702
 
 
 
736
  
 
737
  if ( event->type() == QEvent::KeyPress )
 
738
  {
 
739
    QKeyEvent *keyEvent = static_cast<QKeyEvent*>( event );
 
740
    if ( keyEvent->key() == Qt::Key_Escape )
 
741
    {
 
742
      closeWidgetOrTab();
 
743
      return true;
 
744
    }
 
745
  }
 
746
  
703
747
  // Only manage events for the editors from now on (the event filter code
704
748
  // is complex enough as it is now...)
705
 
  if( obj != messageEdit_ && obj != messageEdit_->viewport()
706
 
  &&  obj != inkEdit_
 
749
  if( obj != messageEdit_
 
750
  &&  obj != messageEdit_->viewport()
 
751
  &&  obj != inkCanvas_
707
752
  &&  obj != winksWidget_
708
753
  &&  obj != standardEmoticonsWidget_
709
754
  &&  obj != customEmoticonsWidget_ )
738
783
        keyEvent->ignore();
739
784
        return true;
740
785
      }
741
 
      // Detect scrolling commands. Shift scrolls faster
742
 
      else if( key == Qt::Key_PageUp || key == Qt::Key_PageDown )
 
786
      // Detect scrolling commands. Alt scrolls faster (shift is used for text selection in the editor)
 
787
      else if( ( key == Qt::Key_PageUp || key == Qt::Key_PageDown ) && ( ! shift ) )
743
788
      {
744
 
        getCurrentChat()->scrollTo( ( key == Qt::Key_PageDown ), shift );
 
789
        getCurrentChat()->scrollTo( ( key == Qt::Key_PageDown ), alt );
 
790
        return true;
745
791
      }
746
792
      else if( alt )
747
793
      {
848
894
      {
849
895
        messageEdit_->setFocus();
850
896
      }
851
 
      else if( inkEdit_->isVisible() )
 
897
      else if( inkCanvas_->isVisible() )
852
898
      {
853
 
        inkEdit_->inkFrame_->setFocus();
 
899
        inkCanvas_->setFocus();
854
900
      }
855
901
      break;
856
902
 
857
903
    case QEvent::FocusOut:
858
904
    case QEvent::Show:
 
905
    {
 
906
      QWidget *focusedWidget = QApplication::focusWidget();
 
907
 
 
908
      // Allow this chat's search bar to take focus away from the message editor
 
909
      if( focusedWidget && QString( focusedWidget->metaObject()->className() ) == "KHistoryComboBox" )
859
910
      {
860
 
        QWidget *focusedWidget = QApplication::focusWidget();
861
 
 
862
 
        // Allow this chat's search bar to take focus away from the message editor
863
 
        if( focusedWidget && QString( focusedWidget->metaObject()->className() ) == "KHistoryComboBox" )
864
 
        {
865
 
          break;
866
 
        }
867
 
 
868
 
        messageEdit_->setFocus( Qt::OtherFocusReason );
 
911
        break;
869
912
      }
 
913
 
 
914
      messageEdit_->setFocus( Qt::OtherFocusReason );
870
915
      break;
 
916
    }
871
917
 
872
918
    case QEvent::DragEnter:
873
 
      {
874
 
        QDragEnterEvent *dragEvent = static_cast<QDragEnterEvent*>( event );
875
 
 
876
 
        if( ! dragEvent || ! dragEvent->mimeData()->hasUrls() )
877
 
        {
878
 
#ifdef KMESSDEBUG_CHATWINDOW
879
 
          kDebug() << "Ignoring invalid drop";
880
 
#endif
881
 
          break;
882
 
        }
883
 
 
 
919
    case QEvent::DragMove:
 
920
    {
 
921
      QDragEnterEvent *dragEvent = static_cast<QDragEnterEvent*>( event );
 
922
 
 
923
      if( ! dragEvent )
 
924
      {
 
925
#ifdef KMESSDEBUG_CHATWINDOW
 
926
        kDebug() << "Ignoring invalid drag event!";
 
927
#endif
 
928
        return false;
 
929
      }
 
930
 
 
931
      const QMimeData *mimeData = dragEvent->mimeData();
 
932
      if( mimeData->hasUrls()
 
933
      ||  mimeData->hasImage() )
 
934
      {
 
935
#ifdef KMESSDEBUG_CHATWINDOW
 
936
        kDebug() << "Accepting drag event of mimetypes:" << dragEvent->mimeData()->formats();
 
937
#endif
884
938
        dragEvent->acceptProposedAction();
 
939
        return true;
885
940
      }
 
941
 
 
942
#ifdef KMESSDEBUG_CHATWINDOW
 
943
      kDebug() << "Ignoring invalid drop having mimetypes:" << dragEvent->mimeData()->formats();
 
944
#endif
 
945
 
886
946
      break;
 
947
    }
887
948
 
888
949
    case QEvent::Drop:
 
950
    {
 
951
      QDropEvent *dropEvent = static_cast<QDropEvent*>( event );
 
952
 
 
953
      // Process the drop only if it comes from out of our application.
 
954
      if( ! dropEvent || dropEvent->source() != 0 )
889
955
      {
890
 
        QDropEvent *dropEvent = static_cast<QDropEvent*>( event );
891
 
 
892
 
        // Process the drop only if it contains file URLs and comes from out of our application.
893
 
        if( ! dropEvent || ! dropEvent->mimeData()->hasUrls() || dropEvent->source() != 0 )
894
 
        {
895
956
#ifdef KMESSDEBUG_CHATWINDOW
896
 
          kDebug() << "Ignoring invalid drop";
 
957
        kDebug() << "Ignoring invalid drop!";
897
958
#endif
898
 
          break;
899
 
        }
 
959
        break;
 
960
      }
900
961
 
 
962
      const QMimeData *mimeData = dropEvent->mimeData();
 
963
      if( mimeData->hasUrls() )
 
964
      {
901
965
#ifdef KMESSDEBUG_CHATWINDOW
902
 
        kDebug() << "Drag'n'dropped files:" << dropEvent->mimeData()->urls();
 
966
        kDebug() << "Drag'n'dropped files:" << mimeData->urls();
903
967
#endif
904
968
 
905
969
        // Send the files to the contact
906
 
        getCurrentChat()->startFileTransfer( dropEvent->mimeData()->urls() );
907
 
 
908
 
        dropEvent->acceptProposedAction();
909
 
        return true;
910
 
      }
 
970
        getCurrentChat()->startFileTransfer( mimeData->urls() );
 
971
 
 
972
        dropEvent->acceptProposedAction();
 
973
        return true;
 
974
      }
 
975
 
 
976
      if( mimeData->hasImage() )
 
977
      {
 
978
        QImage image( qvariant_cast<QImage>( mimeData->imageData() ) );
 
979
 
 
980
        if( image.isNull() )
 
981
        {
 
982
#ifdef KMESSDEBUG_CHATVIEW
 
983
          kDebug() << "Drag'n'dropped an invalid image!";
 
984
#endif
 
985
          return true;
 
986
        }
 
987
 
 
988
#ifdef KMESSDEBUG_CHATWINDOW
 
989
        kDebug() << "Drag'n'dropped a" << image.size() << "image";
 
990
#endif
 
991
 
 
992
        // Create a temporary file where the image will be stored.
 
993
        // TODO: The file is not destroyed, as it needs to be kept
 
994
        // available until the transfer is completed. Find a way
 
995
        // to remove it when KMess quits or as soon as the transfer
 
996
        // is done.
 
997
        QTemporaryFile file;
 
998
        file.setAutoRemove( false );
 
999
        file.setFileTemplate( QDir::tempPath() + "/kmess.XXXXXX.jpg" );
 
1000
 
 
1001
        if( ! file.open() )
 
1002
        {
 
1003
#ifdef KMESSDEBUG_CHATWINDOW
 
1004
          kDebug() << "Cannot create temporary image file!";
 
1005
#endif
 
1006
          return true;
 
1007
        }
 
1008
 
 
1009
        dropEvent->acceptProposedAction();
 
1010
 
 
1011
        // Save the image and get its local URL
 
1012
        image.save( &file, "JPG" );
 
1013
        file.close();
 
1014
        QUrl imageUrl( "file://" + file.fileName() );
 
1015
 
 
1016
        // Send the image to the contact
 
1017
        QList<QUrl> urlList;
 
1018
        urlList.append( imageUrl );
 
1019
        getCurrentChat()->startFileTransfer( urlList );
 
1020
 
 
1021
        return true;
 
1022
      }
 
1023
 
911
1024
      break;
 
1025
    }
912
1026
 
913
1027
    default:
914
1028
      break;
1325
1439
// Send a ink via server
1326
1440
void ChatWindow::sendInk()
1327
1441
{
1328
 
  // Get the image bytes and send them
1329
 
  const QByteArray& ink( inkEdit_->getImageBytes() );
1330
 
 
1331
 
  getCurrentChat()->sendInkMessage( ink );
1332
 
 
1333
 
  // Clear and reset the state of send button
1334
 
  inkEdit_->clearImage();
 
1442
  bool supportGifInk = true;
 
1443
  bool supportIsfInk = true;
 
1444
 
 
1445
  // Find out which ink formats are supported by all participants
 
1446
  const QStringList &participants( getCurrentChat()->getParticipants() );
 
1447
  foreach( const QString &handle, participants )
 
1448
  {
 
1449
    const ContactBase *contact = currentAccount_->getContactByHandle( handle );
 
1450
    if( contact == 0 )
 
1451
    {
 
1452
      continue;
 
1453
    }
 
1454
 
 
1455
    supportGifInk &= contact->hasCapability( ContactBase::MSN_CAP_INK_GIF );
 
1456
    supportIsfInk &= contact->hasCapability( ContactBase::MSN_CAP_INK_ISF );
 
1457
  }
 
1458
 
 
1459
  // The contacts don't support either formats! Something is wrong, since the ink editor
 
1460
  // was enabled...
 
1461
  if( ! supportGifInk && ! supportIsfInk )
 
1462
  {
 
1463
    kWarning() << "Neither Ink formats are supported by the participants!";
 
1464
 
 
1465
    getCurrentChat()->showMessage( ChatMessage( ChatMessage::TYPE_SYSTEM,
 
1466
                                                ChatMessage::CONTENT_SYSTEM_ERROR,
 
1467
                                                true,
 
1468
                                                i18nc( "Error message shown in chat",
 
1469
                                                       "Failed to send the handwritten message: "
 
1470
                                                       "the contacts do not support it." ),
 
1471
                                                QString(),
 
1472
                                                QString() ) );
 
1473
    return;
 
1474
  }
 
1475
 
 
1476
  InkFormat format;
 
1477
  QByteArray ink;
 
1478
 
 
1479
  if( supportIsfInk )
 
1480
  {
 
1481
#ifdef KMESSDEBUG_CHATWINDOW
 
1482
    kDebug() << "Retrieving ISF ink data";
 
1483
#endif
 
1484
 
 
1485
    format = FORMAT_ISF;
 
1486
    ink = Isf::Stream::writer( *( inkCanvas_->drawing() ) );
 
1487
  }
 
1488
  else if( supportGifInk )
 
1489
  {
 
1490
#ifdef KMESSDEBUG_CHATWINDOW
 
1491
    kDebug() << "Retrieving GIF ink data";
 
1492
#endif
 
1493
 
 
1494
    format = FORMAT_GIF;
 
1495
    ink = Isf::Stream::writerGif( *( inkCanvas_->drawing() ) );
 
1496
  }
 
1497
  // Any other possibility has been excluded above
 
1498
 
 
1499
  if( ink.isEmpty() )
 
1500
  {
 
1501
    kWarning() << "An error occured while creating the" << ( supportIsfInk ? "ISF" : "GIF" ) << "Ink data!";
 
1502
 
 
1503
    getCurrentChat()->showMessage( ChatMessage( ChatMessage::TYPE_SYSTEM,
 
1504
                                                ChatMessage::CONTENT_SYSTEM_ERROR,
 
1505
                                                true,
 
1506
                                                i18nc( "Error message shown in chat",
 
1507
                                                       "Failed to send the handwritten message: "
 
1508
                                                       "an error has occurred while creating it." ),
 
1509
                                                QString(),
 
1510
                                                QString() ) );
 
1511
    return;
 
1512
  }
 
1513
 
 
1514
  getCurrentChat()->sendInkMessage( format, ink );
 
1515
 
 
1516
  // Get the pixels, to show the ink in chat
 
1517
  QImage image( inkCanvas_->image() );
 
1518
 
 
1519
  // Save it as a PNG image, which KHTML will be able to show
 
1520
  QBuffer buffer;
 
1521
  buffer.open( QIODevice::WriteOnly );
 
1522
  image.save( &buffer, "PNG" );
 
1523
  buffer.close();
 
1524
 
 
1525
  // Show the message in the browser window
 
1526
  const QString& text( "<img src='data:image/png;base64," + buffer.data().toBase64() + "'>" );
 
1527
 
 
1528
  ChatMessage message( ChatMessage::TYPE_OUTGOING,
 
1529
                       ChatMessage::CONTENT_MESSAGE_INK,
 
1530
                       false,
 
1531
                       text,
 
1532
                       currentAccount_->getHandle(),
 
1533
                       currentAccount_->getFriendlyName( STRING_ORIGINAL ),
 
1534
                       currentAccount_->getPicturePath() );
 
1535
 
 
1536
  getCurrentChat()->showMessage( message );
 
1537
 
 
1538
  // Clear and reset the state of the send button
 
1539
  inkCanvas_->clear();
1335
1540
  sendButton_->setEnabled( false );
1336
 
 
1337
 
  // Show the message in the browser window
1338
 
  const QString& text( "<img src='data:image/gif;base64," + ink.toBase64() + "'>" );
1339
 
 
1340
 
  ChatMessage message( ChatMessage::TYPE_OUTGOING,
1341
 
                       ChatMessage::CONTENT_MESSAGE_INK,
1342
 
                       false,
1343
 
                       text,
1344
 
                       currentAccount_->getHandle(),
1345
 
                       currentAccount_->getFriendlyName( STRING_ORIGINAL ),
1346
 
                       currentAccount_->getPicturePath());
1347
 
 
1348
 
  getCurrentChat()->showMessage(message);
1349
1541
}
1350
1542
 
1351
1543
 
1370
1562
  // Messages like "//hello" should be sent as "/hello"
1371
1563
  // Messages like "/hello" are commands.
1372
1564
  // Check if this is a command, and if so, emit handleCommand signal
1373
 
  if( text.left( 2 ) == "//" )
1374
 
  {
1375
 
    text = text.mid( 1 );
1376
 
  }
1377
 
  else if( text.left( 1 ) == "/" )
1378
 
  {
1379
 
    const QString& command( text.mid( 1 ) );
 
1565
  if( text.size() > 2 && text.mid( 2, 1 ) != "/" )
 
1566
  {
 
1567
    if( text.left( 2 ) == "//" )
 
1568
    {
 
1569
      text = text.mid( 1 );
 
1570
    }
 
1571
    else if( text.left( 1 ) == "/" )
 
1572
    {
 
1573
      const QString& command( text.mid( 1 ) );
1380
1574
 
1381
 
    // Handle command. If 'false' is returned, send it anyway.
1382
 
    if ( handleCommand( command ) )
1383
 
    {
1384
 
      return;
 
1575
      // Handle command. If 'false' is returned, send it anyway.
 
1576
      if ( handleCommand( command ) )
 
1577
      {
 
1578
        return;
 
1579
      }
1385
1580
    }
1386
1581
  }
1387
1582
 
1503
1698
  customEmoticonsDock_    ->setEnabled( isEnabled );
1504
1699
  standardEmoticonsDock_  ->setEnabled( isEnabled );
1505
1700
 
1506
 
  inkEdit_                ->setEnabled( isEnabled );
 
1701
  inkCanvas_              ->setEnabled( isEnabled );
1507
1702
  messageEdit_            ->setEnabled( isEnabled );
1508
1703
  newLineButton_          ->setEnabled( isEnabled );
1509
1704
  sendButton_             ->setEnabled( isEnabled );
1510
1705
  standardEmoticonButton_ ->setEnabled( isEnabled );
1511
1706
  customEmoticonButton_   ->setEnabled( isEnabled );
 
1707
  fontButton_             ->setEnabled( isEnabled );
 
1708
  fontColorButton_        ->setEnabled( isEnabled );
1512
1709
  inviteButton_           ->setEnabled( isEnabled );
1513
1710
  textButton_             ->setEnabled( isEnabled );
1514
1711
 
1691
1888
 
1692
1889
 
1693
1890
 
 
1891
 
 
1892
// Change color for current pen
 
1893
void ChatWindow::slotChangeInkColor()
 
1894
{
 
1895
  QColor color;
 
1896
  if ( KColorDialog::getColor( color ) == QDialog::Accepted )
 
1897
  {
 
1898
    inkCanvas_->setPenColor( color );
 
1899
  }
 
1900
}
 
1901
 
 
1902
 
 
1903
 
 
1904
// Erase brush was selected
 
1905
void ChatWindow::slotChangeInkBrush()
 
1906
{
 
1907
  if( inkCanvas_->penType() == Isf::InkCanvas::DrawingPen )
 
1908
  {
 
1909
    inkCanvas_->setPenType( Isf::InkCanvas::EraserPen );
 
1910
    inkEraseButton_->setIcon( KIcon( "draw-freehand" ) );
 
1911
    inkEraseButton_->setToolTip( i18n( "Drawing brush" ) );
 
1912
  }
 
1913
  else
 
1914
  {
 
1915
    inkCanvas_->setPenType( Isf::InkCanvas::DrawingPen );
 
1916
    inkEraseButton_->setIcon( KIcon( "draw-eraser" ) );
 
1917
    inkEraseButton_->setToolTip( i18n( "Erase brush" ) );
 
1918
  }
 
1919
}
 
1920
 
 
1921
 
 
1922
 
1694
1923
// Make the caption blink if the window still doesn't have focus
1695
1924
void ChatWindow::slotBlinkCaption()
1696
1925
{
1937
2166
  // The ink drawing was changed
1938
2167
  else
1939
2168
  {
1940
 
    disable = ( inkEdit_->isEmpty() );
 
2169
    disable = ( inkCanvas_->isEmpty() );
1941
2170
  }
1942
2171
 
1943
2172
  // Something has been typed, enable the button so the user can send the message
1994
2223
  if( inkButton_->isChecked() )
1995
2224
  {
1996
2225
    sendInk();
1997
 
    inkEdit_->inkFrame_->setFocus();
 
2226
    inkCanvas_->setFocus();
1998
2227
  }
1999
2228
  else if( winksButton_->isChecked() )
2000
2229
  {
2024
2253
  kDebug() << "Switching editors: caller:" << caller;
2025
2254
#endif
2026
2255
 
 
2256
  // Some widgets are pretty high, hide them unless they're needed
 
2257
  standardEmoticonsWidget_->hide();
 
2258
  customEmoticonsWidget_->hide();
 
2259
  winksWidget_->hide();
 
2260
 
 
2261
  // Show the text control frame by default
 
2262
  inkCtlFrame_->setVisible( false );
 
2263
  textCtlFrame_->setVisible( true );
 
2264
 
2027
2265
  // Called by the winks button, show the available winks
2028
2266
  if( caller == winksButton_ && winksButton_->isChecked() )
2029
2267
  {
2031
2269
    kDebug() << "Switching to winks list.";
2032
2270
#endif
2033
2271
    winksWidget_->refresh();
 
2272
    winksWidget_->show();
 
2273
 
2034
2274
    editorChooser_->setCurrentWidget( winksPage_ );
 
2275
 
2035
2276
    winksButton_->setChecked( true );
2036
2277
    inkButton_->setChecked( false );
2037
2278
    standardEmoticonButton_->setChecked( false );
2053
2294
    customEmoticonButton_->setChecked( false );
2054
2295
    textButton_->setChecked( false );
2055
2296
 
2056
 
    disableSendButton = ( inkEdit_->isEmpty() );
 
2297
    inkCtlFrame_->setVisible( true );
 
2298
    textCtlFrame_->setVisible( false );
 
2299
 
 
2300
    disableSendButton = ( inkCanvas_->isEmpty() );
2057
2301
  }
2058
2302
  // Called by the standard emoticon button
2059
2303
  else if( caller == standardEmoticonButton_
2062
2306
#ifdef KMESSDEBUG_CHATWINDOW
2063
2307
    kDebug() << "Switching to standard emoticons widget.";
2064
2308
#endif
 
2309
    standardEmoticonsWidget_->show();
 
2310
 
2065
2311
    editorChooser_->setCurrentWidget( stdEmoPage_ );
 
2312
 
2066
2313
    winksButton_->setChecked( false );
2067
2314
    inkButton_->setChecked( false );
2068
2315
    standardEmoticonButton_->setChecked( true );
2076
2323
#ifdef KMESSDEBUG_CHATWINDOW
2077
2324
    kDebug() << "Switching to custom emoticons widget.";
2078
2325
#endif
 
2326
    customEmoticonsWidget_->show();
 
2327
 
2079
2328
    editorChooser_->setCurrentWidget( cusEmoPage_ );
 
2329
 
2080
2330
    winksButton_->setChecked( false );
2081
2331
    inkButton_->setChecked( false );
2082
2332
    standardEmoticonButton_->setChecked( false );
2187
2437
    messageEdit_->setDocument( new QTextDocument( messageEdit_ ) );
2188
2438
    updateModeButtons();
2189
2439
    updateEditorFont();
2190
 
    inkEdit_->setImage( 0 );
2191
2440
    return;
2192
2441
  }
2193
2442
 
2217
2466
  // Display the new chat contents in the UI. Block the signals to avoid the editors
2218
2467
  // from firing the "message changed" signal, which sends a typing message.
2219
2468
  messageEdit_ ->blockSignals( true );
2220
 
  inkEdit_     ->blockSignals( true );
 
2469
  inkCanvas_   ->blockSignals( true );
2221
2470
  contactsDock_->setWidget( chat->getContactsWidget() );
2222
2471
  messageEdit_ ->setDocument( chat->getMessageEditContents() );
2223
 
  inkEdit_     ->setImage( chat->getInkEditContents() );
 
2472
  inkCanvas_   ->setDrawing( chat->getInkDrawing() );
2224
2473
  messageEdit_ ->blockSignals( false );
2225
 
  inkEdit_     ->blockSignals( false );
 
2474
  inkCanvas_   ->blockSignals( false );
2226
2475
 
2227
2476
  // Reset quick re-type index
2228
2477
  indexSentences_ = chat->getQuickRetypeList().size();
2435
2684
    return;
2436
2685
  }
2437
2686
 
2438
 
#if KMESS_ENABLE_INK == 1
2439
2687
  bool enableInkButton   = true;
2440
 
#else
2441
 
  bool enableInkButton   = false;
2442
 
#endif
2443
 
 
2444
2688
  bool enableWinksButton = true;
2445
2689
 
 
2690
#if KMESS_ENABLE_INK == 0
 
2691
  enableInkButton = false;
 
2692
#endif
 
2693
 
2446
2694
  const QStringList &participants( getCurrentChat()->getParticipants() );
2447
2695
  foreach( const QString &handle, participants )
2448
2696
  {
2455
2703
#if KMESS_ENABLE_INK == 1
2456
2704
    if( enableInkButton )
2457
2705
    {
2458
 
      // Disable the Ink button if the contact doesn't support GIF Ink
2459
 
      if( ! contact->hasCapability( ContactBase::MSN_CAP_INK_GIF ) )
2460
 
      {
2461
 
        enableInkButton = false;
2462
 
      }
2463
 
 
2464
 
      // TODO Fix sending Ink to WLM 8.5 and 2009 (probably by implementing ISF support)
2465
 
      // Disable the Ink button also if we're chatting with an ISF-enabled WLM8.5 / WLM2009
2466
 
      if( ( contact->getClientName() == "Windows Live Messenger 8.5"
2467
 
         || contact->getClientName() == "Windows Live Messenger 2009" )
2468
 
      &&  contact->hasCapability( ContactBase::MSN_CAP_INK_ISF ) )
 
2706
      // Disable the Ink button if the contact doesn't support Ink
 
2707
      if( ! contact->hasCapability( ContactBase::MSN_CAP_INK_GIF )
 
2708
      &&  ! contact->hasCapability( ContactBase::MSN_CAP_INK_ISF ) )
2469
2709
      {
2470
2710
        enableInkButton = false;
2471
2711
      }
2491
2731
  // Set a tooltip or a status bar message to either buttons.
2492
2732
  // The tooltip covers the status message otherwise.
2493
2733
 
2494
 
#if KMESS_ENABLE_INK == 1 // else, the ink button isn't showed anyway
 
2734
#if KMESS_ENABLE_INK == 1 // else, the ink button isn't shown anyway
2495
2735
  if( enableInkButton )
2496
2736
  {
2497
2737
    inkButton_->setToolTip  ( i18n( "Handwriting mode" ) );
2503
2743
    if( getCurrentChat()->getParticipants().count() > 1 )
2504
2744
    {
2505
2745
      inkButton_->setStatusTip( i18nc( "Label text",
2506
 
                                       "Handwriting is disabled: KMess cannot send drawings to "
2507
 
                                       "some of the contacts." ) );
 
2746
                                       "Handwriting is disabled: some of the contacts do not "
 
2747
                                       "support receiving handwritten messages." ) );
2508
2748
    }
2509
2749
    else
2510
2750
    {
2511
2751
      inkButton_->setStatusTip( i18nc( "Label text",
2512
 
                                       "Handwriting is disabled: KMess cannot send drawings to "
2513
 
                                       "this contact." ) );
 
2752
                                       "Handwriting is disabled: this contact does not "
 
2753
                                       "support receiving handwritten messages." ) );
2514
2754
    }
2515
2755
  }
2516
2756
#endif
2526
2766
    if( getCurrentChat()->getParticipants().count() > 1 )
2527
2767
    {
2528
2768
      winksButton_->setStatusTip( i18nc( "Label text",
2529
 
                                       "Winks are disabled: KMess cannot send winks to "
2530
 
                                       "some of the contacts." ) );
 
2769
                                       "Winks are disabled: some of the contacts do not "
 
2770
                                       "support receiving winks." ) );
2531
2771
    }
2532
2772
    else
2533
2773
    {
2534
2774
      winksButton_->setStatusTip( i18nc( "Label text",
2535
 
                                       "Winks are disabled: KMess cannot send winks to "
2536
 
                                       "this contact." ) );
 
2775
                                       "Winks are disabled: this contact does not "
 
2776
                                       "support receiving winks." ) );
2537
2777
    }
2538
2778
  }
2539
2779
}