File indexing completed on 2025-01-05 05:23:30
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 "gotooffsetview.hpp" 0010 0011 // tool 0012 #include "gotooffsettool.hpp" 0013 // libconfigentries 0014 #include <addresscomboboxcodingconfigentry.hpp> 0015 #include <directionconfigentry.hpp> 0016 // Okteta Kasten gui 0017 #include <Kasten/Okteta/AddressValidator> 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::GotoOffsetView::GotoDirection KConfigGroup::readEntry(const char *key, const Kasten::GotoOffsetView::GotoDirection &defaultValue) const 0033 { 0034 return static_cast<Kasten::GotoOffsetView::GotoDirection>(KConfigGroup::readEntry(key, static_cast<Kasten::Direction>(defaultValue))); 0035 } 0036 0037 template <> 0038 inline void KConfigGroup::writeEntry(const char *key, const Kasten::GotoOffsetView::GotoDirection &value, 0039 KConfigBase::WriteConfigFlags flags) 0040 { 0041 writeEntry(key, static_cast<Kasten::Direction>(value), flags); 0042 } 0043 0044 0045 namespace Kasten { 0046 0047 GotoOffsetView::GotoOffsetView(GotoOffsetTool* tool, QWidget* parent) 0048 : AbstractToolWidget(parent) 0049 , mTool(tool) 0050 { 0051 auto* baseLayout = new QHBoxLayout(this); 0052 baseLayout->setContentsMargins(0, 0, 0, 0); 0053 0054 // offset 0055 auto* offsetLayout = new QHBoxLayout(); 0056 offsetLayout->setContentsMargins(0, 0, 0, 0); 0057 0058 auto* label = new QLabel(i18nc("@label:listbox", "O&ffset:"), this); 0059 mAddressEdit = new Okteta::AddressComboBox(this); 0060 connect(mAddressEdit, &Okteta::AddressComboBox::addressChanged, 0061 mTool, &GotoOffsetTool::setTargetOffset); 0062 connect(mAddressEdit, &Okteta::AddressComboBox::formatChanged, 0063 this, &GotoOffsetView::onFormatChanged); 0064 connect(mAddressEdit, &Okteta::AddressComboBox::addressTypeChanged, 0065 this, &GotoOffsetView::onAddressTypeChanged); 0066 label->setBuddy(mAddressEdit); 0067 const QString inputWhatsThis = 0068 i18nc("@info:whatsthis", "Enter an offset to go to, or select a previous offset from the list."); 0069 label->setWhatsThis(inputWhatsThis); 0070 mAddressEdit->setWhatsThis(inputWhatsThis); 0071 0072 offsetLayout->addWidget(label); 0073 offsetLayout->addWidget(mAddressEdit, 1); 0074 0075 baseLayout->addLayout(offsetLayout, 1); 0076 baseLayout->setAlignment(offsetLayout, Qt::AlignTop); 0077 0078 setFocusProxy(mAddressEdit); // TODO: see how KDialog does it, e.g. see if there is already a focuswidget as child 0079 0080 // options 0081 auto* optionsLayout = new QVBoxLayout(); 0082 optionsLayout->setContentsMargins(0, 0, 0, 0); 0083 0084 mAtCursorCheckBox = new QCheckBox(i18nc("@option:check", "From c&ursor"), this); 0085 mAtCursorCheckBox->setWhatsThis( 0086 i18nc("@info:whatsthis", "Go relative from the current cursor location and not absolute.")); 0087 connect(mAtCursorCheckBox, &QCheckBox::toggled, 0088 mTool, &GotoOffsetTool::setIsRelative); 0089 mExtendSelectionCheckBox = new QCheckBox(i18nc("@option:check", "&Extend selection"), this); 0090 mExtendSelectionCheckBox->setWhatsThis( 0091 i18nc("@info:whatsthis", "Extend the selection by the cursor move.")); 0092 connect(mExtendSelectionCheckBox, &QCheckBox::toggled, 0093 mTool, &GotoOffsetTool::setIsSelectionToExtent); 0094 mBackwardsCheckBox = new QCheckBox(i18nc("@option:check", "&Backwards"), this); 0095 mBackwardsCheckBox->setWhatsThis( 0096 i18nc("@info:whatsthis", "Go backwards from the end or the current cursor location.")); 0097 connect(mBackwardsCheckBox, &QCheckBox::toggled, mTool, &GotoOffsetTool::setIsBackwards); 0098 0099 auto* upperOptionsLayout = new QHBoxLayout(); 0100 upperOptionsLayout->setContentsMargins(0, 0, 0, 0); 0101 upperOptionsLayout->addWidget(mAtCursorCheckBox); 0102 upperOptionsLayout->addWidget(mBackwardsCheckBox); 0103 0104 optionsLayout->addLayout(upperOptionsLayout); 0105 optionsLayout->addWidget(mExtendSelectionCheckBox); 0106 0107 baseLayout->addLayout(optionsLayout); 0108 0109 // Goto button 0110 const KGuiItem gotoGuiItem = 0111 KGuiItem(i18nc("@action:button", "&Go"), 0112 QStringLiteral("go-jump"), 0113 i18nc("@info:tooltip", 0114 "Go to the Offset"), 0115 xi18nc("@info:whatsthis", 0116 "If you press the <interface>Go</interface> " 0117 "button, the cursor will be moved in the document to or, " 0118 "on your option, by the offset you entered above.")); 0119 mGotoButton = new QPushButton(this); 0120 KGuiItem::assign(mGotoButton, gotoGuiItem); 0121 connect(mGotoButton, &QPushButton::clicked, this, &GotoOffsetView::onGotoButtonClicked); 0122 addButton(mGotoButton, AbstractToolWidget::Default); 0123 baseLayout->addWidget(mGotoButton); 0124 baseLayout->setAlignment(mGotoButton, Qt::AlignTop); 0125 0126 setTabOrder(mAddressEdit, mAtCursorCheckBox); 0127 setTabOrder(mAtCursorCheckBox, mBackwardsCheckBox); 0128 setTabOrder(mBackwardsCheckBox, mExtendSelectionCheckBox); 0129 setTabOrder(mExtendSelectionCheckBox, mGotoButton); 0130 0131 const KConfigGroup configGroup(KSharedConfig::openConfig(), ConfigGroupId); 0132 0133 const bool fromCursor = configGroup.readEntry(FromCursorConfigKey, DefaultFromCursor); 0134 mAtCursorCheckBox->setChecked(fromCursor); 0135 0136 const GotoDirection direction = configGroup.readEntry(DirectionConfigKey, DefaultDirection); 0137 mBackwardsCheckBox->setChecked(direction == GotoBackward); 0138 0139 const bool extendSelection = configGroup.readEntry(ExtendSelectionConfigKey, DefaultExtendSelection); 0140 mExtendSelectionCheckBox->setChecked(extendSelection); 0141 0142 const Okteta::AddressComboBox::Coding offsetCoding = configGroup.readEntry(OffsetCodingConfigKey, DefaultOffsetCoding); 0143 mAddressEdit->setFormat(offsetCoding); 0144 0145 connect(mTool, &GotoOffsetTool::isApplyableChanged, 0146 this, &GotoOffsetView::onApplyableChanged); 0147 0148 onApplyableChanged(mTool->isApplyable()); 0149 } 0150 0151 GotoOffsetView::~GotoOffsetView() = default; 0152 0153 void GotoOffsetView::onApplyableChanged(bool isApplyable) 0154 { 0155 // TODO: set error tooltip, like offset out of range or no document 0156 // TODO: set color flag to offset input 0157 mGotoButton->setEnabled(isApplyable); 0158 } 0159 0160 void GotoOffsetView::onGotoButtonClicked() 0161 { 0162 // TODO: collect recently used offset in tool instead? 0163 mAddressEdit->rememberCurrentAddress(); 0164 0165 KConfigGroup configGroup(KSharedConfig::openConfig(), ConfigGroupId); 0166 configGroup.writeEntry(OffsetCodingConfigKey, static_cast<Okteta::AddressComboBox::Coding>(mAddressEdit->format())); 0167 configGroup.writeEntry(DirectionConfigKey, 0168 mBackwardsCheckBox->isChecked() ? GotoBackward : GotoForward); 0169 configGroup.writeEntry(ExtendSelectionConfigKey, mExtendSelectionCheckBox->isChecked()); 0170 configGroup.writeEntry(FromCursorConfigKey, mAtCursorCheckBox->isChecked()); 0171 0172 mTool->gotoOffset(); 0173 // Q_EMIT toolUsed(); 0174 } 0175 0176 void GotoOffsetView::onAddressTypeChanged(int addressType) 0177 { 0178 const bool isNotExpression = (mAddressEdit->format() != Okteta::AddressComboBox::ExpressionCoding); 0179 if (isNotExpression 0180 || addressType == Okteta::AddressValidator::InvalidAddressType) { 0181 return; 0182 } 0183 0184 bool fromCursor = false; 0185 bool backwards = false; 0186 0187 if (addressType == Okteta::AddressValidator::AbsoluteAddress) { 0188 fromCursor = false; 0189 backwards = false; // TODO: there is no way yet for: absolute from end 0190 } else if (addressType == Okteta::AddressValidator::RelativeForwards) { 0191 fromCursor = true; 0192 backwards = false; 0193 } else if (addressType == Okteta::AddressValidator::RelativeBackwards) { 0194 fromCursor = true; 0195 backwards = true; 0196 } 0197 0198 mAtCursorCheckBox->setChecked(fromCursor); 0199 mTool->setIsRelative(fromCursor); 0200 mBackwardsCheckBox->setChecked(backwards); 0201 mTool->setIsBackwards(backwards); 0202 } 0203 0204 void GotoOffsetView::onFormatChanged(int formatIndex) 0205 { 0206 const bool isNotExpression = (formatIndex != Okteta::AddressComboBox::ExpressionCoding); 0207 0208 mAtCursorCheckBox->setEnabled(isNotExpression); 0209 mBackwardsCheckBox->setEnabled(isNotExpression); 0210 } 0211 0212 } 0213 0214 #include "moc_gotooffsetview.cpp"