File indexing completed on 2024-09-22 05:15:37
0001 /* 0002 This file is part of the Okteta Kasten module, made within the KDE community. 0003 0004 SPDX-FileCopyrightText: 2011 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 "charsetconversionview.hpp" 0010 0011 // tool 0012 #include "charsetconversiontool.hpp" 0013 // Okteta Kasten gui 0014 #include <Kasten/Okteta/ByteArrayComboBox> 0015 // Okteta core 0016 #include <Okteta/CharCodec> 0017 // KF 0018 #include <KMessageBox> 0019 #include <KComboBox> 0020 #include <KLocalizedString> 0021 // Qt 0022 #include <QToolBar> 0023 #include <QPushButton> 0024 #include <QFormLayout> 0025 #include <QVBoxLayout> 0026 #include <QCheckBox> 0027 #include <QGroupBox> 0028 #include <QAction> 0029 #include <QIcon> 0030 0031 namespace Kasten { 0032 0033 CharsetConversionView::CharsetConversionView(CharsetConversionTool* tool, QWidget* parent) 0034 : QWidget(parent) 0035 , mTool(tool) 0036 { 0037 auto* baseLayout = new QVBoxLayout(this); 0038 baseLayout->setContentsMargins(0, 0, 0, 0); 0039 baseLayout->setSpacing(0); 0040 0041 // source/target charset 0042 auto* directionCharsetToolBar = new QToolBar(this); 0043 0044 mDirectionComboBox = new KComboBox(this); 0045 const QStringList directionList { 0046 i18nc("@item:inmenu Is converted _from_ charset (selected in combobox next to this)", 0047 "From"), 0048 i18nc("@item:inmenu Is converted _to_ charset (selected in combobox next to this)", 0049 "To"), 0050 }; 0051 mDirectionComboBox->addItems(directionList); 0052 mDirectionComboBox->setCurrentIndex(mTool->conversionDirection()); 0053 0054 const QString directionToolTip = 0055 i18nc("@info:tooltip", 0056 "The direction the bytes are converted, to or from the selected charset."); 0057 mDirectionComboBox->setToolTip(directionToolTip); 0058 const QString directionWhatsThis = 0059 i18nc("@info:whatsthis", 0060 "Select the direction the bytes are converted, to or from the selected charset."); 0061 mDirectionComboBox->setWhatsThis(directionWhatsThis); 0062 connect(mDirectionComboBox, qOverload<int>(&KComboBox::activated), 0063 mTool, &CharsetConversionTool::setConversionDirection); 0064 0065 directionCharsetToolBar->addWidget(mDirectionComboBox); 0066 0067 mOtherCharSetComboBox = new KComboBox(this); 0068 const QStringList charCodecNames = Okteta::CharCodec::codecNames(); 0069 const int indexOfCurrentCharCodec = charCodecNames.indexOf(mTool->otherCharCodecName()); 0070 mOtherCharSetComboBox->addItems(charCodecNames); 0071 mOtherCharSetComboBox->setCurrentIndex(indexOfCurrentCharCodec); 0072 mOtherCharSetComboBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); 0073 0074 const QString targetCharsetToolTip = 0075 i18nc("@info:tooltip", 0076 "The charset the bytes are converted to."); 0077 mOtherCharSetComboBox->setToolTip(targetCharsetToolTip); 0078 const QString targetCharsetWhatsThis = 0079 i18nc("@info:whatsthis", 0080 "Select the charset the bytes are converted to."); 0081 mOtherCharSetComboBox->setWhatsThis(targetCharsetWhatsThis); 0082 0083 connect(mOtherCharSetComboBox, &KComboBox::textActivated, 0084 mTool, &CharsetConversionTool::setOtherCharCodecName); 0085 0086 directionCharsetToolBar->addWidget(mOtherCharSetComboBox); 0087 baseLayout->addWidget(directionCharsetToolBar); 0088 0089 // settings 0090 auto* settingsBox = new QGroupBox(i18nc("@title:group", "Parameters"), this); 0091 0092 auto* settingsLayout = new QFormLayout(); 0093 0094 const QString substituteMissingCharLabelText = 0095 i18nc("@option:check substitute bytes whose char is not part of the target charset", 0096 "Substitute missing:"); 0097 mSubstituteMissingCharCheckBox = new QCheckBox(this); 0098 mSubstituteMissingCharCheckBox->setChecked(mTool->isSubstitutingMissingChars()); 0099 const QString substituteMissingCharToolTip = 0100 i18nc("@info:tooltip", 0101 "Selects if bytes should be substituted with a default byte " 0102 "if its char in the source charset is not part of the target charset."); 0103 const QString substituteMissingCharWhatsThis = 0104 i18nc("@info:whatsthis", 0105 "Set to true if bytes should be substituted with a default byte " 0106 "if its char in the source charset is not part of the target charset."); 0107 mSubstituteMissingCharCheckBox->setToolTip(substituteMissingCharToolTip); 0108 mSubstituteMissingCharCheckBox->setWhatsThis(substituteMissingCharWhatsThis); 0109 connect(mSubstituteMissingCharCheckBox, &QCheckBox::toggled, 0110 mTool, &CharsetConversionTool::setSubstitutingMissingChars); 0111 settingsLayout->addRow(substituteMissingCharLabelText, mSubstituteMissingCharCheckBox); 0112 // TODO: control what happens on conflicts or unmatched chars in the target set 0113 // option to try only if no conflicts or unmatched chars are hit 0114 // choosing substitute for unmatched and resolve conflicts (general/case-by-case) 0115 // TODO: extra button to request check if all chars are matched, shows state 0116 // TODO: option to switch view to target charset, once done, if "to" other charset 0117 0118 // default byte 0119 const QString substituteByteLabelText = 0120 i18nc("@label:textbox byte to use for chars which are not part of the target charset", 0121 "Substitute byte:"); 0122 mSubstituteByteEdit = new Okteta::ByteArrayComboBox(this); 0123 mSubstituteByteEdit->setMinLength(1); 0124 mSubstituteByteEdit->setMaxLength(1); 0125 const QString substituteByteToolTip = 0126 i18nc("@info:tooltip", 0127 "The byte to use for chars which are not part of the target charset."); 0128 const QString substituteByteWhatsThis = 0129 i18nc("@info:whatsthis", 0130 "Define the byte to use for chars which are not part of the target charset."); 0131 mSubstituteByteEdit->setToolTip(substituteByteToolTip); 0132 mSubstituteByteEdit->setWhatsThis(substituteByteWhatsThis); 0133 // mSubstituteByteEdit->setEnabled( mTool->isSubstitutingMissingChars() ); 0134 mSubstituteByteEdit->setEnabled(false); // TODO: fix char entering and enable again 0135 connect(mSubstituteByteEdit, &Okteta::ByteArrayComboBox::byteArrayChanged, 0136 this, &CharsetConversionView::onDefaultByteEditChanged); 0137 // connect( mSubstituteMissingCharCheckBox, SIGNAL(toggled(bool)), 0138 // mSubstituteByteEdit, SLOT(setEnabled(bool)) ); 0139 mSubstituteByteEdit->setByteArray(QByteArray(1, mTool->substituteByte())); 0140 settingsLayout->addRow(substituteByteLabelText, mSubstituteByteEdit); 0141 0142 settingsBox->setLayout(settingsLayout); 0143 0144 baseLayout->addWidget(settingsBox); 0145 0146 // action 0147 auto* actionToolBar = new QToolBar(this); 0148 actionToolBar->setToolButtonStyle(Qt::ToolButtonFollowStyle); 0149 0150 auto* stretcher = new QWidget(this); 0151 stretcher->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); 0152 actionToolBar->addWidget(stretcher); 0153 0154 mConvertAction = 0155 actionToolBar->addAction(QIcon::fromTheme(QStringLiteral("run-build")), 0156 i18n("Con&vert"), 0157 this, &CharsetConversionView::onConvertButtonClicked); 0158 mConvertAction->setToolTip(i18nc("@info:tooltip", 0159 "Converts the bytes in the selected range.")); 0160 mConvertAction->setWhatsThis(xi18nc("@info:whatsthis", 0161 "If you press the <interface>Convert</interface> button, " 0162 "all bytes in the selected range " 0163 "will be replaced by bytes which represent the same character " 0164 "in the selected target charset.")); 0165 baseLayout->addWidget(actionToolBar); 0166 baseLayout->addStretch(); 0167 0168 connect(mTool, &CharsetConversionTool::isApplyableChanged, 0169 this, &CharsetConversionView::onApplyableChanged); 0170 connect(mTool, &CharsetConversionTool::conversionDone, 0171 this, &CharsetConversionView::onConversionDone); 0172 } 0173 0174 CharsetConversionView::~CharsetConversionView() = default; 0175 0176 void CharsetConversionView::onApplyableChanged(bool isApplyable) 0177 { 0178 mConvertAction->setEnabled(isApplyable); 0179 } 0180 0181 void CharsetConversionView::onDefaultByteEditChanged(const QByteArray& byteArray) 0182 { 0183 Q_UNUSED(byteArray); 0184 } 0185 0186 void CharsetConversionView::onConvertButtonClicked() 0187 { 0188 mTool->convertChars(); 0189 } 0190 0191 void CharsetConversionView::onConversionDone(bool success, int convertedBytesCount, 0192 const QMap<Okteta::Byte, int>& failedPerByteCount) 0193 { 0194 0195 const QString messageBoxTitle = mTool->title(); 0196 0197 if (success) { 0198 QString conversionReport = (convertedBytesCount == 0) ? 0199 i18nc("@info", "No bytes converted.") : 0200 i18ncp("@info", "1 byte converted.", "%1 bytes converted.", convertedBytesCount); 0201 if (mTool->isSubstitutingMissingChars()) { 0202 int totalFailedByteCount = 0; 0203 for (int failedByteCount : failedPerByteCount) { 0204 totalFailedByteCount += failedByteCount; 0205 } 0206 0207 // TODO: show table with failed bytes and their number. 0208 conversionReport += QLatin1String("<br />"); 0209 conversionReport += (totalFailedByteCount == 0) ? 0210 i18nc("@info", "No bytes substituted.") : 0211 i18ncp("@info", "1 byte substituted.", "%1 bytes substituted.", totalFailedByteCount); 0212 } 0213 KMessageBox::information(/*mParentWidget*/ nullptr, 0214 conversionReport, 0215 messageBoxTitle); 0216 } else { 0217 // TODO: show/goto byte which on which conversion fails 0218 KMessageBox::error(/*mParentWidget*/ nullptr, 0219 i18nc("@info", 0220 "Conversion cancelled because of chars which are not " 0221 "in the target charset."), 0222 messageBoxTitle); 0223 0224 } 0225 } 0226 0227 } 0228 0229 #include "moc_charsetconversionview.cpp"