1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 #include <QtInstanceMessageDialog.hxx>
11 #include <QtInstanceMessageDialog.moc>
13 #include <vcl/qt/QtUtils.hxx>
15 #include <QtWidgets/QLabel>
16 #include <QtWidgets/QPushButton>
17 #include <QtWidgets/QVBoxLayout>
19 QtInstanceMessageDialog::QtInstanceMessageDialog(QMessageBox
* pMessageDialog
)
20 : QtInstanceDialog(pMessageDialog
)
21 , m_pMessageDialog(pMessageDialog
)
23 assert(m_pMessageDialog
);
25 m_pExtraControlsContainer
= new QWidget
;
26 m_pExtraControlsContainer
->setLayout(new QVBoxLayout
);
27 positionExtraControlsContainer();
30 void QtInstanceMessageDialog::set_primary_text(const rtl::OUString
& rText
)
33 QtInstance
& rQtInstance
= GetQtInstance();
34 if (!rQtInstance
.IsMainThread())
36 rQtInstance
.RunInMainThread([&] { set_primary_text(rText
); });
40 // update text and ensure that extra controls are contained in the
41 // dialog's layout (new layout gets set when setting text)
42 m_pMessageDialog
->setText(toQString(rText
));
43 positionExtraControlsContainer();
46 void QtInstanceMessageDialog::set_secondary_text(const rtl::OUString
& rText
)
49 QtInstance
& rQtInstance
= GetQtInstance();
50 if (!rQtInstance
.IsMainThread())
52 rQtInstance
.RunInMainThread([&] { set_secondary_text(rText
); });
56 // update text and ensure that extra controls are contained in the
57 // dialog's layout (new layout gets set when setting text)
58 m_pMessageDialog
->setInformativeText(toQString(rText
));
59 positionExtraControlsContainer();
62 std::unique_ptr
<weld::Container
> QtInstanceMessageDialog::weld_message_area()
64 return std::make_unique
<QtInstanceContainer
>(m_pExtraControlsContainer
);
67 OUString
QtInstanceMessageDialog::get_primary_text() const
70 QtInstance
& rQtInstance
= GetQtInstance();
72 if (!rQtInstance
.IsMainThread())
74 rQtInstance
.RunInMainThread([&] { sText
= get_primary_text(); });
78 assert(m_pMessageDialog
);
79 return toOUString(m_pMessageDialog
->text());
82 OUString
QtInstanceMessageDialog::get_secondary_text() const
85 QtInstance
& rQtInstance
= GetQtInstance();
87 if (!rQtInstance
.IsMainThread())
89 rQtInstance
.RunInMainThread([&] { sText
= get_secondary_text(); });
93 assert(m_pMessageDialog
);
94 return toOUString(m_pMessageDialog
->informativeText());
97 void QtInstanceMessageDialog::add_button(const OUString
& rText
, int nResponse
, const OUString
&)
100 QtInstance
& rQtInstance
= GetQtInstance();
101 if (!rQtInstance
.IsMainThread())
103 rQtInstance
.RunInMainThread([&] { add_button(rText
, nResponse
); });
107 assert(m_pMessageDialog
);
108 QPushButton
* pButton
= m_pMessageDialog
->addButton(vclToQtStringWithAccelerator(rText
),
109 QMessageBox::ButtonRole::ActionRole
);
110 pButton
->setProperty(PROPERTY_VCL_RESPONSE_CODE
, QVariant::fromValue(nResponse
));
113 void QtInstanceMessageDialog::set_default_response(int nResponse
)
116 QtInstance
& rQtInstance
= GetQtInstance();
117 if (!rQtInstance
.IsMainThread())
119 rQtInstance
.RunInMainThread([&] { set_default_response(nResponse
); });
123 assert(m_pMessageDialog
);
125 QPushButton
* pButton
= buttonForResponseCode(nResponse
);
127 m_pMessageDialog
->setDefaultButton(pButton
);
130 std::unique_ptr
<weld::Button
> QtInstanceMessageDialog::weld_button_for_response(int nResponse
)
133 QtInstance
& rQtInstance
= GetQtInstance();
134 if (!rQtInstance
.IsMainThread())
136 std::unique_ptr
<weld::Button
> xButton
;
137 rQtInstance
.RunInMainThread([&] { xButton
= weld_button_for_response(nResponse
); });
141 if (QPushButton
* pButton
= buttonForResponseCode(nResponse
))
142 return std::make_unique
<QtInstanceButton
>(pButton
);
147 int QtInstanceMessageDialog::run()
150 QtInstance
& rQtInstance
= GetQtInstance();
151 if (!rQtInstance
.IsMainThread())
154 rQtInstance
.RunInMainThread([&] { nRet
= run(); });
158 // if a button was clicked, return its response code
159 int nRet
= m_pMessageDialog
->exec();
160 if (QAbstractButton
* pClickedButton
= m_pMessageDialog
->clickedButton())
161 return pClickedButton
->property(PROPERTY_VCL_RESPONSE_CODE
).toInt();
166 void QtInstanceMessageDialog::dialogFinished(int nResult
)
169 QtInstance
& rQtInstance
= GetQtInstance();
170 if (!rQtInstance
.IsMainThread())
172 rQtInstance
.RunInMainThread([&] { dialogFinished(nResult
); });
176 // if a button was clicked, use its response code, otherwise the passed one
177 int nResponseCode
= nResult
;
178 if (QAbstractButton
* pClickedButton
= m_pMessageDialog
->clickedButton())
179 nResponseCode
= pClickedButton
->property(PROPERTY_VCL_RESPONSE_CODE
).toInt();
181 QtInstanceDialog::dialogFinished(nResponseCode
);
183 void QtInstanceMessageDialog::positionExtraControlsContainer()
185 assert(m_pExtraControlsContainer
);
187 // make use of implementation detail that QMessageBox uses QGridLayout for its layout
188 // (logic here will need to be adjusted if that ever changes)
189 QGridLayout
* pDialogLayout
= qobject_cast
<QGridLayout
*>(m_pMessageDialog
->layout());
190 assert(pDialogLayout
&& "QMessageBox has unexpected layout");
192 // no need to reposition if layout didn't change
193 if (pDialogLayout
->indexOf(m_pExtraControlsContainer
) >= 0)
197 const int nItemCount
= pDialogLayout
->count();
198 int nLastLabelIndex
= -1;
199 for (int i
= nItemCount
- 1; i
>= 0; --i
)
201 if (QLayoutItem
* pItem
= pDialogLayout
->itemAt(i
))
203 if (qobject_cast
<QLabel
*>(pItem
->widget()))
210 assert(nLastLabelIndex
>= 0 && "didn't find label in message box");
212 // shift everything after the last label down by one row
213 for (int i
= nLastLabelIndex
+ 1; i
< nItemCount
; ++i
)
215 if (QLayoutItem
* pItem
= pDialogLayout
->itemAt(i
))
221 pDialogLayout
->getItemPosition(i
, &nRow
, &nCol
, &nRowSpan
, &nColSpan
);
222 pDialogLayout
->removeItem(pItem
);
223 pDialogLayout
->addItem(pItem
, nRow
+ 1, nCol
, nRowSpan
, nColSpan
);
227 // insert an additional layout in the now empty row, underneath the last label
230 int nLabelRowSpan
= 0;
231 int nLabelColSpan
= 0;
232 pDialogLayout
->getItemPosition(nLastLabelIndex
, &nLabelRow
, &nLabelCol
, &nLabelRowSpan
,
234 pDialogLayout
->addWidget(m_pExtraControlsContainer
, nLabelRow
+ 1, nLabelCol
);
237 QPushButton
* QtInstanceMessageDialog::buttonForResponseCode(int nResponse
)
240 QtInstance
& rQtInstance
= GetQtInstance();
241 if (!rQtInstance
.IsMainThread())
243 QPushButton
* pButton
;
244 rQtInstance
.RunInMainThread([&] { pButton
= buttonForResponseCode(nResponse
); });
248 assert(m_pMessageDialog
);
250 const QList
<QAbstractButton
*> aButtons
= m_pMessageDialog
->buttons();
251 for (QAbstractButton
* pAbstractButton
: aButtons
)
253 if (pAbstractButton
->property(PROPERTY_VCL_RESPONSE_CODE
).toInt() == nResponse
)
255 QPushButton
* pButton
= qobject_cast
<QPushButton
*>(pAbstractButton
);
263 /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */