File indexing completed on 2024-04-28 07:29:23

0001 /*
0002     This file is part of Kiten, a KDE Japanese Reference Tool
0003     SPDX-FileCopyrightText: 2006 Joseph Kerian <jkerian@gmail.com>
0004 
0005     SPDX-License-Identifier: LGPL-2.0-or-later
0006 */
0007 
0008 /*
0009  *    Future Plans:
0010  *  Build a proper exception handling framework
0011  */
0012 
0013 #include "radselectview.h"
0014 
0015 #include "buttongrid.h"
0016 #include "radselectconfig.h"
0017 
0018 #include <KLocalizedString>
0019 #include <KMessageBox>
0020 
0021 #include <QApplication>
0022 #include <QClipboard>
0023 #include <QListWidget>
0024 #include <QPushButton>
0025 #include <QString>
0026 
0027 RadSelectView::RadSelectView(QWidget *parent)
0028     : QWidget(parent)
0029 {
0030     // Setup the ui from the .ui file
0031     setupUi(this);
0032     m_radicalInfo = nullptr;
0033 
0034     // Load the radical information
0035     QString radkfilename = QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("kiten/radkfile"));
0036     if (radkfilename.isNull()) {
0037         KMessageBox::error(nullptr,
0038                            i18n("Kanji radical information does not seem to "
0039                                 "be installed (file kiten/radkfile), this "
0040                                 "file is required for this app to function."));
0041     } else {
0042         QString kanjidicname = QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("kiten/kanjidic"));
0043         if (kanjidicname.isNull()) {
0044             KMessageBox::error(nullptr,
0045                                i18n("Kanji dictionary does not seem to "
0046                                     "be installed (file kiten/kanjidic), stroke "
0047                                     "count information will be unavailable."));
0048             strokes_low->setEnabled(false);
0049             strokes_high->setEnabled(false);
0050         }
0051 
0052         m_radicalInfo = new RadicalFile(radkfilename, kanjidicname);
0053     }
0054 
0055     // Configure the scrolling area
0056     m_buttongrid = new ButtonGrid(radical_box, m_radicalInfo);
0057     radical_box->setWidget(m_buttongrid);
0058     radical_box->setWidgetResizable(true);
0059 
0060     // Configure the stroke selectors
0061     strokes_low->setSpecialValueText(i18nc("Minimum number of strokes for a kanji", "Min"));
0062     strokes_high->setSpecialValueText(i18nc("Maximum number of strokes for a kanji", "Max"));
0063 
0064     //== Now we connect all our signals ==
0065     // Connect our radical grid to our adding method
0066     connect(m_buttongrid, &ButtonGrid::possibleKanji, this, &RadSelectView::listPossibleKanji);
0067     // Connect the results selection to our logic
0068     connect(selected_radicals, &QListWidget::itemClicked, this, &RadSelectView::kanjiClicked);
0069     connect(selected_radicals, &QListWidget::itemDoubleClicked, this, &RadSelectView::kanjiDoubleClicked);
0070     // Connect our stroke limit actions
0071     connect(strokes_low, SIGNAL(valueChanged(int)), this, SLOT(strokeLimitChanged(int)));
0072     connect(strokes_high, SIGNAL(valueChanged(int)), this, SLOT(strokeLimitChanged(int)));
0073     // Connect statusbar updates
0074     connect(m_buttongrid, &ButtonGrid::signalChangeStatusbar, this, &RadSelectView::signalChangeStatusbar);
0075 
0076     // Connect our clear button
0077     connect(clear_button, &QAbstractButton::clicked, this, &RadSelectView::clearSearch);
0078 
0079     // copy text from copied_line (QLineEdit) to clipboard
0080     connect(copy_button, &QAbstractButton::clicked, this, &RadSelectView::toClipboard);
0081 
0082     loadSettings();
0083 }
0084 
0085 RadSelectView::~RadSelectView()
0086 {
0087     delete m_radicalInfo;
0088 }
0089 
0090 void RadSelectView::changedSearch()
0091 {
0092     Q_EMIT searchModified();
0093 }
0094 
0095 void RadSelectView::clearSearch()
0096 {
0097     m_possibleKanji.clear();
0098     m_buttongrid->clearSelections();
0099     selected_radicals->clear();
0100     strokes_low->setValue(0);
0101     strokes_high->setValue(0);
0102 }
0103 
0104 void RadSelectView::kanjiClicked(QListWidgetItem *item)
0105 {
0106     QString allText = i18nc("@item:inlist all matches should be found", "(ALL)");
0107     QString finalText;
0108     if (item->text() == allText) {
0109         for (QListWidgetItem *listItem : selected_radicals->findItems(QStringLiteral("*"), Qt::MatchWildcard)) {
0110             if (listItem->text() != allText) {
0111                 finalText += listItem->text();
0112             }
0113         }
0114     } else {
0115         finalText = item->text();
0116     }
0117 
0118     QApplication::clipboard()->setText(finalText, QClipboard::Selection);
0119 }
0120 
0121 void RadSelectView::kanjiDoubleClicked(QListWidgetItem *item)
0122 {
0123     QString str = copied_line->text();
0124     int pos = copied_line->cursorPosition();
0125     str.insert(pos, item->text());
0126     copied_line->setText(str);
0127     copied_line->setCursorPosition(pos + 1);
0128 }
0129 
0130 void RadSelectView::listPossibleKanji(const QList<Kanji> &list)
0131 {
0132     unsigned int low = strokes_low->value();
0133     unsigned int high = strokes_high->value();
0134 
0135     // Modification of the stroke boxes
0136     // We want to move the max value to something reasonable...
0137     // for example, 5 above the current max value so that rollover
0138     // works nicely. We want to reset to all if the list is empty.
0139     // And we also don't limit if the current value is higher than
0140     // max value in the list
0141     int newMax = 20;
0142     if (list.count() < 1 || list.last().strokes() < low || list.last().strokes() + 5 < high) {
0143         newMax = 99;
0144     } else {
0145         newMax = list.last().strokes() + 5;
0146     }
0147 
0148     strokes_low->setMaximum(newMax);
0149     strokes_high->setMaximum(newMax);
0150     if (high == 0) {
0151         high = 99;
0152     }
0153 
0154     selected_radicals->clear();
0155     for (const Kanji &it : list) {
0156         if (low <= it.strokes() && it.strokes() <= high) {
0157             new QListWidgetItem((QString)it, selected_radicals);
0158         }
0159     }
0160 
0161     m_possibleKanji = list;
0162 
0163     Q_EMIT searchModified();
0164 }
0165 
0166 void RadSelectView::loadKanji(QString &kanji)
0167 {
0168     Q_UNUSED(kanji)
0169     // TODO: loadKanji method
0170 }
0171 
0172 void RadSelectView::loadRadicals(const QString &radicals, int strokeMin, int strokeMax)
0173 {
0174     Q_UNUSED(radicals)
0175     Q_UNUSED(strokeMin)
0176     Q_UNUSED(strokeMax)
0177     // TODO: loadRadicals method
0178     Q_EMIT searchModified();
0179 }
0180 
0181 void RadSelectView::loadSettings()
0182 {
0183     // TODO: Add preferences for what to do on single/double click
0184     // Suggested options: Lookup in Kiten, Add to Search Bar, Copy to Clipboard
0185     selected_radicals->setFont(RadSelectConfigSkeleton::self()->resultListFont());
0186     m_buttongrid->setFont(RadSelectConfigSkeleton::self()->font());
0187 
0188     m_buttongrid->setSortByFrequency(RadSelectConfigSkeleton::self()->sortByFrequency());
0189 }
0190 
0191 void RadSelectView::strokeLimitChanged(int newvalue)
0192 {
0193     int low = strokes_low->value();
0194     int high = strokes_high->value();
0195     if (low > high) {
0196         if (low == newvalue) {
0197             strokes_high->setValue(newvalue);
0198         } else {
0199             strokes_low->setValue(newvalue);
0200         }
0201     }
0202 
0203     // This will force reevaluation of the list if it's needed
0204     QList<Kanji> newList = m_possibleKanji;
0205     listPossibleKanji(newList);
0206 }
0207 
0208 void RadSelectView::toClipboard()
0209 {
0210     QClipboard *cb = QApplication::clipboard();
0211     cb->setText(copied_line->text(), QClipboard::Clipboard);
0212     cb->setText(copied_line->text(), QClipboard::Selection);
0213 }
0214 
0215 #include "moc_radselectview.cpp"