[kde-doc-english] [parley/Applications/16.04] src/practice: Redesign of Multiple-Choice Test

Julian Helfferich julian.helfferich at googlemail.com
Fri Mar 25 13:26:36 UTC 2016


Git commit 5e27c8c3da7cd95d9bc84649babc9d045c97e109 by Julian Helfferich.
Committed on 25/03/2016 at 12:49.
Pushed by helfferich into branch 'Applications/16.04'.

Redesign of Multiple-Choice Test

In the new design the QRadioButtons have been replaced with
QPushButtons and the design further specified using QStyleSheets. The
new design contains several improvements:

* Labels numbering the entries indicate which entry is selected by
  which keyboard shortcut.
* Borders around the QPushButton make it very clear which entry has the
  keyboard focus and over which entry the mouse is hovering.
* For correct and wrong answers, the background is changed to green and
  red respectively. The black text on colored background is more
  legible than colored text.

REVIEW: 127305
GUI: Re-design of multiple choice widget. Pictures of the multiple
choice widget are used in the handbook in Chapters "Practice" and
"Grammar Practice Modes".

M  +107  -33   src/practice/multiplechoicemodewidget.cpp
M  +5    -3    src/practice/multiplechoicemodewidget.h

http://commits.kde.org/parley/5e27c8c3da7cd95d9bc84649babc9d045c97e109

diff --git a/src/practice/multiplechoicemodewidget.cpp b/src/practice/multiplechoicemodewidget.cpp
index 74b3279..a4eff53 100644
--- a/src/practice/multiplechoicemodewidget.cpp
+++ b/src/practice/multiplechoicemodewidget.cpp
@@ -20,7 +20,7 @@
 
 #include <QDebug>
 #include <kcolorscheme.h>
-#include <QtWidgets/QRadioButton>
+#include <QPushButton>
 #include <QTimer>
 #include <QKeyEvent>
 #include <QVBoxLayout>
@@ -53,9 +53,7 @@ void MultiplechoiceModeWidget::setQuestionFont(const QFont& font)
 void MultiplechoiceModeWidget::setSolutionFont(const QFont& font)
 {
     m_solutionFont = font;
-    foreach(QRadioButton * radio, m_choiceButtons) {
-        radio->setFont(m_solutionFont);
-    }
+    resetButtonStyleSheet();
 }
 
 void MultiplechoiceModeWidget::setQuestion(const QVariant& question)
@@ -80,14 +78,14 @@ void MultiplechoiceModeWidget::setQuestion(const QVariant& question)
     if (m_choiceButtons.size() != data.choices.size()) {
         qDeleteAll(m_choiceButtons);
         m_choiceButtons.clear();
-        setNumberOfRadioButtons(data.choices.size());
+        setNumberOfPushButtons(data.choices.size());
     }
 
     int j = 0;
-    foreach(QRadioButton * radio, m_choiceButtons) {
-        radio->setText(data.choices[j]);
-        radio->setToolTip(data.choices[j]);
-        radio->setFont(m_solutionFont);
+    foreach(QPushButton * pushButton, m_choiceButtons) {
+        pushButton->setText(data.choices[j]);
+        pushButton->setToolTip(data.choices[j]);
+        pushButton->setFont(m_solutionFont);
         j++;
     }
 }
@@ -100,35 +98,46 @@ void MultiplechoiceModeWidget::showQuestion()
     m_ui->solutionSoundButton->setVisible(false);
     m_ui->feedbackLabel->clear();
 
+    resetButtonStyleSheet();
+
     if ( ! m_choiceButtons.isEmpty() ) {
-        //necessary trick to uncheck'em all
-        m_choiceButtons[0]->setChecked(true);
-        m_choiceButtons[0]->setAutoExclusive(false);
-        m_choiceButtons[0]->setChecked(false);
-        m_choiceButtons[0]->setAutoExclusive(true);
-        foreach(QRadioButton * radio, m_choiceButtons) {
-            radio->setPalette(palette());
-            radio->setEnabled(true);
+        foreach(QPushButton * pushButton, m_choiceButtons) {
+            pushButton->setChecked(false);
+            pushButton->setEnabled(true);
         }
 
         QTimer::singleShot(0, m_choiceButtons[0], SLOT(setFocus()));
     }
 }
 
-void MultiplechoiceModeWidget::setNumberOfRadioButtons(const int numberOfChoices)
+void MultiplechoiceModeWidget::setNumberOfPushButtons(const int numberOfChoices)
 {
     QVBoxLayout *verticalLayout = new QVBoxLayout();
     m_ui->gridLayout->addLayout(verticalLayout, 2, 0);
 
     for (int i = 0; i < numberOfChoices; i++) {
-        QRadioButton *radio_button = new QRadioButton(this);
-        verticalLayout->addWidget(radio_button);
-        m_choiceButtons.append(radio_button);
+        QHBoxLayout *horizontalLayout = new QHBoxLayout();
+        verticalLayout->addLayout(horizontalLayout);
+
+        // Display number of entry
+        QLabel *label = new QLabel(QString::number(i+1) + QString(":"), this);
+        horizontalLayout->addWidget(label);
+
+        // Button displaying choice
+        QPushButton *pushButton = new QPushButton(this);
+        pushButton->setCheckable(true);
+        pushButton->setFlat(true);
+        pushButton->sizePolicy().setHorizontalPolicy(QSizePolicy::Maximum);
+        m_choiceButtons.append(pushButton);
         if (i < 5) {
-            connect(m_actions.at(i), &QAction::triggered, radio_button, &QAbstractButton::click);
+            connect(m_actions.at(i), &QAction::triggered, pushButton, &QAbstractButton::click);
         }
-        connect(radio_button, &QRadioButton::clicked, this, &MultiplechoiceModeWidget::continueAction);
-        radio_button->installEventFilter(this);
+        connect(pushButton, &QPushButton::clicked, this, &MultiplechoiceModeWidget::continueAction);
+        pushButton->installEventFilter(this);
+        horizontalLayout->addWidget(pushButton);
+
+        // Spacer to align button to the left
+        horizontalLayout->addStretch(1);
     }
 }
 
@@ -149,9 +158,9 @@ bool MultiplechoiceModeWidget::eventFilter(QObject *obj, QEvent *event)
     if (event->type() == QEvent::KeyPress) {
         QKeyEvent *keyEvent = static_cast<QKeyEvent*>(event);
         if (keyEvent->key() == Qt::Key_Enter || keyEvent->key() == Qt::Key_Return) {
-            QRadioButton *radioButton = qobject_cast<QRadioButton*>(obj);
-            if (radioButton) {
-                radioButton->click();
+            QPushButton *pushButton = qobject_cast<QPushButton*>(obj);
+            if (pushButton) {
+                pushButton->click();
                 return true;
             }
         }
@@ -181,12 +190,41 @@ void MultiplechoiceModeWidget::showSolution()
     if (userInput().isValid()) {
         input = userInput().toInt();
     }
-    m_choiceButtons[m_solution]->setPalette(m_correctPalette);
+
+    const QColor textColor = palette().color(QPalette::WindowText);
+    // Set border to text color with light transparency
+    const QString borderColor = QStringLiteral("#90") +
+                palette().color(QPalette::WindowText).name().remove(0,1);
+    // Set background to correct color, but with transparency
+    const QString correctBackground = QStringLiteral("#7D") +
+                m_correctPalette.color(QPalette::Text).name().remove(0,1);
+
+    m_choiceButtons[m_solution]->setStyleSheet(
+        m_choiceButtons[m_solution]->styleSheet() +
+        " QPushButton:checked { "
+                "color: " + textColor.name() + "; "
+                "border-color: " + borderColor + "; "
+                "background-color: " + correctBackground +
+                            " }"
+    );
+    // Always check correct button to highlight correct answer
+    m_choiceButtons[m_solution]->setChecked(true);
+
     if (input != -1 && input != m_solution) {
-        m_choiceButtons[input]->setPalette(m_wrongPalette);
+        const QString wrongBackground = QStringLiteral("#7D") +
+                m_wrongPalette.color(QPalette::Text).name().remove(0,1);
+
+        m_choiceButtons[input]->setStyleSheet(
+            m_choiceButtons[input]->styleSheet() +
+            " QPushButton:checked { "
+                    "color: " + textColor.name() + "; "
+                    "border-color: " + borderColor + "; "
+                    "background-color: " + wrongBackground +
+                                " }"
+        );
     }
-    foreach(QRadioButton * radio, m_choiceButtons) {
-        radio->setEnabled(false);
+    foreach(QPushButton * pushButton, m_choiceButtons) {
+        pushButton->setEnabled(false);
     }
     m_ui->solutionPronunciationLabel->setVisible(m_ui->solutionPronunciationLabel->isEnabled());
     m_ui->solutionSoundButton->setVisible(m_ui->solutionSoundButton->isEnabled());
@@ -196,8 +234,8 @@ QVariant MultiplechoiceModeWidget::userInput()
 {
 
     int i = 0;
-    foreach(QRadioButton * radio, m_choiceButtons) {
-        if (radio->isChecked()) return i;
+    foreach(QPushButton * pushButton, m_choiceButtons) {
+        if (pushButton->isChecked()) return i;
         i++;
     }
 
@@ -225,3 +263,39 @@ void MultiplechoiceModeWidget::setQuestionPronunciation(const QString& pronuncia
     m_ui->questionPronunciationLabel->setText('[' + pronunciationText + ']');
     m_ui->questionPronunciationLabel->setEnabled(!pronunciationText.isNull());
 }
+
+void MultiplechoiceModeWidget::resetButtonStyleSheet()
+{
+    // Define default QPushButton StyleSheet
+    const QColor textColor = palette().color(QPalette::WindowText);
+    // Set border to text color with light transparency
+    const QString borderColor = QStringLiteral("#90") +
+                        palette().color(QPalette::WindowText).name().remove(0,1);
+    const QString defaultStyleSheet =
+        "QPushButton { text-align: left; "
+                      "color: " + textColor.name() + "; "
+                      "padding: 5px; "
+                      "border-color: #00FFFFFF; " // Make border transparent
+                      "border-style: solid; "
+                      "border-width: 1px; "
+                      "border-radius: 4px; "
+                      "font-style: " +
+                        m_solutionFont.styleName() + "; " +
+                      "font-weight: " +
+                        QString::number(m_solutionFont.weight()) + "; " +
+                      "font-size: " +
+                        QString::number(m_solutionFont.pointSize()) + "pt } "+
+        "QPushButton:hover { "
+                      "border-color: " + borderColor + " } "
+        "QPushButton:focus { "
+                      "color: " + textColor.name() + " } "
+        "QPushButton:focus:!hover { "
+                      "border-style: dashed; "
+                      "border-color: " + borderColor + " }";
+
+    if (!m_choiceButtons.isEmpty()) {
+        foreach(QPushButton * pushButton, m_choiceButtons) {
+            pushButton->setStyleSheet(defaultStyleSheet);
+        }
+    }
+}
diff --git a/src/practice/multiplechoicemodewidget.h b/src/practice/multiplechoicemodewidget.h
index 0d0b43c..6af1292 100644
--- a/src/practice/multiplechoicemodewidget.h
+++ b/src/practice/multiplechoicemodewidget.h
@@ -22,7 +22,7 @@ namespace Ui
 {
 class MultiplechoicePracticeWidget;
 }
-class QRadioButton;
+class QPushButton;
 
 namespace Practice
 {
@@ -59,15 +59,17 @@ public:
 public Q_SLOTS:
     virtual void showQuestion();
     virtual void showSolution();
-    virtual void setNumberOfRadioButtons(const int numberOfChoices);
+    virtual void setNumberOfPushButtons(const int numberOfChoices);
     virtual void showSynonym();
 
 protected:
     virtual bool eventFilter(QObject *obj, QEvent *event);
+    virtual void resetButtonStyleSheet();
+
 private:
     Ui::MultiplechoicePracticeWidget* m_ui;
     int m_solution;
-    QList<QRadioButton*> m_choiceButtons;
+    QList<QPushButton*> m_choiceButtons;
     QList<QAction*> m_actions;
     LatexRenderer *m_latexRenderer;
     QFont m_solutionFont;


More information about the kde-doc-english mailing list