e02b856f6b9081b242245cc47b52fc9f95eb0ef7
[quassel.git] / src / contrib / libqxt-2007-10-24 / src / gui / qxtconfirmationmessage.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) Qxt Foundation. Some rights reserved.
4 **
5 ** This file is part of the QxtGui module of the Qt eXTension library
6 **
7 ** This library is free software; you can redistribute it and/or modify it
8 ** under the terms of th Common Public License, version 1.0, as published by
9 ** IBM.
10 **
11 ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY
12 ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
13 ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR
14 ** FITNESS FOR A PARTICULAR PURPOSE.
15 **
16 ** You should have received a copy of the CPL along with this file.
17 ** See the LICENSE file and the cpl1.0.txt file included with the source
18 ** distribution for more information. If you did not receive a copy of the
19 ** license, contact the Qxt Foundation.
20 **
21 ** <http://libqxt.sourceforge.net>  <foundation@libqxt.org>
22 **
23 ****************************************************************************/
24 #include "qxtconfirmationmessage.h"
25
26 #include <QCoreApplication>
27 #if QT_VERSION >= 0x040200
28 #include <QDialogButtonBox>
29 #endif // QT_VERSION
30 #include <QPushButton>
31 #include <QGridLayout>
32 #include <QCheckBox>
33
34 static const QLatin1String DEFAULT_ORGANIZATION("QxtGui");
35 static const QLatin1String DEFAULT_APPLICATION("QxtConfirmationMessage");
36
37 class QxtConfirmationMessagePrivate : public QxtPrivate<QxtConfirmationMessage>
38 {
39 public:
40     QXT_DECLARE_PUBLIC(QxtConfirmationMessage);
41     void init(const QString& message = QString());
42     QString key() const;
43     static QString key(const QString& title, const QString& text, const QString& informativeText = QString());
44     int showAgain();
45     void doNotShowAgain(int result);
46     static void reset(const QString& title, const QString& text, const QString& informativeText);
47
48     QCheckBox* confirm;
49     static QString path;
50     static QSettings::Scope scope;
51 };
52
53 QString QxtConfirmationMessagePrivate::path;
54 QSettings::Scope QxtConfirmationMessagePrivate::scope = QSettings::UserScope;
55
56 void QxtConfirmationMessagePrivate::init(const QString& message)
57 {
58 #if QT_VERSION >= 0x040200
59     confirm = new QCheckBox(&qxt_p());
60     if (!message.isNull())
61         confirm->setText(message);
62     else
63         confirm->setText(QxtConfirmationMessage::tr("Do not show again."));
64
65     QGridLayout* grid = qobject_cast<QGridLayout*>(qxt_p().layout());
66     QDialogButtonBox* buttons = qFindChild<QDialogButtonBox*>(&qxt_p());
67     if (grid && buttons)
68     {
69         const int idx = grid->indexOf(buttons);
70         int row, column, rowSpan, columnSpan = 0;
71         grid->getItemPosition(idx, &row, &column, &rowSpan, &columnSpan);
72         QLayoutItem* buttonsItem = grid->takeAt(idx);
73         grid->addWidget(confirm, row, column, rowSpan, columnSpan, Qt::AlignLeft | Qt::AlignTop);
74         grid->addItem(buttonsItem, ++row, column, rowSpan, columnSpan);
75     }
76 #endif // QT_VERSION
77 }
78
79 QString QxtConfirmationMessagePrivate::key() const
80 {
81 #if QT_VERSION >= 0x040200
82     return key(qxt_p().windowTitle(), qxt_p().text(), qxt_p().informativeText());
83 #else
84     return key(qxt_p().windowTitle(), qxt_p().text());
85 #endif // QT_VERSION
86 }
87
88 QString QxtConfirmationMessagePrivate::key(const QString& title, const QString& text, const QString& informativeText)
89 {
90     const QString all = title + text + informativeText;
91     const QByteArray data = all.toLocal8Bit();
92     return QString::number(qChecksum(data.constData(), data.length()));
93 }
94
95 int QxtConfirmationMessagePrivate::showAgain()
96 {
97     QString organization = QCoreApplication::organizationName();
98     QString application  = QCoreApplication::applicationName();
99     if (organization.isEmpty())
100         organization = DEFAULT_ORGANIZATION;
101     if (application.isEmpty())
102         application = DEFAULT_APPLICATION;
103     QSettings settings(scope, organization, application);
104     if (!path.isEmpty())
105         settings.beginGroup(path);
106     return settings.value(key(), -1).toInt();
107 }
108
109 void QxtConfirmationMessagePrivate::doNotShowAgain(int result)
110 {
111     QString organization = QCoreApplication::organizationName();
112     QString application  = QCoreApplication::applicationName();
113     if (organization.isEmpty())
114         organization = DEFAULT_ORGANIZATION;
115     if (application.isEmpty())
116         application = DEFAULT_APPLICATION;
117     QSettings settings(scope, organization, application);
118     if (!path.isEmpty())
119         settings.beginGroup(path);
120     settings.setValue(key(), result);
121 }
122
123 void QxtConfirmationMessagePrivate::reset(const QString& title, const QString& text, const QString& informativeText)
124 {
125     QString organization = QCoreApplication::organizationName();
126     QString application  = QCoreApplication::applicationName();
127     if (organization.isEmpty())
128         organization = DEFAULT_ORGANIZATION;
129     if (application.isEmpty())
130         application = DEFAULT_APPLICATION;
131     QSettings settings(scope, organization, application);
132     if (!path.isEmpty())
133         settings.beginGroup(path);
134     settings.remove(key(title, text, informativeText));
135 }
136
137 /*!
138     \class QxtConfirmationMessage QxtConfirmationMessage
139     \ingroup QxtGui
140     \brief A confirmation message.
141
142     QxtConfirmationMessage is a confirmation message with checkable
143     <b>"Do not show again."</b> option. A checked and accepted confirmation
144     message is no more shown until reseted.
145
146     Example usage:
147     \code
148     void MainWindow::closeEvent(QCloseEvent* event)
149     {
150         static const QString text(tr("Are you sure you want to quit?"));
151         if (QxtConfirmationMessage::confirm(this, tr("Confirm"), text) == QMessageBox::No)
152             event->ignore();
153     }
154     \endcode
155
156     \image html qxtconfirmationmessage.png "QxtConfirmationMessage in action."
157
158     \note \b QCoreApplication::organizationName and \b QCoreApplication::applicationName
159     are used for storing settings. In case these properties are empty, \b "QxtGui" and
160     \b "QxtConfirmationMessage" are used, respectively.
161
162     \note Requires Qt 4.2 or newer.
163  */
164
165 /*!
166     Constructs a new QxtConfirmationMessage with \a parent.
167  */
168 QxtConfirmationMessage::QxtConfirmationMessage(QWidget* parent)
169         : QMessageBox(parent)
170 {
171     QXT_INIT_PRIVATE(QxtConfirmationMessage);
172     qxt_d().init();
173 }
174
175 /*!
176     Constructs a new QxtConfirmationMessage with \a icon, \a title, \a text, \a confirmation, \a buttons, \a parent and \a flags.
177  */
178 #if QT_VERSION >= 0x040200
179 QxtConfirmationMessage::QxtConfirmationMessage(QMessageBox::Icon icon, const QString& title, const QString& text, const QString& confirmation,
180         QMessageBox::StandardButtons buttons, QWidget* parent, Qt::WindowFlags flags)
181         : QMessageBox(icon, title, text, buttons, parent, flags)
182 {
183     QXT_INIT_PRIVATE(QxtConfirmationMessage);
184     qxt_d().init(confirmation);
185 }
186 #endif // QT_VERSION
187
188 /*!
189     Destructs the confirmation message.
190  */
191 QxtConfirmationMessage::~QxtConfirmationMessage()
192 {}
193
194 // QMessageBox::StandardButton showNewMessageBox() (qmessagebox.cpp)
195 #if QT_VERSION >= 0x040200
196 QMessageBox::StandardButton QxtConfirmationMessage::confirm(QWidget* parent,
197         const QString& title, const QString& text, const QString& confirmation,
198         QMessageBox::StandardButtons buttons, QMessageBox::StandardButton defaultButton)
199 {
200     QxtConfirmationMessage msgBox(QMessageBox::NoIcon, title, text, confirmation, QMessageBox::NoButton, parent);
201     QDialogButtonBox* buttonBox = qFindChild<QDialogButtonBox*>(&msgBox);
202     Q_ASSERT(buttonBox != 0);
203
204     uint mask = QMessageBox::FirstButton;
205     while (mask <= QMessageBox::LastButton)
206     {
207         uint sb = buttons & mask;
208         mask <<= 1;
209         if (!sb)
210             continue;
211         QPushButton* button = msgBox.addButton((QMessageBox::StandardButton)sb);
212         // Choose the first accept role as the default
213         if (msgBox.defaultButton())
214             continue;
215         if ((defaultButton == QMessageBox::NoButton && buttonBox->buttonRole(button) == QDialogButtonBox::AcceptRole)
216                 || (defaultButton != QMessageBox::NoButton && sb == uint(defaultButton)))
217             msgBox.setDefaultButton(button);
218     }
219     if (msgBox.exec() == -1)
220         return QMessageBox::Cancel;
221     return msgBox.standardButton(msgBox.clickedButton());
222 }
223 #endif // QT_VERSION
224
225 /*!
226     \property QxtConfirmationMessage::confirmationText
227     \brief This property holds the confirmation text
228
229     The default value is <b>"Do not show again."</b>
230  */
231 QString QxtConfirmationMessage::confirmationText() const
232 {
233     return qxt_d().confirm->text();
234 }
235
236 void QxtConfirmationMessage::setConfirmationText(const QString& confirmation)
237 {
238     qxt_d().confirm->setText(confirmation);
239 }
240
241 /*!
242     \return The scope used for storing settings.
243
244     The default value is \b QSettings::UserScope.
245  */
246 QSettings::Scope QxtConfirmationMessage::settingsScope()
247 {
248     return QxtConfirmationMessagePrivate::scope;
249 }
250
251 /*!
252     Sets the scope used for storing settings.
253  */
254 void QxtConfirmationMessage::setSettingsScope(QSettings::Scope scope)
255 {
256     QxtConfirmationMessagePrivate::scope = scope;
257 }
258
259 /*!
260     \return The path used for storing settings.
261
262     The default value is an empty string.
263  */
264 QString QxtConfirmationMessage::settingsPath()
265 {
266     return QxtConfirmationMessagePrivate::path;
267 }
268
269 /*!
270     Sets the path used for storing settings.
271  */
272 void QxtConfirmationMessage::setSettingsPath(const QString& path)
273 {
274     QxtConfirmationMessagePrivate::path = path;
275 }
276
277 /*!
278     Shows the confirmation message if necessary. The confirmation message is not
279     shown in case <b>"Do not show again."</b> has been checked while the same
280     confirmation message was earlierly accepted.
281
282     A confirmation message is identified by the combination of title,
283     \b QMessageBox::text and optional \b QMessageBox::informativeText.
284
285     A clicked button with role \b QDialogButtonBox::AcceptRole or
286     \b QDialogButtonBox::YesRole is considered as "accepted".
287
288     \warning This function does not reimplement but shadows \b QMessageBox::exec().
289
290     \sa QWidget::windowTitle, QMessageBox::text, QMessageBox::informativeText
291  */
292 int QxtConfirmationMessage::exec()
293 {
294     int res = qxt_d().showAgain();
295     if (res == -1)
296         res = QMessageBox::exec();
297     return res;
298 }
299
300 void QxtConfirmationMessage::done(int result)
301 {
302 #if QT_VERSION >= 0x040200
303     QDialogButtonBox* buttons = qFindChild<QDialogButtonBox*>(this);
304     Q_ASSERT(buttons != 0);
305
306     int role = buttons->buttonRole(clickedButton());
307     if (qxt_d().confirm->isChecked() &&
308             (role == QDialogButtonBox::AcceptRole || role == QDialogButtonBox::YesRole))
309     {
310         qxt_d().doNotShowAgain(result);
311     }
312 #endif // QT_VERSION
313     QMessageBox::done(result);
314 }
315
316 /*!
317     Resets confirmation message with given \a title, \a text and optional
318     \a informativeText. A reseted confirmation message is shown again until
319     user checks <b>"Do not show again."</b> and accepts the confirmation message.
320  */
321 void QxtConfirmationMessage::reset(const QString& title, const QString& text, const QString& informativeText)
322 {
323     QxtConfirmationMessagePrivate::reset(title, text, informativeText);
324 }
325
326 /*!
327     Resets this instance of QxtConfirmationMessage. A reseted confirmation
328     message is shown again until user checks <b>"Do not show again."</b> and
329     accepts the confirmation message.
330  */
331 void QxtConfirmationMessage::reset()
332 {
333 #if QT_VERSION >= 0x040200
334     QxtConfirmationMessagePrivate::reset(windowTitle(), text(), informativeText());
335 #endif // QT_VERSION
336 }