File indexing completed on 2024-04-28 05:08:21

0001 /***************************************************************************
0002     Copyright (C) 2006-2009 Robby Stephenson <robby@periapsis.org>
0003  ***************************************************************************/
0004 
0005 /***************************************************************************
0006  *                                                                         *
0007  *   This program is free software; you can redistribute it and/or         *
0008  *   modify it under the terms of the GNU General Public License as        *
0009  *   published by the Free Software Foundation; either version 2 of        *
0010  *   the License or (at your option) version 3 or any later version        *
0011  *   accepted by the membership of KDE e.V. (or its successor approved     *
0012  *   by the membership of KDE e.V.), which shall act as a proxy            *
0013  *   defined in Section 14 of version 3 of the license.                    *
0014  *                                                                         *
0015  *   This program is distributed in the hope that it will be useful,       *
0016  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
0017  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
0018  *   GNU General Public License for more details.                          *
0019  *                                                                         *
0020  *   You should have received a copy of the GNU General Public License     *
0021  *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
0022  *                                                                         *
0023  ***************************************************************************/
0024 
0025 #include "fetcherconfigdialog.h"
0026 #include "fetch/fetchmanager.h"
0027 #include "gui/combobox.h"
0028 #include "utils/string_utils.h"
0029 #include "tellico_debug.h"
0030 
0031 #include <KLocalizedString>
0032 #include <KComboBox>
0033 #include <KIconLoader>
0034 #include <KHelpClient>
0035 
0036 #include <QLineEdit>
0037 #include <QLabel>
0038 #include <QLayout>
0039 #include <QStackedWidget>
0040 #include <QGroupBox>
0041 #include <QCheckBox>
0042 #include <QHBoxLayout>
0043 #include <QGridLayout>
0044 #include <QVBoxLayout>
0045 #include <QDialogButtonBox>
0046 #include <QPushButton>
0047 
0048 namespace {
0049   static const int FETCHER_CONFIG_MIN_WIDTH = 600;
0050 }
0051 
0052 using Tellico::FetcherConfigDialog;
0053 
0054 FetcherConfigDialog::FetcherConfigDialog(QWidget* parent_)
0055     : QDialog(parent_)
0056     , m_newSource(true)
0057     , m_useDefaultName(true)
0058     , m_configWidget(nullptr) {
0059   init(Fetch::Unknown);
0060 }
0061 
0062 FetcherConfigDialog::FetcherConfigDialog(const QString& sourceName_, Tellico::Fetch::Type type_, bool updateOverwrite_,
0063                                          Tellico::Fetch::ConfigWidget* configWidget_, QWidget* parent_)
0064     : QDialog(parent_)
0065     , m_newSource(false)
0066     , m_useDefaultName(false)
0067     , m_configWidget(configWidget_) {
0068   init(type_);
0069   m_nameEdit->setText(sourceName_);
0070   m_cbOverwrite->setChecked(updateOverwrite_);
0071 }
0072 
0073 void FetcherConfigDialog::init(Tellico::Fetch::Type type_) {
0074   setModal(true);
0075   setWindowTitle(i18n("Data Source Properties"));
0076 
0077   QVBoxLayout* mainLayout = new QVBoxLayout();
0078   setLayout(mainLayout);
0079 
0080   setMinimumWidth(FETCHER_CONFIG_MIN_WIDTH);
0081 
0082   QWidget* widget = new QWidget(this);
0083   QBoxLayout* topLayout = new QHBoxLayout(widget);
0084   widget->setLayout(topLayout);
0085 
0086   QBoxLayout* vlay1 = new QVBoxLayout();
0087   topLayout->addLayout(vlay1);
0088   m_iconLabel = new QLabel(widget);
0089   if(type_ == Fetch::Unknown) {
0090     m_iconLabel->setPixmap(KIconLoader::global()->loadIcon(QStringLiteral("network-wired"), KIconLoader::Panel, 64));
0091   } else {
0092     m_iconLabel->setPixmap(Fetch::Manager::self()->fetcherIcon(type_, KIconLoader::Panel, 64));
0093   }
0094   vlay1->addWidget(m_iconLabel);
0095   vlay1->addStretch(1);
0096 
0097   QBoxLayout* vlay2 = new QVBoxLayout();
0098   topLayout->addLayout(vlay2);
0099 
0100   QGridLayout* gl = new QGridLayout();
0101   vlay2->addLayout(gl);
0102   int row = -1;
0103 
0104   QLabel* label = new QLabel(i18n("&Source name: "), widget);
0105   gl->addWidget(label, ++row, 0);
0106   QString w = i18n("The name identifies the data source and should be unique and informative.");
0107   label->setWhatsThis(w);
0108 
0109   m_nameEdit = new QLineEdit(widget);
0110   gl->addWidget(m_nameEdit, row, 1);
0111   m_nameEdit->setFocus();
0112   m_nameEdit->setWhatsThis(w);
0113   label->setBuddy(m_nameEdit);
0114   connect(m_nameEdit, &QLineEdit::textChanged, this, &FetcherConfigDialog::slotNameChanged);
0115 
0116   const QString labelText(i18n("Source &type: "));
0117   if(m_newSource) {
0118     label = new QLabel(labelText, widget);
0119   } else {
0120     // since the label doesn't have a buddy, we don't want an accel,
0121     // but also want to reuse string we already have
0122     label = new QLabel(KLocalizedString::removeAcceleratorMarker(labelText), widget);
0123   }
0124   gl->addWidget(label, ++row, 0);
0125   w = i18n("Tellico supports several different data sources.");
0126   label->setWhatsThis(w);
0127 
0128   if(m_newSource) {
0129     m_typeCombo = new GUI::ComboBox(widget);
0130     gl->addWidget(m_typeCombo, row, 1);
0131     m_typeCombo->setWhatsThis(w);
0132     label->setBuddy(m_typeCombo);
0133   } else {
0134     m_typeCombo = nullptr;
0135     QLabel* lab = new QLabel(Fetch::Manager::typeName(type_), widget);
0136     gl->addWidget(lab, row, 1);
0137     lab->setWhatsThis(w);
0138   }
0139   m_cbOverwrite = new QCheckBox(i18n("Updating from source should overwrite user data"), widget);
0140   ++row;
0141   gl->addWidget(m_cbOverwrite, row, 0, 1, 2);
0142   w = i18n("If checked, updating entries will overwrite any existing information.");
0143   m_cbOverwrite->setWhatsThis(w);
0144 
0145   if(m_newSource) {
0146     m_stack = new QStackedWidget(widget);
0147     vlay2->addWidget(m_stack);
0148     void (QComboBox::* activatedInt)(int) = &QComboBox::activated;
0149     connect(m_typeCombo, activatedInt, this, &FetcherConfigDialog::slotNewSourceSelected);
0150 
0151     int z3950_idx = 0;
0152     const auto typeByName = Fetch::Manager::self()->nameTypeHash();
0153     auto typeKeys = typeByName.keys();
0154     typeKeys.sort(Qt::CaseInsensitive);
0155     // key is the fetcher name, value is the fetcher type
0156     for(auto it = typeKeys.constBegin(); it != typeKeys.constEnd(); ++it) {
0157       const auto typeValue = typeByName.value(*it);
0158       m_typeCombo->addItem(Fetch::Manager::self()->fetcherIcon(typeValue), *it, typeValue);
0159       if(typeValue == Fetch::Z3950) {
0160         z3950_idx = m_typeCombo->count()-1;
0161       }
0162     }
0163     // make sure first widget gets initialized
0164     // I'd like it to be the z39.50 widget
0165     m_typeCombo->setCurrentIndex(z3950_idx);
0166     slotNewSourceSelected(z3950_idx);
0167   } else {
0168     m_stack = nullptr;
0169     // just add config widget and reparent
0170     m_configWidget->setParent(widget);
0171     m_configWidget->show();
0172     vlay2->addWidget(m_configWidget);
0173     connect(m_configWidget, &Fetch::ConfigWidget::signalName, this, &FetcherConfigDialog::slotPossibleNewName);
0174   }
0175 
0176   mainLayout->addWidget(widget);
0177 
0178   QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok|
0179                                                      QDialogButtonBox::Cancel|
0180                                                      QDialogButtonBox::Help);
0181   QPushButton* okButton = buttonBox->button(QDialogButtonBox::Ok);
0182   okButton->setDefault(true);
0183   okButton->setShortcut(Qt::CTRL | Qt::Key_Return);
0184   connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
0185   connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
0186   connect(buttonBox, &QDialogButtonBox::helpRequested, this, &FetcherConfigDialog::slotHelp);
0187   mainLayout->addWidget(buttonBox);
0188 }
0189 
0190 QString FetcherConfigDialog::sourceName() const {
0191   return m_nameEdit->text();
0192 }
0193 
0194 bool FetcherConfigDialog::updateOverwrite() const {
0195   return m_cbOverwrite->isChecked();
0196 }
0197 
0198 Tellico::Fetch::ConfigWidget* FetcherConfigDialog::configWidget() const {
0199   if(m_newSource) {
0200     return dynamic_cast<Fetch::ConfigWidget*>(m_stack->currentWidget());
0201   }
0202   myWarning() << "called for modifying existing fetcher!";
0203   return m_configWidget;
0204 }
0205 
0206 Tellico::Fetch::Type FetcherConfigDialog::sourceType() const {
0207   if(!m_newSource || m_typeCombo->count() == 0) {
0208     myWarning() << "called for modifying existing fetcher!";
0209     return Fetch::Unknown;
0210   }
0211   return static_cast<Fetch::Type>(m_typeCombo->currentData().toInt());
0212 }
0213 
0214 void FetcherConfigDialog::slotNewSourceSelected(int idx_) {
0215   if(!m_newSource) {
0216     return;
0217   }
0218 
0219   // always change to default name
0220   m_useDefaultName = true;
0221 
0222   Fetch::ConfigWidget* cw = m_configWidgets[idx_];
0223   if(cw) {
0224     m_stack->setCurrentWidget(cw);
0225     slotPossibleNewName(cw->preferredName());
0226     return;
0227   }
0228 
0229   Fetch::Type type = sourceType();
0230   if(type == Fetch::Unknown) {
0231     myWarning() << "unknown source type";
0232     return;
0233   }
0234   m_iconLabel->setPixmap(Fetch::Manager::self()->fetcherIcon(type, KIconLoader::Panel, 64));
0235   cw = Fetch::Manager::self()->configWidget(m_stack, type, m_typeCombo->currentText());
0236   if(!cw) {
0237     // bad bad bad!
0238     myWarning() << "no config widget found for type" << type;
0239     m_typeCombo->setCurrentIndex(0);
0240     slotNewSourceSelected(0);
0241     return;
0242   }
0243   connect(cw, &Fetch::ConfigWidget::signalName, this, &FetcherConfigDialog::slotPossibleNewName);
0244   m_configWidgets.insert(idx_, cw);
0245   m_stack->addWidget(cw);
0246   m_stack->setCurrentWidget(cw);
0247   slotPossibleNewName(cw->preferredName());
0248 }
0249 
0250 void FetcherConfigDialog::slotNameChanged(const QString&) {
0251   m_useDefaultName = false;
0252 }
0253 
0254 void FetcherConfigDialog::slotPossibleNewName(const QString& name_) {
0255   if(name_.isEmpty()) {
0256     return;
0257   }
0258   Fetch::ConfigWidget* cw = m_stack ? static_cast<Fetch::ConfigWidget*>(m_stack->currentWidget()) : m_configWidget;
0259   if(m_useDefaultName || (cw && m_nameEdit->text() == cw->preferredName())) {
0260     m_nameEdit->setText(name_);
0261     m_useDefaultName = true; // it gets reset in slotNameChanged()
0262   }
0263 }
0264 
0265 void FetcherConfigDialog::slotHelp() {
0266   KHelpClient::invokeHelp(QStringLiteral("data-sources-options"));
0267 }