knotes

knoteedit.cpp

00001 /*******************************************************************
00002  KNotes -- Notes for the KDE project
00003 
00004  Copyright (c) 1997-2005, The KNotes Developers
00005 
00006  This program is free software; you can redistribute it and/or
00007  modify it under the terms of the GNU General Public License
00008  as published by the Free Software Foundation; either version 2
00009  of the License, or (at your option) any later version.
00010 
00011  This program is distributed in the hope that it will be useful,
00012  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  GNU General Public License for more details.
00015 
00016  You should have received a copy of the GNU General Public License
00017  along with this program; if not, write to the Free Software
00018  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00019 *******************************************************************/
00020 
00021 #include <qdragobject.h>
00022 #include <qfont.h>
00023 
00024 #include <kdebug.h>
00025 #include <klocale.h>
00026 #include <kaction.h>
00027 #include <kurldrag.h>
00028 #include <kstdaction.h>
00029 #include <kcolordialog.h>
00030 
00031 #include "knoteedit.h"
00032 
00033 static const short SEP = 5;
00034 static const short ICON_SIZE = 10;
00035 
00036 
00037 KNoteEdit::KNoteEdit( KActionCollection *actions, QWidget *parent, const char *name )
00038     : KTextEdit( parent, name )
00039 {
00040     setAcceptDrops( true );
00041     setWordWrap( WidgetWidth );
00042     setWrapPolicy( AtWhiteSpace );
00043     setLinkUnderline( true );
00044 
00045     // create the actions for the RMB menu
00046     KAction* undo = KStdAction::undo( this, SLOT(undo()), actions );
00047     KAction* redo = KStdAction::redo( this, SLOT(redo()), actions );
00048     undo->setEnabled( isUndoAvailable() );
00049     redo->setEnabled( isRedoAvailable() );
00050 
00051     m_cut = KStdAction::cut( this, SLOT(cut()), actions );
00052     m_copy = KStdAction::copy( this, SLOT(copy()), actions );
00053     m_paste = KStdAction::paste( this, SLOT(paste()), actions );
00054 
00055     m_cut->setEnabled( false );
00056     m_copy->setEnabled( false );
00057     m_paste->setEnabled( true );
00058 
00059     connect( this, SIGNAL(undoAvailable(bool)), undo, SLOT(setEnabled(bool)) );
00060     connect( this, SIGNAL(redoAvailable(bool)), redo, SLOT(setEnabled(bool)) );
00061 
00062     connect( this, SIGNAL(copyAvailable(bool)), m_cut, SLOT(setEnabled(bool)) );
00063     connect( this, SIGNAL(copyAvailable(bool)), m_copy, SLOT(setEnabled(bool)) );
00064 
00065     new KAction( KStdGuiItem::clear(), 0, this, SLOT(clear()), actions, "edit_clear" );
00066     KStdAction::selectAll( this, SLOT(selectAll()), actions );
00067 
00068     // create the actions modifying the text format
00069     m_textBold = new KToggleAction( i18n("Bold"), "text_bold", CTRL + Key_B, 0, 0,
00070                                     actions, "format_bold" );
00071     m_textItalic = new KToggleAction( i18n("Italic"), "text_italic", CTRL + Key_I, 0, 0,
00072                                       actions, "format_italic" );
00073     m_textUnderline = new KToggleAction( i18n("Underline"), "text_under", CTRL + Key_U, 0, 0,
00074                                          actions, "format_underline" );
00075     m_textStrikeOut = new KToggleAction( i18n("Strike Out"), "text_strike", CTRL + Key_S, 0, 0,
00076                                          actions, "format_strikeout" );
00077 
00078     connect( m_textBold, SIGNAL(toggled(bool)), SLOT(setBold(bool)) );
00079     connect( m_textItalic, SIGNAL(toggled(bool)), SLOT(setItalic(bool)) );
00080     connect( m_textUnderline, SIGNAL(toggled(bool)), SLOT(setUnderline(bool)) );
00081     connect( m_textStrikeOut, SIGNAL(toggled(bool)), SLOT(textStrikeOut(bool)) );
00082 
00083     m_textAlignLeft = new KToggleAction( i18n("Align Left"), "text_left", ALT + Key_L,
00084                                  this, SLOT(textAlignLeft()),
00085                                  actions, "format_alignleft" );
00086     m_textAlignLeft->setChecked( true ); // just a dummy, will be updated later
00087     m_textAlignCenter = new KToggleAction( i18n("Align Center"), "text_center", ALT + Key_C,
00088                                  this, SLOT(textAlignCenter()),
00089                                  actions, "format_aligncenter" );
00090     m_textAlignRight = new KToggleAction( i18n("Align Right"), "text_right", ALT + Key_R,
00091                                  this, SLOT(textAlignRight()),
00092                                  actions, "format_alignright" );
00093     m_textAlignBlock = new KToggleAction( i18n("Align Block"), "text_block", ALT + Key_B,
00094                                  this, SLOT(textAlignBlock()),
00095                                  actions, "format_alignblock" );
00096 
00097     m_textAlignLeft->setExclusiveGroup( "align" );
00098     m_textAlignCenter->setExclusiveGroup( "align" );
00099     m_textAlignRight->setExclusiveGroup( "align" );
00100     m_textAlignBlock->setExclusiveGroup( "align" );
00101 
00102     m_textList = new KToggleAction( i18n("List"), "enum_list", 0,
00103                                     this, SLOT(textList()),
00104                                     actions, "format_list" );
00105 
00106     m_textList->setExclusiveGroup( "style" );
00107 
00108     m_textSuper = new KToggleAction( i18n("Superscript"), "text_super", 0,
00109                                      this, SLOT(textSuperScript()),
00110                                      actions, "format_super" );
00111     m_textSub = new KToggleAction( i18n("Subscript"), "text_sub", 0,
00112                                    this, SLOT(textSubScript()),
00113                                    actions, "format_sub" );
00114 
00115     m_textSuper->setExclusiveGroup( "valign" );
00116     m_textSub->setExclusiveGroup( "valign" );
00117 
00118 // There is no easy possibility to implement text indenting with QTextEdit
00119 //
00120 //     m_textIncreaseIndent = new KAction( i18n("Increase Indent"), "format_increaseindent", 0,
00121 //                                         this, SLOT(textIncreaseIndent()),
00122 //                                         actions, "format_increaseindent" );
00123 //
00124 //     m_textDecreaseIndent = new KAction( i18n("Decrease Indent"), "format_decreaseindent", 0,
00125 //                                         this, SLOT(textDecreaseIndent()),
00126 //                                         actions, "format_decreaseindent" );
00127 
00128     QPixmap pix( ICON_SIZE, ICON_SIZE );
00129     pix.fill( black );     // just a dummy, gets updated before widget is shown
00130     m_textColor = new KAction( i18n("Text Color..."), pix, 0, this,
00131                                   SLOT(textColor()), actions, "format_color" );
00132 
00133     m_textFont = new KFontAction( i18n("Text Font"), "text", KKey(),
00134                                   actions, "format_font" );
00135     connect( m_textFont, SIGNAL(activated( const QString & )),
00136              this, SLOT(setFamily( const QString & )) );
00137 
00138     m_textSize = new KFontSizeAction( i18n("Text Size"), KKey(),
00139                                       actions, "format_size" );
00140     connect( m_textSize, SIGNAL(fontSizeChanged( int )),
00141              this, SLOT(setPointSize( int )) );
00142 
00143     // QTextEdit connections
00144     connect( this, SIGNAL(returnPressed()), SLOT(slotReturnPressed()) );
00145     connect( this, SIGNAL(currentFontChanged( const QFont & )),
00146              this, SLOT(fontChanged( const QFont & )) );
00147     connect( this, SIGNAL(currentColorChanged( const QColor & )),
00148              this, SLOT(colorChanged( const QColor & )) );
00149     connect( this, SIGNAL(currentAlignmentChanged( int )),
00150              this, SLOT(alignmentChanged( int )) );
00151     connect( this, SIGNAL(currentVerticalAlignmentChanged( VerticalAlignment )),
00152              this, SLOT(verticalAlignmentChanged( VerticalAlignment )) );
00153 }
00154 
00155 KNoteEdit::~KNoteEdit()
00156 {
00157 }
00158 
00159 void KNoteEdit::setText( const QString& text )
00160 {
00161     // to update the font and font size combo box - QTextEdit stopped
00162     // emitting the currentFontChanged signal with the new optimizations
00163     KTextEdit::setText( text );
00164     fontChanged( currentFont() );
00165 }
00166 
00167 void KNoteEdit::setTextFont( const QFont& font )
00168 {
00169     if ( textFormat() == PlainText )
00170         setFont( font );
00171     else
00172         setCurrentFont( font );
00173 }
00174 
00175 void KNoteEdit::setTextColor( const QColor& color )
00176 {
00177     setColor( color );
00178     colorChanged( color );
00179 }
00180 
00181 void KNoteEdit::setTabStop( int tabs )
00182 {
00183     QFontMetrics fm( font() );
00184     setTabStopWidth( fm.width( 'x' ) * tabs );
00185 }
00186 
00187 void KNoteEdit::setAutoIndentMode( bool newmode )
00188 {
00189     m_autoIndentMode = newmode;
00190 }
00191 
00192 
00195 void KNoteEdit::setTextFormat( TextFormat f )
00196 {
00197     if ( f == textFormat() )
00198         return;
00199 
00200     if ( f == RichText )
00201     {
00202         QString t = text();
00203         KTextEdit::setTextFormat( f );
00204 
00205         // if the note contains html/xml source try to display it, otherwise
00206         // get the modified text again and set it to preserve newlines
00207         if ( QStyleSheet::mightBeRichText( t ) )
00208             setText( t );
00209         else
00210             setText( text() );
00211 
00212         enableRichTextActions();
00213     }
00214     else
00215     {
00216         KTextEdit::setTextFormat( f );
00217         QString t = text();
00218         setText( t );
00219 
00220         disableRichTextActions();
00221     }
00222 }
00223 
00224 void KNoteEdit::textStrikeOut( bool s )
00225 {
00226     // QTextEdit does not support stroke out text (no saving,
00227     // no changing of more than one selected character)
00228     QFont font;
00229 
00230     if ( !hasSelectedText() )
00231     {
00232         font = currentFont();
00233         font.setStrikeOut( s );
00234         setCurrentFont( font );
00235     }
00236     else
00237     {
00238         int pFrom, pTo, iFrom, iTo, iF, iT;
00239         int cp, ci;
00240 
00241         getSelection( &pFrom, &iFrom, &pTo, &iTo );
00242         getCursorPosition( &cp, &ci );
00243 
00244         for ( int p = pFrom; p <= pTo; p++ )
00245         {
00246             iF = 0;
00247             iT = paragraphLength( p );
00248 
00249             if ( p == pFrom )
00250                 iF = iFrom;
00251 
00252             if ( p == pTo )
00253                 iT = iTo;
00254 
00255             for ( int i = iF; i < iT; i++ )
00256             {
00257                 setCursorPosition( p, i + 1 );
00258                 setSelection( p, i, p, i + 1 );
00259                 font = currentFont();
00260                 font.setStrikeOut( s );
00261                 setCurrentFont( font );
00262             }
00263         }
00264 
00265         setSelection( pFrom, iFrom, pTo, iTo );
00266         setCursorPosition( cp, ci );
00267     }
00268 }
00269 
00270 void KNoteEdit::textColor()
00271 {
00272     QColor c = color();
00273     int ret = KColorDialog::getColor( c, this );
00274     if ( ret == QDialog::Accepted )
00275         setTextColor( c );
00276 }
00277 
00278 void KNoteEdit::textAlignLeft()
00279 {
00280     setAlignment( AlignLeft );
00281     m_textAlignLeft->setChecked( true );
00282 }
00283 
00284 void KNoteEdit::textAlignCenter()
00285 {
00286     setAlignment( AlignCenter );
00287     m_textAlignCenter->setChecked( true );
00288 }
00289 
00290 void KNoteEdit::textAlignRight()
00291 {
00292     setAlignment( AlignRight );
00293     m_textAlignRight->setChecked( true );
00294 }
00295 
00296 void KNoteEdit::textAlignBlock()
00297 {
00298     setAlignment( AlignJustify );
00299     m_textAlignBlock->setChecked( true );
00300 }
00301 
00302 void KNoteEdit::textList()
00303 {
00304     if ( m_textList->isChecked() )
00305         setParagType( QStyleSheetItem::DisplayListItem, QStyleSheetItem::ListDisc );
00306     else
00307         setParagType( QStyleSheetItem::DisplayBlock, QStyleSheetItem::ListDisc );
00308 }
00309 
00310 void KNoteEdit::textSuperScript()
00311 {
00312     if ( m_textSuper->isChecked() )
00313         setVerticalAlignment( AlignSuperScript );
00314     else
00315         setVerticalAlignment( AlignNormal );
00316 }
00317 
00318 void KNoteEdit::textSubScript()
00319 {
00320     if ( m_textSub->isChecked() )
00321         setVerticalAlignment( AlignSubScript );
00322     else
00323         setVerticalAlignment( AlignNormal );
00324 }
00325 
00326 //void KNoteEdit::textIncreaseIndent()
00327 //{
00328 //}
00329 
00330 //void KNoteEdit::textDecreaseIndent()
00331 //{
00332 //}
00333 
00334 
00337 void KNoteEdit::contentsDragEnterEvent( QDragEnterEvent *e )
00338 {
00339     if ( KURLDrag::canDecode( e ) )
00340         e->accept();
00341     else
00342         KTextEdit::contentsDragEnterEvent( e );
00343 }
00344 
00345 void KNoteEdit::contentsDropEvent( QDropEvent *e )
00346 {
00347     KURL::List list;
00348 
00349     if ( KURLDrag::decode( e, list ) )
00350         for ( KURL::List::Iterator it = list.begin(); it != list.end(); ++it )
00351         {
00352             if ( it != list.begin() )
00353                 insert( ", " );
00354 
00355             insert( (*it).prettyURL() );
00356         }
00357     else
00358         KTextEdit::contentsDropEvent( e );
00359 }
00360 
00363 void KNoteEdit::slotReturnPressed()
00364 {
00365     if ( m_autoIndentMode )
00366         autoIndent();
00367 }
00368 
00369 void KNoteEdit::fontChanged( const QFont &f )
00370 {
00371     m_textFont->setFont( f.family() );
00372     m_textSize->setFontSize( f.pointSize() );
00373 
00374     m_textBold->setChecked( f.bold() );
00375     m_textItalic->setChecked( f.italic() );
00376     m_textUnderline->setChecked( f.underline() );
00377     m_textStrikeOut->setChecked( f.strikeOut() );
00378 }
00379 
00380 void KNoteEdit::colorChanged( const QColor &c )
00381 {
00382     QPixmap pix( ICON_SIZE, ICON_SIZE );
00383     pix.fill( c );
00384     m_textColor->setIconSet( pix );
00385 }
00386 
00387 void KNoteEdit::alignmentChanged( int a )
00388 {
00389     // TODO: AlignAuto
00390     if ( ( a == AlignAuto ) || ( a & AlignLeft ) )
00391         m_textAlignLeft->setChecked( true );
00392     else if ( ( a & AlignHCenter ) )
00393         m_textAlignCenter->setChecked( true );
00394     else if ( ( a & AlignRight ) )
00395         m_textAlignRight->setChecked( true );
00396     else if ( ( a & AlignJustify ) )
00397         m_textAlignBlock->setChecked( true );
00398 }
00399 
00400 void KNoteEdit::verticalAlignmentChanged( VerticalAlignment a )
00401 {
00402     if ( a == AlignNormal )
00403     {
00404         m_textSuper->setChecked( false );
00405         m_textSub->setChecked( false );
00406     }
00407     else if ( a == AlignSuperScript )
00408         m_textSuper->setChecked( true );
00409     else if ( a == AlignSubScript )
00410         m_textSub->setChecked( true );
00411 }
00412 
00413 
00416 void KNoteEdit::autoIndent()
00417 {
00418     int para, index;
00419     QString string;
00420     getCursorPosition( &para, &index );
00421     while ( para > 0 && string.stripWhiteSpace().isEmpty() )
00422         string = text( --para );
00423 
00424     if ( string.stripWhiteSpace().isEmpty() )
00425         return;
00426 
00427     // This routine returns the whitespace before the first non white space
00428     // character in string.
00429     // It is assumed that string contains at least one non whitespace character
00430     // ie \n \r \t \v \f and space
00431     QString indentString;
00432 
00433     int len = string.length();
00434     int i = 0;
00435     while ( i < len && string.at(i).isSpace() )
00436         indentString += string.at( i++ );
00437 
00438     if ( !indentString.isEmpty() )
00439         insert( indentString );
00440 }
00441 
00442 void KNoteEdit::emitLinkClicked( const QString &s )
00443 {
00444     kdDebug(5500) << k_funcinfo << s << endl;
00445 }
00446 
00447 void KNoteEdit::enableRichTextActions()
00448 {
00449     m_textColor->setEnabled( true );
00450     m_textFont->setEnabled( true );
00451     m_textSize->setEnabled( true );
00452 
00453     m_textBold->setEnabled( true );
00454     m_textItalic->setEnabled( true );
00455     m_textUnderline->setEnabled( true );
00456     m_textStrikeOut->setEnabled( true );
00457 
00458     m_textAlignLeft->setEnabled( true );
00459     m_textAlignCenter->setEnabled( true );
00460     m_textAlignRight->setEnabled( true );
00461     m_textAlignBlock->setEnabled( true );
00462 
00463     m_textList->setEnabled( true );
00464     m_textSuper->setEnabled( true );
00465     m_textSub->setEnabled( true );
00466 
00467 //    m_textIncreaseIndent->setEnabled( true );
00468 //    m_textDecreaseIndent->setEnabled( true );
00469 }
00470 
00471 void KNoteEdit::disableRichTextActions()
00472 {
00473     m_textColor->setEnabled( false );
00474     m_textFont->setEnabled( false );
00475     m_textSize->setEnabled( false );
00476 
00477     m_textBold->setEnabled( false );
00478     m_textItalic->setEnabled( false );
00479     m_textUnderline->setEnabled( false );
00480     m_textStrikeOut->setEnabled( false );
00481 
00482     m_textAlignLeft->setEnabled( false );
00483     m_textAlignCenter->setEnabled( false );
00484     m_textAlignRight->setEnabled( false );
00485     m_textAlignBlock->setEnabled( false );
00486 
00487     m_textList->setEnabled( false );
00488     m_textSuper->setEnabled( false );
00489     m_textSub->setEnabled( false );
00490 
00491 //    m_textIncreaseIndent->setEnabled( false );
00492 //    m_textDecreaseIndent->setEnabled( false );
00493 }
00494 
00495 #include "knoteedit.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys