Ver código fonte

Merge branch 'ctkMessageBox'

* ctkMessageBox:
  Fix various misbehavior of ctkMessageBox
Julien Finet 13 anos atrás
pai
commit
4298ab24b6

+ 2 - 1
Libs/Widgets/Testing/Cpp/CMakeLists.txt

@@ -118,8 +118,9 @@ set(Tests_MOC_SRCS
 set(Tests_MOC_CPP)
 QT4_WRAP_CPP(Tests_MOC_CPP ${Tests_MOC_SRCS})
 QT4_GENERATE_MOCS(
-  ctkRangeSliderTest.cpp
   ctkFlatProxyModelTest.cpp
+  ctkMessageBoxDontShowAgainTest.cpp
+  ctkRangeSliderTest.cpp
   )
 
 add_executable(${KIT}CppTests ${Tests} ${Tests_SRCS} ${Tests_MOC_CPP})

+ 465 - 51
Libs/Widgets/Testing/Cpp/ctkMessageBoxDontShowAgainTest.cpp

@@ -27,73 +27,487 @@
 
 // CTK includes
 #include "ctkMessageBox.h"
+#include "ctkTest.h"
 
 // STD includes
 #include <cstdlib>
 #include <iostream>
 
-//-----------------------------------------------------------------------------
-int ctkMessageBoxDontShowAgainTest(int argc, char * argv [] )
+Q_DECLARE_METATYPE(QMessageBox::StandardButton);
+Q_DECLARE_METATYPE(QMessageBox::ButtonRole);
+
+// ----------------------------------------------------------------------------
+class ctkMessageBoxDontShowAgainTester: public QObject
 {
-  QApplication app(argc, argv);
-  /// set the names for QSettings to work
-  app.setOrganizationName("CommonToolKit");
-  app.setOrganizationDomain("www.commontk.org");
-  app.setApplicationName("CTK");
+  Q_OBJECT
+  void testExecMessageBox(ctkMessageBox& messageBox);
 
-  ctkMessageBox confirmDialog;
+private Q_SLOTS:
+  void initTestCase();
+  void init();
+  void cleanup();
 
-  // Test default values.
-  if (confirmDialog.isDontShowAgainVisible() != false ||
-      confirmDialog.dontShowAgain() != false ||
-      confirmDialog.dontShowAgainSettingsKey().isEmpty() != true)
-    {
-    std::cerr << "ctkMessageBox default values failed" << std::endl;
-    return EXIT_FAILURE;
-    }
-  confirmDialog.setText("Are you sure you want to exit?");
-  confirmDialog.setIcon(QMessageBox::Question);
-  confirmDialog.setDontShowAgainVisible(true);
+  // Check default values of ctkMessageBox
+  void testDefaults();
+
+  // Ensure the "dont's show again" checkbox works correctly with 1 button (Ok)
+  void testDontShowAgain();
+  void testDontShowAgain_data();
+
+  // Ensure the "dont's show again" checkbox works correctly with 2 buttons
+  // Ok and Cancel
+  void testOkCancel();
+  void testOkCancel_data();
+
+  // Test Settings key with 1 button (Ok)
+  void testDontShowAgainSettingsKey();
+  void testDontShowAgainSettingsKey_data();
+
+  // Test with 2 buttons (Ok and Cancel)
+  void testDontShowAgainSettingsKeyOkCancel();
+  void testDontShowAgainSettingsKeyOkCancel_data();
+
+  // Check "Don't show again" before the the dialog is shown.
+  // -> doesn't show the dialog.
+  void testDontShowAgainSettingsKeySetDontShowAgain();
+  void testDontShowAgainSettingsKeySetDontShowAgain_data();
 
+  // After the dialog is shown, simulate a click on the
+  // "don't show again" checkbox.
+  void testDontShowAgainSettingsKeyClickDontShowAgain();
+  void testDontShowAgainSettingsKeyClickDontShowAgain_data();
+
+  // static utility function
+  void testConfirmExit();
+  void testConfirmExit_data();
+  //void testCustomButton();
+};
+
+// ----------------------------------------------------------------------------
+void ctkMessageBoxDontShowAgainTester::initTestCase()
+{
+  // Setup QApplication for settings
+  qApp->setOrganizationName("CommonToolKit");
+  qApp->setOrganizationDomain("www.commontk.org");
+  qApp->setApplicationName("CTK");
+}
+
+// ----------------------------------------------------------------------------
+void ctkMessageBoxDontShowAgainTester::init()
+{
   QSettings settings;
-  settings.setValue("DontShow", true);
+  settings.setValue("Show", int(QMessageBox::InvalidRole));
+  settings.setValue("DontShowWithOkButton", int(QMessageBox::Ok));
+  settings.setValue("DontShowWithAcceptRole", int(QMessageBox::AcceptRole));
 
-  confirmDialog.setDontShowAgainSettingsKey("DontShow");
-  if (confirmDialog.dontShowAgainSettingsKey() != "DontShow")
-    {
-    std::cerr << "ctkMessageBox::setDontShowAgainSettingsKey failed:"
-              << confirmDialog.dontShowAgainSettingsKey().toStdString() << std::endl;
-    return EXIT_FAILURE;
-    }
-  if (confirmDialog.dontShowAgain() != true)
-    {
-    std::cerr << "ctkMessageBox::setDontShowAgainSettingsKey failed:"
-              << confirmDialog.dontShowAgain() << std::endl;
-    return EXIT_FAILURE;
-    }
+  settings.setValue("DontShowWithCancelButton", int(QMessageBox::Cancel));
+  settings.setValue("DontShowWithRejectRole", int(QMessageBox::RejectRole));
+}
 
-  // exec() should return automatically because DontShowAgain is true
-  if (confirmDialog.exec() != QDialog::Accepted)
-    {
-    std::cerr << "ctkMessageBox::exec failed:" << std::endl;
-    return EXIT_FAILURE;
-    }
+// ----------------------------------------------------------------------------
+void ctkMessageBoxDontShowAgainTester::cleanup()
+{
+  QSettings settings;
+  settings.clear();
+}
 
-  // test the static version
-  if (ctkMessageBox::confirmExit("DontShow") != true)
-    {
-    std::cerr << "ctkMessageBox::confirmExit failed:" << std::endl;
-    return EXIT_FAILURE;
-    }
+// ----------------------------------------------------------------------------
+void ctkMessageBoxDontShowAgainTester::testDefaults()
+{
+  ctkMessageBox messageBox;
 
-  confirmDialog.setDontShowAgain(false);
+  QCOMPARE(messageBox.isDontShowAgainVisible(), false);
+  QCOMPARE(messageBox.dontShowAgain(), false);
+  QCOMPARE(messageBox.dontShowAgainSettingsKey(), QString());
+  QCOMPARE(messageBox.buttons().size(), 0);
+  QCOMPARE(messageBox.standardButtons(), QMessageBox::NoButton);
 
-  // modal dialog
-  confirmDialog.open();
+  messageBox.show();
+  qApp->processEvents();
 
-  if (argc < 2 || QString(argv[1]) != "-I" )
+  QCOMPARE(messageBox.buttons().size(), 1);
+  QCOMPARE(messageBox.standardButtons(), QMessageBox::Ok);
+}
+
+// ----------------------------------------------------------------------------
+void ctkMessageBoxDontShowAgainTester::testExecMessageBox(ctkMessageBox& messageBox)
+{
+  QFETCH(int, buttonOrRole);
+  if (buttonOrRole != QMessageBox::InvalidRole)
     {
-    QTimer::singleShot(200, &confirmDialog, SLOT(accept()));
+    if (messageBox.standardButtons() == QMessageBox::NoButton &&
+        messageBox.buttons().size() == 0)
+      {
+      messageBox.addButton(QMessageBox::Ok);
+      }
+    if (messageBox.standardButtons() & buttonOrRole)
+      {
+      QAbstractButton* button = messageBox.button(
+        static_cast<QMessageBox::StandardButton>(buttonOrRole));
+      QVERIFY(button);
+      QTimer::singleShot(0, button, SLOT(click()));
+      }
+    else
+      {
+      const char* slot = 0;
+      if (buttonOrRole == QMessageBox::AcceptRole)
+        {
+        slot = SLOT(accept());
+        }
+      else if (buttonOrRole == QMessageBox::RejectRole)
+        {
+        slot = SLOT(reject());
+        }
+      QTimer::singleShot(0, &messageBox, slot);
+      }
     }
-  return app.exec();
+  // shouldn't hang
+  int execResult = messageBox.exec();
+  QFETCH(int, result);
+  QCOMPARE(execResult, result);
+
+  QFETCH(QMessageBox::ButtonRole, resultRole);
+  QCOMPARE(messageBox.buttonRole(messageBox.clickedButton()), resultRole);
+}
+
+// ----------------------------------------------------------------------------
+void ctkMessageBoxDontShowAgainTester::testDontShowAgain()
+{
+  ctkMessageBox messageBox;
+
+  QFETCH(bool, visible);
+  messageBox.setDontShowAgainVisible(visible);
+
+  QFETCH(bool, dontShowAgain);
+  messageBox.setDontShowAgain(dontShowAgain);
+
+  this->testExecMessageBox(messageBox);
+}
+
+// ----------------------------------------------------------------------------
+void ctkMessageBoxDontShowAgainTester::testDontShowAgain_data()
+{
+  QTest::addColumn<bool>("visible");
+  QTest::addColumn<bool>("dontShowAgain");
+  QTest::addColumn<int>("buttonOrRole");
+  QTest::addColumn<int>("result");
+  QTest::addColumn<QMessageBox::ButtonRole>("resultRole");
+
+  QTest::newRow("invisible dont show") << false << true << int(QMessageBox::InvalidRole) << int(QMessageBox::Ok) << QMessageBox::AcceptRole;
+  QTest::newRow("visible dont show") << true << true << int(QMessageBox::InvalidRole) << int(QMessageBox::Ok) << QMessageBox::AcceptRole;
+
+  QTest::newRow("invisible show click ok") << false << false << int(QMessageBox::Ok) << int(QMessageBox::Ok) << QMessageBox::AcceptRole;
+  QTest::newRow("visible show click ok") << true << false << int(QMessageBox::Ok) << int(QMessageBox::Ok) << QMessageBox::AcceptRole;
+  QTest::newRow("invisible show accept") << false << false << int(QMessageBox::AcceptRole) << int(QDialog::Accepted) << QMessageBox::InvalidRole;
+  QTest::newRow("visible show accept") << true << false << int(QMessageBox::AcceptRole) << int(QDialog::Accepted) << QMessageBox::InvalidRole;
+}
+
+// ----------------------------------------------------------------------------
+void ctkMessageBoxDontShowAgainTester::testOkCancel()
+{
+  ctkMessageBox messageBox;
+  messageBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
+
+  QFETCH(bool, visible);
+  messageBox.setDontShowAgainVisible(visible);
+
+  QFETCH(bool, dontShowAgain);
+  messageBox.setDontShowAgain(dontShowAgain);
+
+  this->testExecMessageBox(messageBox);
+}
+
+// ----------------------------------------------------------------------------
+void ctkMessageBoxDontShowAgainTester::testOkCancel_data()
+{
+  this->testDontShowAgain_data();
+
+  QTest::newRow("invisible show click cancel") << false << false << int(QMessageBox::Cancel) << int(QMessageBox::Cancel) << QMessageBox::RejectRole;
+  QTest::newRow("visible show click cancel") << true << false << int(QMessageBox::Cancel) << int(QMessageBox::Cancel) << QMessageBox::RejectRole;
+  QTest::newRow("invisible show reject") << false << false << int(QMessageBox::RejectRole) << int(QMessageBox::Rejected) << QMessageBox::InvalidRole;
+  QTest::newRow("visible show click cancel") << true << false << int(QMessageBox::RejectRole) << int(QMessageBox::Rejected) << QMessageBox::InvalidRole;
+}
+
+// ----------------------------------------------------------------------------
+void ctkMessageBoxDontShowAgainTester::testDontShowAgainSettingsKey()
+{
+  ctkMessageBox messageBox;
+
+  QFETCH(bool, visible);
+  messageBox.setDontShowAgain(visible);
+
+  QFETCH(QString, key);
+  messageBox.setDontShowAgainSettingsKey(key);
+  QCOMPARE(messageBox.dontShowAgainSettingsKey(), key);
+
+  QFETCH(bool, dontShowAgain);
+  QCOMPARE(messageBox.dontShowAgain(), dontShowAgain);
+
+  this->testExecMessageBox(messageBox);
+
+  QSettings settings;
+  QFETCH(int, keyValue);
+  QCOMPARE(settings.value(key).toInt(), keyValue);
 }
+
+// ----------------------------------------------------------------------------
+void ctkMessageBoxDontShowAgainTester::testDontShowAgainSettingsKey_data()
+{
+  QTest::addColumn<bool>("visible");
+  QTest::addColumn<QString>("key");
+  QTest::addColumn<bool>("dontShowAgain");
+  QTest::addColumn<int>("buttonOrRole");
+  QTest::addColumn<int>("result");
+  QTest::addColumn<QMessageBox::ButtonRole>("resultRole");
+  QTest::addColumn<int>("keyValue");
+
+  QTest::newRow("invisible NonExistingKey")
+    << false << "NonExistingKey" << false << int(QMessageBox::Ok)
+    << int(QMessageBox::Ok) << QMessageBox::AcceptRole
+    << int(QMessageBox::InvalidRole);
+  QTest::newRow("visible NonExistingKey")
+    << true << "NonExistingKey" << false << int(QMessageBox::Ok)
+    << int(QMessageBox::Ok) << QMessageBox::AcceptRole
+    << int(QMessageBox::InvalidRole);
+
+  QTest::newRow("invisible Show")
+    << false << "Show" << false << int(QMessageBox::Ok)
+    << int(QMessageBox::Ok) << QMessageBox::AcceptRole
+    << int(QMessageBox::InvalidRole);
+  QTest::newRow("visible Show")
+    << true << "Show" << false << int(QMessageBox::Ok)
+    << int(QMessageBox::Ok) << QMessageBox::AcceptRole
+    << int(QMessageBox::InvalidRole);
+
+  QTest::newRow("invisible DontShow Ok")
+    << false << "DontShowWithOkButton" << true << int(QMessageBox::InvalidRole)
+    << int(QMessageBox::Ok) << QMessageBox::AcceptRole
+    << int(QMessageBox::Ok);
+  QTest::newRow("visible DontShow Ok")
+    << true << "DontShowWithOkButton" << true << int(QMessageBox::InvalidRole)
+    << int(QMessageBox::Ok) << QMessageBox::AcceptRole
+    << int(QMessageBox::Ok);
+
+  QTest::newRow("invisible DontShow Accept")
+    << false << "DontShowWithAcceptRole" << true << int(QMessageBox::InvalidRole)
+    << int(QMessageBox::Ok) << QMessageBox::AcceptRole
+    << int(QMessageBox::Ok);
+  QTest::newRow("visible DontShow Accept")
+    << true << "DontShowWithAcceptRole" << true << int(QMessageBox::InvalidRole)
+    << int(QMessageBox::Ok) << QMessageBox::AcceptRole
+    << int(QMessageBox::Ok);
+}
+
+// ----------------------------------------------------------------------------
+void ctkMessageBoxDontShowAgainTester::testDontShowAgainSettingsKeyOkCancel()
+{
+  ctkMessageBox messageBox;
+  messageBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
+
+  QFETCH(bool, visible);
+  messageBox.setDontShowAgain(visible);
+
+  QFETCH(QString, key);
+  messageBox.setDontShowAgainSettingsKey(key);
+  QCOMPARE(messageBox.dontShowAgainSettingsKey(), key);
+
+  QFETCH(bool, dontShowAgain);
+  QCOMPARE(messageBox.dontShowAgain(), dontShowAgain);
+
+  this->testExecMessageBox(messageBox);
+
+  QSettings settings;
+  QFETCH(int, keyValue);
+  QCOMPARE(settings.value(key).toInt(), keyValue);
+}
+
+// ----------------------------------------------------------------------------
+void ctkMessageBoxDontShowAgainTester::testDontShowAgainSettingsKeyOkCancel_data()
+{
+  this->testDontShowAgainSettingsKey_data();
+
+  QTest::newRow("invisible DontShow Cancel")
+    << false << "DontShowWithCancelButton" << true << int(QMessageBox::InvalidRole)
+    << int(QMessageBox::Cancel) << QMessageBox::RejectRole
+    << int(QMessageBox::Cancel);
+  QTest::newRow("visible DontShow Cancel")
+    << true << "DontShowWithCancelButton" << true << int(QMessageBox::InvalidRole)
+    << int(QMessageBox::Cancel) << QMessageBox::RejectRole
+    << int(QMessageBox::Cancel);
+
+  QTest::newRow("invisible DontShow Reject")
+    << false << "DontShowWithRejectRole" << true << int(QMessageBox::InvalidRole)
+    << int(QMessageBox::Cancel) << QMessageBox::RejectRole
+    << int(QMessageBox::RejectRole);
+  QTest::newRow("visible DontShow Reject")
+    << true << "DontShowWithRejectRole" << true << int(QMessageBox::InvalidRole)
+    << int(QMessageBox::Cancel) << QMessageBox::RejectRole
+    << int(QMessageBox::RejectRole);
+}
+
+// ----------------------------------------------------------------------------
+void ctkMessageBoxDontShowAgainTester::testDontShowAgainSettingsKeySetDontShowAgain()
+{
+  ctkMessageBox messageBox;
+  messageBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
+
+  QFETCH(QString, key);
+  messageBox.setDontShowAgainSettingsKey(key);
+  QCOMPARE(messageBox.dontShowAgainSettingsKey(), key);
+
+  QFETCH(bool, dontShowAgain);
+  messageBox.setDontShowAgain(dontShowAgain);
+
+  this->testExecMessageBox(messageBox);
+
+  QSettings settings;
+  QFETCH(int, keyValue);
+  QCOMPARE(settings.value(key).toInt(), keyValue);
+}
+
+// ----------------------------------------------------------------------------
+void ctkMessageBoxDontShowAgainTester::testDontShowAgainSettingsKeySetDontShowAgain_data()
+{
+  QTest::addColumn<QString>("key");
+  QTest::addColumn<bool>("dontShowAgain");
+  QTest::addColumn<int>("buttonOrRole");
+  QTest::addColumn<int>("result");
+  QTest::addColumn<QMessageBox::ButtonRole>("resultRole");
+  QTest::addColumn<int>("keyValue");
+
+  // Doesn't have time to click on anything, the dialog is already skipped
+  QTest::newRow("NonExistingKey dont show again")
+    << "NonExistingKey" << true << int(QMessageBox::InvalidRole)
+    << int(QMessageBox::Ok) << QMessageBox::AcceptRole
+    << int(QMessageBox::Ok);
+
+  QTest::newRow("Show dont show again accept")
+    << "Show" << true << int(QMessageBox::InvalidRole)
+    << int(QMessageBox::Ok) << QMessageBox::AcceptRole
+    << int(QMessageBox::Ok);
+
+  QTest::newRow("NonExistingKey show again accept")
+    << "NonExistingKey" << false << int(QMessageBox::Ok)
+    << int(QMessageBox::Ok) << QMessageBox::AcceptRole
+    << int(QMessageBox::InvalidRole);
+  // ctkMessageBox never write the settings.
+  QTest::newRow("NonExistingKey show again reject")
+    << "NonExistingKey" << false << int(QMessageBox::Cancel)
+    << int(QMessageBox::Cancel) << QMessageBox::RejectRole
+    << QVariant().toInt();
+
+  QTest::newRow("Show show again accept")
+    << "Show" << false << int(QMessageBox::Ok)
+    << int(QMessageBox::Ok) << QMessageBox::AcceptRole
+    << int(QMessageBox::InvalidRole);
+  // ctkMessageBox never write the settings but the settings exists.
+  QTest::newRow("Show dont show reject")
+    << "Show" << false << int(QMessageBox::Cancel)
+    << int(QMessageBox::Cancel) << QMessageBox::RejectRole
+    << int(QMessageBox::InvalidRole);
+
+  QTest::newRow("Show show again accept")
+    << "DontShowWithOkButton" << false << int(QMessageBox::Ok)
+    << int(QMessageBox::Ok) << QMessageBox::AcceptRole
+    << int(QMessageBox::InvalidRole);
+  QTest::newRow("Show dont show reject")
+    << "DontShowWithOkButton" << false << int(QMessageBox::Cancel)
+    << int(QMessageBox::Cancel) << QMessageBox::RejectRole
+    << int(QMessageBox::Ok);
+
+}
+
+// ----------------------------------------------------------------------------
+void ctkMessageBoxDontShowAgainTester::testDontShowAgainSettingsKeyClickDontShowAgain()
+{
+  ctkMessageBox messageBox;
+  messageBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
+
+  QFETCH(QString, key);
+  messageBox.setDontShowAgainSettingsKey(key);
+  QCOMPARE(messageBox.dontShowAgainSettingsKey(), key);
+
+  QFETCH(bool, dontShowAgain);
+  QCheckBox* checkBox =
+    messageBox.findChild<QCheckBox*>("ctk_msgbox_dontshowcheckbox");
+  QMetaObject::invokeMethod(checkBox, "setChecked", Qt::QueuedConnection,
+                            Q_ARG(bool, dontShowAgain));
+  this->testExecMessageBox(messageBox);
+
+  QSettings settings;
+  QFETCH(int, keyValue);
+  QCOMPARE(settings.value(key).toInt(), keyValue);
+}
+
+// ----------------------------------------------------------------------------
+void ctkMessageBoxDontShowAgainTester::testDontShowAgainSettingsKeyClickDontShowAgain_data()
+{
+  QTest::addColumn<QString>("key");
+  QTest::addColumn<bool>("dontShowAgain");
+  QTest::addColumn<int>("buttonOrRole");
+  QTest::addColumn<int>("result");
+  QTest::addColumn<QMessageBox::ButtonRole>("resultRole");
+  QTest::addColumn<int>("keyValue");
+
+  QTest::newRow("NonExistingKey dont show again ok")
+    << "NonExistingKey" << true << int(QMessageBox::Ok)
+    << int(QMessageBox::Ok) << QMessageBox::AcceptRole
+    << int(QMessageBox::Ok);
+  QTest::newRow("NonExistingKey dont show again cancel")
+    << "NonExistingKey" << true << int(QMessageBox::Cancel)
+    << int(QMessageBox::Cancel) << QMessageBox::RejectRole
+    << QVariant().toInt();
+
+  QTest::newRow("Show dont show again accept")
+    << "Show" << true << int(QMessageBox::Ok)
+    << int(QMessageBox::Ok) << QMessageBox::AcceptRole
+    << int(QMessageBox::Ok);
+  QTest::newRow("Show dont show again cancel")
+    << "Show" << true << int(QMessageBox::Cancel)
+    << int(QMessageBox::Cancel) << QMessageBox::RejectRole
+    << int(QMessageBox::InvalidRole);
+
+  QTest::newRow("NonExistingKey show again accept")
+    << "NonExistingKey" << false << int(QMessageBox::Ok)
+    << int(QMessageBox::Ok) << QMessageBox::AcceptRole
+    << int(QMessageBox::InvalidRole);
+  QTest::newRow("NonExistingKey show again reject")
+    << "NonExistingKey" << false << int(QMessageBox::Cancel)
+    << int(QMessageBox::Cancel) << QMessageBox::RejectRole
+    << QVariant().toInt();
+
+  QTest::newRow("Show show again accept")
+    << "Show" << false << int(QMessageBox::Ok)
+    << int(QMessageBox::Ok) << QMessageBox::AcceptRole
+    << int(QMessageBox::InvalidRole);
+  QTest::newRow("Show dont show reject")
+    << "Show" << false << int(QMessageBox::Cancel)
+    << int(QMessageBox::Cancel) << QMessageBox::RejectRole
+    << int(QMessageBox::InvalidRole);
+}
+
+// ----------------------------------------------------------------------------
+void ctkMessageBoxDontShowAgainTester::testConfirmExit()
+{
+  QFETCH(QString, key);
+  bool res = ctkMessageBox::confirmExit(key);
+
+  QFETCH(bool, expectedRes);
+  QCOMPARE(res, expectedRes);
+}
+
+// ----------------------------------------------------------------------------
+void ctkMessageBoxDontShowAgainTester::testConfirmExit_data()
+{
+  QTest::addColumn<QString>("key");
+  QTest::addColumn<bool>("expectedRes");
+
+  QTest::newRow("DontShowWithOkButton") << "DontShowWithOkButton" << true;
+  QTest::newRow("DontShowWithAcceptRole") << "DontShowWithAcceptRole" << true;
+  QTest::newRow("DontShowWithCancelButton") << "DontShowWithCancelButton" << false;
+  QTest::newRow("DontShowWithRejectRole") << "DontShowWithRejectRole" << false;
+}
+
+// ----------------------------------------------------------------------------
+CTK_TEST_MAIN(ctkMessageBoxDontShowAgainTest)
+#include "moc_ctkMessageBoxDontShowAgainTest.cpp"

+ 91 - 15
Libs/Widgets/ctkMessageBox.cpp

@@ -22,6 +22,7 @@
 #include <QCheckBox>
 #include <QDebug>
 #include <QGridLayout>
+#include <QPushButton>
 #include <QSettings>
 #include <QTimer>
 
@@ -42,18 +43,24 @@ public:
   virtual ~ctkMessageBoxPrivate();
 
   void init();
+  int dontShowAgainButtonOrRole();
+  QAbstractButton* button(int buttonOrRole);
+  int buttonFromSettings();
   void readSettings();
-  void writeSettings();
+  void writeSettings(int button);
 public:
   QString        DontShowAgainSettingsKey;
   QCheckBox*     DontShowAgainCheckBox;
+  bool           SaveDontShowAgainSettingsOnAcceptOnly;
 };
 
 //-----------------------------------------------------------------------------
 ctkMessageBoxPrivate::ctkMessageBoxPrivate(ctkMessageBox& object)
   : q_ptr(&object)
 {
+  this->DontShowAgainSettingsKey = QString();
   this->DontShowAgainCheckBox = 0;
+  this->SaveDontShowAgainSettingsOnAcceptOnly = true;
 }
 
 //-----------------------------------------------------------------------------
@@ -72,6 +79,62 @@ void ctkMessageBoxPrivate::init()
   // is bigger than the text+checkbox height, it would be truncated.
   this->DontShowAgainCheckBox->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
   this->DontShowAgainCheckBox->setChecked(false);
+  this->DontShowAgainCheckBox->hide();
+}
+
+//-----------------------------------------------------------------------------
+int ctkMessageBoxPrivate::dontShowAgainButtonOrRole()
+{
+  int buttonOrRole = QMessageBox::InvalidRole;
+  if (this->DontShowAgainCheckBox->isChecked())
+    {
+    buttonOrRole = this->buttonFromSettings();
+    if (buttonOrRole == QMessageBox::InvalidRole)
+      {
+      buttonOrRole = QMessageBox::AcceptRole;
+      }
+    }
+  return buttonOrRole;
+}
+
+
+//-----------------------------------------------------------------------------
+QAbstractButton* ctkMessageBoxPrivate::button(int buttonOrRole)
+{
+  Q_Q(ctkMessageBox);
+  QAbstractButton* autoAcceptButton = 0;
+  // Special case when no button is in a dialog, QMessageBox adds the Ok
+  // button automatically.
+  if (q->buttons().size() == 0 &&
+      buttonOrRole != QMessageBox::InvalidRole)
+    {
+    q->addButton(QMessageBox::Ok);
+    }
+  if ( q->standardButtons() & buttonOrRole)
+    {
+    autoAcceptButton = q->button(static_cast<QMessageBox::StandardButton>(buttonOrRole));
+    }
+  else
+    {
+    foreach(QAbstractButton* button, q->buttons())
+      {
+      if (q->buttonRole(button) == buttonOrRole)
+        {
+        autoAcceptButton = button;
+        break;
+        }
+      }
+    }
+  return autoAcceptButton;
+}
+
+//-----------------------------------------------------------------------------
+int ctkMessageBoxPrivate::buttonFromSettings()
+{
+  QSettings settings;
+  int button = settings.value(this->DontShowAgainSettingsKey,
+                              static_cast<int>(QMessageBox::InvalidRole)).toInt();
+  return button;
 }
 
 //-----------------------------------------------------------------------------
@@ -81,22 +144,21 @@ void ctkMessageBoxPrivate::readSettings()
     {
     return;
     }
-  QSettings settings;
-  bool dontShow = settings.value(this->DontShowAgainSettingsKey,
-    this->DontShowAgainCheckBox->isChecked()).toBool();
-  this->DontShowAgainCheckBox->setChecked(dontShow);
+  int button = this->buttonFromSettings();
+  this->DontShowAgainCheckBox->setChecked(button != QMessageBox::InvalidRole);
 }
 
 //-----------------------------------------------------------------------------
-void ctkMessageBoxPrivate::writeSettings()
+void ctkMessageBoxPrivate::writeSettings(int button)
 {
   if (this->DontShowAgainSettingsKey.isEmpty())
     {
     return;
     }
   QSettings settings;
-  settings.setValue(this->DontShowAgainSettingsKey, this->DontShowAgainCheckBox->isChecked());
-  qDebug() << "write...";
+  settings.setValue(this->DontShowAgainSettingsKey,
+                    QVariant(this->DontShowAgainCheckBox->isChecked() ?
+                             button : QMessageBox::InvalidRole));
 }
 
 //-----------------------------------------------------------------------------
@@ -137,6 +199,7 @@ void ctkMessageBox::setDontShowAgainVisible(bool visible)
     return;
     }
   QGridLayout *grid = static_cast<QGridLayout *>(this->layout());
+  d->DontShowAgainCheckBox->setVisible(true);
   grid->addWidget(d->DontShowAgainCheckBox, 1, 1, 1, 1);
 }
 
@@ -178,17 +241,24 @@ void ctkMessageBox::setDontShowAgain(bool dontShow)
 {
   Q_D(ctkMessageBox);
   d->DontShowAgainCheckBox->setChecked(dontShow);
-  d->writeSettings();
+  // We don't write into settings here because we want the same behavior
+  // as if the user clicked on the checkbox.
+  // If you want to save the preference into settings even if the user
+  // escape/cancel/reject the dialog, then you must set the QSettings value
+  // manually
 }
 
 //-----------------------------------------------------------------------------
 void ctkMessageBox::done(int resultCode)
 {
   Q_D(ctkMessageBox);
-  if (resultCode == QDialog::Accepted)
+  // Don't save if the button is not an accepting button
+  if (!d->SaveDontShowAgainSettingsOnAcceptOnly ||
+      this->buttonRole( this->clickedButton() ) == QMessageBox::AcceptRole )
     {
-    d->writeSettings();
+    d->writeSettings(resultCode);
     }
+
   this->Superclass::done(resultCode);
 }
 
@@ -198,10 +268,14 @@ void ctkMessageBox::setVisible(bool visible)
   Q_D(ctkMessageBox);
   if (visible)
     {
-    d->readSettings();
-    if (d->DontShowAgainCheckBox->isChecked())
+    int dontShowAgainButtonOrRole = d->dontShowAgainButtonOrRole();
+    QAbstractButton* autoAcceptButton = d->button(dontShowAgainButtonOrRole);
+    if (autoAcceptButton)
       {
-      QTimer::singleShot(0, this, SLOT(accept()));
+      // Don't call click now, it would destroy the message box. The calling
+      // function might expect the message box to be still valid after
+      // setVisible() return.
+      QTimer::singleShot(0, autoAcceptButton, SLOT(click()));
       return;
       }
     }
@@ -214,7 +288,9 @@ bool ctkMessageBox
 {
   ctkMessageBox dialog(parentWidget);
   dialog.setText(tr("Are you sure you want to exit?"));
+  dialog.setIcon(QMessageBox::Question);
+  dialog.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel);
   dialog.setDontShowAgainVisible(!dontShowAgainKey.isEmpty());
   dialog.setDontShowAgainSettingsKey(dontShowAgainKey);
-  return dialog.exec() == QDialog::Accepted;
+  return dialog.exec() == QMessageBox::Ok;
 }

+ 11 - 5
Libs/Widgets/ctkMessageBox.h

@@ -35,7 +35,10 @@ class ctkMessageBoxPrivate;
 class CTK_WIDGETS_EXPORT ctkMessageBox : public QMessageBox
 {
   Q_OBJECT
-  /// This property controls the visibility of the "Dont show again" checkbox.
+  /// This property controls the visibility of the "Don't show again" checkbox.
+  /// Even if the checkbox is not visible, the dialog is not not shown if
+  /// \a dontShowAgain is true.
+  /// By default, the "Don't show again" checkbox is not visible.
   Q_PROPERTY(bool dontShowAgainVisible READ isDontShowAgainVisible WRITE setDontShowAgainVisible)
 
   /// This property holds wether the dialog should be shown next time exec()
@@ -45,15 +48,18 @@ class CTK_WIDGETS_EXPORT ctkMessageBox : public QMessageBox
   /// checkbox and the dialog is accepted.
   /// If the checkbox is checked by the user but the dialog is rejected (click
   /// on Cancel), \a dontShowAgain is not changed.
-  /// If \a dontShowAgainSettingsKey is set, the \a dontShowAgain is set as
-  /// the value for the key.
+  /// If \a dontShowAgainSettingsKey is set, the \a dontShowAgain is set with
+  /// the value of the key.
   /// By default, dontShowAgain is false.
   Q_PROPERTY(bool dontShowAgain READ dontShowAgain WRITE setDontShowAgain)
 
   /// This property holds the settings key that is used to synchronize the state
   /// of the checkbox "Don't show this message again"
-  /// with the given key value within QSettings.
-  /// By default, no key is set
+  /// with the given key value within QSettings. If the settings value is !=
+  /// QMessageBox::InvalidRole, the dialog is shown, otherwise it is skipped by
+  /// simulating a click on the button corresponding to the settings value (QMessageButton::StandardButton or
+  /// QMessageBox::ButtonRole)
+  /// By default, no key is set.
   Q_PROPERTY(QString dontShowAgainSettingsKey READ dontShowAgainSettingsKey WRITE setDontShowAgainSettingsKey)
 
 public: