Mixxx

/home/maxime/Projets/Mixxx/1.10/mixxx/src/errordialoghandler.cpp

Go to the documentation of this file.
00001 /***************************************************************************
00002                           errordialoghandler.cpp  -  description
00003                              -------------------
00004     begin                : Sun Feb 22 2009
00005     copyright            : (C) 2009 by Sean M. Pappalardo
00006     email                : pegasus@c64.org
00007 ***************************************************************************/
00008 
00009 /***************************************************************************
00010 *                                                                         *
00011 *   This program is free software; you can redistribute it and/or modify  *
00012 *   it under the terms of the GNU General Public License as published by  *
00013 *   the Free Software Foundation; either version 2 of the License, or     *
00014 *   (at your option) any later version.                                   *
00015 *                                                                         *
00016 ***************************************************************************/
00017 
00018 #include "errordialoghandler.h"
00019 #include <QMessageBox>
00020 #include <QtDebug>
00021 #include <QtCore>
00022 
00023 ErrorDialogProperties::ErrorDialogProperties() {
00024     m_type = DLG_NONE;
00025     m_icon = QMessageBox::NoIcon;
00026     m_title = "Mixxx";
00027     m_modal = true;
00028 }
00029 
00030 void ErrorDialogProperties::setTitle(QString title) {
00031     m_title.append(" - ").append(title);
00032 }
00033 
00034 void ErrorDialogProperties::setText(QString text) {
00035     // If no key is set, use this window text since it is likely to be unique
00036     if (m_key.isEmpty()) m_key = text;
00037     m_text = text;
00038 }
00039 
00040 void ErrorDialogProperties::setType(DialogType typeToSet) {
00041     m_type = typeToSet;
00042     switch (m_type) {
00043         case DLG_FATAL:     // Fatal uses critical icon
00044         case DLG_CRITICAL:  m_icon = QMessageBox::Critical; break;
00045         case DLG_WARNING:   m_icon = QMessageBox::Warning; break;
00046         case DLG_INFO:      m_icon = QMessageBox::Information; break;
00047         case DLG_QUESTION:  m_icon = QMessageBox::Question; break;
00048         case DLG_NONE:
00049         default:
00050             // default is NoIcon
00051             break;
00052     }
00053 }
00054 
00055 void ErrorDialogProperties::addButton(QMessageBox::StandardButton button) {
00056     m_buttons.append(button);
00057 }
00058 
00059 
00060 // ----------------------------------------------------
00061 // ---------- ErrorDialogHandler begins here ----------
00062 
00063 ErrorDialogHandler* ErrorDialogHandler::s_pInstance = NULL;
00064 
00065 ErrorDialogHandler::ErrorDialogHandler() {
00066     m_pSignalMapper = new QSignalMapper(this);
00067     connect(m_pSignalMapper, SIGNAL(mapped(QString)), this, SLOT(boxClosed(QString)));
00068 
00069     m_errorCondition=false;
00070     connect(this, SIGNAL(showErrorDialog(ErrorDialogProperties*)),
00071             this, SLOT(errorDialog(ErrorDialogProperties*)));
00072 }
00073 
00074 ErrorDialogHandler::~ErrorDialogHandler()
00075 {
00076     delete m_pSignalMapper;
00077     delete s_pInstance;
00078 }
00079 
00080 ErrorDialogProperties* ErrorDialogHandler::newDialogProperties() {
00081     ErrorDialogProperties* props = new ErrorDialogProperties();
00082     return props;
00083 }
00084 
00085 bool ErrorDialogHandler::requestErrorDialog(DialogType type, QString message) {
00086     ErrorDialogProperties* props = newDialogProperties();
00087     props->setType(type);
00088     props->setText(message);
00089     switch (type) {
00090         case DLG_FATAL:     props->setTitle(tr("Fatal error")); break;
00091         case DLG_CRITICAL:  props->setTitle(tr("Critical error")); break;
00092         case DLG_WARNING:   props->setTitle(tr("Warning")); break;
00093         case DLG_INFO:      props->setTitle(tr("Information")); break;
00094         case DLG_QUESTION:  props->setTitle(tr("Question")); break;
00095         case DLG_NONE:
00096         default:
00097             // Default title & (lack of) icon is fine
00098             break;
00099     }
00100     return requestErrorDialog(props);
00101 }
00102 
00103 bool ErrorDialogHandler::requestErrorDialog(ErrorDialogProperties* props) {
00104 
00105     // Make sure the minimum items are set
00106     QString text = props->getText();
00107     Q_ASSERT(!text.isEmpty());
00108 
00109     // Skip if a dialog with the same key is already displayed
00110     m_mutex.lock();
00111     bool keyExists = m_dialogKeys.contains(props->getKey());
00112     m_mutex.unlock();
00113     if (keyExists) {
00114         ErrorDialogProperties* dlgPropsTemp = props;
00115         props = NULL;
00116         delete dlgPropsTemp;
00117         return false;
00118     }
00119 
00120     emit (showErrorDialog(props));
00121     return true;
00122 }
00123 
00124 void ErrorDialogHandler::errorDialog(ErrorDialogProperties* props) {
00125 
00126     // Jest makin' sho' this is only run in the main (GUI) thread
00127     Q_ASSERT(QThread::currentThread()->objectName() == "Main");
00128 
00129     QMessageBox* msgBox = new QMessageBox();
00130 
00131     msgBox->setIcon(props->m_icon);
00132     msgBox->setWindowTitle(props->m_title);
00133     msgBox->setText(props->m_text);
00134     if (!props->m_infoText.isEmpty()) msgBox->setInformativeText(props->m_infoText);
00135     if (!props->m_details.isEmpty()) msgBox->setDetailedText(props->m_details);
00136 
00137     QPushButton* buttonToSet;
00138     bool setDefault;
00139     while(!props->m_buttons.isEmpty()) {
00140         setDefault = false;
00141         if (props->m_buttons.first() == props->m_defaultButton) setDefault = true;
00142 
00143         buttonToSet = msgBox->addButton(props->m_buttons.takeFirst());
00144 
00145         if (setDefault) msgBox->setDefaultButton(buttonToSet);
00146     }
00147 
00148     if (props->m_escapeButton) msgBox->setEscapeButton(msgBox->button(props->m_escapeButton));
00149 
00150     msgBox->setModal(props->m_modal);
00151 
00152     // This deletes the msgBox automatically, avoiding a memory leak
00153     msgBox->setAttribute(Qt::WA_DeleteOnClose, true);
00154 
00155     m_mutex.lock();
00156     m_dialogKeys.append(props->m_key);    // To avoid duplicate dialogs on the same error
00157     m_mutex.unlock();
00158 
00159     // Signal mapper calls our slot with the key parameter so it knows which to remove from the list
00160     connect(msgBox, SIGNAL(finished(int)), m_pSignalMapper, SLOT(map()));
00161     m_pSignalMapper->setMapping(msgBox, props->m_key);
00162 
00163     if (props->m_modal) msgBox->exec();    // Blocks so the user has a chance to read it before application exit
00164     else msgBox->show();
00165 
00166     // If fatal, should we just abort here and not try to exit gracefully?
00167 
00168     if (props->m_type>=DLG_CRITICAL) {  // If critical/fatal, gracefully exit application if possible
00169         m_errorCondition=true;
00170         if (QCoreApplication::instance()) {
00171             QCoreApplication::instance()->exit(-1);
00172         }
00173         else {
00174             qDebug() << "QCoreApplication::instance() is NULL! Abruptly quitting...";
00175             if (props->m_type==DLG_FATAL) abort();
00176             else exit(-1);
00177         }
00178     }
00179 
00180     ErrorDialogProperties* dlgPropsTemp = props;
00181     props = NULL;
00182     delete dlgPropsTemp;
00183 }
00184 
00185 void ErrorDialogHandler::boxClosed(QString key)
00186 {
00187     QMessageBox* msgBox = (QMessageBox*)m_pSignalMapper->mapping(key);
00188 
00189     QMessageBox::StandardButton whichStdButton = msgBox->standardButton(msgBox->clickedButton());
00190 
00191     emit stdButtonClicked(key, whichStdButton);
00192 
00193     // If the user clicks "Ignore," we leave the key in the list so the same
00194     //  error is not displayed again for the duration of the session
00195     if (whichStdButton == QMessageBox::Ignore) {
00196         qWarning() << "Suppressing this" << msgBox->windowTitle() << "error box for the duration of the application.";
00197         return;
00198     }
00199 
00200     m_mutex.lock();
00201     if (m_dialogKeys.contains(key)) {
00202         if (!m_dialogKeys.removeOne(key)) qWarning() << "Error dialog key removal from list failed!";
00203     }
00204     else qWarning() << "Error dialog key is missing from key list!";
00205     m_mutex.unlock();
00206 }
00207 
00208 bool ErrorDialogHandler::checkError() {
00209     return m_errorCondition;
00210 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines