diff --git a/CMakeLists.txt b/CMakeLists.txt --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,6 +9,7 @@ find_package(ECM ${KF5_MIN_VERSION} CONFIG REQUIRED) set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH}) +set(CMAKE_CXX_STANDARD 14) include(KDEInstallDirs) include(KDECMakeSettings) diff --git a/src/contact-editor/CMakeLists.txt b/src/contact-editor/CMakeLists.txt --- a/src/contact-editor/CMakeLists.txt +++ b/src/contact-editor/CMakeLists.txt @@ -30,9 +30,6 @@ -set(contacteditor_abstractaddresslocation_SRCS - editor/addresseditor/abstractaddresslocationwidget.cpp) - set(contacteditor_customfieldseditor_SRCS editor/customfieldeditor/customfieldswidget.cpp editor/customfieldeditor/customfieldeditorwidget.cpp @@ -91,11 +88,15 @@ ${contacteditor_editor_generalinfo_phone_SRCS} ${contacteditor_editor_generalinfo_web_SRCS} ${contacteditor_editor_generalinfo_mail_SRCS} - ${contacteditor_abstractaddresslocation_SRCS} ) set(contacteditor_addresslocation_editor_SRCS + editor/addresseditor/addressdelegate.cpp + editor/addresseditor/addressmodel.cpp editor/addresseditor/addresseslocationwidget.cpp + editor/addresseditor/addresslocationwidget.cpp + editor/addresseditor/addresstypedialog.cpp + editor/addresseditor/selectaddresstypecombobox.cpp ) set(contacteditor_personal_editor_SRCS @@ -203,32 +204,23 @@ RELATIVE editor/widgets/ ) -ecm_generate_headers(ContactEditorAddressLocationWidget_CamelCase_HEADERS - HEADER_NAMES - AbstractAddressLocationWidget - REQUIRED_HEADERS ContactEditorAddressLocationWidget_HEADERS - PREFIX ContactEditor - RELATIVE editor/addresseditor/ - ) - install( FILES ${ContactEditor_CamelCase_HEADERS} ${ContactEditorWidget_CamelCase_HEADERS} - ${ContactEditorAddressLocationWidget_CamelCase_HEADERS} DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF5}/ContactEditor COMPONENT Devel ) install( FILES ${ContactEditor_HEADERS} ${ContactEditorWidget_HEADERS} - ${ContactEditorAddressLocationWidget_HEADERS} ${CMAKE_CURRENT_BINARY_DIR}/contacteditor_export.h DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF5}/contacteditor COMPONENT Devel ) if (BUILD_TESTING) + add_subdirectory(editor/addresseditor/autotests/) add_subdirectory(editor/generalinfoeditor/autotests/) add_subdirectory(editor/generalinfoeditor/tests) add_subdirectory(editor/customfieldeditor/autotests/) diff --git a/src/contact-editor/editor/addresseditor/abstractaddresslocationwidget.h b/src/contact-editor/editor/addresseditor/addressdelegate.h rename from src/contact-editor/editor/addresseditor/abstractaddresslocationwidget.h rename to src/contact-editor/editor/addresseditor/addressdelegate.h --- a/src/contact-editor/editor/addresseditor/abstractaddresslocationwidget.h +++ b/src/contact-editor/editor/addresseditor/addressdelegate.h @@ -1,7 +1,7 @@ /* This file is part of Contact Editor. - Copyright (C) 2017-2019 Laurent Montel + Copyright (C) 2019 Volker Krause This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by @@ -19,26 +19,23 @@ 02110-1301, USA. */ -#ifndef ABSTRACTADDRESSLOCATIONWIDGET_H -#define ABSTRACTADDRESSLOCATIONWIDGET_H +#ifndef CONTACTEDITOR_ADDRESSDELEGATE_H +#define CONTACTEDITOR_ADDRESSDELEGATE_H -#include - -#include -#include "contacteditor_export.h" +#include namespace ContactEditor { -class CONTACTEDITOR_EXPORT AbstractAddressLocationWidget : public QWidget + +class AddressDelegate : public QStyledItemDelegate { Q_OBJECT public: - explicit AbstractAddressLocationWidget(QWidget *parent = nullptr); - ~AbstractAddressLocationWidget(); - - virtual void loadContact(const KContacts::Addressee &contact); - virtual void storeContact(KContacts::Addressee &contact) const; + explicit AddressDelegate(QObject *parent = nullptr); - virtual void setReadOnly(bool readOnly); + QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const override; + void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override; }; + } -#endif // ABSTRACTADDRESSLOCATIONWIDGET_H + +#endif // CONTACTEDITOR_ADDRESSDELEGATE_H diff --git a/src/contact-editor/editor/addresseditor/addressdelegate.cpp b/src/contact-editor/editor/addresseditor/addressdelegate.cpp new file mode 100644 --- /dev/null +++ b/src/contact-editor/editor/addresseditor/addressdelegate.cpp @@ -0,0 +1,66 @@ +/* + This file is part of Contact Editor. + + Copyright (C) 2019 Volker Krause + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by + the Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + This library is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public + License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. +*/ + +#include "addressdelegate.h" + +#include +#include +#include + +using namespace ContactEditor; + +AddressDelegate::AddressDelegate(QObject *parent) + : QStyledItemDelegate(parent) +{ +} + +QSize AddressDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const +{ + QStyleOptionViewItem options = option; + initStyleOption(&options, index); + + QTextDocument doc; + doc.setHtml(options.text); + doc.setTextWidth(options.rect.width()); + return QSize(doc.idealWidth(), doc.size().height()); +} + +void AddressDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const +{ + QStyleOptionViewItem options = option; + initStyleOption(&options, index); + + painter->save(); + QTextDocument doc; + doc.setHtml(options.text); + options.text = QString(); + options.widget->style()->drawControl(QStyle::CE_ItemViewItem, &options, painter); + painter->translate(options.rect.left(), options.rect.top()); + + const QRect clip(0, 0, options.rect.width(), options.rect.height()); + QAbstractTextDocumentLayout::PaintContext ctx; + ctx.clip = clip; + if (option.state & QStyle::State_Selected) { + ctx.palette.setColor(QPalette::Text, options.palette.color(QPalette::HighlightedText)); + } + doc.documentLayout()->draw(painter, ctx); + painter->restore(); +} diff --git a/src/contact-editor/editor/addresseditor/addresseslocationwidget.h b/src/contact-editor/editor/addresseditor/addresseslocationwidget.h --- a/src/contact-editor/editor/addresseditor/addresseslocationwidget.h +++ b/src/contact-editor/editor/addresseditor/addresseslocationwidget.h @@ -22,11 +22,16 @@ #ifndef ADDRESSESLOCATIONWIDGET_H #define ADDRESSESLOCATIONWIDGET_H -#include +#include #include + +class QTreeView; + namespace ContactEditor { -class AbstractAddressLocationWidget; -class AddressesLocationWidget : public QWidget +class AddressModel; +class AddressLocationWidget; + +class AddressesLocationWidget : public QSplitter { Q_OBJECT public: @@ -38,7 +43,10 @@ void setReadOnly(bool readOnly); private: - AbstractAddressLocationWidget *mAbstractAddressLocationWidget = nullptr; + AddressLocationWidget *mAddressLocationWidget = nullptr; + QTreeView *mAddressesLocationView = nullptr; + AddressModel *mAddressModel = nullptr; + bool mReadOnly = false; }; } #endif // ADDRESSESLOCATIONWIDGET_H diff --git a/src/contact-editor/editor/addresseditor/addresseslocationwidget.cpp b/src/contact-editor/editor/addresseditor/addresseslocationwidget.cpp --- a/src/contact-editor/editor/addresseditor/addresseslocationwidget.cpp +++ b/src/contact-editor/editor/addresseditor/addresseslocationwidget.cpp @@ -21,58 +21,101 @@ */ #include "addresseslocationwidget.h" -#include "abstractaddresslocationwidget.h" +#include "addresslocationwidget.h" +#include "addressdelegate.h" +#include "addressmodel.h" #include "contacteditor_debug.h" -#include -#include + #include +#include #include #include +#include +#include + using namespace ContactEditor; AddressesLocationWidget::AddressesLocationWidget(QWidget *parent) - : QWidget(parent) + : QSplitter(parent) + , mAddressModel(new AddressModel(this)) { - QHBoxLayout *mainLayout = new QHBoxLayout(this); - mainLayout->setContentsMargins(0, 0, 0, 0); - - KPluginLoader loader(QStringLiteral("contacteditor/addresslocationeditorplugin")); - KPluginFactory *factory = loader.factory(); - if (factory) { - mAbstractAddressLocationWidget = factory->create(); - mainLayout->addWidget(mAbstractAddressLocationWidget); - } else { - qCWarning(CONTACTEDITOR_LOG) << " error during loading contacteditor plugin : " << loader.errorString(); - QLabel *lab = new QLabel(i18n("Missing plugins. Please verify your installation"), this); - QFont font = lab->font(); - font.setBold(true); - lab->setFont(font); - lab->setAlignment(Qt::AlignCenter); - mainLayout->addWidget(lab); - } -} + mAddressLocationWidget = new AddressLocationWidget(this); + mAddressLocationWidget->setObjectName(QStringLiteral("addresslocationwidget")); + addWidget(mAddressLocationWidget); -AddressesLocationWidget::~AddressesLocationWidget() -{ + mAddressesLocationView = new QTreeView(this); + mAddressesLocationView->setRootIsDecorated(false); + mAddressesLocationView->setHeaderHidden(true); + mAddressesLocationView->setModel(mAddressModel); + mAddressesLocationView->setItemDelegate(new AddressDelegate); + mAddressesLocationView->setContextMenuPolicy(Qt::CustomContextMenu); + mAddressesLocationView->setObjectName(QStringLiteral("addresseslocationviewer")); + addWidget(mAddressesLocationView); + + connect(mAddressesLocationView->selectionModel(), &QItemSelectionModel::selectionChanged, this, [this](const QItemSelection &selection) { + mAddressLocationWidget->clear(); + if (selection.size() != 1) { + return; + } + const auto idx = selection.at(0).topLeft(); + if (!idx.isValid()) { + return; + } + mAddressLocationWidget->slotModifyAddress(idx.data(Qt::UserRole).value(), idx.row()); + }); + connect(mAddressLocationWidget, &AddressLocationWidget::addNewAddress, mAddressModel, &AddressModel::addAddress); + connect(mAddressLocationWidget, &AddressLocationWidget::updateAddressCanceled, mAddressesLocationView->selectionModel(), &QItemSelectionModel::clearSelection); + connect(mAddressLocationWidget, &AddressLocationWidget::updateAddress, mAddressModel, &AddressModel::replaceAddress); + connect(mAddressesLocationView, &QWidget::customContextMenuRequested, this, [this](QPoint pos) { + const auto idx = mAddressesLocationView->indexAt(pos); + if (!idx.isValid()) { + return; + } + QMenu menu; + auto action = menu.addAction(QIcon::fromTheme(QStringLiteral("edit-delete")), i18n("Remove Address")); + action->setEnabled(!mReadOnly); + connect(action, &QAction::triggered, this, [this, idx]() { + const auto result = KMessageBox::questionYesNo(this, i18n("Do you really want to delete this address?")); + if (result == KMessageBox::Yes) { + mAddressModel->removeAddress(idx.row()); + } + }); + menu.exec(mAddressesLocationView->viewport()->mapToGlobal(pos)); + }); + + setChildrenCollapsible(false); + setSizes(QList() << 400 << 300); } +AddressesLocationWidget::~AddressesLocationWidget() = default; + void AddressesLocationWidget::loadContact(const KContacts::Addressee &contact) { - if (mAbstractAddressLocationWidget) { - mAbstractAddressLocationWidget->loadContact(contact); - } + mAddressModel->setAddresses(contact.addresses()); } void AddressesLocationWidget::storeContact(KContacts::Addressee &contact) const { - if (mAbstractAddressLocationWidget) { - mAbstractAddressLocationWidget->storeContact(contact); + // delete all previous addresses + const KContacts::Address::List oldAddresses = contact.addresses(); + const int numberOfOldAddresses(oldAddresses.count()); + for (int i = 0; i < numberOfOldAddresses; ++i) { + contact.removeAddress(oldAddresses.at(i)); + } + + const KContacts::Address::List addressList = mAddressModel->addresses(); + // insert the new ones + const int numberOfAddress(addressList.count()); + for (int i = 0; i < numberOfAddress; ++i) { + const KContacts::Address address(addressList.at(i)); + if (!address.isEmpty()) { + contact.insertAddress(address); + } } } void AddressesLocationWidget::setReadOnly(bool readOnly) { - if (mAbstractAddressLocationWidget) { - mAbstractAddressLocationWidget->setReadOnly(readOnly); - } + mReadOnly = readOnly; + mAddressLocationWidget->setReadOnly(readOnly); } diff --git a/src/contact-editor/editor/addresseditor/addresslocationwidget.h b/src/contact-editor/editor/addresseditor/addresslocationwidget.h new file mode 100644 --- /dev/null +++ b/src/contact-editor/editor/addresseditor/addresslocationwidget.h @@ -0,0 +1,91 @@ +/* + This file is part of Contact Editor. + + Copyright (C) 2016 eyeOS S.L.U., a Telefonica company, sales@eyeos.com + Copyright (C) 2016-2019 Laurent Montel + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by + the Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + This library is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public + License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. +*/ + +#ifndef ADDRESSLOCATIONWIDGET_H +#define ADDRESSLOCATIONWIDGET_H + +#include +#include + +class QStackedWidget; +class QCheckBox; +class KLineEdit; +class KComboBox; +class QPushButton; + +namespace ContactEditor { + +class SelectAddressTypeComboBox; + +class AddressLocationWidget : public QWidget +{ + Q_OBJECT +public: + enum Mode { + CreateAddress = 0, + ModifyAddress + }; + + explicit AddressLocationWidget(QWidget *parent = nullptr); + ~AddressLocationWidget(); + + void setAddress(const KContacts::Address &address); + KContacts::Address address() const; + + void slotModifyAddress(const KContacts::Address &address, int currentIndex); + + void clear(); + + void setReadOnly(bool readOnly); + +Q_SIGNALS: + void addNewAddress(const KContacts::Address &address); + void updateAddress(const KContacts::Address &address, int index); + void updateAddressCanceled(); + +private: + void slotAddAddress(); + void slotUpdateAddress(); + void slotCancelModifyAddress(); + void fillCountryCombo(); + void switchMode(); + void reset(); + KContacts::Address mAddress; + QCheckBox *mPreferredCheckBox = nullptr; + KLineEdit *mPOBoxEdit = nullptr; + KLineEdit *mLocalityEdit = nullptr; + KLineEdit *mRegionEdit = nullptr; + KLineEdit *mPostalCodeEdit = nullptr; + KLineEdit *mStreetEdit = nullptr; + KComboBox *mCountryCombo = nullptr; + QPushButton *mAddAddress = nullptr; + QPushButton *mModifyAddress = nullptr; + QPushButton *mCancelAddress = nullptr; + QStackedWidget *mButtonStack = nullptr; + SelectAddressTypeComboBox *mTypeCombo = nullptr; + int mCurrentAddress; + Mode mCurrentMode; +}; + +} + +#endif // ADDRESSLOCATIONWIDGET_H diff --git a/src/contact-editor/editor/addresseditor/addresslocationwidget.cpp b/src/contact-editor/editor/addresseditor/addresslocationwidget.cpp new file mode 100644 --- /dev/null +++ b/src/contact-editor/editor/addresseditor/addresslocationwidget.cpp @@ -0,0 +1,296 @@ +/* + This file is part of Contact Editor. + + Copyright (C) 2016 eyeOS S.L.U., a Telefonica company, sales@eyeos.com + Copyright (C) 2016-2019 Laurent Montel + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by + the Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + This library is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public + License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. +*/ + +#include "addresslocationwidget.h" +#include "selectaddresstypecombobox.h" + +#include +#include +#include + +#include +#include +#include +#include +#include + +using namespace ContactEditor; + +struct LocaleAwareLessThan : std::binary_function { + bool operator()(const QString &s1, const QString &s2) const + { + return QString::localeAwareCompare(s1, s2) < 0; + } +}; + +AddressLocationWidget::AddressLocationWidget(QWidget *parent) + : QWidget(parent) + , mCurrentAddress(-1) + , mCurrentMode(CreateAddress) +{ + QVBoxLayout *topLayout = new QVBoxLayout(this); + + QGridLayout *gridLayout = new QGridLayout; + topLayout->addLayout(gridLayout); + + mTypeCombo = new SelectAddressTypeComboBox(this); + mTypeCombo->setObjectName(QStringLiteral("typeaddress")); + gridLayout->addWidget(mTypeCombo, 0, 0, 1, 2); + + QLabel *label = new QLabel(KContacts::Address::streetLabel(), this); + label->setObjectName(QStringLiteral("streetlabel")); + gridLayout->addWidget(label, 1, 0); + + mStreetEdit = new KLineEdit(this); + mStreetEdit->setPlaceholderText(i18n("Add Street")); + mStreetEdit->setObjectName(QStringLiteral("streetlineedit")); + mStreetEdit->setTrapReturnKey(true); + gridLayout->addWidget(mStreetEdit, 2, 0); + + label = new QLabel(KContacts::Address::postOfficeBoxLabel(), this); + label->setObjectName(QStringLiteral("postofficeboxlabel")); + gridLayout->addWidget(label, 1, 1); + + mPOBoxEdit = new KLineEdit(this); + mPOBoxEdit->setPlaceholderText(i18n("Add Post Office Box")); + mPOBoxEdit->setObjectName(QStringLiteral("postofficeboxlineedit")); + mPOBoxEdit->setTrapReturnKey(true); + gridLayout->addWidget(mPOBoxEdit, 2, 1); + + label = new QLabel(KContacts::Address::postalCodeLabel(), this); + label->setObjectName(QStringLiteral("postalcodelabel")); + gridLayout->addWidget(label, 3, 0); + mPostalCodeEdit = new KLineEdit(this); + mPostalCodeEdit->setPlaceholderText(i18n("Add Postal Code")); + mPostalCodeEdit->setObjectName(QStringLiteral("postalcodelineedit")); + mPostalCodeEdit->setTrapReturnKey(true); + gridLayout->addWidget(mPostalCodeEdit, 4, 0); + + label = new QLabel(KContacts::Address::localityLabel(), this); + label->setObjectName(QStringLiteral("localitylabel")); + gridLayout->addWidget(label, 3, 1); + mLocalityEdit = new KLineEdit(this); + mLocalityEdit->setPlaceholderText(i18n("Add Locality")); + mLocalityEdit->setObjectName(QStringLiteral("localitylineedit")); + mLocalityEdit->setTrapReturnKey(true); + gridLayout->addWidget(mLocalityEdit, 4, 1); + + label = new QLabel(KContacts::Address::regionLabel(), this); + label->setObjectName(QStringLiteral("regionlabel")); + gridLayout->addWidget(label, 5, 0); + mRegionEdit = new KLineEdit(this); + mRegionEdit->setPlaceholderText(i18n("Add Region")); + mRegionEdit->setObjectName(QStringLiteral("regionlineedit")); + mRegionEdit->setTrapReturnKey(true); + gridLayout->addWidget(mRegionEdit, 6, 0); + + label = new QLabel(KContacts::Address::countryLabel(), this); + label->setObjectName(QStringLiteral("countrylabel")); + gridLayout->addWidget(label, 5, 1); + mCountryCombo = new KComboBox(this); + KLineEdit *edit = new KLineEdit(this); + edit->setTrapReturnKey(true); + mCountryCombo->setLineEdit(edit); + mCountryCombo->setObjectName(QStringLiteral("countrycombobox")); + mCountryCombo->setEditable(true); + mCountryCombo->lineEdit()->setPlaceholderText(i18n("Add a Country")); + mCountryCombo->setDuplicatesEnabled(false); + gridLayout->addWidget(mCountryCombo, 6, 1); + + mPreferredCheckBox = new QCheckBox(i18nc("street/postal", "This is the preferred address"), this); + mPreferredCheckBox->setObjectName(QStringLiteral("preferredcheckbox")); + gridLayout->addWidget(mPreferredCheckBox, 7, 0, 1, 2); + + mButtonStack = new QStackedWidget(this); + mButtonStack->setObjectName(QStringLiteral("buttonstacked")); + topLayout->addWidget(mButtonStack); + + QWidget *addButtonWidget = new QWidget(this); + QHBoxLayout *addButtonWidgetLayout = new QHBoxLayout(addButtonWidget); + addButtonWidgetLayout->setContentsMargins(0, 0, 0, 0); + mAddAddress = new QPushButton(i18n("Add Address"), this); + mAddAddress->setObjectName(QStringLiteral("addbuttonaddress")); + connect(mAddAddress, &QPushButton::clicked, this, &AddressLocationWidget::slotAddAddress); + addButtonWidgetLayout->addWidget(mAddAddress); + addButtonWidgetLayout->addStretch(1); + mButtonStack->addWidget(addButtonWidget); + + QWidget *modifyButtonWidget = new QWidget(this); + QHBoxLayout *modifyButtonWidgetLayout = new QHBoxLayout(modifyButtonWidget); + modifyButtonWidgetLayout->setContentsMargins(0, 0, 0, 0); + mButtonStack->addWidget(modifyButtonWidget); + + mModifyAddress = new QPushButton(i18n("Update Address"), this); + mModifyAddress->setObjectName(QStringLiteral("modifybuttonaddress")); + modifyButtonWidgetLayout->addWidget(mModifyAddress); + connect(mModifyAddress, &QPushButton::clicked, this, &AddressLocationWidget::slotUpdateAddress); + + mCancelAddress = new QPushButton(i18n("Cancel"), this); + mCancelAddress->setObjectName(QStringLiteral("cancelbuttonaddress")); + connect(mCancelAddress, &QPushButton::clicked, this, &AddressLocationWidget::slotCancelModifyAddress); + modifyButtonWidgetLayout->addWidget(mCancelAddress); + modifyButtonWidgetLayout->addStretch(1); + const int buttonWidth = qMax(mCancelAddress->width(), mModifyAddress->width()); + mModifyAddress->setMinimumWidth(buttonWidth); + mCancelAddress->setMinimumWidth(buttonWidth); + + topLayout->addStretch(1); + fillCountryCombo(); + switchMode(); +} + +AddressLocationWidget::~AddressLocationWidget() +{ +} + +void AddressLocationWidget::setReadOnly(bool readOnly) +{ + mPreferredCheckBox->setEnabled(!readOnly); + mPOBoxEdit->setReadOnly(readOnly); + mLocalityEdit->setReadOnly(readOnly); + mRegionEdit->setReadOnly(readOnly); + mPostalCodeEdit->setReadOnly(readOnly); + mStreetEdit->setReadOnly(readOnly); + mCountryCombo->setEnabled(!readOnly); + mTypeCombo->setEnabled(!readOnly); + + mAddAddress->setEnabled(!readOnly); + mModifyAddress->setEnabled(!readOnly); + mCancelAddress->setEnabled(!readOnly); +} + +void AddressLocationWidget::fillCountryCombo() +{ + QStringList countries; + const QList localeList = QLocale::matchingLocales(QLocale::AnyLanguage, QLocale::AnyScript, QLocale::AnyCountry); + countries.reserve(localeList.count()); + for (const QLocale &locale : localeList) { + const QString localeStr = QLocale::countryToString(locale.country()); + if (countries.contains(localeStr)) { + continue; + } + countries.append(localeStr); + } + + std::sort(countries.begin(), countries.end(), LocaleAwareLessThan()); + + mCountryCombo->addItems(countries); + mCountryCombo->setAutoCompletion(true); + mCountryCombo->completionObject()->setItems(countries); + mCountryCombo->completionObject()->setIgnoreCase(true); + + const QString currentCountry = QLocale::countryToString(QLocale().country()); + mCountryCombo->setCurrentIndex(mCountryCombo->findText(currentCountry)); +} + +void AddressLocationWidget::slotAddAddress() +{ + KContacts::Address addr = address(); + if (!addr.isEmpty()) { + Q_EMIT addNewAddress(addr); + reset(); + } +} + +void AddressLocationWidget::setAddress(const KContacts::Address &address) +{ + mAddress = address; + mTypeCombo->setType(mAddress.type()); + mStreetEdit->setText(mAddress.street()); + mRegionEdit->setText(address.region()); + mLocalityEdit->setText(address.locality()); + mPostalCodeEdit->setText(address.postalCode()); + mPOBoxEdit->setText(address.postOfficeBox()); + mPreferredCheckBox->setChecked(address.type() &KContacts::Address::Pref); + if (address.isEmpty()) { + mCountryCombo->setItemText(mCountryCombo->currentIndex(), + QLocale::countryToString(QLocale().country())); + } else { + mCountryCombo->setItemText(mCountryCombo->currentIndex(), mAddress.country()); + } +} + +KContacts::Address AddressLocationWidget::address() const +{ + KContacts::Address address(mAddress); + + address.setType(mTypeCombo->type()); + address.setLocality(mLocalityEdit->text()); + address.setRegion(mRegionEdit->text()); + address.setPostalCode(mPostalCodeEdit->text()); + address.setCountry(mCountryCombo->currentText()); + address.setPostOfficeBox(mPOBoxEdit->text()); + address.setStreet(mStreetEdit->text()); + if (mPreferredCheckBox->isChecked()) { + address.setType(address.type() | KContacts::Address::Pref); + } else { + address.setType(address.type() & ~(KContacts::Address::Pref)); + } + return address; +} + +void AddressLocationWidget::switchMode() +{ + switch (mCurrentMode) { + case CreateAddress: + mButtonStack->setCurrentIndex(0); + break; + case ModifyAddress: + mButtonStack->setCurrentIndex(1); + break; + } +} + +void AddressLocationWidget::slotModifyAddress(const KContacts::Address &address, int currentIndex) +{ + setAddress(address); + mCurrentMode = ModifyAddress; + mCurrentAddress = currentIndex; + switchMode(); +} + +void AddressLocationWidget::clear() +{ + mCurrentMode = CreateAddress; + setAddress(KContacts::Address()); + switchMode(); +} + +void AddressLocationWidget::slotUpdateAddress() +{ + if (mCurrentMode == ModifyAddress) { + Q_EMIT updateAddress(address(), mCurrentAddress); + reset(); + } +} + +void AddressLocationWidget::reset() +{ + Q_EMIT updateAddressCanceled(); + mCurrentAddress = -1; + clear(); +} + +void AddressLocationWidget::slotCancelModifyAddress() +{ + reset(); +} diff --git a/src/contact-editor/editor/addresseditor/addresseslocationwidget.h b/src/contact-editor/editor/addresseditor/addressmodel.h copy from src/contact-editor/editor/addresseditor/addresseslocationwidget.h copy to src/contact-editor/editor/addresseditor/addressmodel.h --- a/src/contact-editor/editor/addresseditor/addresseslocationwidget.h +++ b/src/contact-editor/editor/addresseditor/addressmodel.h @@ -1,8 +1,7 @@ /* This file is part of Contact Editor. - Copyright (C) 2016 eyeOS S.L.U., a Telefonica company, sales@eyeos.com - Copyright (C) 2016-2019 Laurent Montel + Copyright (C) 2019 Volker Krause This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by @@ -20,25 +19,35 @@ 02110-1301, USA. */ -#ifndef ADDRESSESLOCATIONWIDGET_H -#define ADDRESSESLOCATIONWIDGET_H -#include -#include +#ifndef CONTACTEDITOR_ADDRESSMODEL_H +#define CONTACTEDITOR_ADDRESSMODEL_H + +#include + +#include + namespace ContactEditor { -class AbstractAddressLocationWidget; -class AddressesLocationWidget : public QWidget + +class AddressModel : public QAbstractListModel { Q_OBJECT public: - explicit AddressesLocationWidget(QWidget *parent = nullptr); - ~AddressesLocationWidget(); + explicit AddressModel(QObject *parent = nullptr); + ~AddressModel(); - void loadContact(const KContacts::Addressee &contact); - void storeContact(KContacts::Addressee &contact) const; + KContacts::Address::List addresses() const; + void setAddresses(const KContacts::Address::List &addresses); + void addAddress(const KContacts::Address &address); + void replaceAddress(const KContacts::Address &address, int row); + void removeAddress(int row); + + int rowCount(const QModelIndex& parent) const override; + QVariant data(const QModelIndex& index, int role) const override; - void setReadOnly(bool readOnly); private: - AbstractAddressLocationWidget *mAbstractAddressLocationWidget = nullptr; + KContacts::Address::List mAddresses; }; + } -#endif // ADDRESSESLOCATIONWIDGET_H + +#endif // CONTACTEDITOR_ADDRESSMODEL_H diff --git a/src/contact-editor/editor/addresseditor/addressmodel.cpp b/src/contact-editor/editor/addresseditor/addressmodel.cpp new file mode 100644 --- /dev/null +++ b/src/contact-editor/editor/addresseditor/addressmodel.cpp @@ -0,0 +1,106 @@ +/* + This file is part of Contact Editor. + + Copyright (C) 2019 Volker Krause + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by + the Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + This library is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public + License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. +*/ + +#include "addressmodel.h" + +using namespace ContactEditor; + +AddressModel::AddressModel(QObject *parent) + : QAbstractListModel(parent) +{ +} + +AddressModel::~AddressModel() = default; + +KContacts::Address::List AddressModel::addresses() const +{ + return mAddresses; +} + +void AddressModel::setAddresses(const KContacts::Address::List &addresses) +{ + beginResetModel(); + mAddresses = addresses; + endResetModel(); +} + +void AddressModel::addAddress(const KContacts::Address &address) +{ + if (!address.isEmpty()) { + beginInsertRows({}, mAddresses.size(), mAddresses.size()); + mAddresses.push_back(address); + endInsertRows(); + } +} + +void AddressModel::replaceAddress(const KContacts::Address &address, int row) +{ + if (row < 0 || row >= mAddresses.size()) { + return; + } + + mAddresses[row] = address; + emit dataChanged(index(row, 0), index(row, 0)); +} + +void AddressModel::removeAddress(int row) +{ + if (row < 0 || row >= mAddresses.size()) { + return; + } + + beginRemoveRows({}, row, row); + mAddresses.remove(row); + endRemoveRows(); +} + +int AddressModel::rowCount(const QModelIndex &parent) const +{ + if (parent.isValid()) { + return 0; + } + return mAddresses.size(); +} + +QVariant AddressModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) { + return {}; + } + + switch (role) { + case Qt::DisplayRole: + { + const auto addr = mAddresses.at(index.row()); + QString str = QLatin1String("") + KContacts::Address::typeLabel(addr.type()) + QLatin1String("
"); + if (!addr.label().isEmpty()) { + str += addr.label().toHtmlEscaped().replace(QLatin1Char('\n'), QLatin1String("
")); + } else { + str += addr.formattedAddress().trimmed().toHtmlEscaped().replace(QLatin1Char('\n'), QLatin1String("
")); + } + return str; + } + case Qt::UserRole: + return QVariant::fromValue(mAddresses.at(index.row())); + } + + return {}; +} diff --git a/src/contact-editor/editor/addresseditor/abstractaddresslocationwidget.h b/src/contact-editor/editor/addresseditor/addresstypedialog.h rename from src/contact-editor/editor/addresseditor/abstractaddresslocationwidget.h rename to src/contact-editor/editor/addresseditor/addresstypedialog.h --- a/src/contact-editor/editor/addresseditor/abstractaddresslocationwidget.h +++ b/src/contact-editor/editor/addresseditor/addresstypedialog.h @@ -1,7 +1,7 @@ /* This file is part of Contact Editor. - Copyright (C) 2017-2019 Laurent Montel + Copyright (c) 2009 Tobias Koenig This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by @@ -19,26 +19,34 @@ 02110-1301, USA. */ -#ifndef ABSTRACTADDRESSLOCATIONWIDGET_H -#define ABSTRACTADDRESSLOCATIONWIDGET_H +#ifndef ADDRESSTYPEDIALOG_H +#define ADDRESSTYPEDIALOG_H -#include +#include +#include -#include -#include "contacteditor_export.h" +class QButtonGroup; namespace ContactEditor { -class CONTACTEDITOR_EXPORT AbstractAddressLocationWidget : public QWidget +/** + * Dialog for creating a new address types. + * + * @note This dialog is only used by AddressTypeCombo. + */ +class AddressTypeDialog : public QDialog { Q_OBJECT public: - explicit AbstractAddressLocationWidget(QWidget *parent = nullptr); - ~AbstractAddressLocationWidget(); + AddressTypeDialog(KContacts::Address::Type type, QWidget *parent); + ~AddressTypeDialog(); - virtual void loadContact(const KContacts::Addressee &contact); - virtual void storeContact(KContacts::Addressee &contact) const; + KContacts::Address::Type type() const; - virtual void setReadOnly(bool readOnly); +private: + QButtonGroup *mGroup = nullptr; + + KContacts::Address::TypeList mTypeList; }; } -#endif // ABSTRACTADDRESSLOCATIONWIDGET_H + +#endif // ADDRESSTYPEDIALOG_H diff --git a/src/contact-editor/editor/addresseditor/addresstypedialog.cpp b/src/contact-editor/editor/addresseditor/addresstypedialog.cpp new file mode 100644 --- /dev/null +++ b/src/contact-editor/editor/addresseditor/addresstypedialog.cpp @@ -0,0 +1,94 @@ +/* + This file is part of Contact Editor. + + Copyright (c) 2009 Tobias Koenig + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by + the Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + This library is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public + License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. +*/ + +#include "addresstypedialog.h" +#include +#include +#include +#include +#include +#include +#include + +using namespace ContactEditor; + +AddressTypeDialog::AddressTypeDialog(KContacts::Address::Type type, QWidget *parent) + : QDialog(parent) +{ + QVBoxLayout *mainLayout = new QVBoxLayout(this); + setWindowTitle(i18nc("street/postal", "Edit Address Type")); + QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this); + QPushButton *okButton = buttonBox->button(QDialogButtonBox::Ok); + okButton->setDefault(true); + okButton->setShortcut(Qt::CTRL | Qt::Key_Return); + connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept); + connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); + + QWidget *page = new QWidget(this); + mainLayout->addWidget(page); + mainLayout->addWidget(buttonBox); + QVBoxLayout *layout = new QVBoxLayout(page); + layout->setContentsMargins(0, 0, 0, 0); + + QGroupBox *box = new QGroupBox(i18nc("street/postal", "Address Types"), page); + mainLayout->addWidget(box); + layout->addWidget(box); + mGroup = new QButtonGroup(box); + mGroup->setExclusive(false); + + QGridLayout *buttonLayout = new QGridLayout(box); + + mTypeList = KContacts::Address::typeList(); + mTypeList.removeAll(KContacts::Address::Pref); + + KContacts::Address::TypeList::ConstIterator it; + int i = 0; + int row = 0; + KContacts::Address::TypeList::ConstIterator end(mTypeList.constEnd()); + for (it = mTypeList.constBegin(); it != end; ++it, ++i) { + QCheckBox *cb = new QCheckBox(KContacts::Address::typeLabel(*it), box); + cb->setChecked(type & mTypeList[i]); + buttonLayout->addWidget(cb, row, i % 3); + + if (i % 3 == 2) { + ++row; + } + mGroup->addButton(cb); + } +} + +AddressTypeDialog::~AddressTypeDialog() +{ +} + +KContacts::Address::Type AddressTypeDialog::type() const +{ + KContacts::Address::Type type; + const int numberOfButtons(mGroup->buttons().count()); + for (int i = 0; i < numberOfButtons; ++i) { + QCheckBox *box = qobject_cast(mGroup->buttons().at(i)); + if (box && box->isChecked()) { + type |= mTypeList[i]; + } + } + + return type; +} diff --git a/src/contact-editor/editor/addresseditor/autotests/CMakeLists.txt b/src/contact-editor/editor/addresseditor/autotests/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/src/contact-editor/editor/addresseditor/autotests/CMakeLists.txt @@ -0,0 +1,10 @@ +include(ECMMarkAsTest) + +#ecm_qt_declare_logging_category(contacteditor_addresslocation_web_editor_SRCS HEADER addresslocationeditorplugin_debug.h IDENTIFIER +# ADDRESSLOCATIONEDITORPLUGIN_LOG CATEGORY_NAME org.kde.pim.addresslocationeditorplugin) + +set(addresslocationwidget_SRCS addresslocationwidgettest.cpp ../addresslocationwidget.cpp ../selectaddresstypecombobox.cpp ../addresstypedialog.cpp) +add_executable(addresslocationwidget ${addresslocationwidget_SRCS}) +add_test(NAME addresslocationwidget COMMAND addresslocationwidget) +ecm_mark_as_test(addresslocationwidget) +target_link_libraries(addresslocationwidget Qt5::Test Qt5::Widgets KF5::ContactEditor KF5::Contacts KF5::I18n KF5::Completion) diff --git a/src/contact-editor/editor/addresseditor/abstractaddresslocationwidget.cpp b/src/contact-editor/editor/addresseditor/autotests/addresslocationwidgettest.h rename from src/contact-editor/editor/addresseditor/abstractaddresslocationwidget.cpp rename to src/contact-editor/editor/addresseditor/autotests/addresslocationwidgettest.h --- a/src/contact-editor/editor/addresseditor/abstractaddresslocationwidget.cpp +++ b/src/contact-editor/editor/addresseditor/autotests/addresslocationwidgettest.h @@ -1,7 +1,8 @@ /* This file is part of Contact Editor. - Copyright (C) 2017-2019 Laurent Montel + Copyright (C) 2016 eyeOS S.L.U., a Telefonica company, sales@eyeos.com + Copyright (C) 2016-2019 Laurent Montel This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by @@ -19,29 +20,21 @@ 02110-1301, USA. */ -#include "abstractaddresslocationwidget.h" +#ifndef ADDRESSLOCATIONWIDGETTEST_H +#define ADDRESSLOCATIONWIDGETTEST_H -using namespace ContactEditor; -AbstractAddressLocationWidget::AbstractAddressLocationWidget(QWidget *parent) - : QWidget(parent) -{ -} +#include -AbstractAddressLocationWidget::~AbstractAddressLocationWidget() +class AddressLocationWidgetTest : public QObject { -} + Q_OBJECT +public: + explicit AddressLocationWidgetTest(QObject *parent = nullptr); + ~AddressLocationWidgetTest(); -void AbstractAddressLocationWidget::loadContact(const KContacts::Addressee &contact) -{ - Q_UNUSED(contact); -} +private Q_SLOTS: + void shouldHaveDefaultValue(); + void shouldChangeReadOnlyStatus(); +}; -void AbstractAddressLocationWidget::storeContact(KContacts::Addressee &contact) const -{ - Q_UNUSED(contact); -} - -void AbstractAddressLocationWidget::setReadOnly(bool readOnly) -{ - Q_UNUSED(readOnly); -} +#endif // ADDRESSLOCATIONWIDGETTEST_H diff --git a/src/contact-editor/editor/addresseditor/autotests/addresslocationwidgettest.cpp b/src/contact-editor/editor/addresseditor/autotests/addresslocationwidgettest.cpp new file mode 100644 --- /dev/null +++ b/src/contact-editor/editor/addresseditor/autotests/addresslocationwidgettest.cpp @@ -0,0 +1,123 @@ +/* + This file is part of Contact Editor. + + Copyright (C) 2016 eyeOS S.L.U., a Telefonica company, sales@eyeos.com + Copyright (C) 2016-2019 Laurent Montel + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by + the Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + This library is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public + License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. +*/ + +#include "addresslocationwidgettest.h" +#include "../addresslocationwidget.h" +#include +#include +#include +#include +#include +#include +#include "../selectaddresstypecombobox.h" + +using namespace ContactEditor; + +AddressLocationWidgetTest::AddressLocationWidgetTest(QObject *parent) + : QObject(parent) +{ +} + +AddressLocationWidgetTest::~AddressLocationWidgetTest() +{ +} + +void AddressLocationWidgetTest::shouldHaveDefaultValue() +{ + AddressLocationWidget w; + + SelectAddressTypeComboBox *typeAddress = w.findChild(QStringLiteral("typeaddress")); + QVERIFY(typeAddress); + + QLabel *streetlabel = w.findChild(QStringLiteral("streetlabel")); + QVERIFY(streetlabel); + KLineEdit *mStreetEdit = w.findChild(QStringLiteral("streetlineedit")); + QVERIFY(mStreetEdit); + + QLabel *postofficeboxlabel = w.findChild(QStringLiteral("postofficeboxlabel")); + QVERIFY(postofficeboxlabel); + KLineEdit *postofficeboxlineedit = w.findChild(QStringLiteral("postofficeboxlineedit")); + QVERIFY(postofficeboxlineedit); + + QLabel *localitylabel = w.findChild(QStringLiteral("localitylabel")); + QVERIFY(localitylabel); + KLineEdit *localitylineedit = w.findChild(QStringLiteral("localitylineedit")); + QVERIFY(localitylineedit); + + QLabel *regionlabel = w.findChild(QStringLiteral("regionlabel")); + QVERIFY(regionlabel); + KLineEdit *regionlineedit = w.findChild(QStringLiteral("regionlineedit")); + QVERIFY(regionlineedit); + + QLabel *postalcodelabel = w.findChild(QStringLiteral("postalcodelabel")); + QVERIFY(postalcodelabel); + KLineEdit *postalcodelineedit = w.findChild(QStringLiteral("postalcodelineedit")); + QVERIFY(postalcodelineedit); + + QLabel *countrylabel = w.findChild(QStringLiteral("countrylabel")); + QVERIFY(countrylabel); + KComboBox *countrycombobox = w.findChild(QStringLiteral("countrycombobox")); + QVERIFY(countrycombobox); + + QCheckBox *preferredcheckbox = w.findChild(QStringLiteral("preferredcheckbox")); + QVERIFY(preferredcheckbox); + + QPushButton *addbuttonaddress = w.findChild(QStringLiteral("addbuttonaddress")); + QVERIFY(addbuttonaddress); + + QPushButton *modifybuttonaddress = w.findChild(QStringLiteral("modifybuttonaddress")); + QVERIFY(modifybuttonaddress); + + QPushButton *cancelbuttonaddress = w.findChild(QStringLiteral("cancelbuttonaddress")); + QVERIFY(cancelbuttonaddress); +} + +void AddressLocationWidgetTest::shouldChangeReadOnlyStatus() +{ + AddressLocationWidget w; + + w.setReadOnly(true); + SelectAddressTypeComboBox *typeAddress = w.findChild(QStringLiteral("typeaddress")); + QCOMPARE(typeAddress->isEnabled(), false); + KLineEdit *mStreetEdit = w.findChild(QStringLiteral("streetlineedit")); + QCOMPARE(mStreetEdit->isReadOnly(), true); + KLineEdit *postofficeboxlineedit = w.findChild(QStringLiteral("postofficeboxlineedit")); + QCOMPARE(postofficeboxlineedit->isReadOnly(), true); + KLineEdit *localitylineedit = w.findChild(QStringLiteral("localitylineedit")); + QCOMPARE(localitylineedit->isReadOnly(), true); + KLineEdit *regionlineedit = w.findChild(QStringLiteral("regionlineedit")); + QCOMPARE(regionlineedit->isReadOnly(), true); + KLineEdit *postalcodelineedit = w.findChild(QStringLiteral("postalcodelineedit")); + QCOMPARE(postalcodelineedit->isReadOnly(), true); + KComboBox *countrycombobox = w.findChild(QStringLiteral("countrycombobox")); + QCOMPARE(countrycombobox->isEnabled(), false); + QCheckBox *preferredcheckbox = w.findChild(QStringLiteral("preferredcheckbox")); + QCOMPARE(preferredcheckbox->isEnabled(), false); + QPushButton *addbuttonaddress = w.findChild(QStringLiteral("addbuttonaddress")); + QCOMPARE(addbuttonaddress->isEnabled(), false); + QPushButton *modifybuttonaddress = w.findChild(QStringLiteral("modifybuttonaddress")); + QCOMPARE(modifybuttonaddress->isEnabled(), false); + QPushButton *cancelbuttonaddress = w.findChild(QStringLiteral("cancelbuttonaddress")); + QCOMPARE(cancelbuttonaddress->isEnabled(), false); +} + +QTEST_MAIN(AddressLocationWidgetTest) diff --git a/src/contact-editor/editor/addresseditor/addresseslocationwidget.h b/src/contact-editor/editor/addresseditor/selectaddresstypecombobox.h copy from src/contact-editor/editor/addresseditor/addresseslocationwidget.h copy to src/contact-editor/editor/addresseditor/selectaddresstypecombobox.h --- a/src/contact-editor/editor/addresseditor/addresseslocationwidget.h +++ b/src/contact-editor/editor/addresseditor/selectaddresstypecombobox.h @@ -20,25 +20,57 @@ 02110-1301, USA. */ -#ifndef ADDRESSESLOCATIONWIDGET_H -#define ADDRESSESLOCATIONWIDGET_H -#include -#include +#ifndef SELECTADDRESSTYPECOMBOBOX_H +#define SELECTADDRESSTYPECOMBOBOX_H + +#include +#include + namespace ContactEditor { -class AbstractAddressLocationWidget; -class AddressesLocationWidget : public QWidget + +/** + * @short A widget for selecting the type of an address. + */ +class SelectAddressTypeComboBox : public QComboBox { Q_OBJECT + public: - explicit AddressesLocationWidget(QWidget *parent = nullptr); - ~AddressesLocationWidget(); + /** + * Creates a new address type combo. + * + * @param parent The parent widget. + */ + explicit SelectAddressTypeComboBox(QWidget *parent = nullptr); + + /** + * Destroys the address type combo. + */ + ~SelectAddressTypeComboBox(); - void loadContact(const KContacts::Addressee &contact); - void storeContact(KContacts::Addressee &contact) const; + /** + * Sets the type that shall be selected in the combobox. + * @param type KABC address type to set. + */ + void setType(KContacts::Address::Type type); + + /** + * Returns the type that is currently selected. + */ + KContacts::Address::Type type() const; + +private Q_SLOTS: + void selected(int); + void otherSelected(); - void setReadOnly(bool readOnly); private: - AbstractAddressLocationWidget *mAbstractAddressLocationWidget = nullptr; + void update(); + + KContacts::Address::Type mType; + int mLastSelected; + QList mTypeList; }; + } -#endif // ADDRESSESLOCATIONWIDGET_H + +#endif diff --git a/src/contact-editor/editor/addresseditor/selectaddresstypecombobox.cpp b/src/contact-editor/editor/addresseditor/selectaddresstypecombobox.cpp new file mode 100644 --- /dev/null +++ b/src/contact-editor/editor/addresseditor/selectaddresstypecombobox.cpp @@ -0,0 +1,116 @@ +/* + This file is part of Contact Editor. + + Copyright (C) 2016 eyeOS S.L.U., a Telefonica company, sales@eyeos.com + Copyright (C) 2016-2019 Laurent Montel + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by + the Free Software Foundation; either version 2 of the License, or (at your + option) any later version. + + This library is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public + License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to the + Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. +*/ + +#include "selectaddresstypecombobox.h" +#include "addresstypedialog.h" +#include + +#include + +using namespace ContactEditor; + +SelectAddressTypeComboBox::SelectAddressTypeComboBox(QWidget *parent) + : QComboBox(parent) + , mType(KContacts::Address::Home) + , mLastSelected(0) +{ + const int count = KContacts::Address::typeList().count(); + mTypeList.reserve(count + 2); + mTypeList.append(-2); // Add initial message + for (int i = 0; i < count; ++i) { + mTypeList.append(KContacts::Address::typeList().at(i)); + } + mTypeList.append(-1); // Others... + + update(); + + connect(this, qOverload(&QComboBox::activated), this, &SelectAddressTypeComboBox::selected); +} + +SelectAddressTypeComboBox::~SelectAddressTypeComboBox() +{ +} + +void SelectAddressTypeComboBox::setType(KContacts::Address::Type type) +{ + if (!mTypeList.contains(static_cast(type))) { + // insert at the end, but before the 'Others...' entry + mTypeList.insert(mTypeList.at(mTypeList.count() - 1), static_cast(type)); + } + + mType = type; + update(); +} + +KContacts::Address::Type SelectAddressTypeComboBox::type() const +{ + return mType; +} + +void SelectAddressTypeComboBox::update() +{ + bool blocked = signalsBlocked(); + blockSignals(true); + + clear(); + const int numberOfType(mTypeList.count()); + for (int i = 0; i < numberOfType; ++i) { + if (mTypeList.at(i) == -1) { // "Other..." entry + addItem(i18nc("@item:inlistbox Category of contact info field", "Other...")); + } else if (mTypeList.at(i) == -2) { + addItem(i18nc("@item:inlistbox Category of contact info field", "New Address Type")); + } else { + addItem(KContacts::Address::typeLabel(KContacts::Address::Type(mTypeList.at(i)))); + } + } + + setCurrentIndex(mLastSelected = mTypeList.indexOf(mType)); + + blockSignals(blocked); +} + +void SelectAddressTypeComboBox::selected(int pos) +{ + if (mTypeList.at(pos) == -1) { + otherSelected(); + } else if (mTypeList.at(pos) == -2) { + return; + } else { + mType = KContacts::Address::Type(mTypeList.at(pos)); + mLastSelected = pos; + } +} + +void SelectAddressTypeComboBox::otherSelected() +{ + QPointer dlg = new AddressTypeDialog(mType, this); + if (dlg->exec()) { + mType = dlg->type(); + if (!mTypeList.contains(mType)) { + mTypeList.insert(mTypeList.at(mTypeList.count() - 1), mType); + } + } else { + setType(KContacts::Address::Type(mTypeList.at(mLastSelected))); + } + delete dlg; + update(); +}