TDE personal information management applications
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

558 lines
18 KiB

  1. /*******************************************************************
  2. KNotes -- Notes for the KDE project
  3. Copyright (c) 1997-2005, The KNotes Developers
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  15. *******************************************************************/
  16. #include <tqdragobject.h>
  17. #include <tqfont.h>
  18. #include <kdebug.h>
  19. #include <tdelocale.h>
  20. #include <tdeaction.h>
  21. #include <kurldrag.h>
  22. #include <kstdaction.h>
  23. #include <kcolordialog.h>
  24. #include <tqpopupmenu.h>
  25. #include <kiconloader.h>
  26. #include "knoteedit.h"
  27. #include "knote.h"
  28. static const short SEP = 5;
  29. static const short ICON_SIZE = 10;
  30. KNoteEdit::KNoteEdit( TDEActionCollection *actions, TQWidget *parent, const char *name )
  31. : KTextEdit( parent, name ), m_note( 0 )
  32. {
  33. setAcceptDrops( true );
  34. setWordWrap( WidgetWidth );
  35. setWrapPolicy( AtWhiteSpace );
  36. setLinkUnderline( true );
  37. setCheckSpellingEnabled(false);
  38. // create the actions for the RMB menu
  39. undo = KStdAction::undo( TQT_TQOBJECT(this), TQT_SLOT(undo()), actions );
  40. redo = KStdAction::redo( TQT_TQOBJECT(this), TQT_SLOT(redo()), actions );
  41. undo->setEnabled( isUndoAvailable() );
  42. redo->setEnabled( isRedoAvailable() );
  43. m_cut = KStdAction::cut( TQT_TQOBJECT(this), TQT_SLOT(cut()), actions );
  44. m_copy = KStdAction::copy( TQT_TQOBJECT(this), TQT_SLOT(copy()), actions );
  45. m_paste = KStdAction::paste( TQT_TQOBJECT(this), TQT_SLOT(paste()), actions );
  46. m_cut->setEnabled( false );
  47. m_copy->setEnabled( false );
  48. m_paste->setEnabled( true );
  49. connect( this, TQT_SIGNAL(undoAvailable(bool)), TQT_TQOBJECT(this), TQT_SLOT(setEnabledUndo(bool)) );
  50. connect( this, TQT_SIGNAL(redoAvailable(bool)), TQT_TQOBJECT(this), TQT_SLOT(setEnabledRedo(bool)) );
  51. connect( this, TQT_SIGNAL(copyAvailable(bool)), TQT_TQOBJECT(this), TQT_SLOT( slotCutEnabled( bool ) ) );
  52. connect( this, TQT_SIGNAL(copyAvailable(bool)), m_copy, TQT_SLOT(setEnabled(bool)) );
  53. new TDEAction( KStdGuiItem::clear(), 0, TQT_TQOBJECT(this), TQT_SLOT(clear()), actions, "edit_clear" );
  54. KStdAction::selectAll( TQT_TQOBJECT(this), TQT_SLOT(selectAll()), actions );
  55. // create the actions modifying the text format
  56. m_textBold = new TDEToggleAction( i18n("Bold"), "format-text-bold", CTRL + Key_B, 0, 0,
  57. actions, "format_bold" );
  58. m_textItalic = new TDEToggleAction( i18n("Italic"), "format-text-italic", CTRL + Key_I, 0, 0,
  59. actions, "format_italic" );
  60. m_textUnderline = new TDEToggleAction( i18n("Underline"), "format-text-underline", CTRL + Key_U, 0, 0,
  61. actions, "format_underline" );
  62. m_textStrikeOut = new TDEToggleAction( i18n("Strike Out"), "format-text-strikethrough", CTRL + Key_S, 0, 0,
  63. actions, "format_strikeout" );
  64. connect( m_textBold, TQT_SIGNAL(toggled(bool)), TQT_SLOT(setBold(bool)) );
  65. connect( m_textItalic, TQT_SIGNAL(toggled(bool)), TQT_SLOT(setItalic(bool)) );
  66. connect( m_textUnderline, TQT_SIGNAL(toggled(bool)), TQT_SLOT(setUnderline(bool)) );
  67. connect( m_textStrikeOut, TQT_SIGNAL(toggled(bool)), TQT_SLOT(textStrikeOut(bool)) );
  68. m_textAlignLeft = new TDEToggleAction( i18n("Align Left"), "format-text-direction-ltr", ALT + Key_L,
  69. TQT_TQOBJECT(this), TQT_SLOT(textAlignLeft()),
  70. actions, "format_alignleft" );
  71. m_textAlignLeft->setChecked( true ); // just a dummy, will be updated later
  72. m_textAlignCenter = new TDEToggleAction( i18n("Align Center"), "text_center", ALT + Key_C,
  73. TQT_TQOBJECT(this), TQT_SLOT(textAlignCenter()),
  74. actions, "format_aligncenter" );
  75. m_textAlignRight = new TDEToggleAction( i18n("Align Right"), "format-text-direction-rtl", ALT + Key_R,
  76. TQT_TQOBJECT(this), TQT_SLOT(textAlignRight()),
  77. actions, "format_alignright" );
  78. m_textAlignBlock = new TDEToggleAction( i18n("Align Block"), "text_block", ALT + Key_B,
  79. TQT_TQOBJECT(this), TQT_SLOT(textAlignBlock()),
  80. actions, "format_alignblock" );
  81. m_textAlignLeft->setExclusiveGroup( "align" );
  82. m_textAlignCenter->setExclusiveGroup( "align" );
  83. m_textAlignRight->setExclusiveGroup( "align" );
  84. m_textAlignBlock->setExclusiveGroup( "align" );
  85. m_textList = new TDEToggleAction( i18n("List"), "enum_list", 0,
  86. TQT_TQOBJECT(this), TQT_SLOT(textList()),
  87. actions, "format_list" );
  88. m_textList->setExclusiveGroup( "style" );
  89. m_textSuper = new TDEToggleAction( i18n("Superscript"), "text_super", 0,
  90. TQT_TQOBJECT(this), TQT_SLOT(textSuperScript()),
  91. actions, "format_super" );
  92. m_textSub = new TDEToggleAction( i18n("Subscript"), "text_sub", 0,
  93. TQT_TQOBJECT(this), TQT_SLOT(textSubScript()),
  94. actions, "format_sub" );
  95. m_textSuper->setExclusiveGroup( "valign" );
  96. m_textSub->setExclusiveGroup( "valign" );
  97. // There is no easy possibility to implement text indenting with TQTextEdit
  98. //
  99. // m_textIncreaseIndent = new TDEAction( i18n("Increase Indent"), "format_increaseindent", 0,
  100. // TQT_TQOBJECT(this), TQT_SLOT(textIncreaseIndent()),
  101. // actions, "format_increaseindent" );
  102. //
  103. // m_textDecreaseIndent = new TDEAction( i18n("Decrease Indent"), "format_decreaseindent", 0,
  104. // TQT_TQOBJECT(this), TQT_SLOT(textDecreaseIndent()),
  105. // actions, "format_decreaseindent" );
  106. TQPixmap pix( ICON_SIZE, ICON_SIZE );
  107. pix.fill( black ); // just a dummy, gets updated before widget is shown
  108. m_textColor = new TDEAction( i18n("Text Color..."), pix, 0, TQT_TQOBJECT(this),
  109. TQT_SLOT(textColor()), actions, "format_color" );
  110. m_textFont = new TDEFontAction( i18n("Text Font"), "text", KKey(),
  111. actions, "format_font" );
  112. connect( m_textFont, TQT_SIGNAL(activated( const TQString & )),
  113. TQT_TQOBJECT(this), TQT_SLOT(setFamily( const TQString & )) );
  114. m_textSize = new TDEFontSizeAction( i18n("Text Size"), KKey(),
  115. actions, "format_size" );
  116. connect( m_textSize, TQT_SIGNAL(fontSizeChanged( int )),
  117. TQT_TQOBJECT(this), TQT_SLOT(setPointSize( int )) );
  118. // TQTextEdit connections
  119. connect( this, TQT_SIGNAL(returnPressed()), TQT_SLOT(slotReturnPressed()) );
  120. connect( this, TQT_SIGNAL(currentFontChanged( const TQFont & )),
  121. TQT_TQOBJECT(this), TQT_SLOT(fontChanged( const TQFont & )) );
  122. connect( this, TQT_SIGNAL(currentColorChanged( const TQColor & )),
  123. TQT_TQOBJECT(this), TQT_SLOT(colorChanged( const TQColor & )) );
  124. connect( this, TQT_SIGNAL(currentAlignmentChanged( int )),
  125. TQT_TQOBJECT(this), TQT_SLOT(alignmentChanged( int )) );
  126. connect( this, TQT_SIGNAL(currentVerticalAlignmentChanged( VerticalAlignment )),
  127. TQT_TQOBJECT(this), TQT_SLOT(verticalAlignmentChanged( VerticalAlignment )) );
  128. }
  129. KNoteEdit::~KNoteEdit()
  130. {
  131. }
  132. void KNoteEdit::setEnabledRedo( bool b )
  133. {
  134. redo->setEnabled( b && !isReadOnly() );
  135. }
  136. void KNoteEdit::setEnabledUndo( bool b )
  137. {
  138. undo->setEnabled( b && !isReadOnly() );
  139. }
  140. void KNoteEdit::slotCutEnabled( bool b )
  141. {
  142. m_cut->setEnabled( b && !isReadOnly() );
  143. }
  144. void KNoteEdit::setText( const TQString& text )
  145. {
  146. // to update the font and font size combo box - TQTextEdit stopped
  147. // emitting the currentFontChanged signal with the new optimizations
  148. KTextEdit::setText( text );
  149. fontChanged( currentFont() );
  150. }
  151. void KNoteEdit::setTextFont( const TQFont& font )
  152. {
  153. if ( textFormat() == PlainText )
  154. setFont( font );
  155. else
  156. setCurrentFont( font );
  157. }
  158. void KNoteEdit::setTextColor( const TQColor& color )
  159. {
  160. setColor( color );
  161. colorChanged( color );
  162. }
  163. void KNoteEdit::setTabStop( int tabs )
  164. {
  165. TQFontMetrics fm( font() );
  166. setTabStopWidth( fm.width( 'x' ) * tabs );
  167. }
  168. void KNoteEdit::setAutoIndentMode( bool newmode )
  169. {
  170. m_autoIndentMode = newmode;
  171. }
  172. /** public slots **/
  173. void KNoteEdit::setTextFormat( TextFormat f )
  174. {
  175. if ( f == textFormat() )
  176. return;
  177. if ( f == RichText )
  178. {
  179. TQString t = text();
  180. KTextEdit::setTextFormat( f );
  181. // if the note contains html/xml source try to display it, otherwise
  182. // get the modified text again and set it to preserve newlines
  183. if ( TQStyleSheet::mightBeRichText( t ) )
  184. setText( t );
  185. else
  186. setText( text() );
  187. enableRichTextActions();
  188. }
  189. else
  190. {
  191. KTextEdit::setTextFormat( f );
  192. TQString t = text();
  193. setText( t );
  194. disableRichTextActions();
  195. }
  196. }
  197. void KNoteEdit::textStrikeOut( bool s )
  198. {
  199. // TQTextEdit does not support stroke out text (no saving,
  200. // no changing of more than one selected character)
  201. TQFont font;
  202. if ( !hasSelectedText() )
  203. {
  204. font = currentFont();
  205. font.setStrikeOut( s );
  206. setCurrentFont( font );
  207. }
  208. else
  209. {
  210. int pFrom, pTo, iFrom, iTo, iF, iT;
  211. int cp, ci;
  212. getSelection( &pFrom, &iFrom, &pTo, &iTo );
  213. getCursorPosition( &cp, &ci );
  214. for ( int p = pFrom; p <= pTo; p++ )
  215. {
  216. iF = 0;
  217. iT = paragraphLength( p );
  218. if ( p == pFrom )
  219. iF = iFrom;
  220. if ( p == pTo )
  221. iT = iTo;
  222. for ( int i = iF; i < iT; i++ )
  223. {
  224. setCursorPosition( p, i + 1 );
  225. setSelection( p, i, p, i + 1 );
  226. font = currentFont();
  227. font.setStrikeOut( s );
  228. setCurrentFont( font );
  229. }
  230. }
  231. setSelection( pFrom, iFrom, pTo, iTo );
  232. setCursorPosition( cp, ci );
  233. }
  234. }
  235. void KNoteEdit::textColor()
  236. {
  237. if ( m_note )
  238. m_note->blockEmitDataChanged( true );
  239. TQColor c = color();
  240. int ret = KColorDialog::getColor( c, this );
  241. if ( ret == TQDialog::Accepted )
  242. setTextColor( c );
  243. if ( m_note )
  244. m_note->blockEmitDataChanged( false );
  245. }
  246. void KNoteEdit::textAlignLeft()
  247. {
  248. setAlignment( AlignLeft );
  249. m_textAlignLeft->setChecked( true );
  250. }
  251. void KNoteEdit::textAlignCenter()
  252. {
  253. setAlignment( AlignCenter );
  254. m_textAlignCenter->setChecked( true );
  255. }
  256. void KNoteEdit::textAlignRight()
  257. {
  258. setAlignment( AlignRight );
  259. m_textAlignRight->setChecked( true );
  260. }
  261. void KNoteEdit::textAlignBlock()
  262. {
  263. setAlignment( AlignJustify );
  264. m_textAlignBlock->setChecked( true );
  265. }
  266. void KNoteEdit::textList()
  267. {
  268. if ( m_textList->isChecked() )
  269. setParagType( TQStyleSheetItem::DisplayListItem, TQStyleSheetItem::ListDisc );
  270. else
  271. setParagType( TQStyleSheetItem::DisplayBlock, TQStyleSheetItem::ListDisc );
  272. }
  273. void KNoteEdit::textSuperScript()
  274. {
  275. if ( m_textSuper->isChecked() )
  276. setVerticalAlignment( AlignSuperScript );
  277. else
  278. setVerticalAlignment( AlignNormal );
  279. }
  280. void KNoteEdit::textSubScript()
  281. {
  282. if ( m_textSub->isChecked() )
  283. setVerticalAlignment( AlignSubScript );
  284. else
  285. setVerticalAlignment( AlignNormal );
  286. }
  287. //void KNoteEdit::textIncreaseIndent()
  288. //{
  289. //}
  290. //void KNoteEdit::textDecreaseIndent()
  291. //{
  292. //}
  293. /** protected methods **/
  294. void KNoteEdit::contentsDragEnterEvent( TQDragEnterEvent *e )
  295. {
  296. if ( KURLDrag::canDecode( e ) )
  297. e->accept();
  298. else
  299. KTextEdit::contentsDragEnterEvent( e );
  300. }
  301. void KNoteEdit::contentsDropEvent( TQDropEvent *e )
  302. {
  303. KURL::List list;
  304. if ( KURLDrag::decode( e, list ) )
  305. {
  306. KURL::List::ConstIterator begin = list.constBegin();
  307. KURL::List::ConstIterator end = list.constEnd();
  308. for ( KURL::List::ConstIterator it = begin; it != end; ++it )
  309. {
  310. if ( it != begin )
  311. insert( ", " );
  312. insert( (*it).prettyURL() );
  313. }
  314. }
  315. else
  316. KTextEdit::contentsDropEvent( e );
  317. }
  318. /** private slots **/
  319. void KNoteEdit::slotReturnPressed()
  320. {
  321. if ( m_autoIndentMode )
  322. autoIndent();
  323. }
  324. void KNoteEdit::fontChanged( const TQFont &f )
  325. {
  326. m_textFont->setFont( f.family() );
  327. m_textSize->setFontSize( f.pointSize() );
  328. m_textBold->setChecked( f.bold() );
  329. m_textItalic->setChecked( f.italic() );
  330. m_textUnderline->setChecked( f.underline() );
  331. m_textStrikeOut->setChecked( f.strikeOut() );
  332. }
  333. void KNoteEdit::colorChanged( const TQColor &c )
  334. {
  335. TQPixmap pix( ICON_SIZE, ICON_SIZE );
  336. pix.fill( c );
  337. m_textColor->setIconSet( pix );
  338. }
  339. void KNoteEdit::alignmentChanged( int a )
  340. {
  341. // TODO: AlignAuto
  342. if ( ( a == AlignAuto ) || ( a & AlignLeft ) )
  343. m_textAlignLeft->setChecked( true );
  344. else if ( ( a & AlignHCenter ) )
  345. m_textAlignCenter->setChecked( true );
  346. else if ( ( a & AlignRight ) )
  347. m_textAlignRight->setChecked( true );
  348. else if ( ( a & AlignJustify ) )
  349. m_textAlignBlock->setChecked( true );
  350. }
  351. void KNoteEdit::verticalAlignmentChanged( VerticalAlignment a )
  352. {
  353. if ( a == AlignNormal )
  354. {
  355. m_textSuper->setChecked( false );
  356. m_textSub->setChecked( false );
  357. }
  358. else if ( a == AlignSuperScript )
  359. m_textSuper->setChecked( true );
  360. else if ( a == AlignSubScript )
  361. m_textSub->setChecked( true );
  362. }
  363. /** private methods **/
  364. void KNoteEdit::autoIndent()
  365. {
  366. int para, index;
  367. TQString string;
  368. getCursorPosition( &para, &index );
  369. while ( para > 0 && string.stripWhiteSpace().isEmpty() )
  370. string = text( --para );
  371. if ( string.stripWhiteSpace().isEmpty() )
  372. return;
  373. // This routine returns the whitespace before the first non white space
  374. // character in string.
  375. // It is assumed that string contains at least one non whitespace character
  376. // ie \n \r \t \v \f and space
  377. TQString indentString;
  378. int len = string.length();
  379. int i = 0;
  380. while ( i < len && string.at(i).isSpace() )
  381. indentString += string.at( i++ );
  382. if ( !indentString.isEmpty() )
  383. insert( indentString );
  384. }
  385. void KNoteEdit::emitLinkClicked( const TQString &s )
  386. {
  387. kdDebug(5500) << k_funcinfo << s << endl;
  388. }
  389. void KNoteEdit::enableRichTextActions()
  390. {
  391. m_textColor->setEnabled( true );
  392. m_textFont->setEnabled( true );
  393. m_textSize->setEnabled( true );
  394. m_textBold->setEnabled( true );
  395. m_textItalic->setEnabled( true );
  396. m_textUnderline->setEnabled( true );
  397. m_textStrikeOut->setEnabled( true );
  398. m_textAlignLeft->setEnabled( true );
  399. m_textAlignCenter->setEnabled( true );
  400. m_textAlignRight->setEnabled( true );
  401. m_textAlignBlock->setEnabled( true );
  402. m_textList->setEnabled( true );
  403. m_textSuper->setEnabled( true );
  404. m_textSub->setEnabled( true );
  405. // m_textIncreaseIndent->setEnabled( true );
  406. // m_textDecreaseIndent->setEnabled( true );
  407. }
  408. void KNoteEdit::disableRichTextActions()
  409. {
  410. m_textColor->setEnabled( false );
  411. m_textFont->setEnabled( false );
  412. m_textSize->setEnabled( false );
  413. m_textBold->setEnabled( false );
  414. m_textItalic->setEnabled( false );
  415. m_textUnderline->setEnabled( false );
  416. m_textStrikeOut->setEnabled( false );
  417. m_textAlignLeft->setEnabled( false );
  418. m_textAlignCenter->setEnabled( false );
  419. m_textAlignRight->setEnabled( false );
  420. m_textAlignBlock->setEnabled( false );
  421. m_textList->setEnabled( false );
  422. m_textSuper->setEnabled( false );
  423. m_textSub->setEnabled( false );
  424. // m_textIncreaseIndent->setEnabled( false );
  425. // m_textDecreaseIndent->setEnabled( false );
  426. }
  427. void KNoteEdit::slotAllowTab()
  428. {
  429. setTabChangesFocus(!tabChangesFocus());
  430. }
  431. TQPopupMenu *KNoteEdit::createPopupMenu( const TQPoint &pos )
  432. {
  433. enum { IdUndo, IdRedo, IdSep1, IdCut, IdCopy, IdPaste, IdClear, IdSep2, IdSelectAll };
  434. TQPopupMenu *menu = TQTextEdit::createPopupMenu( pos );
  435. if ( isReadOnly() )
  436. menu->changeItem( menu->idAt(0), SmallIconSet("edit-copy"), menu->text( menu->idAt(0) ) );
  437. else {
  438. int id = menu->idAt(0);
  439. menu->changeItem( id - IdUndo, SmallIconSet("edit-undo"), menu->text( id - IdUndo) );
  440. menu->changeItem( id - IdRedo, SmallIconSet("edit-redo"), menu->text( id - IdRedo) );
  441. menu->changeItem( id - IdCut, SmallIconSet("edit-cut"), menu->text( id - IdCut) );
  442. menu->changeItem( id - IdCopy, SmallIconSet("edit-copy"), menu->text( id - IdCopy) );
  443. menu->changeItem( id - IdPaste, SmallIconSet("edit-paste"), menu->text( id - IdPaste) );
  444. menu->changeItem( id - IdClear, SmallIconSet("edit-clear"), menu->text( id - IdClear) );
  445. menu->insertSeparator();
  446. id = menu->insertItem( SmallIconSet( "tools-check-spelling" ), i18n( "Check Spelling..." ),
  447. TQT_TQOBJECT(this), TQT_SLOT( checkSpelling() ) );
  448. if( text().isEmpty() )
  449. menu->setItemEnabled( id, false );
  450. menu->insertSeparator();
  451. id=menu->insertItem(i18n("Allow Tabulations"),this,TQT_SLOT(slotAllowTab()));
  452. menu->setItemChecked(id, !tabChangesFocus());
  453. }
  454. return menu;
  455. }
  456. #include "knoteedit.moc"