Warning, file /office/kmymoney/kmymoney/widgets/registersearchline.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 SPDX-FileCopyrightText: 2007-2018 Thomas Baumgart <tbaumgart@kde.org> 0003 SPDX-FileCopyrightText: 2017-2018 Łukasz Wojniłowicz <lukasz.wojnilowicz@gmail.com> 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "registersearchline.h" 0008 0009 // ---------------------------------------------------------------------------- 0010 // QT Includes 0011 0012 #include <QLabel> 0013 #include <QTimer> 0014 #include <QScrollBar> 0015 #include <QHBoxLayout> 0016 #include <QHash> 0017 #include <QIcon> 0018 0019 // ---------------------------------------------------------------------------- 0020 // KDE Includes 0021 0022 #include <KComboBox> 0023 #include <KLocalizedString> 0024 0025 // ---------------------------------------------------------------------------- 0026 // Project Includes 0027 0028 #include "kmymoneyutils.h" 0029 #include "register.h" 0030 #include "registeritem.h" 0031 #include "registerfilter.h" 0032 #include "icons/icons.h" 0033 #include "widgetenums.h" 0034 0035 using namespace eWidgets; 0036 using namespace KMyMoneyRegister; 0037 using namespace Icons; 0038 0039 class RegisterSearchLine::RegisterSearchLinePrivate 0040 { 0041 public: 0042 RegisterSearchLinePrivate() : 0043 reg(0), 0044 combo(0), 0045 queuedSearches(0), 0046 status(eRegister::ItemState::Any) {} 0047 0048 Register* reg; 0049 KComboBox* combo; 0050 QString search; 0051 int queuedSearches; 0052 eRegister::ItemState status; 0053 }; 0054 0055 RegisterSearchLine::RegisterSearchLine(QWidget* parent, Register* reg) : 0056 KLineEdit(parent), 0057 d(new RegisterSearchLinePrivate) 0058 { 0059 setClearButtonEnabled(true); 0060 0061 if (!parentWidget()->layout()) 0062 parentWidget()->setLayout(new QHBoxLayout); 0063 parentWidget()->layout()->addWidget(this); 0064 d->reg = reg; 0065 connect(this, &QLineEdit::textChanged, this, &RegisterSearchLine::queueSearch); 0066 0067 QLabel* label = new QLabel(i18nc("label for status combo", "Stat&us"), parentWidget()); 0068 parentWidget()->layout()->addWidget(label); 0069 d->combo = new KComboBox(parentWidget()); 0070 parentWidget()->layout()->addWidget(d->combo); 0071 // don't change the order of the following lines unless updating 0072 // the case labels in RegisterSearchLine::itemMatches() at the same time 0073 d->combo->insertItem((int)eRegister::ItemState::Any, Icons::get(Icon::Unknown), i18n("Any status")); 0074 d->combo->insertItem((int)eRegister::ItemState::Imported, Icons::get(Icon::DocumentImport), i18n("Imported")); 0075 d->combo->insertItem((int)eRegister::ItemState::Matched, Icons::get(Icon::TransactionMatch), i18n("Matched")); 0076 d->combo->insertItem((int)eRegister::ItemState::Erroneous, Icons::get(Icon::Warning), i18n("Erroneous")); 0077 d->combo->insertItem((int)eRegister::ItemState::Scheduled, Icons::get(Icon::Schedule), i18n("Scheduled")); 0078 d->combo->insertItem((int)eRegister::ItemState::NotMarked, i18n("Not marked")); 0079 d->combo->insertItem((int)eRegister::ItemState::NotReconciled, i18n("Not reconciled")); 0080 d->combo->insertItem((int)eRegister::ItemState::Cleared, i18nc("Reconciliation state 'Cleared'", "Cleared")); 0081 d->combo->setCurrentIndex((int)eRegister::ItemState::Any); 0082 connect(d->combo, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated), this, &RegisterSearchLine::slotStatusChanged); 0083 label->setBuddy(d->combo); 0084 0085 if (reg) { 0086 connect(reg, &QObject::destroyed, this, &RegisterSearchLine::registerDestroyed); 0087 connect(reg, &Register::itemAdded, this, &RegisterSearchLine::itemAdded); 0088 } else { 0089 setEnabled(false); 0090 } 0091 } 0092 0093 RegisterSearchLine::~RegisterSearchLine() 0094 { 0095 delete d; 0096 } 0097 0098 void RegisterSearchLine::setRegister(Register* reg) 0099 { 0100 if (d->reg) { 0101 disconnect(d->reg, &QObject::destroyed, this, &RegisterSearchLine::registerDestroyed); 0102 disconnect(d->reg, &Register::itemAdded, this, &RegisterSearchLine::itemAdded); 0103 } 0104 0105 d->reg = reg; 0106 0107 if (reg) { 0108 connect(reg, &QObject::destroyed, this, &RegisterSearchLine::registerDestroyed); 0109 connect(reg, &Register::itemAdded, this, &RegisterSearchLine::itemAdded); 0110 } 0111 0112 setEnabled(reg != 0); 0113 } 0114 0115 void RegisterSearchLine::slotStatusChanged(int status) 0116 { 0117 d->status = static_cast<eRegister::ItemState>(status); 0118 updateSearch(); 0119 } 0120 0121 void RegisterSearchLine::queueSearch(const QString& search) 0122 { 0123 d->queuedSearches++; 0124 d->search = search; 0125 QTimer::singleShot(200, this, SLOT(activateSearch())); 0126 } 0127 0128 void RegisterSearchLine::activateSearch() 0129 { 0130 --(d->queuedSearches); 0131 if (d->queuedSearches == 0) 0132 updateSearch(d->search); 0133 } 0134 0135 void RegisterSearchLine::updateSearch(const QString& s) 0136 { 0137 if (!d->reg) 0138 return; 0139 0140 d->search = s.isNull() ? text() : s; 0141 0142 // keep track of the current focus item 0143 RegisterItem* focusItem = d->reg->focusItem(); 0144 0145 bool enabled = d->reg->updatesEnabled(); 0146 d->reg->setUpdatesEnabled(false); 0147 0148 bool scrollBarVisible = d->reg->verticalScrollBar()->isVisible(); 0149 0150 RegisterFilter filter(d->search, d->status); 0151 RegisterItem* p = d->reg->firstItem(); 0152 for (; p; p = p->nextItem()) { 0153 p->setVisible(p->matches(filter)); 0154 } 0155 d->reg->suppressAdjacentMarkers(); 0156 d->reg->updateAlternate(); 0157 d->reg->setUpdatesEnabled(enabled); 0158 0159 // if focus item is still visible, then make sure we have 0160 // it on screen 0161 if (focusItem && focusItem->isVisible()) { 0162 d->reg->update(); 0163 /* it's totally fine to call ensureFocusItemVisible instantly 0164 * while narrowing (by adding another letter) filtered results 0165 * because removing items from QTableWidget is fast 0166 * but while widening (by removing some letter) filtered results 0167 * QTableWidget lags and ensureFocusItemVisible() happens before 0168 * its update and focused item isn't made visible therefore 0169 */ 0170 QTimer::singleShot(500, d->reg, SLOT(ensureFocusItemVisible())); 0171 } 0172 // if the scrollbar's visibility changed, we need to resize the contents 0173 if (scrollBarVisible != d->reg->verticalScrollBar()->isVisible()) { 0174 d->reg->resize((int)eTransaction::Column::Detail); 0175 } 0176 } 0177 0178 void RegisterSearchLine::itemAdded(RegisterItem* item) const 0179 { 0180 item->setVisible(item->matches(RegisterFilter(text(), d->status))); 0181 } 0182 0183 void RegisterSearchLine::registerDestroyed() 0184 { 0185 d->reg = 0; 0186 setEnabled(false); 0187 } 0188 0189 0190 class RegisterSearchLineWidget::RegisterSearchLineWidgetPrivate 0191 { 0192 public: 0193 RegisterSearchLineWidgetPrivate() : 0194 reg(0), 0195 searchLine(0) {} 0196 0197 Register* reg; 0198 RegisterSearchLine* searchLine; 0199 }; 0200 0201 0202 RegisterSearchLineWidget::RegisterSearchLineWidget(Register* reg, QWidget* parent) : 0203 QWidget(parent), 0204 d(new RegisterSearchLineWidgetPrivate) 0205 { 0206 d->reg = reg; 0207 createWidgets(); 0208 } 0209 0210 RegisterSearchLineWidget::~RegisterSearchLineWidget() 0211 { 0212 delete d; 0213 } 0214 0215 RegisterSearchLine* RegisterSearchLineWidget::createSearchLine(Register* reg) 0216 { 0217 if (!d->searchLine) 0218 d->searchLine = new RegisterSearchLine(this, reg); 0219 return d->searchLine; 0220 } 0221 0222 void RegisterSearchLineWidget::createWidgets() 0223 { 0224 QHBoxLayout *searchLineLayout = new QHBoxLayout(this); 0225 searchLineLayout->setSpacing(0); 0226 searchLineLayout->setContentsMargins(0, 0, 0, 0); 0227 QLabel *label = new QLabel(i18nc("Filter widget label", "Fi<er:"), this); 0228 searchLineLayout->addWidget(label); 0229 0230 d->searchLine = createSearchLine(d->reg); 0231 d->searchLine->show(); 0232 0233 label->setBuddy(d->searchLine); 0234 label->show(); 0235 } 0236 0237 0238 RegisterSearchLine* RegisterSearchLineWidget::searchLine() const 0239 { 0240 return d->searchLine; 0241 }