![]() |
Mixxx
|
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 }