File indexing completed on 2024-05-26 05:56:27

0001 /*
0002     This file is part of the Okteta Kasten module, made within the KDE community.
0003 
0004     SPDX-FileCopyrightText: 2008-2009, 2022 Friedrich W. H. Kossebau <kossebau@kde.org>
0005 
0006     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0007 */
0008 
0009 #include "filterview.hpp"
0010 
0011 //
0012 #include "filtertool.hpp"
0013 // filter
0014 #include <bytearrayfilterparameterseteditfactory.hpp>
0015 #include <abstractbytearrayfilterparametersetedit.hpp>
0016 #include <abstractbytearrayfilterparameterset.hpp>
0017 #include <abstractbytearrayfilter.hpp>
0018 // utils
0019 #include <labelledtoolbarwidget.hpp>
0020 // KF
0021 #include <KLocalizedString>
0022 #include <KComboBox>
0023 // Qt
0024 #include <QToolBar>
0025 #include <QLabel>
0026 #include <QVBoxLayout>
0027 #include <QStackedWidget>
0028 #include <QAction>
0029 #include <QGroupBox>
0030 #include <QAbstractItemView>
0031 #include <QIcon>
0032 
0033 namespace Kasten {
0034 
0035 FilterView::FilterView(FilterTool* tool, QWidget* parent)
0036     : AbstractToolWidget(parent)
0037     , mTool(tool)
0038 {
0039     auto* baseLayout = new QVBoxLayout(this);
0040     baseLayout->setContentsMargins(0, 0, 0, 0);
0041     baseLayout->setSpacing(0);
0042 
0043     // filter selection
0044     auto* filterSelectionToolBar = new QToolBar(this);
0045     auto* label = new QLabel(i18nc("@label:listbox operation to use by the filter", "Operation:"), this);
0046     mOperationComboBox = new KComboBox(this);
0047     connect(mOperationComboBox, qOverload<int>(&KComboBox::activated),
0048             mTool, &FilterTool::setFilter);
0049 
0050     auto* labelledAlgorithmComboBox = new LabelledToolBarWidget(label, mOperationComboBox, this);
0051     const QString operationToolTip =
0052         i18nc("@info:tooltip", "The operation to use for the filter.");
0053     label->setToolTip(operationToolTip);
0054     mOperationComboBox->setToolTip(operationToolTip);
0055     const QString operationWhatsThis =
0056         i18nc("@info:whatsthis", "Select the operation to use for the filter.");
0057     label->setWhatsThis(operationWhatsThis);
0058     mOperationComboBox->setWhatsThis(operationWhatsThis);
0059     mOperationComboBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
0060 
0061     filterSelectionToolBar->addWidget(labelledAlgorithmComboBox);
0062     baseLayout->addWidget(filterSelectionToolBar);
0063 
0064     auto* parameterSetBox = new QGroupBox(i18nc("@title:group", "Parameters"), this);
0065     baseLayout->addWidget(parameterSetBox);
0066 
0067     auto* parameterSetLayout = new QVBoxLayout;
0068 
0069     parameterSetBox->setLayout(parameterSetLayout);
0070 
0071     mParameterSetEditStack = new QStackedWidget(parameterSetBox);
0072 
0073     parameterSetLayout->addWidget(mParameterSetEditStack);
0074 
0075     // filter button
0076     auto* actionToolBar = new QToolBar(this);
0077     actionToolBar->setToolButtonStyle(Qt::ToolButtonFollowStyle);
0078 
0079     auto* stretcher = new QWidget(this);
0080     stretcher->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
0081     actionToolBar->addWidget(stretcher);
0082 
0083     mFilterAction =
0084         actionToolBar->addAction(QIcon::fromTheme(QStringLiteral("run-build")),
0085                                  i18nc("@action:button", "&Filter"),
0086                                  this, &FilterView::onFilterClicked);
0087     mFilterAction->setToolTip(i18nc("@info:tooltip",
0088                                     "Executes the filter for the bytes in the selected range."));
0089     mFilterAction->setWhatsThis(xi18nc("@info:whatsthis",
0090                                        "If you press the <interface>Filter</interface> button, the operation you selected "
0091                                        "above is executed for the bytes in the selected range with the given options."));
0092     mFilterAction->setEnabled(mTool->hasWriteable());
0093     connect(mTool, &FilterTool::filterChanged, this, &FilterView::onFilterChanged);
0094     connect(mTool, &FilterTool::hasWriteableChanged, this, &FilterView::onHasWriteableChanged);
0095     connect(mTool, &FilterTool::charCodecChanged, this, &FilterView::onCharCodecChanged);
0096     baseLayout->addWidget(actionToolBar);
0097     baseLayout->addStretch(10);
0098 
0099     // automatically set focus to the parameters if a operation has been selected
0100     QAbstractItemView* operationComboBoxListView = mOperationComboBox->view();
0101     QObject::connect(operationComboBoxListView, &QAbstractItemView::activated,
0102                      mParameterSetEditStack, qOverload<>(&QStackedWidget::setFocus));
0103     // TODO: is a workaround for Qt 4.5.1 which doesn't emit activated() for mouse clicks
0104     QObject::connect(operationComboBoxListView, &QAbstractItemView::pressed,
0105                      mParameterSetEditStack, qOverload<>(&QStackedWidget::setFocus));
0106     // TODO: goto filter button if there are no parameters
0107 
0108     addFilters();
0109 }
0110 
0111 FilterView::~FilterView() = default;
0112 
0113 void FilterView::addFilters()
0114 {
0115     //
0116     const QVector<AbstractByteArrayFilter*> filterList = mTool->filterList();
0117     for (AbstractByteArrayFilter* filter : filterList) {
0118         mOperationComboBox->addItem(filter->name());
0119 
0120         const char* parameterSetId = filter->parameterSet()->id();
0121         AbstractByteArrayFilterParameterSetEdit* parameterEdit =
0122             ByteArrayFilterParameterSetEditFactory::createEdit(parameterSetId);
0123 
0124         mParameterSetEditStack->addWidget(parameterEdit);
0125     }
0126 
0127     onFilterChanged(mTool->filterId());
0128 }
0129 
0130 void FilterView::getParameterSet(AbstractByteArrayFilterParameterSet* parameterSet) const
0131 {
0132     auto* parametersetEdit =
0133         qobject_cast<AbstractByteArrayFilterParameterSetEdit*>(mParameterSetEditStack->currentWidget());
0134     if (parametersetEdit) {
0135         parametersetEdit->getParameterSet(parameterSet);
0136     }
0137 }
0138 
0139 void FilterView::onFilterClicked()
0140 {
0141     const int filterId = mTool->filterId();
0142 
0143     auto* parametersetEdit =
0144         qobject_cast<AbstractByteArrayFilterParameterSetEdit*>(mParameterSetEditStack->currentWidget());
0145     if (parametersetEdit) {
0146         parametersetEdit->rememberCurrentSettings();
0147     }
0148 
0149     AbstractByteArrayFilterParameterSet* parameterSet = mTool->parameterSet(filterId);
0150     if (parameterSet) {
0151         getParameterSet(parameterSet);
0152     }
0153 
0154     mTool->filter();
0155 }
0156 
0157 void FilterView::onOperationChange(int index)
0158 {
0159     QWidget* oldWidget = mParameterSetEditStack->currentWidget();
0160     if (oldWidget) {
0161         oldWidget->disconnect(this);
0162     }
0163 
0164     mParameterSetEditStack->setCurrentIndex(index);
0165 
0166     auto* parametersetEdit =
0167         qobject_cast<AbstractByteArrayFilterParameterSetEdit*>(mParameterSetEditStack->currentWidget());
0168     if (parametersetEdit) {
0169         AbstractByteArrayFilterParameterSet* parameterSet = mTool->parameterSet(index);
0170         if (parameterSet) {
0171             parametersetEdit->setValues(parameterSet);
0172         }
0173         connect(parametersetEdit, &AbstractByteArrayFilterParameterSetEdit::validityChanged,
0174                 this, &FilterView::onValidityChanged);
0175         connect(parametersetEdit, &AbstractByteArrayFilterParameterSetEdit::valuesChanged,
0176                 this, &FilterView::onValuesChanged);
0177         onValidityChanged(parametersetEdit->isValid());
0178     }
0179 }
0180 
0181 void FilterView::onFilterChanged(int filterId)
0182 {
0183     mOperationComboBox->setCurrentIndex(filterId);
0184     onOperationChange(filterId);
0185 }
0186 
0187 void FilterView::onHasWriteableChanged(bool hasWriteable)
0188 {
0189     auto* parametersetEdit =
0190         qobject_cast<AbstractByteArrayFilterParameterSetEdit*>(mParameterSetEditStack->currentWidget());
0191     const bool isValid = (parametersetEdit ? parametersetEdit->isValid() : false);
0192 
0193     mFilterAction->setEnabled(hasWriteable && isValid);
0194 }
0195 
0196 void FilterView::onCharCodecChanged(const QString& charCodecName)
0197 {
0198     auto* parametersetEdit =
0199         qobject_cast<AbstractByteArrayFilterParameterSetEdit*>(mParameterSetEditStack->currentWidget());
0200     if (parametersetEdit) {
0201         parametersetEdit->setCharCodec(charCodecName);
0202     }
0203 }
0204 
0205 void FilterView::onValuesChanged()
0206 {
0207     const int filterId = mOperationComboBox->currentIndex();
0208     AbstractByteArrayFilterParameterSet* parameterSet = mTool->parameterSet(filterId);
0209     if (!parameterSet) {
0210         return;
0211     }
0212     getParameterSet(parameterSet);
0213     mTool->saveParameterSet(filterId);
0214 }
0215 
0216 void FilterView::onValidityChanged(bool isValid)
0217 {
0218     mFilterAction->setEnabled(mTool->hasWriteable() && isValid);
0219 }
0220 
0221 }
0222 
0223 #include "moc_filterview.cpp"