File indexing completed on 2024-09-29 10:54:49
0001 // This license reflects the original Adept code: 0002 // -*- C++ -*- (c) 2008 Petr Rockai <me@mornfall.net> 0003 // Redistribution and use in source and binary forms, with or without 0004 // modification, are permitted provided that the following conditions are 0005 // met: 0006 // 0007 // * Redistributions of source code must retain the above copyright 0008 // notice, this list of conditions and the following disclaimer. 0009 // 0010 // * Redistributions in binary form must reproduce the above 0011 // copyright notice, this list of conditions and the following 0012 // disclaimer in the documentation and/or other materials provided 0013 // with the distribution. 0014 // 0015 // * Neither the name of [original copyright holder] nor the names of 0016 // its contributors may be used to endorse or promote products 0017 // derived from this software without specific prior written 0018 // permission. 0019 // 0020 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 0021 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 0022 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 0023 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 0024 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 0025 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 0026 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 0027 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 0028 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 0029 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 0030 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 0031 /* 0032 * All the modifications below are licensed under this license 0033 * Copyright (C) 2010-2018 Daniel Nicoletti <dantti12@gmail.com> 0034 * 0035 * This library is free software; you can redistribute it and/or 0036 * modify it under the terms of the GNU Library General Public 0037 * License as published by the Free Software Foundation; either 0038 * version 2 of the License, or (at your option) any later version. 0039 * 0040 * This library is distributed in the hope that it will be useful, 0041 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0042 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0043 * Library General Public License for more details. 0044 * 0045 * You should have received a copy of the GNU Library General Public License 0046 * along with this library; see the file COPYING.LIB. If not, write to 0047 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0048 * Boston, MA 02110-1301, USA. 0049 */ 0050 0051 #include "DebconfGui.h" 0052 0053 #include "ui_DebconfGui.h" 0054 0055 #include "DebconfBoolean.h" 0056 #include "DebconfError.h" 0057 #include "DebconfMultiselect.h" 0058 #include "DebconfNote.h" 0059 #include "DebconfPassword.h" 0060 #include "DebconfProgress.h" 0061 #include "DebconfSelect.h" 0062 #include "DebconfString.h" 0063 #include "DebconfText.h" 0064 #include "Debug_p.h" 0065 0066 #include <QtCore/QDebug> 0067 #include <QtCore/QProcess> 0068 #include <QtCore/QFile> 0069 #include <QtWidgets/QLabel> 0070 #include <QHostInfo> 0071 0072 #include <KGuiItem> 0073 #include <KIconLoader> 0074 #include <KLocalizedString> 0075 #include <KStandardGuiItem> 0076 #include <KOSRelease> 0077 0078 #include <debconf.h> 0079 0080 using namespace DebconfKde; 0081 0082 class DebconfKde::DebconfGuiPrivate : public Ui::DebconfGui 0083 { 0084 public: 0085 virtual ~DebconfGuiPrivate() { } 0086 DebconfFrontend *frontend; 0087 DebconfProgress *elementProgress = nullptr; 0088 QWidget *parentWidget = nullptr; 0089 QVector<DebconfElement*> elements; 0090 0091 DebconfElement* createElement(const QString &k); 0092 void cleanup(); 0093 }; 0094 0095 DebconfGui::DebconfGui(const QString &socketName, QWidget *parent) 0096 : QWidget(parent), 0097 d_ptr(new DebconfGuiPrivate) 0098 { 0099 Q_D(DebconfGui); 0100 d->frontend = new DebconfFrontendSocket(socketName, this); 0101 init(); 0102 } 0103 0104 DebconfGui::DebconfGui(int readfd, int writefd, QWidget *parent) 0105 : QWidget(parent), 0106 d_ptr(new DebconfGuiPrivate) 0107 { 0108 Q_D(DebconfGui); 0109 d->frontend = new DebconfFrontendFifo(readfd, writefd, this); 0110 init(); 0111 } 0112 0113 DebconfGui::~DebconfGui() 0114 { 0115 delete d_ptr; 0116 } 0117 0118 void DebconfGui::init() 0119 { 0120 Q_D(DebconfGui); 0121 d->setupUi(this); 0122 0123 // Setup buttons. They are marked non-translatable in the UI file. 0124 KGuiItem::assign(d->cancelPB, KStandardGuiItem::cancel()); 0125 KGuiItem::assign(d->backPB, KStandardGuiItem::back()); 0126 KGuiItem::assign(d->nextPB, KStandardGuiItem::cont()); 0127 0128 setMinimumSize(500, 400); 0129 d->cancelPB->setVisible(false); 0130 0131 connect(d->frontend, &DebconfFrontend::go, this, &DebconfGui::cmd_go); 0132 connect(d->frontend, &DebconfFrontend::finished, this, &DebconfGui::deactivated); 0133 connect(d->frontend, &DebconfFrontend::progress, this, &DebconfGui::cmd_progress); 0134 connect(d->frontend, &DebconfFrontend::backup, d->backPB, &QPushButton::setEnabled); 0135 0136 setWindowTitle(i18n("Debconf on %1", QHostInfo::localHostName())); 0137 0138 // find out the distribution logo 0139 QString distroLogo(QLatin1String("/usr/share/pixmaps/debian-logo.png")); 0140 KOSRelease osInfo; 0141 if (!osInfo.logo().isEmpty()) 0142 distroLogo = osInfo.logo(); 0143 0144 const QPixmap icon = KIconLoader::global()->loadIcon(distroLogo, 0145 KIconLoader::NoGroup, 0146 KIconLoader::SizeLarge, 0147 KIconLoader::DefaultState); 0148 if (!icon.isNull()) { 0149 d->iconL->setPixmap(icon); 0150 setWindowIcon(icon); 0151 } 0152 0153 d->scrollArea->viewport()->setAutoFillBackground(false); 0154 } 0155 0156 DebconfElement* DebconfGuiPrivate::createElement(const QString &k) 0157 { 0158 qCDebug(DEBCONF) << "creating widget for " << k; 0159 0160 QString extendedDescription = frontend->property(k, DebconfFrontend::ExtendedDescription); 0161 extendedDescription.replace(QLatin1String("\\n"), QLatin1String("\n")); 0162 0163 switch (frontend->type(k)) { 0164 case DebconfFrontend::Boolean: 0165 { 0166 auto element = new DebconfBoolean(k, parentWidget); 0167 element->setBoolean(extendedDescription, 0168 frontend->property(k, DebconfFrontend::Description), 0169 frontend->value(k) == QLatin1String("true")); 0170 return element; 0171 } 0172 case DebconfFrontend::Error: 0173 { 0174 auto element = new DebconfError(k, parentWidget); 0175 element->setError(extendedDescription, 0176 frontend->property(k, DebconfFrontend::Description)); 0177 return element; 0178 } 0179 case DebconfFrontend::Multiselect: 0180 { 0181 auto element = new DebconfMultiselect(k, parentWidget); 0182 element->setMultiselect(extendedDescription, 0183 frontend->property(k, DebconfFrontend::Description), 0184 frontend->value(k).split(QLatin1String(", ")), 0185 frontend->property(k, DebconfFrontend::Choices).split(QLatin1String(", "))); 0186 return element; 0187 } 0188 case DebconfFrontend::Note: 0189 { 0190 auto element = new DebconfNote(k, parentWidget); 0191 element->setNote(extendedDescription, 0192 frontend->property(k, DebconfFrontend::Description)); 0193 return element; 0194 } 0195 case DebconfFrontend::Password: 0196 { 0197 auto element = new DebconfPassword(k, parentWidget); 0198 element->setPassword(extendedDescription, 0199 frontend->property(k, DebconfFrontend::Description)); 0200 return element; 0201 } 0202 case DebconfFrontend::Select: 0203 { 0204 auto element = new DebconfSelect(k, parentWidget); 0205 element->setSelect(extendedDescription, 0206 frontend->property(k, DebconfFrontend::Description), 0207 frontend->value(k), 0208 frontend->property(k, DebconfFrontend::Choices).split(QLatin1String(", "))); 0209 return element; 0210 } 0211 case DebconfFrontend::String: 0212 { 0213 auto element = new DebconfString(k, parentWidget); 0214 element->setString(extendedDescription, 0215 frontend->property(k, DebconfFrontend::Description), 0216 frontend->value(k)); 0217 return element; 0218 } 0219 case DebconfFrontend::Text: 0220 { 0221 auto element = new DebconfText(k, parentWidget); 0222 element->setText(frontend->property(k, DebconfFrontend::Description)); 0223 return element; 0224 } 0225 default: 0226 qWarning() << "Default REACHED!!!"; 0227 auto element = new DebconfElement(k, parentWidget); 0228 auto label = new QLabel(element); 0229 label->setText(i18n("<b>Not implemented</b>: The input widget for data" 0230 " type '%1' is not implemented. Will use default of '%2'.", 0231 frontend->property(k, DebconfFrontend::Type), 0232 frontend->value(k))); 0233 label->setWordWrap(true); 0234 return element; 0235 } 0236 } 0237 0238 void DebconfGui::cmd_go(const QString &title, const QStringList &input) 0239 { 0240 Q_D(DebconfGui); 0241 qCDebug(DEBCONF) << "# GO GUI"; 0242 d->cleanup(); 0243 auto layout = qobject_cast<QVBoxLayout*>(d->parentWidget->layout()); 0244 // if we have just one element and we are showing 0245 // elements that can make use of extra space 0246 // we don't add stretches 0247 bool needStretch = true; 0248 if (input.size() == 1) { 0249 const QString key = input.first(); 0250 if (d->frontend->type(key) == DebconfFrontend::Text && 0251 d->frontend->type(key) == DebconfFrontend::Note && 0252 d->frontend->type(key) == DebconfFrontend::Error && 0253 d->frontend->type(key) == DebconfFrontend::Multiselect) { 0254 needStretch = false; 0255 } 0256 } 0257 0258 if (needStretch) { 0259 layout->addStretch(); 0260 } 0261 0262 for (const QString &elementName : input) { 0263 DebconfElement *element = d->createElement(elementName); 0264 d->elements.append(element); 0265 layout->addWidget(element); 0266 } 0267 0268 if (needStretch) { 0269 layout->addStretch(); 0270 } 0271 0272 d->parentWidget->setAutoFillBackground(false); 0273 0274 d->titleL->setText(title); 0275 d->nextPB->setEnabled(true); 0276 Q_EMIT activated(); 0277 } 0278 0279 void DebconfGui::cmd_progress(const QString &cmd) 0280 { 0281 Q_D(DebconfGui); 0282 if (!d->elementProgress) { 0283 d->cleanup(); 0284 d->elementProgress = new DebconfProgress(QString(), d->parentWidget); 0285 auto layout = qobject_cast<QVBoxLayout*>(d->parentWidget->layout()); 0286 layout->addStretch(); 0287 layout->addWidget(d->elementProgress); 0288 layout->addStretch(); 0289 d->parentWidget->setAutoFillBackground(false); 0290 d->nextPB->setEnabled(false); 0291 d->backPB->setEnabled(false); 0292 } 0293 DebconfProgress *element = d->elementProgress; 0294 0295 QStringList commands = cmd.split(QLatin1Char(' ')); 0296 qCDebug(DEBCONF) << "KPROGRESS" << commands; 0297 if (commands.first() == QLatin1String("START")) { 0298 d->titleL->setText(d->frontend->property(commands.at(3), DebconfFrontend::Description)); 0299 int progress_min = commands.at(1).toInt(); 0300 int progress_max = commands.at(2).toInt(); 0301 element->startProgress(d->frontend->property(commands.at(3), DebconfFrontend::ExtendedDescription), 0302 progress_min, 0303 progress_max); 0304 } else if (commands.first() == QLatin1String("SET")) { 0305 element->setProgress(commands.at(1).toInt()); 0306 } else if (commands.first() == QLatin1String("STEP")) { 0307 element->stepProgress(commands.at(1).toInt()); 0308 } else if (commands.first() == QLatin1String("INFO")) { 0309 element->setProgressInfo(d->frontend->property(commands.at(1), DebconfFrontend::Description)); 0310 } else if (commands.first() == QLatin1String("STOP")) { 0311 element->stopProgress(); 0312 } 0313 Q_EMIT activated(); 0314 d->frontend->say(QLatin1String("0 ok")); 0315 } 0316 0317 void DebconfGuiPrivate::cleanup() 0318 { 0319 delete parentWidget; 0320 elementProgress = nullptr; 0321 elements.clear(); 0322 0323 parentWidget = new QWidget(scrollArea); 0324 scrollArea->setWidget(parentWidget); 0325 auto layout = new QVBoxLayout(parentWidget); 0326 parentWidget->setLayout(layout); 0327 } 0328 0329 void DebconfGui::on_nextPB_clicked() 0330 { 0331 Q_D(DebconfGui); 0332 // extract all the elements 0333 const auto elements = d->elements; 0334 for (const DebconfElement *element : elements) { 0335 d->frontend->setValue(element->name(), element->value()); 0336 } 0337 0338 d->frontend->next(); 0339 } 0340 0341 void DebconfGui::on_backPB_clicked() 0342 { 0343 Q_D(DebconfGui); 0344 d->frontend->back(); 0345 } 0346 0347 void DebconfGui::on_cancelPB_clicked() 0348 { 0349 Q_D(DebconfGui); 0350 d->frontend->cancel(); 0351 } 0352 0353 void DebconfGui::closeEvent(QCloseEvent *event) 0354 { 0355 Q_D(DebconfGui); 0356 // It would be better to hid the close button on 0357 // on the window decoration: 0358 d->frontend->cancel(); 0359 QWidget::closeEvent(event); 0360 } 0361 0362 #include "moc_DebconfGui.cpp"