File indexing completed on 2024-05-12 05:14:53

0001 /*
0002  *  pickfileradio.cpp  -  radio button with an associated file picker
0003  *  Program:  kalarm
0004  *  SPDX-FileCopyrightText: 2005-2020 David Jarvie <djarvie@kde.org>
0005  *
0006  *  SPDX-License-Identifier: GPL-2.0-or-later
0007  */
0008 
0009 #include "pickfileradio.h"
0010 
0011 #include "lib/buttongroup.h"
0012 #include "lib/lineedit.h"
0013 
0014 #include <QPushButton>
0015 #include <QTimer>
0016 
0017 
0018 PickFileRadio::PickFileRadio(QPushButton* button, LineEdit* edit, const QString& text, ButtonGroup* group, QWidget* parent)
0019     : RadioButton(text, parent)
0020     , mGroup(group)
0021 {
0022     Q_ASSERT(parent);
0023     init(button, edit);
0024 }
0025 
0026 PickFileRadio::PickFileRadio(const QString& text, ButtonGroup* group, QWidget* parent)
0027     : RadioButton(text, parent)
0028     , mGroup(group)
0029     , mButton(nullptr)
0030 {
0031     Q_ASSERT(parent);
0032 }
0033 
0034 void PickFileRadio::init(QPushButton* button, LineEdit* edit)
0035 {
0036     Q_ASSERT(button);
0037     if (mEdit)
0038         mEdit->disconnect(this);
0039     mEdit   = edit;
0040     mButton = button;
0041     mButton->setEnabled(false);
0042     connect(mButton, &QPushButton::clicked, this, &PickFileRadio::slotPickFile);
0043     if (mEdit)
0044     {
0045         mEdit->setEnabled(false);
0046         connect(mEdit, &LineEdit::textChanged, this, &PickFileRadio::fileChanged);
0047     }
0048     connect(mGroup, &ButtonGroup::buttonSet, this, &PickFileRadio::slotSelectionChanged);
0049     PickFileRadio::setReadOnly(RadioButton::isReadOnly());   // avoid calling virtual method from constructor
0050 }
0051 
0052 void PickFileRadio::setReadOnly(bool ro)
0053 {
0054     RadioButton::setReadOnly(ro);
0055     if (mButton)
0056     {
0057         if (mEdit)
0058             mEdit->setReadOnly(ro);
0059         if (ro)
0060             mButton->hide();
0061         else
0062             mButton->show();
0063     }
0064 }
0065 
0066 void PickFileRadio::setFile(const QString& file)
0067 {
0068     mFile = file;
0069 }
0070 
0071 QString PickFileRadio::file() const
0072 {
0073     return mEdit ? mEdit->text() : mFile;
0074 }
0075 
0076 /******************************************************************************
0077 * Set the radio button enabled or disabled.
0078 * Adjusts the enabled/disabled state of other controls appropriately.
0079 */
0080 void PickFileRadio::setEnabled(bool enable)
0081 {
0082     Q_ASSERT(mButton);
0083     RadioButton::setEnabled(enable);
0084     enable = enable  &&  mGroup->checkedButton() == this;
0085     if (enable)
0086     {
0087         if (!pickFileIfNone())
0088             enable = false;    // revert to previously selected type
0089     }
0090     mButton->setEnabled(enable);
0091     if (mEdit)
0092         mEdit->setEnabled(enable);
0093 }
0094 
0095 /******************************************************************************
0096 * Called when the selected radio button changes.
0097 */
0098 void PickFileRadio::slotSelectionChanged(QAbstractButton* button)
0099 {
0100     if (button == mLastButton  ||  mRevertButton)
0101         return;
0102     if (mLastButton == this)
0103     {
0104         mButton->setEnabled(false);
0105         if (mEdit)
0106             mEdit->setEnabled(false);
0107     }
0108     else if (button == this)
0109     {
0110         if (!pickFileIfNone())
0111             return;    // revert to previously selected type
0112         mButton->setEnabled(true);
0113         if (mEdit)
0114             mEdit->setEnabled(true);
0115     }
0116     mLastButton = button;
0117 }
0118 
0119 /******************************************************************************
0120 * Prompt for a file name if there is none currently entered.
0121 */
0122 bool PickFileRadio::pickFileIfNone()
0123 {
0124     if (mEdit)
0125         mFile = mEdit->text();
0126     if (!mFile.isEmpty())
0127         return true;
0128     QString file;
0129     if (!doPickFile(file))
0130        return false;
0131     return !mFile.isEmpty();
0132 }
0133 
0134 /******************************************************************************
0135 * Called when the file picker button is clicked.
0136 */
0137 void PickFileRadio::slotPickFile()
0138 {
0139     QString file;
0140     doPickFile(file);
0141 }
0142 
0143 /******************************************************************************
0144 * Called when the file picker button is clicked.
0145 * @param file  Updated with the file which was selected, or empty if no file
0146 *              was selected.
0147 * Reply = true if 'file' value can be used.
0148 *       = false if the dialogue was deleted while visible (indicating that
0149 *         the parent widget was probably also deleted).
0150 */
0151 bool PickFileRadio::doPickFile(QString& file)
0152 {
0153     // To avoid crashes on application quit, we need to check whether the
0154     // dialogue, and hence this PickFileRadio, was deleted while active,
0155     // before accessing class members.
0156     file.clear();
0157     if (!pickFile(file))
0158         return false;   // 'this' is probably invalid now
0159     if (!file.isEmpty())
0160     {
0161         mFile = file;
0162         if (mEdit)
0163             mEdit->setText(mFile);
0164     }
0165     if (mFile.isEmpty())
0166     {
0167         // No file is selected, so revert to the previous radio button selection.
0168         // But wait a moment before setting the radio button, or it won't work.
0169         mRevertButton = true;   // prevent picker dialog popping up twice
0170         QTimer::singleShot(0, this, &PickFileRadio::setLastButton);   //NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks)
0171     }
0172     file = mFile;
0173     return true;
0174 }
0175 
0176 /******************************************************************************
0177 * Select the previously selected radio button in the group.
0178 */
0179 void PickFileRadio::setLastButton()
0180 {
0181     if (!mLastButton)
0182         setChecked(false);   // we don't know the previous selection, so just turn this button off
0183     else
0184         mLastButton->setChecked(true);
0185     mRevertButton = false;
0186 }
0187 
0188 #include "moc_pickfileradio.cpp"
0189 
0190 // vim: et sw=4: