+#include "texteditor.h"
+
+#include <QAction>
+#include <QActionGroup>
+#include <QApplication>
+#include <QColorDialog>
+#include <QComboBox>
+#include <QFileDialog>
+#include <QFontDialog>
+#include <QMenuBar>
+#include <QMessageBox>
+#include <QPrintDialog>
+#include <QPrinter>
+#include <QStatusBar>
+#include <QTextEdit>
+#include <QToolBar>
+
+#include <typeinfo>
+
+#include "mainwindow.h"
+#include "settings.h"
+#include "shortcuts.h"
+
+extern Main *mainWindow;
+extern int statusbarTime;
+extern Settings settings;
+
+extern QAction *actionViewToggleNoteEditor;
+
+extern QString vymName;
+
+extern Switchboard switchboard;
+
+extern QPrinter *printer;
+extern bool debug;
+
+///////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////
+
+TextEditor::TextEditor()
+{
+ statusBar()->hide(); // Hide sizeGrip on default, which comes with statusBar
+
+ e = new QTextEdit(this);
+ e->setFocus();
+ e->setTabStopDistance(20); // unit is pixel, default would be 80
+ e->setAutoFillBackground(true);
+ e->installEventFilter(this);
+ connect(e, SIGNAL(textChanged()), this, SLOT(editorChanged()));
+ setCentralWidget(e);
+ statusBar()->showMessage(tr("Ready", "Statusbar message"), statusbarTime);
+
+ connect(e, SIGNAL(currentCharFormatChanged(const QTextCharFormat &)), this,
+ SLOT(formatChanged(const QTextCharFormat &)));
+
+ // Don't show menubar per default
+ menuBar()->hide();
+
+ // Toolbars
+ setupFileActions();
+ setupEditActions();
+ setupFormatActions();
+ setupSettingsActions();
+
+ // Various states
+ blockChangedSignal = false;
+ blockTextUpdate = false;
+ setInactive();
+
+ editorName = "Text editor";
+ setEditorTitle("");
+}
+
+TextEditor::~TextEditor()
+{
+ // Save Settings
+ QString n = QString("/satellite/%1/").arg(shortcutScope);
+ settings.setValue(n + "geometry/size", size());
+ settings.setValue(n + "geometry/pos", pos());
+ settings.setValue(n + "state", saveState(0));
+
+ QString s;
+ if (actionSettingsFonthintDefault->isChecked())
+ s = "fixed";
+ else
+ s = "variable";
+ settings.setValue(n + "fonts/fonthintDefault", s);
+ settings.setValue(n + "fonts/varFont", varFont.toString());
+ settings.setValue(n + "fonts/fixedFont", fixedFont.toString());
+
+ settings.setValue(n + "colors/richTextDefaultBackground", colorRichTextDefaultBackground.name());
+ settings.setValue(n + "colors/richTextDefaultForeground", colorRichTextDefaultForeground.name());
+}
+
+void TextEditor::init(const QString &scope)
+{
+ shortcutScope = scope;
+ QString n = QString("/satellite/%1/").arg(shortcutScope);
+ restoreState(settings.value(n + "state", 0).toByteArray());
+ filenameHint = "";
+ fixedFont.fromString(
+ settings.value(n + "fonts/fixedFont", "Courier,12,-1,5,48,0,0,0,1,0")
+ .toString());
+ varFont.fromString(
+ settings
+ .value(n + "fonts/varFont", "DejaVu Sans Mono,12,-1,0,50,0,0,0,0,0")
+ .toString());
+ QString s =
+ settings.value(n + "fonts/fonthintDefault", "variable").toString();
+ if (s == "fixed") {
+ actionSettingsFonthintDefault->setChecked(true);
+ e->setCurrentFont(fixedFont);
+ }
+ else {
+ actionSettingsFonthintDefault->setChecked(false);
+ e->setCurrentFont(varFont);
+ }
+
+ // Default colors for RichText //FIXME-2 here? Though we use plainText as default?
+ QPixmap pix(16, 16);
+ colorRichTextDefaultBackground.setNamedColor(
+ settings.value(n + "colors/richTextDefaultBackground", "#ffffff").toString());
+ pix.fill(colorRichTextDefaultBackground);
+ actionFilledEditorColor->setIcon(pix);
+
+
+ colorRichTextDefaultForeground.setNamedColor(
+ settings.value(n + "colors/richTextDefaultForeground", "#000000").toString());
+ pix.fill(colorRichTextDefaultForeground);
+ actionFontColor->setIcon(pix);
+
+ // Default is PlainText
+ actionFormatRichText->setChecked(false);
+ clear();
+}
+
+bool TextEditor::isEmpty()
+{
+ if (e->toPlainText().length() > 0)
+ return false;
+ else
+ return true;
+}
+
+void TextEditor::setEditorTitle(const QString &s)
+{
+ editorTitle = (s.isEmpty()) ? editorName : editorName + ": " + s;
+
+ // Set title of parent dockWidget
+ if (parentWidget())
+ parentWidget()->setWindowTitle(editorTitle);
+
+ setWindowTitle(editorTitle);
+}
+
+QString TextEditor::getEditorTitle() { return editorTitle; }
+
+void TextEditor::setEditorName(const QString &s) { editorName = s; }
+
+void TextEditor::setFont(const QFont &font)
+{
+ blockChangedSignal = true;
+
+ QTextCursor tc = e->textCursor();
+ QTextCharFormat format = tc.charFormat();
+
+ tc.select(QTextCursor::Document);
+ format.setFont(font);
+ tc.setCharFormat(format);
+ tc.clearSelection();
+ fontChanged(fixedFont);
+
+ blockChangedSignal = false;
+}
+
+void TextEditor::setFontHint(const QString &fh)
+{
+ if (fh == "fixed") {
+ actionFormatUseFixedFont->setChecked(true);
+ e->setCurrentFont(fixedFont);
+ setFont(fixedFont);
+ }
+ else {
+ actionFormatUseFixedFont->setChecked(false);
+ e->setCurrentFont(varFont);
+ setFont(varFont);
+ }
+}
+
+QString TextEditor::getFontHint()
+{
+ if (actionFormatUseFixedFont->isChecked())
+ return "fixed";
+ else
+ return "var";
+}
+
+QString TextEditor::getFontHintDefault()
+{
+ if (actionSettingsFonthintDefault->isChecked())
+ return "fixed";
+ else
+ return "var";
+}
+
+void TextEditor::setFilename(const QString &fn)
+{
+ if (state == filledEditor) {
+ if (fn.isEmpty()) {
+ filename = "";
+ statusBar()->showMessage(
+ tr("No filename available for this note.", "Statusbar message"),
+ statusbarTime);
+ }
+ else {
+ filename = fn;
+ statusBar()->showMessage(
+ tr(QString("Current filename is %1").arg(filename).toUtf8(),
+ "Statusbar message"),
+ statusbarTime);
+ }
+ }
+}
+
+QString TextEditor::getFilename() { return filename; }
+
+void TextEditor::setFilenameHint(const QString &fnh) { filenameHint = fnh; }
+
+QString TextEditor::getFilenameHint() { return filenameHint; }
+
+QString TextEditor::getText()
+{
+ if (e->toPlainText().isEmpty())
+ return QString();
+
+ if (actionFormatRichText->isChecked())
+ return e->toHtml();
+ else
+ return e->toPlainText();
+}
+
+VymText TextEditor::getVymText()
+{
+ VymText vt;
+
+ if (actionFormatRichText->isChecked())
+ vt.setRichText(e->toHtml());
+ else
+ vt.setPlainText(e->toPlainText());
+
+ if (actionFormatUseFixedFont->isChecked())
+ vt.setFontHint(getFontHint());
+
+ return vt;
+}
+
+bool TextEditor::findText(const QString &t,
+ const QTextDocument::FindFlags &flags)
+{
+ if (e->find(t, flags))
+ return true;
+ else
+ return false;
+}
+
+bool TextEditor::findText(const QString &t,
+ const QTextDocument::FindFlags &flags, int i)
+{
+ // Position at beginning
+ QTextCursor c = e->textCursor();
+ c.setPosition(0, QTextCursor::MoveAnchor);
+ e->setTextCursor(c);
+
+ // Search for t
+ int j = 0;
+ while (j <= i) {
+ if (!e->find(t, flags))
+ return false;
+ j++;
+ }
+ return true;
+}
+
+void TextEditor::setTextCursor(const QTextCursor &cursor)
+{
+ e->setTextCursor(cursor);
+}
+
+QTextCursor TextEditor::getTextCursor() { return e->textCursor(); }
+
+void TextEditor::setFocus() { e->setFocus(); }
+
+void TextEditor::setupFileActions()
+{
+ QToolBar *tb = addToolBar(tr("Note Actions"));
+ tb->setObjectName("noteEditorFileActions");
+ QMenu *fileMenu = menuBar()->addMenu(tr("&Note", "Menubar"));
+
+ QString tag = tr("Texteditor", "Shortcuts");
+ QAction *a;
+ a = new QAction(QPixmap(":/fileopen.png"), tr("&Import..."), this);
+ a->setShortcut(Qt::CTRL + Qt::Key_O);
+ a->setShortcutContext(Qt::WidgetWithChildrenShortcut);
+ switchboard.addSwitch("textLoad", shortcutScope, a, tag);
+ connect(a, SIGNAL(triggered()), this, SLOT(textLoad()));
+ tb->addAction(a);
+ fileMenu->addAction(a);
+ actionFileLoad = a;
+
+ fileMenu->addSeparator();
+ a = new QAction(QPixmap(":/filesave.png"), tr("&Export..."), this);
+ a->setShortcut(Qt::CTRL + Qt::Key_S);
+ a->setShortcutContext(Qt::WidgetWithChildrenShortcut);
+ switchboard.addSwitch("textSave", shortcutScope, a, tag);
+ connect(a, SIGNAL(triggered()), this, SLOT(textSave()));
+ tb->addAction(a);
+ fileMenu->addAction(a);
+ addAction(a);
+ actionFileSave = a;
+
+ a = new QAction(tr("Export &As... (HTML)"), this);
+ connect(a, SIGNAL(triggered()), this, SLOT(textSaveAs()));
+ fileMenu->addAction(a);
+ actionFileSaveAs = a;
+
+ a = new QAction(tr("Export &As...(ASCII)"), this);
+ a->setShortcut(Qt::ALT + Qt::Key_X);
+ a->setShortcutContext(Qt::WidgetWithChildrenShortcut);
+ switchboard.addSwitch("textExportAsASCII", shortcutScope, a, tag);
+ connect(a, SIGNAL(triggered()), this, SLOT(textExportAsASCII()));
+ fileMenu->addAction(a);
+ addAction(a);
+ actionFileSaveAs = a;
+
+ fileMenu->addSeparator();
+ a = new QAction(QPixmap(":/fileprint.png"), tr("&Print..."), this);
+ a->setShortcut(Qt::CTRL + Qt::Key_P);
+ switchboard.addSwitch("textPrint", shortcutScope, a, tag);
+ connect(a, SIGNAL(triggered()), this, SLOT(textPrint()));
+ tb->addAction(a);
+ fileMenu->addAction(a);
+ actionFilePrint = a;
+
+ a = new QAction(QPixmap(":/edittrash.png"), tr("&Delete All"), this);
+ connect(a, SIGNAL(triggered()), this, SLOT(deleteAll()));
+ fileMenu->addAction(a);
+ tb->addAction(a);
+ actionFileDeleteAll = a;
+}
+
+void TextEditor::setupEditActions()
+{
+ QString tag = tr("Texteditor", "Shortcuts");
+ QToolBar *editToolBar = addToolBar(tr("Edit Actions"));
+ editToolBar->setObjectName("noteEditorEditActions");
+ editToolBar->hide();
+ QMenu *editMenu = menuBar()->addMenu(tr("Edi&t"));
+
+ QAction *a;
+ a = new QAction(QPixmap(":/undo.png"), tr("&Undo"), this);
+ a->setShortcut(Qt::CTRL + Qt::Key_Z);
+ a->setShortcutContext(Qt::WidgetWithChildrenShortcut);
+ switchboard.addSwitch("textUndo", shortcutScope, a, tag);
+ connect(a, SIGNAL(triggered()), e, SLOT(undo()));
+ editMenu->addAction(a);
+ editToolBar->addAction(a);
+ actionEditUndo = a;
+
+ a = new QAction(QPixmap(":/redo.png"), tr("&Redo"), this);
+ a->setShortcut(Qt::CTRL + Qt::Key_Y);
+ a->setShortcutContext(Qt::WidgetWithChildrenShortcut);
+ switchboard.addSwitch("textRedo", shortcutScope, a, tag);
+ connect(a, SIGNAL(triggered()), e, SLOT(redo()));
+ editMenu->addAction(a);
+ editToolBar->addAction(a);
+ actionEditRedo = a;
+
+ editMenu->addSeparator();
+ a = new QAction(QPixmap(), tr("Select and copy &all"), this);
+ a->setShortcutContext(Qt::WidgetShortcut);
+ a->setShortcut(Qt::CTRL + Qt::Key_A);
+ switchboard.addSwitch("textCopyAll", shortcutScope, a, tag);
+ connect(a, SIGNAL(triggered()), this, SLOT(editCopyAll()));
+ editMenu->addAction(a);
+
+ editMenu->addSeparator();
+ a = new QAction(QPixmap(":/editcopy.png"), tr("&Copy"), this);
+ a->setShortcut(Qt::CTRL + Qt::Key_C);
+ a->setShortcutContext(Qt::WidgetWithChildrenShortcut);
+ switchboard.addSwitch("textCopy", shortcutScope, a, tag);
+ connect(a, SIGNAL(triggered()), e, SLOT(copy()));
+ editMenu->addAction(a);
+ editToolBar->addAction(a);
+ actionEditCopy = a;
+
+ a = new QAction(QPixmap(":/editcut.png"), tr("Cu&t"), this);
+ a->setShortcut(Qt::CTRL + Qt::Key_X);
+ a->setShortcutContext(Qt::WidgetWithChildrenShortcut);
+ switchboard.addSwitch("textCut", shortcutScope, a, tag);
+ connect(a, SIGNAL(triggered()), e, SLOT(cut()));
+ editMenu->addAction(a);
+ editToolBar->addAction(a);
+ actionEditCut = a;
+
+ a = new QAction(QPixmap(":/editpaste.png"), tr("&Paste"), this);
+ a->setShortcut(Qt::CTRL + Qt::Key_V);
+ a->setShortcutContext(Qt::WidgetWithChildrenShortcut);
+ switchboard.addSwitch("textPaste", shortcutScope, a, tag);
+ connect(a, SIGNAL(triggered()), e, SLOT(paste()));
+ editMenu->addAction(a);
+ editToolBar->addAction(a);
+ actionEditPaste = a;
+}
+
+void TextEditor::setupFormatActions()
+{
+ QString tag = tr("Texteditor", "Shortcuts");
+ fontHintsToolBar =
+ addToolBar(tr("Font hints", "toolbar in texteditor"));
+ fontHintsToolBar->setObjectName("noteEditorFontToolBar");
+ QMenu *formatMenu = menuBar()->addMenu(tr("F&ormat"));
+
+ QAction *a;
+
+ a = new QAction(QPixmap(":/formatfixedfont.png"), tr("&Font hint"), this);
+ a->setShortcut(Qt::CTRL + Qt::Key_H);
+ a->setCheckable(true);
+ a->setChecked(
+ settings.value("/noteeditor/fonts/useFixedByDefault", false).toBool());
+ switchboard.addSwitch("textToggleFonthint", shortcutScope, a, tag);
+ connect(a, SIGNAL(triggered()), this, SLOT(toggleFonthint()));
+ formatMenu->addAction(a);
+ fontHintsToolBar->addAction(a);
+ actionFormatUseFixedFont = a;
+
+ // Original icon: ./share/icons/oxygen/22x22/actions/format-text-color.png
+ a = new QAction(QPixmap(":/formatrichtext.png"), tr("&Richtext"), this);
+ a->setShortcut(Qt::CTRL + Qt::Key_R);
+ // a->setShortcutContext (Qt::WidgetShortcut);
+ a->setCheckable(true);
+ switchboard.addSwitch("textToggleRichText", shortcutScope, a, tag);
+ connect(a, SIGNAL(triggered()), this, SLOT(toggleRichText()));
+ formatMenu->addAction(a);
+ fontHintsToolBar->addAction(a);
+ actionFormatRichText = a;
+
+ fontToolBar = addToolBar(tr("Fonts", "toolbar in texteditor"));
+ fontToolBar->setObjectName("noteEditorFontToolBar");
+
+ comboFont = new QComboBox;
+ fontToolBar->addWidget(comboFont);
+ QFontDatabase fontDB;
+ comboFont->insertItems(0, fontDB.families());
+ connect(comboFont, SIGNAL(activated(const QString &)), this,
+ SLOT(textFamily(const QString &)));
+
+ comboSize = new QComboBox;
+ fontToolBar->addWidget(comboSize);
+ QList<int> sizes = fontDB.standardSizes();
+ QList<int>::iterator it = sizes.begin();
+ int i = 0;
+ while (it != sizes.end()) {
+ i++;
+ ++it; // increment i before using it
+ comboSize->insertItem(i, QString::number(*it));
+ }
+ connect(comboSize, SIGNAL(activated(const QString &)), this,
+ SLOT(textSize(const QString &)));
+
+ formatMenu->addSeparator();
+
+ formatToolBar = addToolBar(tr("Format", "toolbar in texteditor"));
+ formatToolBar->setObjectName("noteEditorFormatToolBar");
+
+ QPixmap pix(16, 16);
+ pix.fill(e->textColor());
+ a = new QAction(pix, tr("&Color..."), this);
+ formatMenu->addAction(a);
+ formatToolBar->addAction(a);
+ connect(a, SIGNAL(triggered()), this, SLOT(textColor()));
+ actionTextColor = a;
+
+ a = new QAction(QPixmap(":/text_bold.png"), tr("&Bold"), this);
+ a->setShortcut(Qt::CTRL + Qt::Key_B);
+// a->setShortcutContext(Qt::WidgetWithChildrenShortcut);
+ switchboard.addSwitch("textToggleBold", shortcutScope, a, tag);
+ connect(a, SIGNAL(triggered()), this, SLOT(textBold()));
+ formatToolBar->addAction(a);
+ formatMenu->addAction(a);
+ a->setCheckable(true);
+ actionTextBold = a;
+
+ a = new QAction(QPixmap(":/text_italic.png"), tr("&Italic"), this);
+ a->setShortcut(Qt::CTRL + Qt::Key_I);
+// a->setShortcutContext(Qt::WidgetWithChildrenShortcut);
+ switchboard.addSwitch("textToggleItalic", shortcutScope, a, tag);
+ connect(a, SIGNAL(triggered()), this, SLOT(textItalic()));
+ formatToolBar->addAction(a);
+ formatMenu->addAction(a);
+ a->setCheckable(true);
+ actionTextItalic = a;
+
+ a = new QAction(QPixmap(":/text_under.png"), tr("&Underline"), this);
+ a->setShortcut(Qt::CTRL + Qt::Key_U);
+// a->setShortcutContext(Qt::WidgetWithChildrenShortcut);
+ switchboard.addSwitch("textToggleUnderline", shortcutScope, a, tag);
+ connect(a, SIGNAL(triggered()), this, SLOT(textUnderline()));
+ formatToolBar->addAction(a);
+ formatMenu->addAction(a);
+ a->setCheckable(true);
+ // richTextWidgets.append((QWidget*)a);
+ actionTextUnderline = a;
+ formatMenu->addSeparator();
+
+ QActionGroup *actGrp2 = new QActionGroup(this);
+ actGrp2->setExclusive(true);
+ a = new QAction(QPixmap(":/text_sub.png"), tr("Subs&cript"), actGrp2);
+ a->setShortcut(Qt::CTRL + Qt::SHIFT + Qt::Key_B);
+// a->setShortcutContext(Qt::WidgetWithChildrenShortcut);
+ a->setCheckable(true);
+ formatToolBar->addAction(a);
+ formatMenu->addAction(a);
+ switchboard.addSwitch("textToggleSub", shortcutScope, a, tag);
+ connect(a, SIGNAL(triggered()), this, SLOT(textVAlign()));
+ actionAlignSubScript = a;
+
+ a = new QAction(QPixmap(":/text_super.png"), tr("Su&perscript"), actGrp2);
+ a->setShortcut(Qt::CTRL + Qt::SHIFT + Qt::Key_P);
+// a->setShortcutContext(Qt::WidgetWithChildrenShortcut);
+ a->setCheckable(true);
+ formatToolBar->addAction(a);
+ formatMenu->addAction(a);
+ switchboard.addSwitch("textToggleSuper", shortcutScope, a, tag);
+ connect(a, SIGNAL(triggered()), this, SLOT(textVAlign()));
+ actionAlignSuperScript = a;
+ QActionGroup *grp = new QActionGroup(this);
+ connect(grp, SIGNAL(triggered(QAction *)), this,
+ SLOT(textAlign(QAction *)));
+
+ formatMenu->addSeparator();
+
+ a = new QAction(QPixmap(":/text_left.png"), tr("&Left"), grp);
+ // a->setShortcut( Qt::CTRL+Qt::Key_L );
+ a->setCheckable(true);
+ formatToolBar->addAction(a);
+ formatMenu->addAction(a);
+ actionAlignLeft = a;
+ a = new QAction(QPixmap(":/text_center.png"), tr("C&enter"), grp);
+ // a->setShortcut( Qt::CTRL + Qt::Key_E);
+ a->setCheckable(true);
+ formatToolBar->addAction(a);
+ formatMenu->addAction(a);
+ actionAlignCenter = a;
+ a = new QAction(QPixmap(":/text_right.png"), tr("&Right"), grp);
+ // a->setShortcut(Qt::CTRL + Qt::Key_R );
+ a->setCheckable(true);
+ formatToolBar->addAction(a);
+ formatMenu->addAction(a);
+ actionAlignRight = a;
+ a = new QAction(QPixmap(":/text_block.png"), tr("&Justify"), grp);
+ // a->setShortcut(Qt::CTRL + Qt::Key_J );
+ a->setCheckable(true);
+ formatToolBar->addAction(a);
+ formatMenu->addAction(a);
+ actionAlignJustify = a;
+}
+
+void TextEditor::setupSettingsActions()
+{
+ QMenu *settingsMenu = menuBar()->addMenu(tr("&Settings"));
+
+ QAction *a;
+ a = new QAction(tr("Set &fixed font"), this);
+ connect(a, SIGNAL(triggered()), this, SLOT(setFixedFont()));
+ settingsMenu->addAction(a);
+ actionSettingsFixedFont = a;
+
+ a = new QAction(tr("Set &variable font"), this);
+ connect(a, SIGNAL(triggered()), this, SLOT(setVarFont()));
+ settingsMenu->addAction(a);
+ actionSettingsVarFont = a;
+
+ a = new QAction(tr("&fixed font is default"), this);
+ a->setCheckable(true);
+ // set state later in constructor...
+ settingsMenu->addAction(a);
+ actionSettingsFonthintDefault = a;
+
+ settingsMenu->addSeparator();
+
+ a = new QAction(
+ tr("Set RichText default background color", "TextEditor") + "...", this);
+ settingsMenu->addAction(a);
+ connect(a, SIGNAL(triggered()), this, SLOT(selectColorRichTextDefaultBackground()));
+ actionFilledEditorColor = a;
+
+ a = new QAction(tr("Set RichText default font color", "TextEditor") + "...", this);
+ settingsMenu->addAction(a);
+ connect(a, SIGNAL(triggered()), this, SLOT(selectColorRichTextDefaultForeground()));
+ actionFontColor = a;
+}
+
+void TextEditor::textLoad()
+{
+ if (state != inactiveEditor) {
+ if (!isEmpty()) {
+ QMessageBox mb(vymName + " - " + tr("Note Editor"),
+ "Loading will overwrite the existing note",
+ QMessageBox::Warning,
+ QMessageBox::Yes | QMessageBox::Default,
+ QMessageBox::Cancel, 0);
+ mb.setButtonText(QMessageBox::Yes, "Load note");
+ switch (mb.exec()) {
+ case QMessageBox::Cancel:
+ return;
+ break;
+ }
+ }
+ // Load note
+ QFileDialog *fd = new QFileDialog(this);
+ QStringList types;
+ types << "Text (*.txt *.html)"
+ << "VYM notes and HTML (*.html)"
+ << "ASCII texts (*.txt)"
+ << "All files (*)";
+ fd->setNameFilters(types);
+ fd->setDirectory(QDir().current());
+ fd->show();
+ QString fn;
+ if (fd->exec() == QDialog::Accepted && !fd->selectedFiles().isEmpty())
+ fn = fd->selectedFiles().first();
+
+ if (!fn.isEmpty()) {
+ QFile f(fn);
+ if (!f.open(QIODevice::ReadOnly))
+ return;
+
+ QTextStream ts(&f);
+ setTextAuto(ts.readAll());
+ editorChanged();
+ }
+ }
+}
+
+void TextEditor::closeEvent(QCloseEvent *ce)
+{
+ ce->accept(); // TextEditor can be reopened with show()
+ hide();
+ emit(windowClosed());
+ return;
+}
+
+bool TextEditor::eventFilter(QObject *obj, QEvent *ev)
+{
+ if (obj == e) {
+ if (ev->type() == QEvent::KeyPress) {
+ QKeyEvent *keyEvent = static_cast<QKeyEvent *>(ev);
+ if (keyEvent == QKeySequence::Paste) {
+ // switch editor mode to match clipboard content before pasting
+ const QClipboard *clipboard = QApplication::clipboard();
+ const QMimeData *mimeData = clipboard->mimeData();
+
+ if (mimeData->hasHtml() && !actionFormatRichText->isChecked())
+ setRichTextMode(true);
+ }
+ }
+ }
+ // pass the event on to the parent class
+ return QMainWindow::eventFilter(obj, ev);
+}
+
+void TextEditor::editorChanged()
+{
+ //qDebug() << "TE::editorChanged" << editorName << "blockChanged: " << blockChangedSignal;
+ EditorState oldState = state;
+ if (isEmpty())
+ state = emptyEditor;
+ else
+ state = filledEditor;
+
+ if (!blockChangedSignal) {
+ blockTextUpdate = true;
+ emit(textHasChanged(getVymText()));
+ blockTextUpdate = false;
+ }
+
+ if (state == oldState)
+ return;
+
+ updateState();
+}
+
+void TextEditor::setRichText(const QString &t)
+{
+ blockChangedSignal = true;
+ e->setReadOnly(false);
+ e->setHtml(t);
+ actionFormatRichText->setChecked(true);
+
+ // Update state including colors
+ updateState();
+
+ updateActions();
+ blockChangedSignal = false;
+}
+
+void TextEditor::setPlainText(const QString &t)
+{
+ blockChangedSignal = true;
+ e->setReadOnly(false);
+
+ e->setPlainText(t);
+ actionFormatRichText->setChecked(false);
+
+ // Reset also text format
+ QTextCharFormat textformat;
+ textformat.setForeground(qApp->palette().color(QPalette::WindowText));
+ textformat.setFont(varFont);
+ e->setCurrentCharFormat(textformat);
+
+ // Update state including colors
+ updateState();
+
+ updateActions();
+ blockChangedSignal = false;
+}
+
+void TextEditor::setTextAuto(const QString &t)
+{
+ if (Qt::mightBeRichText(t))
+ setRichText(t);
+ else
+ setPlainText(t);
+}
+
+void TextEditor::setVymText(const VymText &vt)
+{
+ // While a note is being edited, we are sending textHasChanged
+ // Then we don't want to update the text additionally from outside,
+ // as this would position cursor at beginning of text
+ if (blockTextUpdate) return;
+
+ if (vt.getText() == getText()) return;
+
+ if (vt.isRichText())
+ setRichText(vt.getText());
+ else
+ setPlainText(vt.getText());
+}
+
+void TextEditor::setInactive()
+{
+ setState(inactiveEditor);
+}
+
+void TextEditor::editCopyAll()
+{
+ e->selectAll();
+ e->copy();
+}
+
+void TextEditor::clear()
+{
+ //qDebug() << "TE::clear" << editorName;
+ bool blockChangedOrg = blockChangedSignal;
+
+ blockChangedSignal = true;
+ e->clear();
+ setState(emptyEditor);
+
+ blockChangedSignal = blockChangedOrg;
+}
+
+void TextEditor::deleteAll()
+{
+ e->clear();
+}
+
+void TextEditor::textSaveAs()
+{
+ QString caption = tr("Export Note to single file");
+ QString fn = QFileDialog::getSaveFileName(
+ this, caption, QString(), "VYM Note (HTML) (*.html);;All files (*)",
+ 0, QFileDialog::DontConfirmOverwrite);
+
+ if (!fn.isEmpty()) {
+ QFile file(fn);
+ if (file.exists()) {
+ QMessageBox mb(
+ vymName,
+ tr("The file %1\nexists already.\nDo you want to overwrite it?",
+ "dialog 'save note as'")
+ .arg(fn),
+ QMessageBox::Warning, QMessageBox::Yes | QMessageBox::Default,
+ QMessageBox::Cancel | QMessageBox::Escape, Qt::NoButton);
+ mb.setButtonText(QMessageBox::Yes, tr("Overwrite"));
+ mb.setButtonText(QMessageBox::No, tr("Cancel"));
+ switch (mb.exec()) {
+ case QMessageBox::Yes:
+ // save
+ filename = fn;
+ textSave();
+ return;
+ case QMessageBox::Cancel:
+ // do nothing
+ break;
+ }
+ }
+ else {
+ filename = fn;
+ textSave();
+ return;
+ }
+ }
+ statusBar()->showMessage(
+ tr("Couldn't export note ", "dialog 'save note as'") + fn,
+ statusbarTime);
+}
+
+void TextEditor::textSave()
+{
+ if (filename.isEmpty()) {
+ textSaveAs();
+ return;
+ }
+
+ QString text = e->toHtml(); // FIXME-4 or plaintext? check...
+ QFile f(filename);
+ if (!f.open(QIODevice::WriteOnly)) {
+ statusBar()->showMessage(QString("Could not write to %1").arg(filename),
+ statusbarTime);
+ return;
+ }
+
+ QTextStream t(&f);
+ t.setCodec("UTF-8");
+ t << text;
+ f.close();
+
+ e->document()->setModified(false);
+
+ statusBar()->showMessage(QString("Note exported as %1").arg(filename),
+ statusbarTime);
+}
+
+void TextEditor::textExportAsASCII()
+{
+ QString fn, s;
+ if (!filenameHint.isEmpty()) {
+ if (!filenameHint.contains(".txt"))
+ s = filenameHint + ".txt";
+ else
+ s = filenameHint;
+ }
+ else
+ s = QString();
+ QString caption = tr("Export Note to single file (ASCII)");
+ fn = QFileDialog::getSaveFileName(
+ this, caption, s, "VYM Note (ASCII) (*.txt);;All files (*)");
+ int ret = -1;
+
+ if (!fn.isEmpty()) {
+ QFile file(fn);
+ if (file.exists()) {
+ QMessageBox mb(
+ vymName,
+ tr("The file %1\nexists already.\nDo you want to overwrite it?",
+ "dialog 'save note as'")
+ .arg(fn),
+ QMessageBox::Warning, QMessageBox::Yes | QMessageBox::Default,
+ QMessageBox::Cancel | QMessageBox::Escape, Qt::NoButton);
+ mb.setButtonText(QMessageBox::Yes, tr("Overwrite"));
+ mb.setButtonText(QMessageBox::No, tr("Cancel"));
+ ret = mb.exec();
+ }
+ if (ret == QMessageBox::Cancel)
+ return;
+
+ // save
+ if (!file.open(QIODevice::WriteOnly))
+ statusBar()->showMessage(
+ QString("Could not write to %1").arg(filename), statusbarTime);
+ else {
+ QTextStream t(&file);
+ t << getVymText().getTextASCII();
+ file.close();
+
+ statusBar()->showMessage(QString("Note exported as %1").arg(fn),
+ statusbarTime);
+ }
+ }
+}
+
+void TextEditor::textPrint()
+{
+ QTextDocument *document = e->document();
+
+ if (!printer)
+ mainWindow->setupPrinter();
+
+ QPrintDialog dialog(printer, this);
+ dialog.setWindowTitle(tr("Print", "TextEditor"));
+ if (dialog.exec() != QDialog::Accepted)
+ return;
+
+ document->print(printer);
+}
+
+void TextEditor::textEditUndo() {}
+
+void TextEditor::toggleFonthint()
+{
+ if (!actionFormatUseFixedFont->isChecked()) {
+ e->setCurrentFont(varFont);
+ setFont(varFont);
+ }
+ else {
+ e->setCurrentFont(fixedFont);
+ setFont(fixedFont);
+ }
+ emit(textHasChanged(getVymText()));
+}
+
+void TextEditor::setRichTextMode(bool b)
+{
+ //qDebug() << "TE::setRichTextMode b=" << b;
+ actionFormatUseFixedFont->setEnabled(false);
+ if (b) {
+ setRichText(e->toHtml());
+
+ // Use default foreground color for all text when switching to RichText
+ QTextCursor cursor = e->textCursor();
+ e->selectAll();
+ e->setTextColor(colorRichTextDefaultForeground);
+ e->setTextCursor(cursor);
+
+ } else {
+ setPlainText(e->toPlainText());
+ }
+ emit(textHasChanged(getVymText()));
+}
+
+void TextEditor::toggleRichText()
+{
+ if (actionFormatRichText->isChecked())
+ setRichTextMode(true);
+ else
+ setRichTextMode(false);
+}
+
+void TextEditor::setFixedFont()
+{
+ bool ok;
+ QFont font = QFontDialog::getFont(&ok, fixedFont, this);
+ if (ok)
+ fixedFont = font;
+}
+
+void TextEditor::setVarFont()
+{
+ bool ok;
+ QFont font = QFontDialog::getFont(&ok, varFont, this);
+ if (ok)
+ varFont = font;
+}
+
+void TextEditor::textBold()
+{
+ if (actionTextBold->isChecked())
+ e->setFontWeight(QFont::Bold);
+ else
+ e->setFontWeight(QFont::Normal);
+}
+
+void TextEditor::textUnderline()
+{
+ e->setFontUnderline(actionTextUnderline->isChecked());
+}
+
+void TextEditor::textItalic()
+{
+ e->setFontItalic(actionTextItalic->isChecked());
+}
+
+void TextEditor::textFamily(const QString &f) { e->setFontFamily(f); }
+
+void TextEditor::textSize(const QString &p) { e->setFontPointSize(p.toInt()); }
+
+void TextEditor::textColor()
+{
+ QColor col = QColorDialog::getColor(e->textColor(), this);
+ if (!col.isValid())
+ return;
+ e->setTextColor(col);
+ /*
+ QPixmap pix( 16, 16 );
+ pix.fill( col );
+ actionTextColor->setIcon( pix );
+ */
+}
+
+void TextEditor::textAlign(QAction *a)
+{
+ QTextCursor c = e->textCursor();
+
+ if (a == actionAlignLeft)
+ e->setAlignment(Qt::AlignLeft);
+ else if (a == actionAlignCenter)
+ e->setAlignment(Qt::AlignHCenter);
+ else if (a == actionAlignRight)
+ e->setAlignment(Qt::AlignRight);
+ else if (a == actionAlignJustify)
+ e->setAlignment(Qt::AlignJustify);
+}
+
+void TextEditor::textVAlign()
+{
+ QTextCharFormat format;
+
+ if (sender() == actionAlignSuperScript &&
+ actionAlignSuperScript->isChecked()) {
+ format.setVerticalAlignment(QTextCharFormat::AlignSuperScript);
+ }
+ else if (sender() == actionAlignSubScript &&
+ actionAlignSubScript->isChecked()) {
+ format.setVerticalAlignment(QTextCharFormat::AlignSubScript);
+ }
+ else {
+ format.setVerticalAlignment(QTextCharFormat::AlignNormal);
+ }
+ e->mergeCurrentCharFormat(format);
+}
+
+void TextEditor::fontChanged(const QFont &f)
+{
+ int i = comboFont->findText(f.family());
+ if (i >= 0)
+ comboFont->setCurrentIndex(i);
+ i = comboSize->findText(QString::number(f.pointSize()));
+ if (i >= 0)
+ comboSize->setCurrentIndex(i);
+ actionTextBold->setChecked(f.bold());
+ actionTextItalic->setChecked(f.italic());
+ actionTextUnderline->setChecked(f.underline());
+}
+
+void TextEditor::colorChanged(const QColor &c)
+{
+ QPixmap pix(16, 16);
+ pix.fill(c);
+ actionTextColor->setIcon(pix);
+}
+
+void TextEditor::formatChanged(const QTextCharFormat &f)
+{
+ if (!actionFormatRichText->isChecked())
+ return;
+ fontChanged(f.font());
+ colorChanged(f.foreground().color());
+ alignmentChanged(e->alignment());
+ verticalAlignmentChanged(f.verticalAlignment());
+}
+
+void TextEditor::alignmentChanged(int a)
+{
+ if ((a == Qt::AlignLeft) || (a & Qt::AlignLeft))
+ actionAlignLeft->setChecked(true);
+ else if ((a & Qt::AlignHCenter))
+ actionAlignCenter->setChecked(true);
+ else if ((a & Qt::AlignRight))
+ actionAlignRight->setChecked(true);
+ else if ((a & Qt::AlignJustify))
+ actionAlignJustify->setChecked(true);
+}
+
+void TextEditor::verticalAlignmentChanged(QTextCharFormat::VerticalAlignment a)
+{
+ actionAlignSubScript->setChecked(false);
+ actionAlignSuperScript->setChecked(false);
+ switch (a) {
+ case QTextCharFormat::AlignSuperScript:
+ actionAlignSuperScript->setChecked(true);
+ break;
+ case QTextCharFormat::AlignSubScript:
+ actionAlignSubScript->setChecked(true);
+ break;
+ default:;
+ }
+}
+
+void TextEditor::updateActions()
+{
+ bool b;
+ b = (state == inactiveEditor) ? false : true;
+
+ actionFileLoad->setEnabled(b);
+ actionFileSave->setEnabled(b);
+ actionFileSaveAs->setEnabled(b);
+ actionFilePrint->setEnabled(b);
+ actionFileDeleteAll->setEnabled(b);
+ actionEditUndo->setEnabled(b);
+ actionEditRedo->setEnabled(b);
+ actionEditCopy->setEnabled(b);
+ actionEditCut->setEnabled(b);
+ actionEditPaste->setEnabled(b);
+ actionFormatUseFixedFont->setEnabled(b);
+ actionFormatRichText->setEnabled(b);
+
+ if (!actionFormatRichText->isChecked() || !b) {
+ comboFont->setEnabled(false);
+ comboSize->setEnabled(false);
+ fontToolBar->hide();
+ formatToolBar->hide();
+ actionTextColor->setEnabled(false);
+ actionTextBold->setEnabled(false);
+ actionTextUnderline->setEnabled(false);
+ actionTextItalic->setEnabled(false);
+ actionTextColor->setEnabled(false);
+ actionAlignSubScript->setEnabled(false);
+ actionAlignSuperScript->setEnabled(false);
+ actionAlignLeft->setEnabled(false);
+ actionAlignCenter->setEnabled(false);
+ actionAlignRight->setEnabled(false);
+ actionAlignJustify->setEnabled(false);
+ }
+ else {
+ comboFont->setEnabled(true);
+ comboSize->setEnabled(true);
+ fontToolBar->show();
+ formatToolBar->show();
+ actionTextColor->setEnabled(true);
+ actionTextBold->setEnabled(true);
+ actionTextUnderline->setEnabled(true);
+ actionTextItalic->setEnabled(true);
+ actionTextColor->setEnabled(true);
+ actionAlignSubScript->setEnabled(true);
+ actionAlignSuperScript->setEnabled(true);
+ actionAlignLeft->setEnabled(true);
+ actionAlignCenter->setEnabled(true);
+ actionAlignRight->setEnabled(true);
+ actionAlignJustify->setEnabled(true);
+ actionFormatUseFixedFont->setEnabled(false);
+ }
+}
+
+void TextEditor::setState(EditorState s) // FIXME-2 called 12x when reselecting once in ME
+ // 5 alone for HeadingEditor
+{
+ //qDebug() << "TE::setState" << s << editorName;
+ QPalette p = qApp->palette();
+ QColor baseColor;
+ state = s;
+ switch (state) {
+ case emptyEditor:
+ if (actionFormatRichText->isChecked())
+ e->setTextColor(colorRichTextDefaultForeground);
+ else
+ e->setTextColor(p.color(QPalette::Text));
+
+ case filledEditor:
+ if (actionFormatRichText->isChecked()) {
+ if (useColorMapBackground)
+ baseColor = colorMapBackground;
+ else
+ baseColor = colorRichTextDefaultBackground;
+ } else {
+ baseColor = p.color(QPalette::Base);
+ }
+ e->setReadOnly(false);
+ break;
+ case inactiveEditor:
+ baseColor = Qt::black;
+ e->setReadOnly(true);
+ }
+ p.setColor(QPalette::Base, baseColor);
+ e->setPalette(p);
+
+ updateActions();
+}
+
+void TextEditor::updateState()
+{
+ //qDebug() << "TE::updateState" << editorName;
+ if (isEmpty())
+ setState(emptyEditor);
+ else
+ setState(filledEditor);
+}
+
+void TextEditor::selectColorRichTextDefaultBackground()
+{
+ QColor col = QColorDialog::getColor(colorRichTextDefaultBackground, nullptr);
+ if (!col.isValid())
+ return;
+ colorRichTextDefaultBackground = col;
+ QPixmap pix(16, 16);
+ pix.fill(colorRichTextDefaultBackground);
+ actionFilledEditorColor->setIcon(pix);
+}
+
+void TextEditor::selectColorRichTextDefaultForeground()
+{
+ QColor col = QColorDialog::getColor(colorRichTextDefaultForeground, nullptr);
+ if (!col.isValid())
+ return;
+ setColorRichTextDefaultForeground(col);
+}
+
+void TextEditor::setColorRichTextDefaultForeground(const QColor &col)
+{
+ if (!col.isValid()) return;
+
+ colorRichTextDefaultForeground = col;
+ QPixmap pix(16, 16);
+ pix.fill(colorRichTextDefaultForeground);
+ actionFontColor->setIcon(pix);
+}
+
+void TextEditor::setColorMapBackground(const QColor &col)
+{
+ colorMapBackground = col;
+}
+
+void TextEditor::setUseColorMapBackground(bool b)
+{
+ useColorMapBackground = b;
+}
\ No newline at end of file