From f907c40484b5c6044bcb5fd621434536ce7ebc1d Mon Sep 17 00:00:00 2001
From: Erik Larsson <erik@ortogonal.com>
Date: Sun, 15 Dec 2013 16:19:59 +0100
Subject: [PATCH] =?UTF-8?q?Add=20action=20to=20toggle=20=E2=80=98visualize?=
 =?UTF-8?q?=20whitespaces=E2=80=99=20in=20editors?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Add action, in ‘View’, that lets the user toggle the whitespace markers
in editors. Whitespace markers are the small dots/arrows etc. marking
spaces, tabs and new-lines. To some translators this can make it hard
to see the text, hence the reason for making it possible to toggle.

Change-Id: I484b51b078c84dacc1fe534b935dd9f8ce12de42
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@digia.com>
---
 src/linguist/linguist/mainwindow.cpp          | 11 ++++++++
 src/linguist/linguist/mainwindow.h            |  1 +
 src/linguist/linguist/mainwindow.ui           | 12 +++++++++
 src/linguist/linguist/messageeditor.cpp       | 26 +++++++++++++++++++
 src/linguist/linguist/messageeditor.h         |  2 ++
 .../linguist/messageeditorwidgets.cpp         | 20 ++++++++++----
 src/linguist/linguist/messageeditorwidgets.h  |  1 +
 7 files changed, 68 insertions(+), 5 deletions(-)

diff --git a/src/linguist/linguist/mainwindow.cpp b/src/linguist/linguist/mainwindow.cpp
index bb9f83ab1..f2897fbbe 100644
--- a/src/linguist/linguist/mainwindow.cpp
+++ b/src/linguist/linguist/mainwindow.cpp
@@ -489,6 +489,7 @@ MainWindow::MainWindow()
     connect(m_ui.actionLengthVariants, SIGNAL(toggled(bool)),
             m_messageEditor, SLOT(setLengthVariants(bool)));
     m_messageEditor->setLengthVariants(m_ui.actionLengthVariants->isChecked());
+    m_messageEditor->setVisualizeWhitespace(m_ui.actionVisualizeWhitespace->isChecked());
 
     m_focusWatcher = new FocusWatcher(m_messageEditor, this);
     m_contextView->installEventFilter(m_focusWatcher);
@@ -1906,6 +1907,7 @@ void MainWindow::setupMenuBar()
     connect(m_ui.actionResetSorting, SIGNAL(triggered()), this, SLOT(resetSorting()));
     connect(m_ui.actionDisplayGuesses, SIGNAL(triggered()), m_phraseView, SLOT(toggleGuessing()));
     connect(m_ui.actionStatistics, SIGNAL(triggered()), this, SLOT(toggleStatistics()));
+    connect(m_ui.actionVisualizeWhitespace, SIGNAL(triggered()), this, SLOT(toggleVisualizeWhitespace()));
     connect(m_ui.menuView, SIGNAL(aboutToShow()), this, SLOT(updateViewMenu()));
     m_ui.menuViewViews->addAction(m_contextDock->toggleViewAction());
     m_ui.menuViewViews->addAction(m_messagesDock->toggleViewAction());
@@ -2572,6 +2574,8 @@ void MainWindow::readConfig()
         config.value(settingPath("Validators/PlaceMarkers"), true).toBool());
     m_ui.actionLengthVariants->setChecked(
         config.value(settingPath("Options/LengthVariants"), false).toBool());
+    m_ui.actionVisualizeWhitespace->setChecked(
+        config.value(settingPath("Options/VisualizeWhitespace"), true).toBool());
 
     recentFiles().readConfig();
 
@@ -2598,6 +2602,8 @@ void MainWindow::writeConfig()
         m_ui.actionPlaceMarkerMatches->isChecked());
     config.setValue(settingPath("Options/LengthVariants"),
         m_ui.actionLengthVariants->isChecked());
+    config.setValue(settingPath("Options/VisualizeWhitespace"),
+        m_ui.actionVisualizeWhitespace->isChecked());
     config.setValue(settingPath("MainWindowState"),
         saveState());
     recentFiles().writeConfig();
@@ -2650,6 +2656,11 @@ void MainWindow::toggleStatistics()
     }
 }
 
+void MainWindow::toggleVisualizeWhitespace()
+{
+    m_messageEditor->setVisualizeWhitespace(m_ui.actionVisualizeWhitespace->isChecked());
+}
+
 void MainWindow::maybeUpdateStatistics(const MultiDataIndex &index)
 {
     if (index.model() == m_currentIndex.model())
diff --git a/src/linguist/linguist/mainwindow.h b/src/linguist/linguist/mainwindow.h
index ee2ba5e19..8167289c5 100644
--- a/src/linguist/linguist/mainwindow.h
+++ b/src/linguist/linguist/mainwindow.h
@@ -166,6 +166,7 @@ private slots:
                   bool matchCase, bool ignoreAccelerators, bool skipObsolete);
     void revalidate();
     void toggleStatistics();
+    void toggleVisualizeWhitespace();
     void onWhatsThis();
     void updatePhraseDicts();
     void updatePhraseDict(int model);
diff --git a/src/linguist/linguist/mainwindow.ui b/src/linguist/linguist/mainwindow.ui
index 022a2814f..f54fe898c 100644
--- a/src/linguist/linguist/mainwindow.ui
+++ b/src/linguist/linguist/mainwindow.ui
@@ -117,6 +117,7 @@
     <addaction name="actionDisplayGuesses"/>
     <addaction name="actionStatistics"/>
     <addaction name="actionLengthVariants"/>
+    <addaction name="actionVisualizeWhitespace"/>
     <addaction name="separator"/>
     <addaction name="menuToolbars"/>
     <addaction name="menuViewViews"/>
@@ -886,6 +887,17 @@
     <string>Length Variants</string>
    </property>
   </action>
+  <action name="actionVisualizeWhitespace">
+   <property name="checkable">
+    <bool>true</bool>
+   </property>
+   <property name="text">
+    <string>Visualize whitespaces</string>
+   </property>
+   <property name="toolTip">
+    <string>Toogle visualize whitespaces in editors</string>
+   </property>
+  </action>
  </widget>
  <resources/>
  <connections/>
diff --git a/src/linguist/linguist/messageeditor.cpp b/src/linguist/linguist/messageeditor.cpp
index a832e30d8..4ca5f3c2d 100644
--- a/src/linguist/linguist/messageeditor.cpp
+++ b/src/linguist/linguist/messageeditor.cpp
@@ -95,6 +95,7 @@ MessageEditor::MessageEditor(MultiDataModel *dataModel, QMainWindow *parent)
       m_redoAvail(false),
       m_cutAvail(false),
       m_copyAvail(false),
+      m_visualizeWhitespace(true),
       m_selectionHolder(0),
       m_focusWidget(0)
 {
@@ -216,6 +217,7 @@ void MessageEditor::messageModelAppended()
     ed.transCommentText->setWhatsThis(tr("Here you can enter comments for your own use."
                         " They have no effect on the translated applications.") );
     ed.transCommentText->getEditor()->installEventFilter(this);
+    ed.transCommentText->getEditor()->setVisualizeWhitespace(m_visualizeWhitespace);
     connect(ed.transCommentText, SIGNAL(selectionChanged(QTextEdit*)),
             SLOT(selectionChanged(QTextEdit*)));
     connect(ed.transCommentText, SIGNAL(textChanged(QTextEdit*)),
@@ -300,6 +302,15 @@ void MessageEditor::editorCreated(QTextEdit *te)
 
             te->installEventFilter(this);
 
+            if (m_visualizeWhitespace) {
+                QTextOption option = te->document()->defaultTextOption();
+
+                option.setFlags(option.flags()
+                                | QTextOption::ShowLineAndParagraphSeparators
+                                | QTextOption::ShowTabsAndSpaces);
+                te->document()->setDefaultTextOption(option);
+            }
+
             fixTabOrder();
             return;
         }
@@ -914,4 +925,19 @@ bool MessageEditor::focusNextUnfinished()
     return focusNextUnfinished(m_currentModel + 1);
 }
 
+void MessageEditor::setVisualizeWhitespace(bool value)
+{
+    m_visualizeWhitespace = value;
+    m_source->getEditor()->setVisualizeWhitespace(value);
+    m_pluralSource->getEditor()->setVisualizeWhitespace(value);
+    m_commentText->getEditor()->setVisualizeWhitespace(value);
+
+    foreach (const MessageEditorData &med, m_editors) {
+        med.transCommentText->getEditor()->setVisualizeWhitespace(value);
+        foreach (FormMultiWidget *widget, med.transTexts)
+            foreach (FormatTextEdit *te, widget->getEditors())
+                te->setVisualizeWhitespace(value);
+    }
+}
+
 QT_END_NAMESPACE
diff --git a/src/linguist/linguist/messageeditor.h b/src/linguist/linguist/messageeditor.h
index 6f7c657e6..8af58c491 100644
--- a/src/linguist/linguist/messageeditor.h
+++ b/src/linguist/linguist/messageeditor.h
@@ -87,6 +87,7 @@ public:
     void setEditorFocus(int model);
     void setUnfinishedEditorFocus();
     bool focusNextUnfinished();
+    void setVisualizeWhitespace(bool value);
 
 signals:
     void translationChanged(const QStringList &translations);
@@ -172,6 +173,7 @@ private:
     bool m_copyAvail;
 
     bool m_clipboardEmpty;
+    bool m_visualizeWhitespace;
 
     QTextEdit *m_selectionHolder;
     QWidget *m_focusWidget;
diff --git a/src/linguist/linguist/messageeditorwidgets.cpp b/src/linguist/linguist/messageeditorwidgets.cpp
index 0850d30bb..1db7f261b 100644
--- a/src/linguist/linguist/messageeditorwidgets.cpp
+++ b/src/linguist/linguist/messageeditorwidgets.cpp
@@ -114,11 +114,6 @@ FormatTextEdit::FormatTextEdit(QWidget *parent)
 {
     setLineWrapMode(QTextEdit::WidgetWidth);
     setAcceptRichText(false);
-    QTextOption option = document()->defaultTextOption();
-    option.setFlags(option.flags()
-                    | QTextOption::ShowLineAndParagraphSeparators
-                    | QTextOption::ShowTabsAndSpaces);
-    document()->setDefaultTextOption(option);
 
     // Do not set different background if disabled
     QPalette p = palette();
@@ -168,6 +163,21 @@ void FormatTextEdit::setPlainText(const QString &text, bool userAction)
     }
 }
 
+void FormatTextEdit::setVisualizeWhitespace(bool value)
+{
+    QTextOption option = document()->defaultTextOption();
+    if (value) {
+        option.setFlags(option.flags()
+                        | QTextOption::ShowLineAndParagraphSeparators
+                        | QTextOption::ShowTabsAndSpaces);
+    } else {
+        option.setFlags(option.flags()
+                        & ~QTextOption::ShowLineAndParagraphSeparators
+                        & ~QTextOption::ShowTabsAndSpaces);
+    }
+    document()->setDefaultTextOption(option);
+}
+
 FormWidget::FormWidget(const QString &label, bool isEditable, QWidget *parent)
         : QWidget(parent),
           m_hideWhenEmpty(false)
diff --git a/src/linguist/linguist/messageeditorwidgets.h b/src/linguist/linguist/messageeditorwidgets.h
index a5560c5c7..e7cb211d3 100644
--- a/src/linguist/linguist/messageeditorwidgets.h
+++ b/src/linguist/linguist/messageeditorwidgets.h
@@ -99,6 +99,7 @@ signals:
 
 public slots:
     void setPlainText(const QString & text, bool userAction);
+    void setVisualizeWhitespace(bool value);
 
 private:
     MessageHighlighter *m_highlighter;
-- 
GitLab