File indexing completed on 2024-04-28 05:08:23
0001 /*************************************************************************** 0002 Copyright (C) 2005-2009 Robby Stephenson <robby@periapsis.org> 0003 ***************************************************************************/ 0004 0005 /*************************************************************************** 0006 * * 0007 * This program is free software; you can redistribute it and/or * 0008 * modify it under the terms of the GNU General Public License as * 0009 * published by the Free Software Foundation; either version 2 of * 0010 * the License or (at your option) version 3 or any later version * 0011 * accepted by the membership of KDE e.V. (or its successor approved * 0012 * by the membership of KDE e.V.), which shall act as a proxy * 0013 * defined in Section 14 of version 3 of the license. * 0014 * * 0015 * This program is distributed in the hope that it will be useful, * 0016 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 0018 * GNU General Public License for more details. * 0019 * * 0020 * You should have received a copy of the GNU General Public License * 0021 * along with this program. If not, see <http://www.gnu.org/licenses/>. * 0022 * * 0023 ***************************************************************************/ 0024 0025 #include <config.h> 0026 0027 #include "loandialog.h" 0028 #include "borrowerdialog.h" 0029 #include "gui/datewidget.h" 0030 #include "collection.h" 0031 #include "commands/addloans.h" 0032 #include "commands/modifyloans.h" 0033 #include "utils/string_utils.h" 0034 #include "tellico_debug.h" 0035 0036 #include <KLocalizedString> 0037 #include <KLineEdit> 0038 #include <KTextEdit> 0039 #include <KJob> 0040 #include <KSharedConfig> 0041 #include <KConfigGroup> 0042 #include <KWindowConfig> 0043 0044 #ifdef HAVE_KABC 0045 #include <kcontacts/addressee.h> 0046 #include <Akonadi/Contact/ContactSearchJob> 0047 #endif 0048 0049 #include <QLabel> 0050 #include <QCheckBox> 0051 #include <QGridLayout> 0052 #include <QPushButton> 0053 #include <QDialogButtonBox> 0054 #include <QVBoxLayout> 0055 #include <QTimer> 0056 0057 namespace { 0058 static const char* dialogOptionsString = "Loan Dialog Options"; 0059 } 0060 0061 using Tellico::LoanDialog; 0062 0063 LoanDialog::LoanDialog(const Tellico::Data::EntryList& entries_, QWidget* parent_) 0064 : QDialog(parent_), 0065 m_mode(Add), m_borrower(nullptr), m_entries(entries_), m_loan(nullptr) { 0066 setModal(true); 0067 setWindowTitle(i18n("Loan Dialog")); 0068 0069 init(); 0070 } 0071 0072 LoanDialog::LoanDialog(Tellico::Data::LoanPtr loan_, QWidget* parent_) 0073 : QDialog(parent_), 0074 m_mode(Modify), m_borrower(loan_->borrower()), m_loan(loan_) { 0075 m_entries.append(m_loan->entry()); 0076 0077 setModal(true); 0078 setWindowTitle(i18n("Modify Loan")); 0079 0080 init(); 0081 0082 m_borrowerEdit->setText(m_loan->borrower()->name()); 0083 m_loanDate->setDate(m_loan->loanDate()); 0084 if(m_loan->dueDate().isValid()) { 0085 m_dueDate->setDate(m_loan->dueDate()); 0086 #ifdef HAVE_KCAL 0087 m_addEvent->setEnabled(true); 0088 if(m_loan->inCalendar()) { 0089 m_addEvent->setChecked(true); 0090 } 0091 #endif 0092 } 0093 m_note->setPlainText(m_loan->note()); 0094 } 0095 0096 void LoanDialog::init() { 0097 QVBoxLayout* mainLayout = new QVBoxLayout(this); 0098 setLayout(mainLayout); 0099 0100 QWidget* mainWidget = new QWidget(this); 0101 mainLayout->addWidget(mainWidget); 0102 0103 QGridLayout* topLayout = new QGridLayout(mainWidget); 0104 // middle column gets to be the widest 0105 topLayout->setColumnStretch(1, 1); 0106 0107 int row = -1; 0108 0109 QLabel* pixLabel = new QLabel(mainWidget); 0110 mainLayout->addWidget(pixLabel); 0111 pixLabel->setPixmap(QIcon::fromTheme(QStringLiteral("tellico"), 0112 QIcon(QLatin1String(":/icons/tellico"))) 0113 .pixmap(QSize(64, 64))); 0114 pixLabel->setAlignment(Qt::Alignment(Qt::AlignLeft) | Qt::AlignTop); 0115 topLayout->addWidget(pixLabel, ++row, 0); 0116 0117 QString entryString = QStringLiteral("<qt><p>"); 0118 if(m_mode == Add) { 0119 entryString += i18n("The following items are being checked out:"); 0120 entryString += QLatin1String("</p><ol>"); 0121 foreach(Data::EntryPtr entry, m_entries) { 0122 entryString += QLatin1String("<li>") + entry->title() + QLatin1String("</li>"); 0123 } 0124 } else { 0125 entryString += i18n("The following item is on-loan:"); 0126 entryString += QLatin1String("</p><ol>"); 0127 entryString += QLatin1String("<li>") + m_loan->entry()->title() + QLatin1String("</li>"); 0128 } 0129 entryString += QLatin1String("</ol></qt>"); 0130 KTextEdit* entryLabel = new KTextEdit(mainWidget); 0131 mainLayout->addWidget(entryLabel); 0132 entryLabel->setHtml(entryString); 0133 entryLabel->setReadOnly(true); 0134 topLayout->addWidget(entryLabel, row, 1, 1, 2); 0135 0136 QLabel* l = new QLabel(i18n("&Lend to:"), mainWidget); 0137 mainLayout->addWidget(l); 0138 topLayout->addWidget(l, ++row, 0); 0139 m_borrowerEdit = new KLineEdit(mainWidget); //krazy:exclude=qclasses 0140 mainLayout->addWidget(m_borrowerEdit); 0141 topLayout->addWidget(m_borrowerEdit, row, 1); 0142 l->setBuddy(m_borrowerEdit); 0143 m_borrowerEdit->completionObject()->setIgnoreCase(true); 0144 connect(m_borrowerEdit, &QLineEdit::textChanged, 0145 this, &LoanDialog::slotBorrowerNameChanged); 0146 QPushButton* pb = new QPushButton(QIcon::fromTheme(QStringLiteral("kaddressbook")), QString(), mainWidget); 0147 mainLayout->addWidget(pb); 0148 topLayout->addWidget(pb, row, 2); 0149 connect(pb, &QAbstractButton::clicked, this, &LoanDialog::slotGetBorrower); 0150 QString whats = i18n("Enter the name of the person borrowing the items from you. " 0151 "Clicking the button allows you to select from your address book."); 0152 l->setWhatsThis(whats); 0153 // only enable for new loans 0154 if(m_mode == Modify) { 0155 m_borrowerEdit->setEnabled(false); 0156 pb->setEnabled(false); 0157 } 0158 0159 l = new QLabel(i18n("&Loan date:"), mainWidget); 0160 mainLayout->addWidget(l); 0161 topLayout->addWidget(l, ++row, 0); 0162 m_loanDate = new GUI::DateWidget(mainWidget); 0163 m_loanDate->setDate(QDate::currentDate()); 0164 l->setBuddy(m_loanDate); 0165 topLayout->addWidget(m_loanDate, row, 1, 1, 2); 0166 whats = i18n("The check-out date is the date that you lent the items. By default, " 0167 "today's date is used."); 0168 l->setWhatsThis(whats); 0169 m_loanDate->setWhatsThis(whats); 0170 // only enable for new loans 0171 if(m_mode == Modify) { 0172 m_loanDate->setEnabled(false); 0173 } 0174 0175 l = new QLabel(i18n("D&ue date:"), mainWidget); 0176 mainLayout->addWidget(l); 0177 topLayout->addWidget(l, ++row, 0); 0178 m_dueDate = new GUI::DateWidget(mainWidget); 0179 l->setBuddy(m_dueDate); 0180 topLayout->addWidget(m_dueDate, row, 1, 1, 2); 0181 // valid due dates will enable the calendar adding checkbox 0182 connect(m_dueDate, &GUI::DateWidget::signalModified, this, &LoanDialog::slotDueDateChanged); 0183 whats = i18n("The due date is when the items are due to be returned. The due date " 0184 "is not required, unless you want to add the loan to your active calendar."); 0185 l->setWhatsThis(whats); 0186 m_dueDate->setWhatsThis(whats); 0187 0188 l = new QLabel(i18n("&Note:"), mainWidget); 0189 mainLayout->addWidget(l); 0190 topLayout->addWidget(l, ++row, 0); 0191 m_note = new KTextEdit(mainWidget); 0192 mainLayout->addWidget(m_note); 0193 l->setBuddy(m_note); 0194 topLayout->addWidget(m_note, row, 1, 1, 2); 0195 topLayout->setRowStretch(row, 1); 0196 whats = i18n("You can add notes about the loan."); 0197 l->setWhatsThis(whats); 0198 m_note->setWhatsThis(whats); 0199 0200 m_addEvent = new QCheckBox(i18n("&Add a reminder to the active calendar"), mainWidget); 0201 mainLayout->addWidget(m_addEvent); 0202 topLayout->addWidget(m_addEvent, ++row, 0, 1, 3); 0203 m_addEvent->setEnabled(false); // gets enabled when valid due date is entered 0204 m_addEvent->setWhatsThis(i18n("<qt>Checking this box will add a <em>To-do</em> item " 0205 "to your active calendar, which can be viewed using KOrganizer. " 0206 "The box is only active if you set a due date.</qt>")); 0207 0208 #ifdef HAVE_KABC 0209 // Search for all existing contacts 0210 Akonadi::ContactSearchJob* job = new Akonadi::ContactSearchJob(); 0211 connect(job, SIGNAL(result(KJob*)), this, SLOT(akonadiSearchResult(KJob*))); 0212 #endif 0213 populateBorrowerList(); 0214 0215 m_buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel); 0216 QPushButton* okButton = m_buttonBox->button(QDialogButtonBox::Ok); 0217 okButton->setDefault(true); 0218 okButton->setShortcut(Qt::CTRL | Qt::Key_Return); 0219 okButton->setEnabled(false); // disable until a name is entered 0220 connect(m_buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept); 0221 connect(m_buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); 0222 0223 mainLayout->addWidget(m_buttonBox); 0224 0225 QTimer::singleShot(0, this, &LoanDialog::slotUpdateSize); 0226 } 0227 0228 LoanDialog::~LoanDialog() { 0229 KConfigGroup config(KSharedConfig::openConfig(), QStringLiteral("Loan Dialog Options")); 0230 KWindowConfig::saveWindowSize(windowHandle(), config); 0231 } 0232 0233 void LoanDialog::slotBorrowerNameChanged(const QString& str_) { 0234 m_buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!str_.isEmpty()); 0235 } 0236 0237 void LoanDialog::slotDueDateChanged() { 0238 #ifdef HAVE_KCAL 0239 m_addEvent->setEnabled(m_dueDate->date().isValid()); 0240 #endif 0241 } 0242 0243 void LoanDialog::slotGetBorrower() { 0244 Data::BorrowerPtr borrower = BorrowerDialog::getBorrower(this); 0245 if(borrower) { 0246 m_borrowerEdit->setText(borrower->name()); 0247 m_uid = borrower->uid(); 0248 } 0249 } 0250 0251 void LoanDialog::akonadiSearchResult(KJob* job_) { 0252 if(job_->error() != 0) { 0253 myDebug() << job_->errorString(); 0254 return; 0255 } 0256 0257 #ifdef HAVE_KABC 0258 Akonadi::ContactSearchJob* searchJob = qobject_cast<Akonadi::ContactSearchJob*>(job_); 0259 Q_ASSERT(searchJob); 0260 0261 populateBorrowerList(); 0262 0263 foreach(const KContacts::Addressee& addressee, searchJob->contacts()) { 0264 // skip people with no name 0265 const QString name = addressee.realName().trimmed(); 0266 if(name.isEmpty()) { 0267 continue; 0268 } 0269 m_borrowerEdit->completionObject()->addItem(name); 0270 } 0271 #endif 0272 } 0273 0274 void LoanDialog::populateBorrowerList() { 0275 m_borrowerEdit->completionObject()->clear(); 0276 0277 // add current borrowers 0278 Data::BorrowerList borrowers = m_entries.at(0)->collection()->borrowers(); 0279 foreach(Data::BorrowerPtr borrower, borrowers) { 0280 m_borrowerEdit->completionObject()->addItem(borrower->name()); 0281 } 0282 } 0283 0284 QUndoCommand* LoanDialog::createCommand() { 0285 // first, check to see if the borrower is empty 0286 QString name = m_borrowerEdit->text(); 0287 if(name.isEmpty()) { 0288 return nullptr; 0289 } 0290 0291 // ok, first handle creating new loans 0292 if(m_mode == Add) { 0293 return addLoansCommand(); 0294 } else { 0295 return modifyLoansCommand(); 0296 } 0297 } 0298 0299 QUndoCommand* LoanDialog::addLoansCommand() { 0300 if(m_entries.isEmpty()) { 0301 return nullptr; 0302 } 0303 0304 const QString name = m_borrowerEdit->text(); 0305 0306 // see if there's a borrower with this name already 0307 m_borrower = nullptr; 0308 Data::BorrowerList borrowers = m_entries.at(0)->collection()->borrowers(); 0309 foreach(Data::BorrowerPtr borrower, borrowers) { 0310 if(borrower->name() == name) { 0311 m_borrower = borrower; 0312 break; 0313 } 0314 } 0315 0316 if(!m_borrower) { 0317 if(m_uid.isEmpty()) { 0318 m_uid = Tellico::uid(); 0319 } 0320 m_borrower = new Data::Borrower(name, m_uid); 0321 } 0322 0323 Data::LoanList loans; 0324 foreach(Data::EntryPtr entry, m_entries) { 0325 loans.append(Data::LoanPtr(new Data::Loan(entry, m_loanDate->date(), m_dueDate->date(), m_note->toPlainText()))); 0326 } 0327 0328 return new Command::AddLoans(m_borrower, loans, m_addEvent->isChecked()); 0329 } 0330 0331 QUndoCommand* LoanDialog::modifyLoansCommand() { 0332 if(!m_loan) { 0333 return nullptr; 0334 } 0335 0336 Data::LoanPtr newLoan(new Data::Loan(*m_loan)); 0337 newLoan->setDueDate(m_dueDate->date()); 0338 newLoan->setNote(m_note->toPlainText()); 0339 return new Command::ModifyLoans(m_loan, newLoan, m_addEvent->isChecked()); 0340 } 0341 0342 void LoanDialog::slotUpdateSize() { 0343 KConfigGroup config(KSharedConfig::openConfig(), QLatin1String(dialogOptionsString)); 0344 KWindowConfig::restoreWindowSize(windowHandle(), config); 0345 }