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

0001 /*
0002     This file is part of the Okteta Kasten module, made within the KDE community.
0003 
0004     SPDX-FileCopyrightText: 2009 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 "selectrangeview.hpp"
0010 
0011 // tool
0012 #include "selectrangetool.hpp"
0013 // libconfigentries
0014 #include <addresscomboboxcodingconfigentry.hpp>
0015 #include <directionconfigentry.hpp>
0016 // Okteta Kasten gui
0017 #include <Kasten/Okteta/AddressComboBox>
0018 // KF
0019 #include <KGuiItem>
0020 #include <KConfigGroup>
0021 #include <KSharedConfig>
0022 #include <KLocalizedString>
0023 // Qt
0024 #include <QPushButton>
0025 #include <QCheckBox>
0026 #include <QLabel>
0027 #include <QHBoxLayout>
0028 #include <QVBoxLayout>
0029 
0030 
0031 template <>
0032 inline Kasten::SelectRangeView::SelectDirection KConfigGroup::readEntry(const char *key, const Kasten::SelectRangeView::SelectDirection &defaultValue) const
0033 {
0034     return static_cast<Kasten::SelectRangeView::SelectDirection>(KConfigGroup::readEntry(key, static_cast<Kasten::Direction>(defaultValue)));
0035 }
0036 
0037 template <>
0038 inline void KConfigGroup::writeEntry(const char *key, const Kasten::SelectRangeView::SelectDirection &value,
0039                                      KConfigBase::WriteConfigFlags flags)
0040 {
0041     writeEntry(key, static_cast<Kasten::Direction>(value), flags);
0042 }
0043 
0044 namespace Kasten {
0045 
0046 SelectRangeView::SelectRangeView(SelectRangeTool* tool, QWidget* parent)
0047     : AbstractToolWidget(parent)
0048     , mTool(tool)
0049 {
0050     auto* baseLayout = new QHBoxLayout(this);
0051     baseLayout->setContentsMargins(0, 0, 0, 0);
0052 
0053     // offsets
0054     auto* offsetLayout = new QVBoxLayout();
0055     offsetLayout->setContentsMargins(0, 0, 0, 0);
0056 
0057     // start offset
0058     auto* startOffsetLayout = new QHBoxLayout();
0059     startOffsetLayout->setContentsMargins(0, 0, 0, 0);
0060 
0061     auto* label = new QLabel(i18nc("@label:listbox", "Start offset:"), this);
0062     mStartEdit = new Okteta::AddressComboBox(this);
0063     connect(mStartEdit, &Okteta::AddressComboBox::addressChanged,
0064             mTool, &SelectRangeTool::setTargetStart);
0065     label->setBuddy(mStartEdit);
0066     const QString startInputWhatsThis =
0067         i18nc("@info:whatsthis", "Enter an offset to go to, or select a previous offset from the list.");
0068     label->setWhatsThis(startInputWhatsThis);
0069     mStartEdit->setWhatsThis(startInputWhatsThis);
0070 
0071     startOffsetLayout->addWidget(label);
0072     startOffsetLayout->addWidget(mStartEdit);
0073     setFocusProxy(mStartEdit);   // TODO: see how KDialog does it, e.g. see if there is already a focuswidget as child
0074 
0075     offsetLayout->addLayout(startOffsetLayout);
0076 
0077     // end offset
0078     auto* endOffsetLayout = new QHBoxLayout();
0079     endOffsetLayout->setContentsMargins(0, 0, 0, 0);
0080 
0081     label = new QLabel(i18nc("@label:listbox", "End offset:"), this);
0082     mEndEdit = new Okteta::AddressComboBox(this);
0083     connect(mEndEdit, &Okteta::AddressComboBox::addressChanged,
0084             mTool, &SelectRangeTool::setTargetEnd);
0085     label->setBuddy(mEndEdit);
0086     const QString endInputWhatsThis =
0087         i18nc("@info:whatsthis", "Enter an offset to go to, or select a previous offset from the list.");
0088     label->setWhatsThis(endInputWhatsThis);
0089     mEndEdit->setWhatsThis(endInputWhatsThis);
0090 
0091     endOffsetLayout->addWidget(label);
0092     endOffsetLayout->addWidget(mEndEdit);
0093 
0094     offsetLayout->addLayout(endOffsetLayout);
0095     baseLayout->addLayout(offsetLayout);
0096 
0097     // options
0098     auto* optionsLayout = new QVBoxLayout();
0099     optionsLayout->setContentsMargins(0, 0, 0, 0);
0100 
0101     mBackwardsCheckBox = new QCheckBox(i18nc("@option:check", "&Backwards"), this);
0102     mBackwardsCheckBox->setWhatsThis(
0103         i18nc("@info:whatsthis", "Go backwards from the end or the current cursor location."));
0104     connect(mBackwardsCheckBox, &QCheckBox::toggled,
0105             mTool, &SelectRangeTool::setIsEndBackwards);
0106     mBackwardsCheckBox->setChecked(mTool->isEndBackwards());
0107     mRelativeCheckBox = new QCheckBox(i18nc("@option:check", "End relative"), this);
0108     mRelativeCheckBox->setWhatsThis(
0109         i18nc("@info:whatsthis", "Extend the selection by the cursor move."));
0110     connect(mRelativeCheckBox, &QCheckBox::toggled,
0111             mTool, &SelectRangeTool::setIsEndRelative);
0112     mRelativeCheckBox->setChecked(mTool->isEndRelative());
0113 
0114     connect(mRelativeCheckBox, &QCheckBox::toggled, mBackwardsCheckBox, &QCheckBox::setEnabled);
0115     mBackwardsCheckBox->setEnabled(mRelativeCheckBox->isChecked());
0116 
0117     optionsLayout->addWidget(mBackwardsCheckBox);
0118     optionsLayout->addWidget(mRelativeCheckBox);
0119 
0120     baseLayout->addLayout(optionsLayout);
0121 
0122     // Select button
0123     const KGuiItem selectGuiItem =
0124         KGuiItem(i18nc("@action:button",
0125                        "&Select"),
0126                  QStringLiteral("select-rectangular"),
0127                  i18nc("@info:tooltip",
0128                        "Select the range."),
0129                  xi18nc("@info:whatsthis",
0130                         "If you press the <interface>Select</interface> "
0131                         "button, the cursor will be moved in the document to or, "
0132                         "on your option, by the offset you entered above."));
0133     mSelectButton = new QPushButton(this);
0134     KGuiItem::assign(mSelectButton, selectGuiItem);
0135     connect(mSelectButton, &QPushButton::clicked, this, &SelectRangeView::onSelectButtonClicked);
0136     addButton(mSelectButton, AbstractToolWidget::Default);
0137     baseLayout->addWidget(mSelectButton);
0138     baseLayout->setAlignment(mSelectButton, Qt::AlignTop);
0139 
0140     baseLayout->addStretch();
0141 
0142     setTabOrder(mStartEdit, mEndEdit);
0143     setTabOrder(mEndEdit, mRelativeCheckBox);
0144     setTabOrder(mRelativeCheckBox, mBackwardsCheckBox);
0145     setTabOrder(mBackwardsCheckBox, mSelectButton);
0146 
0147     const KConfigGroup configGroup(KSharedConfig::openConfig(), ConfigGroupId);
0148 
0149     const Okteta::AddressComboBox::Coding startOffsetCoding = configGroup.readEntry(StartOffsetCodingConfigKey, DefaultStartOffsetCoding);
0150     mStartEdit->setFormat(startOffsetCoding);
0151 
0152     const Okteta::AddressComboBox::Coding endOffsetCoding = configGroup.readEntry(EndOffsetCodingConfigKey, DefaultEndOffsetCoding);
0153     mEndEdit->setFormat(endOffsetCoding);
0154 
0155     const SelectDirection direction = configGroup.readEntry(DirectionConfigKey, DefaultDirection);
0156     mBackwardsCheckBox->setChecked(direction == SelectBackward);
0157 
0158     const bool relativeToEnd = configGroup.readEntry(RelativeToEndConfigKey, DefaultRelativeToEnd);
0159     mRelativeCheckBox->setChecked(relativeToEnd);
0160 
0161     connect(mTool, &SelectRangeTool::isApplyableChanged, this, &SelectRangeView::onApplyableChanged);
0162 
0163     onApplyableChanged(mTool->isApplyable());
0164 }
0165 
0166 SelectRangeView::~SelectRangeView() = default;
0167 
0168 void SelectRangeView::onApplyableChanged(bool isApplyable)
0169 {
0170     // TODO: set error tooltip, like offset out of range or no document
0171     // TODO: set color flag to offset input
0172     mSelectButton->setEnabled(isApplyable);
0173 }
0174 
0175 void SelectRangeView::onSelectButtonClicked()
0176 {
0177     // TODO: collect recently used offsets in tool instead?
0178     mStartEdit->rememberCurrentAddress();
0179     mEndEdit->rememberCurrentAddress();
0180 
0181     KConfigGroup configGroup(KSharedConfig::openConfig(), ConfigGroupId);
0182     configGroup.writeEntry(StartOffsetCodingConfigKey,
0183                            static_cast<Okteta::AddressComboBox::Coding>(mStartEdit->format()));
0184     configGroup.writeEntry(EndOffsetCodingConfigKey,
0185                            static_cast<Okteta::AddressComboBox::Coding>(mEndEdit->format()));
0186     configGroup.writeEntry(DirectionConfigKey,
0187                            mBackwardsCheckBox->isChecked() ? SelectBackward : SelectForward);
0188     configGroup.writeEntry(RelativeToEndConfigKey, mRelativeCheckBox->isChecked());
0189 
0190     mTool->select();
0191 //     Q_EMIT toolUsed();
0192 }
0193 
0194 }
0195 
0196 #include "moc_selectrangeview.cpp"