00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <QFont>
00022 #include <QPixmap>
00023
00024 #include <kaction.h>
00025 #include <kactioncollection.h>
00026 #include <kcolordialog.h>
00027 #include <kdebug.h>
00028 #include <kfontaction.h>
00029 #include <kfontsizeaction.h>
00030 #include <kicon.h>
00031 #include <klocale.h>
00032 #include <kmenu.h>
00033 #include <kstandardaction.h>
00034 #include <ktoggleaction.h>
00035 #include <kurl.h>
00036
00037 #include "knoteedit.h"
00038
00039 static const short SEP = 5;
00040 static const short ICON_SIZE = 10;
00041
00042
00043 KNoteEdit::KNoteEdit( KActionCollection *actions, QWidget *parent )
00044 : KTextEdit( parent ), m_editMenu( 0 )
00045 {
00046 setAcceptDrops( true );
00047 setWordWrapMode( QTextOption::WordWrap );
00048 setLineWrapMode( WidgetWidth );
00049 setAutoFormatting( AutoAll );
00050
00051
00052 QAction * undo = KStandardAction::undo( this, SLOT( undo() ), actions );
00053 QAction * redo = KStandardAction::redo( this, SLOT( redo() ), actions );
00054 undo->setEnabled( document()->isUndoAvailable() );
00055 redo->setEnabled( document()->isRedoAvailable() );
00056
00057 m_cut = KStandardAction::cut( this, SLOT( cut() ), actions );
00058 m_copy = KStandardAction::copy( this, SLOT( copy() ), actions );
00059 m_paste = KStandardAction::paste( this, SLOT( paste() ), actions );
00060
00061 m_cut->setEnabled( false );
00062 m_copy->setEnabled( false );
00063 m_paste->setEnabled( true );
00064
00065 connect( this, SIGNAL( undoAvailable( bool ) ),
00066 undo, SLOT( setEnabled( bool ) ) );
00067 connect( this, SIGNAL( redoAvailable( bool ) ),
00068 redo, SLOT( setEnabled( bool ) ) );
00069
00070 connect( this, SIGNAL( copyAvailable( bool ) ),
00071 m_cut, SLOT( setEnabled( bool ) ) );
00072 connect( this, SIGNAL( copyAvailable( bool ) ),
00073 m_copy, SLOT( setEnabled( bool ) ) );
00074
00075 KStandardAction::clear( this, SLOT( clear() ), actions );
00076 KStandardAction::selectAll( this, SLOT( selectAll() ), actions );
00077
00078
00079 m_textBold = new KToggleAction( KIcon( "format-text-bold" ), i18n( "Bold" ),
00080 this );
00081 actions->addAction( "format_bold", m_textBold );
00082 m_textBold->setShortcut( QKeySequence( Qt::CTRL + Qt::Key_B ) );
00083 m_textItalic = new KToggleAction( KIcon( "format-text-italic" ),
00084 i18n( "Italic" ), this );
00085 actions->addAction( "format_italic", m_textItalic );
00086 m_textItalic->setShortcut( QKeySequence( Qt::CTRL + Qt::Key_I ) );
00087 m_textUnderline = new KToggleAction( KIcon( "format-text-underline" ),
00088 i18n( "Underline" ), this );
00089 actions->addAction( "format_underline", m_textUnderline );
00090 m_textUnderline->setShortcut( QKeySequence( Qt::CTRL + Qt::Key_U ) );
00091 m_textStrikeOut = new KToggleAction( KIcon( "format-text-strikethrough" ),
00092 i18n( "Strike Out" ), this );
00093 actions->addAction( "format_strikeout", m_textStrikeOut );
00094 m_textStrikeOut->setShortcut( QKeySequence( Qt::CTRL + Qt::Key_S ) );
00095
00096 connect( m_textBold, SIGNAL( toggled( bool ) ), SLOT( textBold( bool ) ) );
00097 connect( m_textItalic, SIGNAL( toggled( bool ) ),
00098 SLOT( setFontItalic( bool ) ) );
00099 connect( m_textUnderline, SIGNAL( toggled( bool ) ),
00100 SLOT( setFontUnderline( bool ) ) );
00101 connect( m_textStrikeOut, SIGNAL( toggled( bool ) ),
00102 SLOT( textStrikeOut( bool ) ) );
00103
00104 m_textAlignLeft = new KToggleAction( KIcon( "format-justify-left" ),
00105 i18n( "Align Left" ), this );
00106 actions->addAction( "format_alignleft", m_textAlignLeft );
00107 connect( m_textAlignLeft, SIGNAL( triggered( bool ) ),
00108 SLOT( textAlignLeft() ) );
00109 m_textAlignLeft->setShortcut( QKeySequence( Qt::ALT + Qt::Key_L ) );
00110 m_textAlignLeft->setChecked( true );
00111 m_textAlignCenter = new KToggleAction( KIcon( "format-justify-center" ),
00112 i18n( "Align Center" ), this );
00113 actions->addAction( "format_aligncenter", m_textAlignCenter );
00114 connect( m_textAlignCenter, SIGNAL( triggered( bool ) ),
00115 SLOT( textAlignCenter() ) );
00116 m_textAlignCenter->setShortcut( QKeySequence( Qt::ALT + Qt::Key_C ) );
00117 m_textAlignRight = new KToggleAction( KIcon( "format-justify-right" ),
00118 i18n( "Align Right" ), this );
00119 actions->addAction( "format_alignright", m_textAlignRight );
00120 connect( m_textAlignRight, SIGNAL( triggered( bool ) ),
00121 SLOT( textAlignRight() ) );
00122 m_textAlignRight->setShortcut( QKeySequence( Qt::ALT + Qt::Key_R ) );
00123 m_textAlignBlock = new KToggleAction( KIcon( "format-justify-fill" ),
00124 i18n( "Align Block" ), this );
00125 actions->addAction( "format_alignblock", m_textAlignBlock );
00126 connect( m_textAlignBlock, SIGNAL( triggered( bool ) ),
00127 SLOT( textAlignBlock() ) );
00128 m_textAlignBlock->setShortcut( QKeySequence( Qt::ALT + Qt::Key_B ) );
00129
00130 QActionGroup *group = new QActionGroup( this );
00131 group->addAction( m_textAlignLeft );
00132 group->addAction( m_textAlignCenter );
00133 group->addAction( m_textAlignRight );
00134 group->addAction( m_textAlignBlock );
00135
00136 m_textList = new KToggleAction( KIcon( "format-list-ordered" ), i18n( "List" ), this );
00137 actions->addAction( "format_list", m_textList );
00138 connect( m_textList, SIGNAL( triggered( bool ) ), SLOT( textList() ) );
00139
00140 group = new QActionGroup( this );
00141 group->addAction( m_textList );
00142
00143 m_textSuper = new KToggleAction( KIcon( "format-text-superscript" ),
00144 i18n( "Superscript" ), this );
00145 actions->addAction( "format_super", m_textSuper );
00146 connect( m_textSuper, SIGNAL( triggered( bool ) ),
00147 SLOT( textSuperScript() ) );
00148 m_textSub = new KToggleAction( KIcon( "format-text-subscript" ), i18n( "Subscript" ),
00149 this );
00150 actions->addAction( "format_sub", m_textSub );
00151 connect( m_textSub, SIGNAL( triggered( bool ) ), SLOT( textSubScript() ) );
00152
00153 group = new QActionGroup( this );
00154 group->addAction( m_textSuper );
00155 group->addAction( m_textSub );
00156
00157 m_textIncreaseIndent = new KAction( KIcon( "format-indent-more" ),
00158 i18n( "Increase Indent" ), this );
00159 actions->addAction( "format_increaseindent", m_textIncreaseIndent );
00160 m_textIncreaseIndent->setShortcut( QKeySequence( Qt::CTRL + Qt::ALT +
00161 Qt::Key_I ) );
00162 connect( m_textIncreaseIndent, SIGNAL( triggered( bool ) ),
00163 SLOT( textIncreaseIndent() ) );
00164
00165 m_textDecreaseIndent = new KAction( KIcon( "format-indent-less" ),
00166 i18n( "Decrease Indent" ), this );
00167 actions->addAction( "format_decreaseindent", m_textDecreaseIndent );
00168 m_textDecreaseIndent->setShortcut( QKeySequence( Qt::CTRL + Qt::ALT +
00169 Qt::Key_D ) );
00170 connect( m_textDecreaseIndent, SIGNAL( triggered( bool ) ), SLOT(
00171 textDecreaseIndent() ) );
00172
00173 group = new QActionGroup( this );
00174 group->addAction( m_textIncreaseIndent );
00175 group->addAction( m_textDecreaseIndent );
00176
00177 QPixmap pix( ICON_SIZE, ICON_SIZE );
00178 pix.fill( Qt::black );
00179 m_textColor = new KAction( i18n( "Text Color..." ), this );
00180 actions->addAction( "format_color", m_textColor );
00181 ( ( QAction * )m_textColor )->setIcon( pix );
00182 connect( m_textColor, SIGNAL( triggered( bool ) ), SLOT( slotTextColor() ) );
00183
00184 m_textFont = new KFontAction( i18n( "Text Font" ), this );
00185 actions->addAction( "format_font", m_textFont );
00186 connect( m_textFont, SIGNAL( triggered( const QString & ) ),
00187 this, SLOT( setFontFamily( const QString & ) ) );
00188
00189 m_textSize = new KFontSizeAction( i18n( "Text Size" ), this );
00190 actions->addAction( "format_size", m_textSize );
00191 connect( m_textSize, SIGNAL( fontSizeChanged( int ) ),
00192 this, SLOT( setFontWeight ( int ) ) );
00193
00194
00195 connect( this, SIGNAL( currentCharFormatChanged( const QTextCharFormat & ) ),
00196 SLOT( slotCurrentCharFormatChanged( const QTextCharFormat & ) ) );
00197
00198 #ifdef __GNUC__
00199 #warning moving the cursor through alignment changes does not update the button!
00200 #endif
00201 slotCurrentCharFormatChanged( currentCharFormat() );
00202 }
00203
00204 KNoteEdit::~KNoteEdit()
00205 {
00206 }
00207
00208 void KNoteEdit::setText( const QString &text )
00209 {
00210 if ( acceptRichText() && Qt::mightBeRichText( text ) ) {
00211 setHtml( text );
00212 } else {
00213 setPlainText( text );
00214 }
00215 }
00216
00217 QString KNoteEdit::text() const
00218 {
00219 if ( acceptRichText() ) {
00220 return toHtml();
00221 } else {
00222 return toPlainText();
00223 }
00224 }
00225
00226 void KNoteEdit::setTextFont( const QFont &font )
00227 {
00228 QTextCharFormat f;
00229 f.setFont( font );
00230 setTextFormat( f );
00231 }
00232
00233 void KNoteEdit::setTextColor( const QColor &color )
00234 {
00235 QTextCharFormat f;
00236 f.setForeground( QBrush( color ) );
00237 setTextFormat( f );
00238 }
00239
00240 void KNoteEdit::setTabStop( int tabs )
00241 {
00242 QFontMetrics fm( font() );
00243 setTabStopWidth( fm.width( 'x' ) * tabs );
00244 }
00245
00246 void KNoteEdit::setAutoIndentMode( bool newmode )
00247 {
00248 m_autoIndentMode = newmode;
00249 }
00250
00251
00254 void KNoteEdit::setRichText( bool f )
00255 {
00256 if ( f == acceptRichText() ) {
00257 return;
00258 }
00259
00260 setAcceptRichText( f );
00261
00262 QString t = toPlainText();
00263 if ( f ) {
00264
00265 if ( Qt::mightBeRichText( t ) ) {
00266 setHtml( t );
00267 } else {
00268 setPlainText( t );
00269 }
00270
00271 enableRichTextActions();
00272 } else {
00273 setPlainText( t );
00274 disableRichTextActions();
00275 }
00276 }
00277
00278 void KNoteEdit::textBold( bool b )
00279 {
00280 QTextCharFormat f;
00281 f.setFontWeight( b ? QFont::Bold : QFont::Normal );
00282 mergeCurrentCharFormat( f );
00283 }
00284
00285 void KNoteEdit::textStrikeOut( bool s )
00286 {
00287 QTextCharFormat f;
00288 f.setFontStrikeOut( s );
00289 mergeCurrentCharFormat( f );
00290 }
00291
00292 void KNoteEdit::slotTextColor()
00293 {
00294 QColor c = textColor();
00295 int ret = KColorDialog::getColor( c, this );
00296
00297 if ( ret == QDialog::Accepted ) {
00298 setTextColor( c );
00299 }
00300 }
00301
00302 void KNoteEdit::textAlignLeft()
00303 {
00304 setAlignment( Qt::AlignLeft );
00305 m_textAlignLeft->setChecked( true );
00306 }
00307
00308 void KNoteEdit::textAlignCenter()
00309 {
00310 setAlignment( Qt::AlignCenter );
00311 m_textAlignCenter->setChecked( true );
00312 }
00313
00314 void KNoteEdit::textAlignRight()
00315 {
00316 setAlignment( Qt::AlignRight );
00317 m_textAlignRight->setChecked( true );
00318 }
00319
00320 void KNoteEdit::textAlignBlock()
00321 {
00322 setAlignment( Qt::AlignJustify );
00323 m_textAlignBlock->setChecked( true );
00324 }
00325
00326 void KNoteEdit::textList()
00327 {
00328 QTextCursor c = textCursor();
00329 c.beginEditBlock();
00330
00331 if ( m_textList->isChecked() ) {
00332 QTextListFormat lf;
00333 QTextBlockFormat bf = c.blockFormat();
00334
00335 lf.setIndent( bf.indent() + 1 );
00336 bf.setIndent( 0 );
00337
00338 lf.setStyle( QTextListFormat::ListDisc );
00339
00340 c.setBlockFormat( bf );
00341 c.createList( lf );
00342 } else {
00343 QTextBlockFormat bf;
00344 bf.setObjectIndex( -1 );
00345 c.mergeBlockFormat( bf );
00346 }
00347
00348 c.endEditBlock();
00349 }
00350
00351 void KNoteEdit::textSuperScript()
00352 {
00353 QTextCharFormat f;
00354
00355 if ( m_textSuper->isChecked() ) {
00356 f.setVerticalAlignment( QTextCharFormat::AlignSuperScript );
00357 } else {
00358 f.setVerticalAlignment( QTextCharFormat::AlignNormal );
00359 }
00360 mergeCurrentCharFormat( f );
00361 }
00362
00363 void KNoteEdit::textSubScript()
00364 {
00365 QTextCharFormat f;
00366
00367 if ( m_textSub->isChecked() ) {
00368 f.setVerticalAlignment( QTextCharFormat::AlignSubScript );
00369 } else {
00370 f.setVerticalAlignment( QTextCharFormat::AlignNormal );
00371 }
00372 mergeCurrentCharFormat( f );
00373 }
00374
00375 void KNoteEdit::textIncreaseIndent()
00376 {
00377 QTextBlockFormat f = textCursor().blockFormat();
00378 f.setIndent( f.indent() + 1 );
00379 textCursor().setBlockFormat( f );
00380 }
00381
00382 void KNoteEdit::textDecreaseIndent()
00383 {
00384 QTextBlockFormat f = textCursor().blockFormat();
00385 short int curIndent = f.indent();
00386
00387 if ( curIndent > 0 ) {
00388 f.setIndent( curIndent - 1 );
00389 }
00390 textCursor().setBlockFormat( f );
00391 }
00392
00393
00396 void KNoteEdit::contextMenuEvent( QContextMenuEvent *e )
00397 {
00398 if ( m_editMenu ) {
00399 m_editMenu->popup( e->globalPos() );
00400 }
00401 }
00402
00403 void KNoteEdit::dragEnterEvent( QDragEnterEvent *e )
00404 {
00405 const QMimeData *md = e->mimeData();
00406 if ( KUrl::List::canDecode( md ) ) {
00407 e->accept();
00408 } else {
00409 KTextEdit::dragEnterEvent( e );
00410 }
00411 }
00412
00413 void KNoteEdit::dropEvent( QDropEvent *e )
00414 {
00415 const QMimeData *md = e->mimeData();
00416
00417 if ( KUrl::List::canDecode( md ) ) {
00418 KUrl::List list = KUrl::List::fromMimeData( md );
00419 for ( KUrl::List::Iterator it = list.begin(); it != list.end(); ++it ) {
00420 if ( it != list.begin() ) {
00421 insertPlainText( ", " );
00422 }
00423 insertPlainText( ( *it ).prettyUrl() );
00424 }
00425 } else { KTextEdit::dropEvent( e ); }
00426 }
00427
00428 void KNoteEdit::keyPressEvent( QKeyEvent *e )
00429 {
00430 KTextEdit::keyPressEvent( e );
00431
00432 if ( m_autoIndentMode &&
00433 ( ( e->key() == Qt::Key_Return ) || ( e->key() == Qt::Key_Enter ) ) ) {
00434 autoIndent();
00435 }
00436 }
00437
00438 void KNoteEdit::focusInEvent( QFocusEvent *e )
00439 {
00440 KTextEdit::focusInEvent( e );
00441
00442 setVerticalScrollBarPolicy( Qt::ScrollBarAsNeeded );
00443 setHorizontalScrollBarPolicy( Qt::ScrollBarAsNeeded );
00444 }
00445
00446 void KNoteEdit::focusOutEvent( QFocusEvent *e )
00447 {
00448 setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
00449 setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
00450
00451 KTextEdit::focusOutEvent( e );
00452 }
00453
00456 void KNoteEdit::slotCurrentCharFormatChanged( const QTextCharFormat &f )
00457 {
00458
00459 m_textFont->setFont( f.fontFamily() );
00460 m_textSize->setFontSize( ( int ) f.fontPointSize() );
00461
00462 m_textBold->setChecked( f.font().bold() );
00463 m_textItalic->setChecked( f.fontItalic() );
00464 m_textUnderline->setChecked( f.fontUnderline() );
00465 m_textStrikeOut->setChecked( f.fontStrikeOut() );
00466
00467
00468 QPixmap pix( ICON_SIZE, ICON_SIZE );
00469 pix.fill( f.foreground().color() );
00470 m_textColor->QAction::setIcon( pix );
00471
00472
00473 Qt::Alignment a = alignment();
00474 if ( a & Qt::AlignLeft ) {
00475 m_textAlignLeft->setChecked( true );
00476 } else if ( a & Qt::AlignHCenter ) {
00477 m_textAlignCenter->setChecked( true );
00478 } else if ( a & Qt::AlignRight ) {
00479 m_textAlignRight->setChecked( true );
00480 } else if ( a & Qt::AlignJustify ) {
00481 m_textAlignBlock->setChecked( true );
00482 }
00483
00484
00485 QTextCharFormat::VerticalAlignment va = f.verticalAlignment();
00486 if ( va == QTextCharFormat::AlignNormal ) {
00487 m_textSuper->setChecked( false );
00488 m_textSub->setChecked( false );
00489 } else if ( va == QTextCharFormat::AlignSuperScript ) {
00490 m_textSuper->setChecked( true );
00491 } else if ( va == QTextCharFormat::AlignSubScript ) {
00492 m_textSub->setChecked( true );
00493 }
00494 }
00495
00496
00499 void KNoteEdit::autoIndent()
00500 {
00501 QTextCursor c = textCursor();
00502 QTextBlock b = c.block();
00503
00504 QString string;
00505 while ( ( b.previous().length() > 0 ) && string.trimmed().isEmpty() ) {
00506 b = b.previous();
00507 string = b.text();
00508 }
00509
00510 if ( string.trimmed().isEmpty() ) {
00511 return;
00512 }
00513
00514
00515
00516
00517
00518 QString indentString;
00519
00520 int len = string.length();
00521 int i = 0;
00522 while ( i < len && string.at( i ).isSpace() ) {
00523 indentString += string.at( i++ );
00524 }
00525
00526 if ( !indentString.isEmpty() ) {
00527 c.insertText( indentString );
00528 }
00529 }
00530
00531 void KNoteEdit::setTextFormat( const QTextCharFormat &f )
00532 {
00533 if ( acceptRichText() ) {
00534 textCursor().mergeCharFormat( f );
00535 } else {
00536 QTextCursor c( document() );
00537 c.movePosition( QTextCursor::Start );
00538 c.movePosition( QTextCursor::End, QTextCursor::KeepAnchor );
00539 c.mergeCharFormat( f );
00540 }
00541 }
00542
00543 void KNoteEdit::enableRichTextActions()
00544 {
00545 m_textColor->setEnabled( true );
00546 m_textFont->setEnabled( true );
00547 m_textSize->setEnabled( true );
00548
00549 m_textBold->setEnabled( true );
00550 m_textItalic->setEnabled( true );
00551 m_textUnderline->setEnabled( true );
00552 m_textStrikeOut->setEnabled( true );
00553
00554 m_textAlignLeft->setEnabled( true );
00555 m_textAlignCenter->setEnabled( true );
00556 m_textAlignRight->setEnabled( true );
00557 m_textAlignBlock->setEnabled( true );
00558
00559 m_textList->setEnabled( true );
00560 m_textSuper->setEnabled( true );
00561 m_textSub->setEnabled( true );
00562
00563 m_textIncreaseIndent->setEnabled( true );
00564 m_textDecreaseIndent->setEnabled( true );
00565 }
00566
00567 void KNoteEdit::disableRichTextActions()
00568 {
00569 m_textColor->setEnabled( false );
00570 m_textFont->setEnabled( false );
00571 m_textSize->setEnabled( false );
00572
00573 m_textBold->setEnabled( false );
00574 m_textItalic->setEnabled( false );
00575 m_textUnderline->setEnabled( false );
00576 m_textStrikeOut->setEnabled( false );
00577
00578 m_textAlignLeft->setEnabled( false );
00579 m_textAlignCenter->setEnabled( false );
00580 m_textAlignRight->setEnabled( false );
00581 m_textAlignBlock->setEnabled( false );
00582
00583 m_textList->setEnabled( false );
00584 m_textSuper->setEnabled( false );
00585 m_textSub->setEnabled( false );
00586
00587 m_textIncreaseIndent->setEnabled( false );
00588 m_textDecreaseIndent->setEnabled( false );
00589 }
00590
00591 #include "knoteedit.moc"