File indexing completed on 2024-05-19 05:08:37

0001 /*
0002     SPDX-FileCopyrightText: 2009-2011 Laurent Montel <montel@kde.org>
0003     SPDX-FileCopyrightText: 2017 Łukasz Wojniłowicz <lukasz.wojnilowicz@gmail.com>
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "transactionsortoption.h"
0008 
0009 // ----------------------------------------------------------------------------
0010 // QT Includes
0011 
0012 #include <QIcon>
0013 
0014 // ----------------------------------------------------------------------------
0015 // KDE Includes
0016 #include <KLazyLocalizedString>
0017 
0018 // ----------------------------------------------------------------------------
0019 // Project Includes
0020 
0021 #include "icons/icons.h"
0022 #include "widgetenums.h"
0023 
0024 #include "ui_transactionsortoption.h"
0025 
0026 using namespace eWidgets;
0027 using namespace Icons;
0028 
0029 /*
0030  * IMPORTANT: Keep this in sync with SortField enum in widgetenums.h
0031  *            Don't touch the order of this list because it will break
0032  *            the sorting in existing data files
0033  */
0034 static constexpr KLazyLocalizedString sortOrderText[] = {
0035     kli18nc("Unknown sort order", "Unknown"),
0036     kli18n("Post date"),
0037     kli18n("Date entered"),
0038     kli18n("Payee"),
0039     kli18n("Amount"),
0040     kli18n("Number"),
0041     kli18n("Entry order"),
0042     kli18n("Type"),
0043     kli18n("Category"),
0044     kli18n("Reconcile state"),
0045     kli18n("Security"),
0046     kli18n("Reconciliation date"),
0047     // add new values above this comment line
0048 };
0049 
0050 TransactionSortOption::TransactionSortOption(QWidget* parent)
0051     : QWidget(parent)
0052     , ui(new Ui::TransactionSortOption)
0053 {
0054     ui->setupUi(this);
0055 
0056     ui->m_addButton->setIcon(Icons::get(Icon::ArrowRight));
0057     ui->m_removeButton->setIcon(Icons::get(Icon::ArrowLeft));
0058     ui->m_upButton->setIcon(Icons::get(Icon::ArrowUp));
0059     ui->m_downButton->setIcon(Icons::get(Icon::ArrowDown));
0060 
0061     // don't allow sorting of the selected entries
0062     ui->m_selectedList->setSortingEnabled(false);
0063 
0064     connect(ui->m_addButton, &QPushButton::pressed, this, &TransactionSortOption::slotAddItem);
0065     connect(ui->m_removeButton, &QPushButton::pressed, this, &TransactionSortOption::slotRemoveItem);
0066     connect(ui->m_upButton, &QPushButton::pressed, this, &TransactionSortOption::slotUpItem);
0067     connect(ui->m_downButton, &QPushButton::pressed, this, &TransactionSortOption::slotDownItem);
0068 
0069     connect(ui->m_availableList, &QListWidget::currentItemChanged, this, &TransactionSortOption::slotUpdateButtons);
0070     connect(ui->m_selectedList, &QListWidget::currentItemChanged, this, &TransactionSortOption::slotUpdateButtons);
0071     connect(ui->m_selectedList, &QListWidget::doubleClicked, this, &TransactionSortOption::slotToggleDirection);
0072 
0073     setSettings(QString());
0074 }
0075 
0076 TransactionSortOption::~TransactionSortOption()
0077 {
0078     delete ui;
0079 }
0080 
0081 /**
0082  * Setup the two lists according to the elements found in @a list.
0083  * If an item is negative, it will show up in the available list,
0084  * if positive, it shows up in the selected list.
0085  *
0086  * Special care is taken about the two values @a EntryDateSort and
0087  * @a EntryOrderSort. These two entries cannot (should not) exist
0088  * alone. Inside this widget, only the @a EntryOrderSort is used.
0089  *
0090  * setSettings() takes care of hiding the @a EntryDateSort item and if
0091  * it exists in @p settings without @a EntryOrderSort being present, it
0092  * will add @a EntryOrderSort.
0093  */
0094 void TransactionSortOption::setSettings(const QString& settings)
0095 {
0096     ui->m_availableList->clear();
0097     ui->m_availableList->setCurrentItem(0);
0098     ui->m_selectedList->clear();
0099     ui->m_selectedList->setCurrentItem(0);
0100 
0101     QStringList list = settings.split(',', Qt::SkipEmptyParts);
0102     QMap<int, bool> selectedMap;
0103 
0104     // fill selected list
0105     QStringList::const_iterator it_s;
0106     QListWidgetItem* last = 0;
0107     for (it_s = list.constBegin(); it_s != list.constEnd(); ++it_s) {
0108         int val = (*it_s).toInt();
0109         selectedMap[abs(val)] = true;
0110         last = addEntry(ui->m_selectedList, last, val);
0111     }
0112 
0113     // fill available list
0114     for (int i = static_cast<int>(SortField::PostDate); i < static_cast<int>(SortField::MaxFields); ++i) {
0115         // Only add those, that are not present in the list of selected items
0116         if (selectedMap.find(i) == selectedMap.end()) {
0117             int val = i;
0118             if (i == static_cast<int>(SortField::Value))
0119                 val = -val;
0120             addEntry(ui->m_availableList, 0, val);
0121         }
0122     }
0123 
0124     // update the current item on the lists
0125     QListWidgetItem* p;
0126     if ((p = ui->m_availableList->item(0)) != 0) {
0127         ui->m_availableList->setCurrentItem(p);
0128     }
0129     if ((p = ui->m_selectedList->item(0)) != 0) {
0130         ui->m_selectedList->setCurrentItem(p);
0131     }
0132 
0133     slotUpdateButtons();
0134 }
0135 
0136 QListWidgetItem* TransactionSortOption::addEntry(QListWidget* p, QListWidgetItem* after, int idx)
0137 {
0138     auto txt = sortOrderToText(static_cast<SortField>(abs(idx)));
0139     if (txt.isEmpty())
0140         txt = "Unknown"; // i18n should be handled in sortOptionToText()
0141 
0142     int row = p->row(after) + 1;
0143     p->insertItem(row, txt);
0144     auto item = p->item(row);
0145     int direction = (idx >= 0) ? 1 : -1;
0146     item->setData(Qt::UserRole, QVariant(direction));
0147     setDirectionIcon(item);
0148     return item;
0149 }
0150 
0151 void TransactionSortOption::slotToggleDirection()
0152 {
0153     const auto item = ui->m_selectedList->currentItem();
0154     if (item) {
0155         int direction = item->data(Qt::UserRole).toInt() * (-1);
0156         item->setData(Qt::UserRole, QVariant(direction));
0157         setDirectionIcon(item);
0158         Q_EMIT settingsChanged(settings());
0159     }
0160 }
0161 
0162 void TransactionSortOption::setDirectionIcon(QListWidgetItem* item)
0163 {
0164     if (item->data(Qt::UserRole).toInt() > 0) {
0165         item->setIcon(Icons::get(Icon::SortAscending));
0166     } else {
0167         item->setIcon(Icons::get(Icon::SortDescending));
0168     }
0169 }
0170 
0171 QString TransactionSortOption::settings() const
0172 {
0173     QString rc;
0174     auto item = dynamic_cast<QListWidgetItem*>(ui->m_selectedList->item(0));
0175     while (item) {
0176         rc += QString::number(static_cast<int>(textToSortOrder(item->text())) * item->data(Qt::UserRole).toInt());
0177         item = ui->m_selectedList->item(ui->m_selectedList->row(item) + 1);
0178         if (item != 0)
0179             rc += ',';
0180     }
0181     return rc;
0182 }
0183 
0184 void TransactionSortOption::slotUpdateButtons()
0185 {
0186     auto availableItem = ui->m_availableList->currentItem();
0187     auto selectedItem = ui->m_selectedList->currentItem();
0188     ui->m_addButton->setEnabled(availableItem != 0);
0189     ui->m_removeButton->setEnabled(selectedItem != 0);
0190     if (selectedItem) {
0191         ui->m_upButton->setEnabled(ui->m_selectedList->row(selectedItem) != 0);
0192         ui->m_downButton->setEnabled(ui->m_selectedList->row(selectedItem) < ui->m_selectedList->count() - 1);
0193     } else {
0194         ui->m_upButton->setEnabled(false);
0195         ui->m_downButton->setEnabled(false);
0196     }
0197 }
0198 
0199 void TransactionSortOption::slotAddItem()
0200 {
0201     QListWidgetItem* item;
0202     if ((item = ui->m_availableList->currentItem()) != 0) {
0203         auto next = ui->m_availableList->item(ui->m_availableList->row(item) + 1);
0204         if (!next)
0205             next = ui->m_availableList->item(ui->m_availableList->row(item) + 1);
0206         ui->m_availableList->takeItem(ui->m_availableList->row(item));
0207         ui->m_selectedList->addItem(item);
0208         ui->m_addButton->setEnabled((ui->m_availableList->count() > 0));
0209         if (next) {
0210             ui->m_availableList->setCurrentItem(next);
0211         }
0212         Q_EMIT settingsChanged(settings());
0213     }
0214 }
0215 
0216 void TransactionSortOption::slotRemoveItem()
0217 {
0218     QListWidgetItem* item;
0219     if ((item = ui->m_selectedList->currentItem()) != 0) {
0220         auto next = ui->m_selectedList->item(ui->m_selectedList->row(item) + 1);
0221         if (!next)
0222             next = ui->m_selectedList->item(ui->m_selectedList->row(item) + 1);
0223         ui->m_selectedList->takeItem(ui->m_selectedList->row(item));
0224         ui->m_availableList->addItem(item);
0225         ui->m_removeButton->setEnabled(ui->m_selectedList->count() > 0);
0226         if (next) {
0227             ui->m_selectedList->setCurrentItem(next);
0228         }
0229         Q_EMIT settingsChanged(settings());
0230     }
0231 }
0232 
0233 void TransactionSortOption::slotUpItem()
0234 {
0235     auto item = ui->m_selectedList->currentItem();
0236     auto prev = ui->m_selectedList->item(ui->m_selectedList->row(item) - 1);
0237     int prevRow = ui->m_selectedList->row(prev);
0238     if (prev) {
0239         ui->m_selectedList->takeItem(ui->m_selectedList->row(item));
0240         ui->m_selectedList->insertItem(prevRow, item);
0241         ui->m_selectedList->setCurrentRow(ui->m_selectedList->row(item));
0242         ui->m_upButton->setEnabled(ui->m_selectedList->row(item) > 0);
0243         ui->m_downButton->setEnabled(ui->m_selectedList->row(item) < ui->m_selectedList->count() - 1);
0244         Q_EMIT settingsChanged(settings());
0245     }
0246 }
0247 
0248 void TransactionSortOption::slotDownItem()
0249 {
0250     auto item = ui->m_selectedList->currentItem();
0251     auto next = ui->m_selectedList->item(ui->m_selectedList->row(item) + 1);
0252     int nextRow = ui->m_selectedList->row(next);
0253     if (next) {
0254         ui->m_selectedList->takeItem(ui->m_selectedList->row(item));
0255         ui->m_selectedList->insertItem(nextRow, item);
0256         ui->m_selectedList->setCurrentRow(ui->m_selectedList->row(item));
0257         ui->m_upButton->setEnabled(ui->m_selectedList->row(item) > 0);
0258         ui->m_downButton->setEnabled(ui->m_selectedList->row(item) < ui->m_selectedList->count() - 1);
0259         Q_EMIT settingsChanged(settings());
0260     }
0261 }
0262 
0263 SortField TransactionSortOption::textToSortOrder(const QString& text)
0264 {
0265     for (auto idx = 1; idx < static_cast<int>(SortField::MaxFields); ++idx) {
0266         if (text == sortOrderText[idx].toString()) {
0267             return static_cast<SortField>(idx);
0268         }
0269     }
0270     return SortField::Unknown;
0271 }
0272 
0273 QString TransactionSortOption::sortOrderToText(SortField idx)
0274 {
0275     if ((int)idx < (int)SortField::PostDate || (int)idx >= (int)SortField::MaxFields)
0276         idx = SortField::Unknown;
0277     return sortOrderText[(int)idx].toString();
0278 }