]> git.sven.stormbind.net Git - sven/vym.git/blob - texteditor.cpp
Import Upstream version 2.6.11
[sven/vym.git] / texteditor.cpp
1 #include "texteditor.h"
2
3 #include <QAction>
4 #include <QActionGroup>
5 #include <QApplication>
6 #include <QColorDialog>
7 #include <QComboBox>
8 #include <QFileDialog>
9 #include <QFontDialog>
10 #include <QMenuBar>
11 #include <QMessageBox>
12 #include <QPrintDialog>
13 #include <QPrinter>
14 #include <QStatusBar>
15 #include <QTextEdit>
16 #include <QToolBar>
17
18 #include <typeinfo>
19
20 #include "settings.h"
21 #include "shortcuts.h"
22
23 extern int statusbarTime;
24 extern Settings settings;
25
26 extern QAction *actionViewToggleNoteEditor;
27
28 extern QString vymName;
29
30 extern Switchboard switchboard;
31
32 extern QPrinter *printer;
33 extern bool debug;
34
35 ///////////////////////////////////////////////////////////////////////
36 ///////////////////////////////////////////////////////////////////////
37
38 TextEditor::TextEditor()
39 {
40     statusBar()->hide();    // Hide sizeGrip on default, which comes with statusBar
41
42     e = new QTextEdit( this);
43     e->setFocus();
44     e->setTabStopWidth (20);            // unit is pixel
45     e->setAutoFillBackground (true);
46     e->installEventFilter(this);
47     connect (e, SIGNAL( textChanged() ), this, SLOT( editorChanged() ) );
48     setCentralWidget( e );
49     statusBar()->showMessage( tr("Ready","Statusbar message"), statusbarTime);
50
51     connect(e, SIGNAL(currentCharFormatChanged(const QTextCharFormat &)),
52             this, SLOT(formatChanged(const QTextCharFormat &)));
53
54     // Don't show menubar per default
55     menuBar()->hide();
56
57     // Toolbars
58     setupFileActions();
59     setupEditActions();
60     setupFormatActions();
61     setupSettingsActions();
62     
63     // Various states
64     blockChangedSignal=false;
65     setInactive();
66
67     editorName = "Text editor";
68     setEditorTitle("");
69 }
70
71
72 TextEditor::~TextEditor()
73 {
74     // Save Settings
75     QString n = QString("/satellite/%1/").arg(shortcutScope);
76     settings.setValue( n + "geometry/size", size() );
77     settings.setValue( n + "geometry/pos", pos() );
78     settings.setValue( n + "state",saveState(0));
79
80     QString s;
81     if (actionSettingsFonthintDefault->isChecked() )
82         s = "fixed";
83     else    
84         s = "variable";
85     settings.setValue(n + "fonts/fonthintDefault",s );
86     settings.setValue(n + "fonts/varFont", varFont.toString() );
87     settings.setValue(n + "fonts/fixedFont", fixedFont.toString() );
88
89     settings.setValue(n + "colors/emptyEditor", colorEmptyEditor.name());
90     settings.setValue(n + "colors/filledEditor", colorFilledEditor.name());
91     settings.setValue(n + "colors/inactiveEditor", colorInactiveEditor.name());
92     settings.setValue(n + "colors/font", colorFont.name());
93 }
94
95 void TextEditor::init (const QString &scope) 
96 {   
97     shortcutScope = scope;
98     QString n = QString("/satellite/%1/").arg(shortcutScope);
99     restoreState (settings.value(n + "state", 0).toByteArray());
100     filenameHint="";
101     fixedFont.fromString (settings.value(
102         n + "fonts/fixedFont", "Courier,12,-1,5,48,0,0,0,1,0").toString()
103                           );
104     varFont.fromString( settings.value(
105         n + "fonts/varFont", "DejaVu Sans Mono,12,-1,0,50,0,0,0,0,0").toString()
106                         );
107     QString s = settings.value (n + "fonts/fonthintDefault", "variable").toString();
108     if (s == "fixed")
109     {
110         actionSettingsFonthintDefault->setChecked (true);
111         e->setCurrentFont (fixedFont);
112     } else
113     {
114         actionSettingsFonthintDefault->setChecked (false);
115         e->setCurrentFont (varFont);
116     }
117     
118     // Default colors
119     QPixmap pix( 16, 16 );
120     colorEmptyEditor.setNamedColor(   settings.value(n + "colors/emptyEditor", "#969696").toString() );
121     pix.fill( colorEmptyEditor );
122     actionEmptyEditorColor->setIcon(pix);
123
124     colorFilledEditor.setNamedColor(  settings.value(n + "colors/filledEditor","#ffffff").toString() );
125     pix.fill( colorFilledEditor );
126     actionFilledEditorColor->setIcon(pix);
127
128     colorInactiveEditor.setNamedColor(settings.value(n + "colors/inactiveEditor","#000000").toString() );
129     pix.fill( colorInactiveEditor );
130     actionInactiveEditorColor->setIcon(pix);
131
132     colorFont.setNamedColor(          settings.value(n + "colors/font","#000000").toString() );
133     e->setTextColor( colorFont );
134     pix.fill( colorFont );
135     actionFontColor->setIcon(pix);
136 }
137
138 bool TextEditor::isEmpty()
139 {
140     if (e->toPlainText().length()>0)
141         return false;
142     else
143         return true;
144 }
145
146
147 void TextEditor::setEditorTitle(const QString &s)
148 {
149     QString h;
150     s.isEmpty() ? h = editorName : h = editorName + ": " + s;
151     editorTitle = h;
152     setWindowTitle (editorTitle);
153 }
154
155 QString TextEditor::getEditorTitle()
156 {
157     return editorTitle;
158 }
159
160 void TextEditor::setEditorName( const QString &s)
161 {
162     editorName = s;
163 }
164
165 void TextEditor::setFont (const QFont &font)
166 {
167     blockChangedSignal = true;
168
169     QTextCursor tc=e->textCursor();
170     QTextCharFormat format=tc.charFormat();
171
172     tc.select(QTextCursor::Document);
173     format.setFont (font);
174     tc.setCharFormat (format);
175     tc.clearSelection();
176     fontChanged(fixedFont);
177
178     blockChangedSignal = false;
179 }
180
181 void TextEditor::setFontHint (const QString &fh)
182 {
183     if (fh=="fixed")
184     {
185         actionFormatUseFixedFont->setChecked (true);
186         e->setCurrentFont (fixedFont);
187         setFont (fixedFont);
188     }
189     else
190     {
191         actionFormatUseFixedFont->setChecked (false);
192         e->setCurrentFont (varFont);
193         setFont (varFont);
194     }
195 }
196
197 QString TextEditor::getFontHint()
198 {
199     if (actionFormatUseFixedFont->isChecked())
200         return "fixed";
201     else
202         return "var";
203 }
204
205 QString TextEditor::getFontHintDefault()
206 {
207     if (actionSettingsFonthintDefault->isChecked())
208         return "fixed";
209     else
210         return "var";
211 }
212
213 void TextEditor::setFilename(const QString &fn)
214 {
215     if (state==filledEditor)
216     {
217         if (fn.isEmpty() )
218         {
219             filename="";
220             statusBar()->showMessage( tr("No filename available for this note.","Statusbar message"), statusbarTime );
221         }
222         else
223         {
224             filename=fn;
225             statusBar()->showMessage( tr(QString( "Current filename is %1" ).arg( filename ).toUtf8(),"Statusbar message"), statusbarTime );
226         }
227     }
228 }
229
230 QString TextEditor::getFilename()
231 {
232     return filename;
233 }
234
235 void TextEditor::setFilenameHint(const QString &fnh)
236 {
237     filenameHint=fnh;
238 }
239
240 QString TextEditor::getFilenameHint()
241 {
242     return filenameHint;
243 }
244
245 QString TextEditor::getText()
246 {
247     if (e->toPlainText().isEmpty()) return QString();
248
249     if (actionFormatRichText->isChecked())
250         return e->toHtml();
251     else
252         return e->toPlainText();
253 }
254
255 VymText TextEditor::getVymText()
256 {
257     VymText vt;
258
259     if (actionFormatRichText->isChecked())
260         vt.setRichText(e->toHtml());
261     else
262         vt.setPlainText(e->toPlainText());
263
264     if (actionFormatUseFixedFont->isChecked() )
265         vt.setFontHint(getFontHint());
266
267     return vt;
268 }
269
270 bool TextEditor::findText(const QString &t, const QTextDocument::FindFlags &flags)
271 {
272     if (e->find (t,flags))
273         return true;
274     else
275         return false;
276 }
277
278 bool TextEditor::findText(const QString &t, const QTextDocument::FindFlags &flags, int i)
279 {
280     // Position at beginning
281     QTextCursor c=e->textCursor();
282     c.setPosition (0,QTextCursor::MoveAnchor);
283     e->setTextCursor (c);
284
285     // Search for t
286     int j=0;
287     while (j<=i)
288     {
289         if (!e->find (t,flags)) return false;
290         j++;
291     }
292     return true;
293
294 }
295
296 void TextEditor::setTextCursor (const QTextCursor &cursor)
297 {
298     e->setTextCursor (cursor);
299 }
300
301 QTextCursor TextEditor::getTextCursor()
302 {
303     return e->textCursor();
304 }
305
306 void TextEditor::setFocus()
307 {
308     e->setFocus();
309 }
310
311 void TextEditor::setupFileActions()
312 {
313     QToolBar *tb = addToolBar ( tr("Note Actions") );
314     tb->setObjectName ("noteEditorFileActions");
315     QMenu *fileMenu = menuBar()->addMenu( tr( "&Note","Menubar" ));
316
317     QString tag = tr ("Texteditor","Shortcuts");
318     QAction *a;
319     a = new QAction( QPixmap( ":/fileopen.png"), tr( "&Import..." ),this);
320     a->setShortcut( Qt::CTRL + Qt::Key_O );
321     a->setShortcutContext (Qt::WidgetWithChildrenShortcut);
322     switchboard.addSwitch( "textLoad", shortcutScope, a, tag);
323     connect( a, SIGNAL( triggered() ), this, SLOT( textLoad() ) );
324     tb->addAction (a);
325     fileMenu->addAction (a);
326     actionFileLoad=a;
327
328     fileMenu->addSeparator();
329     a = new QAction( QPixmap(":/filesave.png" ), tr( "&Export..." ), this);
330     a->setShortcut( Qt::CTRL + Qt::Key_S );
331     a->setShortcutContext (Qt::WidgetWithChildrenShortcut);
332     switchboard.addSwitch( "textSave", shortcutScope, a, tag);
333     connect( a, SIGNAL( triggered() ), this, SLOT( textSave() ) );
334     tb->addAction (a);
335     fileMenu->addAction (a);
336     addAction (a);
337     actionFileSave=a;
338     
339     a = new QAction(  tr( "Export &As... (HTML)" ), this);
340     connect( a, SIGNAL( triggered() ), this, SLOT( textSaveAs() ) );
341     fileMenu->addAction (a);
342     actionFileSaveAs=a;
343
344     a = new QAction( tr( "Export &As...(ASCII)" ), this);
345     a->setShortcut(Qt::ALT + Qt::Key_X );
346     a->setShortcutContext (Qt::WidgetWithChildrenShortcut);
347     switchboard.addSwitch( "textExportAsASCII", shortcutScope, a, tag);
348     connect( a, SIGNAL( triggered() ), this, SLOT( textExportAsASCII() ) );
349     fileMenu->addAction (a);
350     addAction (a);
351     actionFileSaveAs=a;
352
353     fileMenu->addSeparator();
354     a = new QAction( QPixmap(":/fileprint.png" ), tr( "&Print..." ),this);
355     a->setShortcut (Qt::CTRL + Qt::Key_P);
356     switchboard.addSwitch( "textPrint", shortcutScope, a, tag);
357     connect( a, SIGNAL( triggered() ), this, SLOT( textPrint() ) );
358     tb->addAction (a);
359     fileMenu->addAction (a);
360     actionFilePrint=a;
361     
362     a = new QAction( QPixmap( ":/edittrash.png"), tr( "&Delete All" ), this);
363     connect( a, SIGNAL( triggered() ), this, SLOT( reset() ) );
364     fileMenu->addAction (a);
365     tb->addAction (a);
366     actionFileDeleteAll=a;
367 }
368
369 void TextEditor::setupEditActions()
370 {
371     QString tag = tr ("Texteditor","Shortcuts");
372     QToolBar *editToolBar = addToolBar ( tr( "Edit Actions" ));
373     editToolBar->setObjectName ("noteEditorEditActions");
374     editToolBar->hide();
375     QMenu *editMenu = menuBar()->addMenu ( tr( "Edi&t" ));
376
377     QAction *a;
378     a = new QAction(QPixmap(":/undo.png"), tr( "&Undo" ), this );
379     a->setShortcut(Qt::CTRL + Qt::Key_Z );
380     a->setShortcutContext (Qt::WidgetWithChildrenShortcut);
381     switchboard.addSwitch( "textUndo", shortcutScope, a, tag);
382     connect( a, SIGNAL( triggered() ), e, SLOT( undo() ) );
383     editMenu->addAction (a);
384     editToolBar->addAction (a);
385     actionEditUndo=a;
386     
387     a = new QAction(QPixmap(":/redo.png" ), tr( "&Redo" ),this);
388     a->setShortcut( Qt::CTRL + Qt::Key_Y );
389     a->setShortcutContext (Qt::WidgetWithChildrenShortcut);
390     switchboard.addSwitch( "textRedo", shortcutScope, a, tag);
391     connect( a, SIGNAL( triggered() ), e, SLOT( redo() ) );
392     editMenu->addAction (a);
393     editToolBar->addAction (a);
394     actionEditRedo=a;
395
396     editMenu->addSeparator();
397     a = new QAction(QPixmap(), tr( "Select and copy &all" ),this);
398     a->setShortcutContext (Qt::WidgetShortcut);
399     a->setShortcut( Qt::CTRL + Qt::Key_A );
400     switchboard.addSwitch( "textCopyAll", shortcutScope, a, tag);
401     connect( a, SIGNAL( triggered() ), this, SLOT( editCopyAll() ) );
402     editMenu->addAction (a);
403
404     editMenu->addSeparator();
405     a = new QAction(QPixmap(":/editcopy.png" ), tr( "&Copy" ),this);
406     a->setShortcut( Qt::CTRL + Qt::Key_C );
407     a->setShortcutContext (Qt::WidgetWithChildrenShortcut);
408     switchboard.addSwitch( "textCopy", shortcutScope, a, tag);
409     connect( a, SIGNAL( triggered() ), e, SLOT( copy() ) );
410     editMenu->addAction (a);
411     editToolBar->addAction (a);
412     actionEditCopy=a;
413     
414     a = new QAction(QPixmap(":/editcut.png" ), tr( "Cu&t" ),this);
415     a->setShortcut( Qt::CTRL + Qt::Key_X );
416     a->setShortcutContext (Qt::WidgetWithChildrenShortcut);
417     switchboard.addSwitch( "textCut", shortcutScope, a, tag);
418     connect( a, SIGNAL( triggered() ), e, SLOT( cut() ) );
419     editMenu->addAction (a);
420     editToolBar->addAction (a);
421     actionEditCut=a;
422
423     a = new QAction(QPixmap(":/editpaste.png" ), tr( "&Paste" ),this);
424     a->setShortcut( Qt::CTRL + Qt::Key_V );
425     a->setShortcutContext (Qt::WidgetWithChildrenShortcut);
426     switchboard.addSwitch( "textPaste", shortcutScope, a, tag);
427     connect( a, SIGNAL( triggered() ), e, SLOT( paste() ) );
428     editMenu->addAction (a);
429     editToolBar->addAction (a);
430     actionEditPaste=a;
431 }
432
433 void TextEditor::setupFormatActions()
434 {
435     QString tag = tr ("Texteditor","Shortcuts");
436     QToolBar *fontHintsToolBar = addToolBar ( tr("Font hints","toolbar in texteditor" ));
437     fontHintsToolBar->setObjectName ("noteEditorFontToolBar");
438     QMenu *formatMenu = menuBar()->addMenu ( tr( "F&ormat" ));
439
440     QAction *a;
441
442     a = new QAction( QPixmap(":/formatfixedfont.png"), tr( "&Font hint" ), this );
443     a->setShortcut(Qt::CTRL + Qt::Key_H);
444     a->setCheckable (true);
445     a->setChecked (settings.value("/noteeditor/fonts/useFixedByDefault",false).toBool() );
446     switchboard.addSwitch( "textToggleFonthint", shortcutScope, a, tag);
447     connect( a, SIGNAL( triggered() ), this, SLOT( toggleFonthint() ) );
448     formatMenu->addAction (a);
449     fontHintsToolBar->addAction (a);
450     actionFormatUseFixedFont=a;
451
452     // Original icon: ./share/icons/oxygen/22x22/actions/format-text-color.png
453     a = new QAction( QPixmap(":/formatrichtext.png"), tr( "&Richtext" ), this);
454     a->setShortcut ( Qt::CTRL + Qt::Key_R);
455 //    a->setShortcutContext (Qt::WidgetShortcut);
456     a->setCheckable (true);
457     switchboard.addSwitch( "textToggleRichText", shortcutScope, a, tag);
458     connect( a, SIGNAL( triggered() ), this, SLOT( toggleRichText() ) );
459     formatMenu->addAction (a);
460     fontHintsToolBar->addAction (a);
461     actionFormatRichText=a;
462
463     QToolBar *fontToolBar = addToolBar ( tr("Fonts","toolbar in texteditor" ));
464     fontToolBar->setObjectName ("noteEditorFontToolBar");
465
466     comboFont = new QComboBox;
467     fontToolBar->addWidget (comboFont);
468     QFontDatabase fontDB;
469     comboFont->insertItems ( 0,fontDB.families() );
470     connect( comboFont, SIGNAL( activated( const QString & ) ),
471              this, SLOT( textFamily( const QString & ) ) );
472
473     comboSize = new QComboBox;
474     fontToolBar->addWidget (comboSize);
475     QList<int> sizes=fontDB.standardSizes();
476     QList<int>::iterator it = sizes.begin();
477     int i=0;
478     while (it != sizes.end())
479     {
480         i++;
481         ++it; // increment i before using it
482         comboSize->insertItem ( i, QString::number(*it));
483     }
484     connect( comboSize, SIGNAL( activated( const QString & ) ),
485              this, SLOT( textSize( const QString & ) ) );
486
487     formatMenu->addSeparator();
488
489     QToolBar *formatToolBar = addToolBar ( tr("Format","toolbar in texteditor" ));
490     formatToolBar->setObjectName ("noteEditorFormatToolBar");
491
492     QPixmap pix( 16, 16 );
493     pix.fill( e->textColor());
494     a = new QAction( pix, tr( "&Color..." ), this);
495     formatMenu->addAction (a);
496     formatToolBar->addAction (a);
497     connect( a, SIGNAL( triggered() ), this, SLOT( textColor() ) );
498     actionTextColor=a;
499
500     a = new QAction( QPixmap (":/text_bold.png"), tr( "&Bold" ), this);
501     a->setShortcut(Qt::CTRL + Qt::Key_B );
502     a->setShortcutContext (Qt::WidgetWithChildrenShortcut);
503     switchboard.addSwitch( "textToggleBold", shortcutScope, a, tag);
504     connect( a, SIGNAL( triggered() ), this, SLOT( textBold() ) );
505     formatToolBar->addAction (a);
506     formatMenu->addAction (a);
507     a->setCheckable( true );
508     actionTextBold=a;
509     
510     a = new QAction( QPixmap(":/text_italic.png"), tr( "&Italic" ),  this);
511     a->setShortcut(Qt::CTRL + Qt::Key_I);
512     a->setShortcutContext (Qt::WidgetWithChildrenShortcut);
513     switchboard.addSwitch( "textToggleItalic", shortcutScope, a, tag);
514     connect( a, SIGNAL( triggered() ), this, SLOT( textItalic() ) );
515     formatToolBar->addAction (a);
516     formatMenu->addAction (a);
517     a->setCheckable( true );
518     actionTextItalic=a;
519     
520     a = new QAction( QPixmap (":/text_under.png"), tr( "&Underline" ), this);
521     a->setShortcut(Qt::CTRL + Qt::Key_U );
522     a->setShortcutContext (Qt::WidgetWithChildrenShortcut);
523     switchboard.addSwitch( "textToggleUnderline", shortcutScope, a, tag);
524     connect( a, SIGNAL( triggered() ), this, SLOT( textUnderline() ) );
525     formatToolBar->addAction (a);
526     formatMenu->addAction (a);
527     a->setCheckable( true );
528     //richTextWidgets.append((QWidget*)a);
529     actionTextUnderline=a;
530     formatMenu->addSeparator();
531
532     QActionGroup * actGrp2 = new QActionGroup( this );
533     actGrp2->setExclusive(true);
534     a = new QAction( QPixmap (":/text_sub.png"), tr( "Subs&cript" ),actGrp2 );
535     a->setShortcut( Qt::CTRL + Qt::SHIFT + Qt::Key_B );
536     a->setShortcutContext (Qt::WidgetWithChildrenShortcut);
537     a->setCheckable( true );
538     formatToolBar->addAction (a);
539     formatMenu->addAction (a);
540     switchboard.addSwitch( "textToggleSub", shortcutScope, a, tag);
541     connect(a, SIGNAL(triggered()), this, SLOT(textVAlign()));
542     actionAlignSubScript=a;
543
544     a = new QAction( QPixmap (":/text_super.png"), tr( "Su&perscript" ),actGrp2  );
545     a->setShortcut( Qt::CTRL + Qt::SHIFT + Qt::Key_P );
546     a->setShortcutContext (Qt::WidgetWithChildrenShortcut);
547     a->setCheckable( true );
548     formatToolBar->addAction (a);
549     formatMenu->addAction (a);
550     switchboard.addSwitch( "textToggleSuper", shortcutScope, a, tag);
551     connect(a, SIGNAL(triggered()), this, SLOT(textVAlign()));
552     actionAlignSuperScript=a;
553     QActionGroup *grp = new QActionGroup( this );
554     connect( grp, SIGNAL( triggered( QAction* ) ), this, SLOT( textAlign( QAction* ) ) );
555
556     formatMenu->addSeparator();
557
558     a = new QAction( QPixmap (":/text_left.png"), tr( "&Left" ),grp );
559     //a->setShortcut( Qt::CTRL+Qt::Key_L );
560     a->setCheckable( true );
561     formatToolBar->addAction (a);
562     formatMenu->addAction (a);
563     actionAlignLeft=a;
564     a = new QAction( QPixmap (":/text_center.png"), tr( "C&enter" ),grp);
565     //a->setShortcut(  Qt::CTRL + Qt::Key_E);
566     a->setCheckable( true );
567     formatToolBar->addAction (a);
568     formatMenu->addAction (a);
569     actionAlignCenter=a;
570     a = new QAction( QPixmap (":/text_right.png" ), tr( "&Right" ), grp);
571     //a->setShortcut(Qt::CTRL + Qt::Key_R );
572     a->setCheckable( true );
573     formatToolBar->addAction (a);
574     formatMenu->addAction (a);
575     actionAlignRight=a;
576     a = new QAction( QPixmap ( ":/text_block.png"), tr( "&Justify" ), grp );
577     //a->setShortcut(Qt::CTRL + Qt::Key_J );
578     a->setCheckable( true );
579     formatToolBar->addAction (a);
580     formatMenu->addAction (a);
581     actionAlignJustify=a;
582 }
583
584 void TextEditor::setupSettingsActions()
585 {
586     QMenu *settingsMenu = menuBar()->addMenu ( tr( "&Settings" ));
587
588     QAction *a;
589     a = new QAction(tr( "Set &fixed font" ), this);
590     connect( a, SIGNAL( triggered() ), this, SLOT( setFixedFont() ) );
591     settingsMenu->addAction (a);
592     actionSettingsFixedFont=a;
593
594     a = new QAction(tr( "Set &variable font" ), this);
595     connect( a, SIGNAL( triggered() ), this, SLOT( setVarFont() ) );
596     settingsMenu->addAction (a);
597     actionSettingsVarFont=a;
598
599     a = new QAction(tr( "&fixed font is default" ),  this);
600     a->setCheckable (true);
601     // set state later in constructor...
602     settingsMenu->addAction (a);
603     actionSettingsFonthintDefault=a;
604
605     settingsMenu->addSeparator();
606
607     a = new QAction( tr( "Set empty editor background color", "TextEditor") + "...", this  );
608     settingsMenu->addAction (a);
609     connect( a, SIGNAL( triggered() ), this, SLOT( setEmptyEditorColor() ) );
610     actionEmptyEditorColor = a;
611
612     a = new QAction( tr( "Set filled editor background color", "TextEditor") + "...", this  );
613     settingsMenu->addAction (a);
614     connect( a, SIGNAL( triggered() ), this, SLOT( setFilledEditorColor() ) );
615     actionFilledEditorColor = a;
616
617     a = new QAction( tr( "Set inactive editor background color", "TextEditor") + "...", this  );
618     settingsMenu->addAction (a);
619     connect( a, SIGNAL( triggered() ), this, SLOT( setInactiveEditorColor() ) );
620     actionInactiveEditorColor = a;
621
622     a = new QAction( tr( "Set default font color", "TextEditor") + "...", this  );
623     settingsMenu->addAction (a);
624     connect( a, SIGNAL( triggered() ), this, SLOT( setFontColor() ) );
625     actionFontColor = a;
626 }
627
628 void TextEditor::textLoad()
629 {
630     if (state!=inactiveEditor)
631     {
632         if (!isEmpty())
633         {
634             QMessageBox mb( vymName + " - " +tr("Note Editor"),
635                             "Loading will overwrite the existing note",
636                             QMessageBox::Warning,
637                             QMessageBox::Yes | QMessageBox::Default,
638                             QMessageBox::Cancel,
639                             0 );
640             mb.setButtonText( QMessageBox::Yes, "Load note" );
641             switch( mb.exec() ) {
642             case QMessageBox::Cancel:
643                 return;
644                 break;
645             }
646         }
647         // Load note
648         QFileDialog *fd=new QFileDialog( this);
649         QStringList types;
650         types<< "Text (*.txt *.html)"<<
651                 "VYM notes and HTML (*.html)" <<
652                 "ASCII texts (*.txt)" <<
653                 "All files (*)";
654         fd->setNameFilters (types);
655         fd->setDirectory (QDir().current());
656         fd->show();
657         QString fn;
658         if ( fd->exec() == QDialog::Accepted &&!fd->selectedFiles().isEmpty() )
659             fn = fd->selectedFiles().first();
660
661         if ( !fn.isEmpty() )
662         {
663             QFile f( fn );
664             if ( !f.open( QIODevice::ReadOnly ) )
665                 return;
666
667             QTextStream ts( &f );
668             setTextAuto ( ts.readAll() );
669             editorChanged();
670         }
671     }
672 }
673
674 void TextEditor::closeEvent( QCloseEvent* ce )
675 {
676     ce->accept();   // TextEditor can be reopened with show()
677     hide();
678     emit (windowClosed() );
679     return;
680 }
681
682 bool TextEditor::eventFilter( QObject *obj, QEvent *ev)
683 {
684     if (obj == e ) {
685         if (ev->type() == QEvent::KeyPress) {
686             QKeyEvent *keyEvent = static_cast<QKeyEvent*>(ev);
687             if(keyEvent == QKeySequence::Paste) 
688             {
689                 // switch editor mode to match clipboard content before pasting
690                 const QClipboard *clipboard = QApplication::clipboard();
691                 const QMimeData *mimeData = clipboard->mimeData();
692
693                 if (mimeData->hasHtml()) setRichTextMode(true);
694             } 
695         }
696     }
697     // pass the event on to the parent class
698     return QMainWindow::eventFilter(obj, ev);
699 }
700
701 void TextEditor::editorChanged()
702 {
703     if (isEmpty())
704         state=emptyEditor;
705     else
706         state=filledEditor;
707
708     if (state==emptyEditor)
709         setState (emptyEditor);
710     else
711         setState (filledEditor);
712     if (!blockChangedSignal) emit (textHasChanged() );
713 }
714
715 void TextEditor::setRichText(const QString &t)
716 {
717     blockChangedSignal=true;
718     e->setReadOnly(false);
719     reset();
720
721     e->setHtml(t);
722     actionFormatRichText->setChecked (true);
723
724     updateActions();
725     blockChangedSignal=false;
726 }
727
728 void TextEditor::setPlainText(const QString &t)
729 {
730     blockChangedSignal=true;
731     e->setReadOnly(false);
732     reset();
733
734     e->setPlainText(t);
735     actionFormatRichText->setChecked (false);
736
737     updateActions();
738     blockChangedSignal=false;
739 }
740
741
742 void TextEditor::setTextAuto(const QString &t)
743 {
744     if (Qt::mightBeRichText (t))
745         setRichText( t);
746     else
747         setPlainText( t );
748 }
749
750 void TextEditor::setVymText( const VymText &vt)
751 {
752     if (vt.isRichText())
753         setRichText(vt.getText());
754     else
755         setPlainText(vt.getText());
756 }
757
758 void TextEditor::setInactive()
759 {
760     state=inactiveEditor;
761     e->setPlainText("");
762     setState (inactiveEditor);
763     e->setReadOnly (true);
764
765     updateActions();
766 }
767
768 void TextEditor::editCopyAll()
769 {
770     e->selectAll();
771     e->copy();
772 }
773
774 void TextEditor::reset()
775 {
776     e->selectAll();
777     e->textCursor().deleteChar();
778     e->setTextColor( colorFont );
779 }
780
781 void TextEditor::textSaveAs()   
782 {
783     QString caption=tr ("Export Note to single file");
784     QString fn = QFileDialog::getSaveFileName(
785                 this,
786                 caption,
787                 QString::null,
788                 "VYM Note (HTML) (*.html);;All files (*)",
789                 0,
790                 QFileDialog::DontConfirmOverwrite );
791
792     if ( !fn.isEmpty() )
793     {
794         QFile file (fn);
795         if (file.exists())
796         {
797             QMessageBox mb( vymName,
798                             tr("The file %1\nexists already.\nDo you want to overwrite it?","dialog 'save note as'").arg(fn),
799                             QMessageBox::Warning,
800                             QMessageBox::Yes | QMessageBox::Default,
801                             QMessageBox::Cancel | QMessageBox::Escape,
802                             Qt::NoButton );
803             mb.setButtonText( QMessageBox::Yes, tr("Overwrite") );
804             mb.setButtonText( QMessageBox::No, tr("Cancel"));
805             switch( mb.exec() ) {
806             case QMessageBox::Yes:
807                 // save
808                 filename = fn;
809                 textSave();
810                 return;
811             case QMessageBox::Cancel:
812                 // do nothing
813                 break;
814             }
815         } else
816         {
817             filename = fn;
818             textSave();
819             return;
820         }
821     }
822     statusBar()->showMessage(tr( "Couldn't export note ","dialog 'save note as'") + fn, statusbarTime );
823 }
824
825
826 void TextEditor::textSave()
827 {
828     if ( filename.isEmpty() )
829     {
830         textSaveAs();
831         return;
832     }
833
834     QString text = e->toHtml(); //FIXME-4 or plaintext? check...
835     QFile f( filename );
836     if ( !f.open( QIODevice::WriteOnly ) )
837     {
838         statusBar()->showMessage( QString("Could not write to %1").arg(filename),
839                                   statusbarTime );
840         return;
841     }
842
843     QTextStream t( &f );
844     t.setCodec("UTF-8");
845     t << text;
846     f.close();
847
848     e->document()->setModified( false );
849
850     statusBar()->showMessage( QString( "Note exported as %1" ).arg( filename ), statusbarTime );
851 }
852
853 void TextEditor::textExportAsASCII()
854 {
855     QString fn,s;
856     if (!filenameHint.isEmpty())
857     {
858         if (!filenameHint.contains (".txt"))
859             s = filenameHint+".txt";
860         else
861             s = filenameHint;
862     } else
863         s = QString::null;
864     QString caption = tr("Export Note to single file (ASCII)");
865     fn = QFileDialog::getSaveFileName(this, caption, s, "VYM Note (ASCII) (*.txt);;All files (*)" );
866     int ret = -1;
867
868     if ( !fn.isEmpty() )
869     {
870         QFile file (fn);
871         if (file.exists())
872         {
873             QMessageBox mb( vymName,
874                             tr("The file %1\nexists already.\nDo you want to overwrite it?","dialog 'save note as'").arg(fn),
875                             QMessageBox::Warning,
876                             QMessageBox::Yes | QMessageBox::Default,
877                             QMessageBox::Cancel | QMessageBox::Escape,
878                             Qt::NoButton );
879             mb.setButtonText( QMessageBox::Yes, tr("Overwrite") );
880             mb.setButtonText( QMessageBox::No, tr("Cancel"));
881             ret=mb.exec();
882         }
883         if (ret==QMessageBox::Cancel)
884             return;
885
886         // save
887         if ( !file.open( QIODevice::WriteOnly ) )
888             statusBar()->showMessage( QString("Could not write to %1").arg(filename),
889                                       statusbarTime );
890         else
891         {
892             QTextStream t( &file );
893             t << getVymText().getTextASCII();
894             file.close();
895
896             statusBar()->showMessage( QString( "Note exported as %1" ).arg( fn ), statusbarTime );
897         }
898     }
899 }
900
901
902 void TextEditor::textPrint()
903 {
904     QTextDocument *document = e->document();
905
906     QPrintDialog dialog (printer, this);
907     dialog.setWindowTitle(tr("Print","TextEditor"));
908     if (dialog.exec() != QDialog::Accepted)
909         return;
910
911     document->print(printer);
912 }
913
914 void TextEditor::textEditUndo()
915 {
916 }
917
918 void TextEditor::toggleFonthint()
919 {
920     if (!actionFormatUseFixedFont->isChecked() )
921     {
922         e->setCurrentFont (varFont);
923         setFont (varFont);
924     }
925     else
926     {
927         e->setCurrentFont (fixedFont);
928         setFont (fixedFont);
929     }
930     emit( textHasChanged() );
931 }
932
933 void TextEditor::setRichTextMode(bool b)
934 {
935     if (b)
936     {
937         e->setHtml (e->toHtml());
938         actionFormatUseFixedFont->setEnabled(false);
939         actionFormatRichText->setChecked(true);
940     } else
941     {
942         e->setPlainText (e->toPlainText());
943         actionFormatUseFixedFont->setEnabled(true);
944         actionFormatRichText->setChecked(false);
945     }
946     updateActions();
947     emit( textHasChanged() );
948 }
949
950 void TextEditor::toggleRichText()
951 {
952     if (actionFormatRichText->isChecked() )
953         setRichTextMode( true );
954     else
955         setRichTextMode( false );
956 }
957
958 void TextEditor::setFixedFont()
959 {
960     bool ok;
961     QFont font =QFontDialog::getFont( &ok, fixedFont, this );
962     if ( ok ) fixedFont=font;
963 }
964
965 void TextEditor::setVarFont()
966 {
967     bool ok;
968     QFont font =QFontDialog::getFont( &ok, varFont, this );
969     if ( ok ) varFont=font;
970 }
971
972 void TextEditor::textBold()
973 {
974     if ( actionTextBold->isChecked())
975         e->setFontWeight( QFont::Bold );
976     else
977         e->setFontWeight( QFont::Normal);
978 }
979
980 void TextEditor::textUnderline()
981 {
982     e->setFontUnderline( actionTextUnderline->isChecked() );
983 }
984
985 void TextEditor::textItalic()
986 {
987     e->setFontItalic( actionTextItalic->isChecked() );
988 }
989
990 void TextEditor::textFamily( const QString &f )
991 {
992     e->setFontFamily( f );
993 }
994
995 void TextEditor::textSize( const QString &p )
996 {
997     e->setFontPointSize( p.toInt() );
998 }
999
1000
1001 void TextEditor::textColor()
1002 {
1003     QColor col = QColorDialog::getColor( e->textColor(), this );
1004     if ( !col.isValid() ) return;
1005     e->setTextColor( col );
1006     /*
1007     QPixmap pix( 16, 16 );
1008     pix.fill( col );
1009     actionTextColor->setIcon( pix );
1010     */
1011 }
1012
1013 void TextEditor::textAlign( QAction *a ) 
1014 {
1015     QTextCursor c = e->textCursor();
1016
1017     if ( a == actionAlignLeft )
1018         e->setAlignment( Qt::AlignLeft );
1019     else if ( a == actionAlignCenter )
1020         e->setAlignment( Qt::AlignHCenter );
1021     else if ( a == actionAlignRight )
1022         e->setAlignment( Qt::AlignRight );
1023     else if ( a == actionAlignJustify )
1024         e->setAlignment( Qt::AlignJustify );
1025 }
1026
1027 void TextEditor::textVAlign()
1028 {
1029     QTextCharFormat format;
1030
1031     if ( sender() == actionAlignSuperScript && actionAlignSuperScript->isChecked()) {
1032         format.setVerticalAlignment(QTextCharFormat::AlignSuperScript);
1033     } else if (sender() == actionAlignSubScript && actionAlignSubScript->isChecked()) {
1034         format.setVerticalAlignment(QTextCharFormat::AlignSubScript);
1035     } else {
1036         format.setVerticalAlignment(QTextCharFormat::AlignNormal);
1037     }
1038     e->mergeCurrentCharFormat(format);
1039 }
1040
1041
1042 void TextEditor::fontChanged( const QFont &f )
1043 {
1044     int i=comboFont->findText(f.family());
1045     if (i>=0) comboFont->setCurrentIndex (i);
1046     i=comboSize->findText(QString::number(f.pointSize()));
1047     if (i>=0) comboSize->setCurrentIndex(i);
1048     actionTextBold->setChecked( f.bold() );
1049     actionTextItalic->setChecked( f.italic() );
1050     actionTextUnderline->setChecked( f.underline() );
1051 }
1052
1053 void TextEditor::colorChanged( const QColor &c )
1054 {
1055     QPixmap pix( 16, 16 );
1056     pix.fill( c );
1057     actionTextColor->setIcon( pix );
1058 }
1059
1060 void TextEditor::formatChanged( const QTextCharFormat &f )
1061 {
1062     if (!actionFormatRichText->isChecked() ) return;
1063     fontChanged(f.font());
1064     colorChanged(f.foreground().color());
1065     alignmentChanged(e->alignment());
1066     verticalAlignmentChanged (f.verticalAlignment());
1067 }
1068
1069 void TextEditor::alignmentChanged( int a )
1070 {
1071     if ( ( a == Qt::AlignLeft ) || ( a & Qt::AlignLeft ))
1072         actionAlignLeft->setChecked( true );
1073     else if ( ( a & Qt::AlignHCenter ) )
1074         actionAlignCenter->setChecked( true );
1075     else if ( ( a & Qt::AlignRight ) )
1076         actionAlignRight->setChecked( true );
1077     else if ( ( a & Qt::AlignJustify ) )
1078         actionAlignJustify->setChecked( true );
1079 }
1080
1081 void TextEditor::verticalAlignmentChanged(QTextCharFormat::VerticalAlignment a)
1082 {
1083     actionAlignSubScript->setChecked (false);
1084     actionAlignSuperScript->setChecked (false);
1085     switch (a)
1086     {
1087     case QTextCharFormat::AlignSuperScript:
1088         actionAlignSuperScript->setChecked (true);
1089         break;
1090     case QTextCharFormat::AlignSubScript:
1091         actionAlignSubScript->setChecked (true);
1092         break;
1093     default: ;
1094     }
1095 }
1096
1097 void TextEditor::updateActions()
1098 {
1099     bool b;
1100     if (state==inactiveEditor)
1101         b=false;
1102     else
1103         b=true;
1104     actionFileLoad->setEnabled(b);
1105     actionFileSave->setEnabled(b);
1106     actionFileSaveAs->setEnabled(b);
1107     actionFilePrint->setEnabled(b);
1108     actionFileDeleteAll->setEnabled(b);
1109     actionEditUndo->setEnabled(b);
1110     actionEditRedo->setEnabled(b);
1111     actionEditCopy->setEnabled(b);
1112     actionEditCut->setEnabled(b);
1113     actionEditPaste->setEnabled(b);
1114     actionFormatUseFixedFont->setEnabled(b);
1115     actionFormatRichText->setEnabled(b);
1116     
1117     if (!actionFormatRichText->isChecked() || !b)
1118     {
1119         comboFont->setEnabled (false);
1120         comboSize->setEnabled (false);
1121         actionTextColor->setEnabled (false);
1122         actionTextBold->setEnabled (false);
1123         actionTextUnderline->setEnabled(false);
1124         actionTextItalic->setEnabled(false);
1125         actionTextColor->setEnabled(false);
1126         actionAlignSubScript->setEnabled(false);
1127         actionAlignSuperScript->setEnabled(false);
1128         actionAlignLeft->setEnabled(false);
1129         actionAlignCenter->setEnabled(false);
1130         actionAlignRight->setEnabled(false);
1131         actionAlignJustify->setEnabled(false);
1132     }
1133     else
1134     {
1135         comboFont->setEnabled (true);
1136         comboSize->setEnabled (true);
1137         actionTextColor->setEnabled (true);
1138         actionTextBold->setEnabled (true);
1139         actionTextUnderline->setEnabled(true);
1140         actionTextItalic->setEnabled(true);
1141         actionTextColor->setEnabled(true);
1142         actionAlignSubScript->setEnabled(true);
1143         actionAlignSuperScript->setEnabled(true);
1144         actionAlignLeft->setEnabled(true);
1145         actionAlignCenter->setEnabled(true);
1146         actionAlignRight->setEnabled(true);
1147         actionAlignJustify->setEnabled(true);
1148         actionFormatUseFixedFont->setEnabled(false);
1149     }
1150 }
1151
1152 void TextEditor::setState (EditorState s)
1153 {
1154     
1155     QPalette p = palette();
1156     QColor c;
1157     switch (s)
1158     {
1159         case emptyEditor:    c = colorEmptyEditor; break;
1160         case filledEditor:   c = colorFilledEditor; break; 
1161         case inactiveEditor: c = colorInactiveEditor;
1162     }
1163     p.setColor(QPalette::Active, static_cast<QPalette::ColorRole>(9), c);
1164     p.setColor(QPalette::Inactive, static_cast<QPalette::ColorRole>(9), c);
1165     e->setPalette(p);
1166 }
1167
1168 void TextEditor::setEmptyEditorColor()
1169 {
1170     QColor col = QColorDialog::getColor( colorEmptyEditor, NULL);
1171     if ( !col.isValid() ) return;
1172     colorEmptyEditor = col;
1173     QPixmap pix( 16, 16 );
1174     pix.fill( colorEmptyEditor );
1175     actionEmptyEditorColor->setIcon(pix);
1176 }
1177
1178 void TextEditor::setInactiveEditorColor()
1179 {
1180     QColor col = QColorDialog::getColor( colorInactiveEditor, NULL);
1181     if ( !col.isValid() ) return;
1182     colorInactiveEditor = col;
1183     QPixmap pix( 16, 16 );
1184     pix.fill( colorInactiveEditor );
1185     actionInactiveEditorColor->setIcon(pix);
1186 }
1187
1188 void TextEditor::setFilledEditorColor()
1189 {
1190     QColor col = QColorDialog::getColor( colorFilledEditor, NULL);
1191     if ( !col.isValid() ) return;
1192     colorFilledEditor = col;
1193     QPixmap pix( 16, 16 );
1194     pix.fill( colorFilledEditor );
1195     actionFilledEditorColor->setIcon(pix);
1196 }
1197
1198 void TextEditor::setFontColor()
1199 {
1200     QColor col = QColorDialog::getColor( colorFont, NULL);
1201     if ( !col.isValid() ) return;
1202     colorFont = col;
1203     QPixmap pix( 16, 16 );
1204     pix.fill( colorFont );
1205     actionFontColor->setIcon(pix);
1206 }
1207