1 /*
2     This file is part of the Okteta Kasten module, made within the KDE community.
3 
4     SPDX-FileCopyrightText: 2009 Friedrich W. H. Kossebau <kossebau@kde.org>
5 
6     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
7 */
8 
9 #include "checksumview.hpp"
10 
11 // tool
12 #include "checksumtool.hpp"
13 // lib
14 #include <bytearraychecksumparameterseteditfactory.hpp>
15 #include <abstractbytearraychecksumparametersetedit.hpp>
16 #include <abstractbytearraychecksumparameterset.hpp>
17 #include <abstractbytearraychecksumalgorithm.hpp>
18 // KF
19 #include <KComboBox>
20 #include <KGuiItem>
21 #include <KLocalizedString>
22 // Qt
23 #include <QLabel>
24 #include <QGroupBox>
25 #include <QStackedWidget>
26 #include <QLineEdit>
27 #include <QPushButton>
28 #include <QLayout>
29 #include <QClipboard>
30 #include <QApplication>
31 #include <QAbstractItemView>
32 
33 namespace Kasten {
34 
ChecksumView(ChecksumTool * tool,QWidget * parent)35 ChecksumView::ChecksumView(ChecksumTool* tool, QWidget* parent)
36     : AbstractToolWidget(parent)
37     , mTool(tool)
38 {
39     auto* baseLayout = new QVBoxLayout(this);
40     baseLayout->setContentsMargins(0, 0, 0, 0);
41 
42     // algorithm
43     auto* algorithmLayout = new QHBoxLayout();
44     QLabel* label = new QLabel(i18nc("@label:listbox algorithm to use for the checksum", "Algorithm:"), this);
45     mAlgorithmComboBox = new KComboBox(this);
46     connect(mAlgorithmComboBox, QOverload<int>::of(&KComboBox::activated),
47             this, &ChecksumView::onOperationChange);
48 
49     label->setBuddy(mAlgorithmComboBox);
50     const QString algorithmWhatsThis =
51         i18nc("@info:whatsthis", "Select the algorithm to use for the checksum.");
52     label->setWhatsThis(algorithmWhatsThis);
53     mAlgorithmComboBox->setWhatsThis(algorithmWhatsThis);
54 
55     algorithmLayout->addWidget(label);
56     algorithmLayout->addWidget(mAlgorithmComboBox, 10);
57     baseLayout->addLayout(algorithmLayout);
58 
59     // parameter
60     QGroupBox* parameterSetBox = new QGroupBox(i18nc("@title:group", "Parameters"), this);
61     baseLayout->addWidget(parameterSetBox);
62 
63     auto* parameterSetLayout = new QVBoxLayout(parameterSetBox);
64 
65     mParameterSetEditStack = new QStackedWidget(parameterSetBox);
66     parameterSetLayout->addWidget(mParameterSetEditStack);
67 
68     // calculate
69     auto* calculateLayout = new QHBoxLayout();
70 
71     calculateLayout->addStretch();
72     const KGuiItem updateGuiItem =
73         KGuiItem(i18nc("@action:button calculate the checksum", "&Calculate"),
74                  QStringLiteral("run-build"),
75                  i18nc("@info:tooltip",
76                        "Calculate the checksum for the bytes in the selected range."),
77                  xi18nc("@info:whatsthis",
78                         "If you press the <interface>Calculate</interface> button, the list will be updated "
79                         "to all strings which are contained in the selected range and have the set minimum length."));
80     mCalculateButton = new QPushButton(this);
81     KGuiItem::assign(mCalculateButton, updateGuiItem);
82     mCalculateButton->setEnabled(mTool->isApplyable());
83     connect(mCalculateButton, &QPushButton::clicked, this, &ChecksumView::onCalculateClicked);
84     addButton(mCalculateButton, AbstractToolWidget::Default);
85     calculateLayout->addWidget(mCalculateButton);
86     baseLayout->addLayout(calculateLayout);
87 
88     mChecksumLabel = new QLineEdit(this);
89     mChecksumLabel->setReadOnly(true);
90     mChecksumLabel->setText(mTool->checkSum());
91     connect(mTool, &ChecksumTool::checksumChanged, mChecksumLabel, &QLineEdit::setText);
92     baseLayout->addWidget(mChecksumLabel, 10);
93 
94     baseLayout->addStretch(10);
95 
96     connect(mTool, &ChecksumTool::uptodateChanged, this, &ChecksumView::onChecksumUptodateChanged);
97     connect(mTool, &ChecksumTool::isApplyableChanged, this, &ChecksumView::onApplyableChanged);
98 
99     // automatically set focus to the parameters if a operation has been selected
100     QAbstractItemView* algorithmComboBoxListView = mAlgorithmComboBox->view();
101     QObject::connect(algorithmComboBoxListView, &QAbstractItemView::activated,
102                      mParameterSetEditStack, QOverload<>::of(&QStackedWidget::setFocus));
103     // TODO: is a workaround for Qt 4.5.1 which doesn't emit activated() for mouse clicks
104     QObject::connect(algorithmComboBoxListView, &QAbstractItemView::pressed,
105                      mParameterSetEditStack, QOverload<>::of(&QStackedWidget::setFocus));
106     // TODO: goto filter button if there are no parameters
107 
108     addAlgorithms();
109 }
110 
111 ChecksumView::~ChecksumView() = default;
112 
addAlgorithms()113 void ChecksumView::addAlgorithms()
114 {
115     //
116     const QVector<AbstractByteArrayChecksumAlgorithm*> algorithmList = mTool->algorithmList();
117     for (AbstractByteArrayChecksumAlgorithm* algorithm : algorithmList) {
118         mAlgorithmComboBox->addItem(algorithm->name());
119 
120         const char* const parameterSetId = algorithm->parameterSet()->id();
121         AbstractByteArrayChecksumParameterSetEdit* parameterEdit =
122             ByteArrayChecksumParameterSetEditFactory::createEdit(parameterSetId);
123 
124         mParameterSetEditStack->addWidget(parameterEdit);
125     }
126 
127     onOperationChange(mTool->algorithmId());
128 }
129 
getParameterSet(AbstractByteArrayChecksumParameterSet * parameterSet) const130 void ChecksumView::getParameterSet(AbstractByteArrayChecksumParameterSet* parameterSet) const
131 {
132     auto* parametersetEdit =
133         qobject_cast<AbstractByteArrayChecksumParameterSetEdit*>(mParameterSetEditStack->currentWidget());
134     if (parametersetEdit) {
135         parametersetEdit->getParameterSet(parameterSet);
136     }
137 }
138 
onCalculateClicked()139 void ChecksumView::onCalculateClicked()
140 {
141     AbstractByteArrayChecksumParameterSet* parameterSet = mTool->parameterSet();
142     if (parameterSet) {
143         getParameterSet(parameterSet);
144     }
145 
146     mTool->calculateChecksum();
147 }
148 
onOperationChange(int index)149 void ChecksumView::onOperationChange(int index)
150 {
151     QWidget* oldWidget = mParameterSetEditStack->currentWidget();
152     if (oldWidget) {
153         oldWidget->disconnect(this);
154         oldWidget->disconnect(mTool);
155     }
156 
157     mTool->setAlgorithm(index);
158     mParameterSetEditStack->setCurrentIndex(index);
159 
160     auto* parametersetEdit =
161         qobject_cast<AbstractByteArrayChecksumParameterSetEdit*>(mParameterSetEditStack->currentWidget());
162     if (parametersetEdit) {
163         connect(parametersetEdit, &AbstractByteArrayChecksumParameterSetEdit::validityChanged,
164                 this, &ChecksumView::onValidityChanged);
165         // TODO: hack, see checksum source
166         connect(parametersetEdit, &AbstractByteArrayChecksumParameterSetEdit::valuesChanged,
167                 mTool, &ChecksumTool::resetSourceTool);
168         onValidityChanged(parametersetEdit->isValid());
169     }
170 }
171 
onChecksumUptodateChanged(bool checksumUptodate)172 void ChecksumView::onChecksumUptodateChanged(bool checksumUptodate)
173 {
174     const bool isApplyable = mTool->isApplyable();
175     mCalculateButton->setEnabled(!checksumUptodate && isApplyable);
176 }
177 
onApplyableChanged(bool isApplyable)178 void ChecksumView::onApplyableChanged(bool isApplyable)
179 {
180     mCalculateButton->setEnabled(!mTool->isUptodate() && isApplyable);
181 }
182 
onValidityChanged(bool isValid)183 void ChecksumView::onValidityChanged(bool isValid)
184 {
185     mCalculateButton->setEnabled(mTool->isApplyable() && isValid);
186 }
187 
188 }
189