diff --git a/messagecomposer/src/followupreminder/followupreminderselectdatedialog.cpp b/messagecomposer/src/followupreminder/followupreminderselectdatedialog.cpp index f6a7472d..294aed76 100644 --- a/messagecomposer/src/followupreminder/followupreminderselectdatedialog.cpp +++ b/messagecomposer/src/followupreminder/followupreminderselectdatedialog.cpp @@ -1,140 +1,136 @@ /* Copyright (C) 2014-2020 Laurent Montel This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "followupreminderselectdatedialog.h" #include #include #include #include #include #include #include #include #include #include #include using namespace MessageComposer; class MessageComposer::FollowUpReminderSelectDateDialogPrivate { public: FollowUpReminderSelectDateDialogPrivate() { } KDateComboBox *mDateComboBox = nullptr; Akonadi::CollectionComboBox *mCollectionCombobox = nullptr; QPushButton *mOkButton = nullptr; }; FollowUpReminderSelectDateDialog::FollowUpReminderSelectDateDialog(QWidget *parent, QAbstractItemModel *model) : QDialog(parent) , d(new MessageComposer::FollowUpReminderSelectDateDialogPrivate) { setWindowTitle(i18nc("@title:window", "Select Date")); QVBoxLayout *topLayout = new QVBoxLayout(this); QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this); d->mOkButton = buttonBox->button(QDialogButtonBox::Ok); d->mOkButton->setObjectName(QStringLiteral("ok_button")); d->mOkButton->setDefault(true); d->mOkButton->setShortcut(Qt::CTRL | Qt::Key_Return); connect(buttonBox, &QDialogButtonBox::accepted, this, &FollowUpReminderSelectDateDialog::accept); connect(buttonBox, &QDialogButtonBox::rejected, this, &FollowUpReminderSelectDateDialog::reject); setModal(true); QWidget *mainWidget = new QWidget(this); topLayout->addWidget(mainWidget); topLayout->addWidget(buttonBox); QVBoxLayout *mainLayout = new QVBoxLayout(mainWidget); mainLayout->setContentsMargins(0, 0, 0, 0); QFormLayout *formLayout = new QFormLayout; formLayout->setContentsMargins(0, 0, 0, 0); mainLayout->addLayout(formLayout); d->mDateComboBox = new KDateComboBox; QDate currentDate = QDate::currentDate().addDays(1); d->mDateComboBox->setMinimumDate(QDate::currentDate()); d->mDateComboBox->setObjectName(QStringLiteral("datecombobox")); d->mDateComboBox->setDate(currentDate); formLayout->addRow(i18n("Date:"), d->mDateComboBox); d->mCollectionCombobox = new Akonadi::CollectionComboBox(model); d->mCollectionCombobox->setMinimumWidth(250); d->mCollectionCombobox->setAccessRightsFilter(Akonadi::Collection::CanCreateItem); d->mCollectionCombobox->setMimeTypeFilter(QStringList() << KCalendarCore::Todo::todoMimeType()); d->mCollectionCombobox->setObjectName(QStringLiteral("collectioncombobox")); formLayout->addRow(i18n("Store ToDo in:"), d->mCollectionCombobox); connect(d->mDateComboBox->lineEdit(), &QLineEdit::textChanged, this, &FollowUpReminderSelectDateDialog::slotDateChanged); -#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) connect(d->mCollectionCombobox, qOverload(&Akonadi::CollectionComboBox::currentIndexChanged), this, &FollowUpReminderSelectDateDialog::updateOkButton); -#else - connect(d->mCollectionCombobox, qOverload(&Akonadi::CollectionComboBox::currentIndexChanged), this, &FollowUpReminderSelectDateDialog::updateOkButton); -#endif updateOkButton(); } FollowUpReminderSelectDateDialog::~FollowUpReminderSelectDateDialog() { delete d; } void FollowUpReminderSelectDateDialog::updateOkButton() { d->mOkButton->setEnabled(!d->mDateComboBox->lineEdit()->text().isEmpty() && d->mDateComboBox->date().isValid() && (d->mCollectionCombobox->count() > 0) && d->mCollectionCombobox->currentCollection().isValid()); } void FollowUpReminderSelectDateDialog::slotDateChanged() { updateOkButton(); } QDate FollowUpReminderSelectDateDialog::selectedDate() const { return d->mDateComboBox->date(); } Akonadi::Collection FollowUpReminderSelectDateDialog::collection() const { return d->mCollectionCombobox->currentCollection(); } void FollowUpReminderSelectDateDialog::accept() { const QDate date = selectedDate(); if (date < QDate::currentDate()) { KMessageBox::error(this, i18n("The selected date must be greater than the current date."), i18n("Invalid date")); return; } if (!d->mCollectionCombobox->currentCollection().isValid()) { KMessageBox::error(this, i18n("The selected folder is not valid."), i18n("Invalid folder")); return; } QDialog::accept(); } diff --git a/messagecomposer/src/imagescaling/imagescalingwidget.cpp b/messagecomposer/src/imagescaling/imagescalingwidget.cpp index e0a238c1..e05e0f2d 100644 --- a/messagecomposer/src/imagescaling/imagescalingwidget.cpp +++ b/messagecomposer/src/imagescaling/imagescalingwidget.cpp @@ -1,390 +1,374 @@ /* Copyright (C) 2012-2020 Laurent Montel This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "imagescalingwidget.h" #include "ui_imagescalingwidget.h" #include "settings/messagecomposersettings.h" #include #include #include #include #include #include #include using namespace MessageComposer; class MessageComposer::ImageScalingWidgetPrivate { public: ImageScalingWidgetPrivate() : ui(new Ui::ImageScalingWidget) { } ~ImageScalingWidgetPrivate() { delete ui; } Ui::ImageScalingWidget *ui = nullptr; QButtonGroup *mSourceFilenameFilterGroup = nullptr; QButtonGroup *mRecipientFilterGroup = nullptr; bool mWasChanged = false; }; ImageScalingWidget::ImageScalingWidget(QWidget *parent) : QWidget(parent) , d(new MessageComposer::ImageScalingWidgetPrivate) { d->ui->setupUi(this); initComboBox(d->ui->CBMaximumWidth); initComboBox(d->ui->CBMaximumHeight); initComboBox(d->ui->CBMinimumWidth); initComboBox(d->ui->CBMinimumHeight); initWriteImageFormat(); connect(d->ui->enabledAutoResize, &QCheckBox::clicked, this, &ImageScalingWidget::changed); connect(d->ui->KeepImageRatio, &QCheckBox::clicked, this, &ImageScalingWidget::changed); connect(d->ui->AskBeforeResizing, &QCheckBox::clicked, this, &ImageScalingWidget::changed); connect(d->ui->EnlargeImageToMinimum, &QCheckBox::clicked, this, &ImageScalingWidget::changed); connect(d->ui->ReduceImageToMaximum, &QCheckBox::clicked, this, &ImageScalingWidget::changed); connect(d->ui->customMaximumWidth, qOverload(&QSpinBox::valueChanged), this, &ImageScalingWidget::changed); connect(d->ui->customMaximumHeight, qOverload(&QSpinBox::valueChanged), this, &ImageScalingWidget::changed); connect(d->ui->customMinimumWidth, qOverload(&QSpinBox::valueChanged), this, &ImageScalingWidget::changed); connect(d->ui->customMinimumHeight, qOverload(&QSpinBox::valueChanged), this, &ImageScalingWidget::changed); connect(d->ui->skipImageSizeLower, &QCheckBox::clicked, this, &ImageScalingWidget::changed); connect(d->ui->imageSize, qOverload(&QSpinBox::valueChanged), this, &ImageScalingWidget::changed); connect(d->ui->pattern, &KLineEdit::textChanged, this, &ImageScalingWidget::changed); -#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) connect(d->ui->CBMaximumWidth, qOverload(&QComboBox::currentIndexChanged), this, &ImageScalingWidget::slotComboboxChanged); -#else - connect(d->ui->CBMaximumWidth, qOverload(&QComboBox::currentIndexChanged), this, &ImageScalingWidget::slotComboboxChanged); -#endif -#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) connect(d->ui->CBMaximumHeight, qOverload(&QComboBox::currentIndexChanged), this, &ImageScalingWidget::slotComboboxChanged); -#else - connect(d->ui->CBMaximumHeight, qOverload(&QComboBox::currentIndexChanged), this, &ImageScalingWidget::slotComboboxChanged); -#endif -#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) connect(d->ui->CBMinimumWidth, qOverload(&QComboBox::currentIndexChanged), this, &ImageScalingWidget::slotComboboxChanged); -#else - connect(d->ui->CBMinimumWidth, qOverload(&QComboBox::currentIndexChanged), this, &ImageScalingWidget::slotComboboxChanged); -#endif -#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) connect(d->ui->CBMinimumHeight, qOverload(&QComboBox::currentIndexChanged), this, &ImageScalingWidget::slotComboboxChanged); -#else - connect(d->ui->CBMinimumHeight, qOverload(&QComboBox::currentIndexChanged), this, &ImageScalingWidget::slotComboboxChanged); -#endif connect(d->ui->WriteToImageFormat, qOverload(&QComboBox::activated), this, &ImageScalingWidget::changed); connect(d->ui->renameResizedImage, &QCheckBox::clicked, this, &ImageScalingWidget::changed); connect(d->ui->renameResizedImage, &QCheckBox::clicked, d->ui->renameResizedImagePattern, &KLineEdit::setEnabled); connect(d->ui->renameResizedImagePattern, &KLineEdit::textChanged, this, &ImageScalingWidget::changed); connect(d->ui->resizeEmailsPattern, &KLineEdit::textChanged, this, &ImageScalingWidget::changed); connect(d->ui->doNotResizePattern, &KLineEdit::textChanged, this, &ImageScalingWidget::changed); connect(d->ui->resizeImageWithFormatsType, &MessageComposer::ImageScalingSelectFormat::textChanged, this, &ImageScalingWidget::changed); connect(d->ui->resizeImageWithFormats, &QCheckBox::clicked, this, &ImageScalingWidget::changed); connect(d->ui->resizeImageWithFormats, &QCheckBox::clicked, d->ui->resizeImageWithFormatsType, &MessageComposer::ImageScalingSelectFormat::setEnabled); d->ui->resizeImageWithFormatsType->setEnabled(false); d->ui->pattern->setEnabled(false); d->mSourceFilenameFilterGroup = new QButtonGroup(d->ui->filterSourceGroupBox); #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) connect(d->mSourceFilenameFilterGroup, qOverload(&QButtonGroup::buttonClicked), this, &ImageScalingWidget::slotSourceFilterClicked); #else connect(d->mSourceFilenameFilterGroup, qOverload(&QButtonGroup::buttonClicked), this, &ImageScalingWidget::slotSourceFilterAbstractButtonClicked); #endif d->mSourceFilenameFilterGroup->addButton(d->ui->notFilterFilename, MessageComposer::MessageComposerSettings::EnumFilterSourceType::NoFilter); d->mSourceFilenameFilterGroup->addButton(d->ui->includeFilesWithPattern, MessageComposer::MessageComposerSettings::EnumFilterSourceType::IncludeFilesWithPattern); d->mSourceFilenameFilterGroup->addButton(d->ui->excludeFilesWithPattern, MessageComposer::MessageComposerSettings::EnumFilterSourceType::ExcludeFilesWithPattern); d->mRecipientFilterGroup = new QButtonGroup(d->ui->tab_4); #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) connect(d->mRecipientFilterGroup, qOverload(&QButtonGroup::buttonClicked), this, &ImageScalingWidget::slotRecipientFilterClicked); #else connect(d->mRecipientFilterGroup, qOverload(&QButtonGroup::buttonClicked), this, &ImageScalingWidget::slotRecipientFilterAbstractClicked); #endif d->ui->doNotResizePattern->setEnabled(false); d->ui->resizeEmailsPattern->setEnabled(false); d->mRecipientFilterGroup->addButton(d->ui->doNotFilterRecipients, MessageComposer::MessageComposerSettings::EnumFilterRecipientType::NoFilter); d->mRecipientFilterGroup->addButton(d->ui->resizeEachEmails, MessageComposer::MessageComposerSettings::EnumFilterRecipientType::ResizeEachEmailsContainsPattern); d->mRecipientFilterGroup->addButton(d->ui->resizeOneEmails, MessageComposer::MessageComposerSettings::EnumFilterRecipientType::ResizeOneEmailContainsPattern); d->mRecipientFilterGroup->addButton(d->ui->doNotResizeEachEmails, MessageComposer::MessageComposerSettings::EnumFilterRecipientType::DontResizeEachEmailsContainsPattern); d->mRecipientFilterGroup->addButton(d->ui->doNotResizeOneEmails, MessageComposer::MessageComposerSettings::EnumFilterRecipientType::DontResizeOneEmailContainsPattern); d->ui->help->setText(i18n("How does this work?")); connect(d->ui->help, &QLabel::linkActivated, this, &ImageScalingWidget::slotHelpLinkClicked); d->ui->help->setContextMenuPolicy(Qt::NoContextMenu); } ImageScalingWidget::~ImageScalingWidget() { delete d; } void ImageScalingWidget::slotHelpLinkClicked(const QString &) { const QString help = i18n("" "

Here you can define image filename. " "You can use:

" "
    " "
  • %t set current time
  • " "
  • %d set current date
  • " "
  • %n original filename
  • " "
  • %e original extension
  • " "
  • %x new extension
  • " "
" "
"); QWhatsThis::showText(QCursor::pos(), help); } void ImageScalingWidget::slotSourceFilterAbstractButtonClicked(QAbstractButton *button) { if (button) { const int buttonId = d->mRecipientFilterGroup->id(button); slotSourceFilterClicked(buttonId); } } void ImageScalingWidget::slotSourceFilterClicked(int button) { d->ui->pattern->setEnabled(button != 0); Q_EMIT changed(); } void ImageScalingWidget::slotRecipientFilterClicked(int button) { d->ui->resizeEmailsPattern->setEnabled((button == MessageComposer::MessageComposerSettings::EnumFilterRecipientType::ResizeEachEmailsContainsPattern) || (button == MessageComposer::MessageComposerSettings::EnumFilterRecipientType::ResizeOneEmailContainsPattern)); d->ui->doNotResizePattern->setEnabled((button == MessageComposer::MessageComposerSettings::EnumFilterRecipientType::DontResizeEachEmailsContainsPattern) || (button == MessageComposer::MessageComposerSettings::EnumFilterRecipientType::DontResizeOneEmailContainsPattern)); Q_EMIT changed(); } void ImageScalingWidget::slotRecipientFilterAbstractClicked(QAbstractButton *button) { if (button) { const int buttonId = d->mRecipientFilterGroup->id(button); slotRecipientFilterClicked(buttonId); } } void ImageScalingWidget::slotComboboxChanged(int index) { QComboBox *combo = qobject_cast< QComboBox * >(sender()); if (combo) { const bool isCustom = combo->itemData(index) == -1; if (combo == d->ui->CBMaximumWidth) { d->ui->customMaximumWidth->setEnabled(isCustom); } else if (combo == d->ui->CBMaximumHeight) { d->ui->customMaximumHeight->setEnabled(isCustom); } else if (combo == d->ui->CBMinimumWidth) { d->ui->customMinimumWidth->setEnabled(isCustom); } else if (combo == d->ui->CBMinimumHeight) { d->ui->customMinimumHeight->setEnabled(isCustom); } Q_EMIT changed(); } } void ImageScalingWidget::initComboBox(QComboBox *combo) { const QVector size = { 240, 320, 512, 640, 800, 1024, 1600, 2048 }; for (int val : size) { combo->addItem(QString::number(val), val); } combo->addItem(i18n("Custom"), -1); } void ImageScalingWidget::initWriteImageFormat() { /* Too many format :) QList listWriteFormat = QImageWriter::supportedImageFormats(); Q_FOREACH(const QByteArray& format, listWriteFormat) { d->ui->WriteToImageFormat->addItem(QString::fromLatin1(format)); } */ //known by several mailer. d->ui->WriteToImageFormat->addItem(QStringLiteral("JPG")); d->ui->WriteToImageFormat->addItem(QStringLiteral("PNG")); } void ImageScalingWidget::updateSettings() { d->ui->enabledAutoResize->setChecked(MessageComposer::MessageComposerSettings::self()->autoResizeImageEnabled()); d->ui->KeepImageRatio->setChecked(MessageComposer::MessageComposerSettings::self()->keepImageRatio()); d->ui->AskBeforeResizing->setChecked(MessageComposer::MessageComposerSettings::self()->askBeforeResizing()); d->ui->EnlargeImageToMinimum->setChecked(MessageComposer::MessageComposerSettings::self()->enlargeImageToMinimum()); d->ui->ReduceImageToMaximum->setChecked(MessageComposer::MessageComposerSettings::self()->reduceImageToMaximum()); d->ui->skipImageSizeLower->setChecked(MessageComposer::MessageComposerSettings::self()->skipImageLowerSizeEnabled()); d->ui->imageSize->setValue(MessageComposer::MessageComposerSettings::self()->skipImageLowerSize()); d->ui->customMaximumWidth->setValue(MessageComposer::MessageComposerSettings::self()->customMaximumWidth()); d->ui->customMaximumHeight->setValue(MessageComposer::MessageComposerSettings::self()->customMaximumHeight()); d->ui->customMinimumWidth->setValue(MessageComposer::MessageComposerSettings::self()->customMinimumWidth()); d->ui->customMinimumHeight->setValue(MessageComposer::MessageComposerSettings::self()->customMinimumHeight()); int index = qMax(0, d->ui->CBMaximumWidth->findData(MessageComposer::MessageComposerSettings::self()->maximumWidth())); d->ui->CBMaximumWidth->setCurrentIndex(index); d->ui->customMaximumWidth->setEnabled(d->ui->CBMaximumWidth->itemData(index) == -1); index = qMax(0, d->ui->CBMaximumHeight->findData(MessageComposer::MessageComposerSettings::self()->maximumHeight())); d->ui->CBMaximumHeight->setCurrentIndex(index); d->ui->customMaximumHeight->setEnabled(d->ui->CBMaximumHeight->itemData(index) == -1); index = qMax(0, d->ui->CBMinimumWidth->findData(MessageComposer::MessageComposerSettings::self()->minimumWidth())); d->ui->CBMinimumWidth->setCurrentIndex(index); d->ui->customMinimumWidth->setEnabled(d->ui->CBMinimumWidth->itemData(index) == -1); index = qMax(0, d->ui->CBMinimumHeight->findData(MessageComposer::MessageComposerSettings::self()->minimumHeight())); d->ui->CBMinimumHeight->setCurrentIndex(index); d->ui->customMinimumHeight->setEnabled(d->ui->CBMinimumHeight->itemData(index) == -1); index = d->ui->WriteToImageFormat->findData(MessageComposer::MessageComposerSettings::self()->writeFormat()); if (index == -1) { d->ui->WriteToImageFormat->setCurrentIndex(0); } else { d->ui->WriteToImageFormat->setCurrentIndex(index); } d->ui->pattern->setText(MessageComposer::MessageComposerSettings::self()->filterSourcePattern()); d->ui->renameResizedImage->setChecked(MessageComposer::MessageComposerSettings::self()->renameResizedImages()); d->ui->renameResizedImagePattern->setText(MessageComposer::MessageComposerSettings::self()->renameResizedImagesPattern()); d->ui->renameResizedImagePattern->setEnabled(d->ui->renameResizedImage->isChecked()); d->ui->doNotResizePattern->setText(MessageComposer::MessageComposerSettings::self()->doNotResizeEmailsPattern()); d->ui->resizeEmailsPattern->setText(MessageComposer::MessageComposerSettings::self()->resizeEmailsPattern()); d->ui->resizeImageWithFormats->setChecked(MessageComposer::MessageComposerSettings::self()->resizeImagesWithFormats()); d->ui->resizeImageWithFormatsType->setFormat(MessageComposer::MessageComposerSettings::self()->resizeImagesWithFormatsType()); d->ui->resizeImageWithFormatsType->setEnabled(d->ui->resizeImageWithFormats->isChecked()); updateFilterSourceTypeSettings(); updateEmailsFilterTypeSettings(); } void ImageScalingWidget::loadConfig() { updateSettings(); d->mWasChanged = false; } void ImageScalingWidget::updateFilterSourceTypeSettings() { switch (MessageComposer::MessageComposerSettings::self()->filterSourceType()) { case MessageComposer::MessageComposerSettings::EnumFilterSourceType::NoFilter: d->ui->notFilterFilename->setChecked(true); d->ui->pattern->setEnabled(false); break; case MessageComposer::MessageComposerSettings::EnumFilterSourceType::IncludeFilesWithPattern: d->ui->includeFilesWithPattern->setChecked(true); d->ui->pattern->setEnabled(true); break; case MessageComposer::MessageComposerSettings::EnumFilterSourceType::ExcludeFilesWithPattern: d->ui->excludeFilesWithPattern->setChecked(true); d->ui->pattern->setEnabled(true); break; } } void ImageScalingWidget::updateEmailsFilterTypeSettings() { d->ui->doNotResizePattern->setEnabled(false); d->ui->resizeEmailsPattern->setEnabled(false); switch (MessageComposer::MessageComposerSettings::self()->filterRecipientType()) { case MessageComposer::MessageComposerSettings::EnumFilterRecipientType::NoFilter: d->ui->doNotFilterRecipients->setChecked(true); break; case MessageComposer::MessageComposerSettings::EnumFilterRecipientType::ResizeEachEmailsContainsPattern: d->ui->resizeEachEmails->setChecked(true); d->ui->resizeEmailsPattern->setEnabled(true); break; case MessageComposer::MessageComposerSettings::EnumFilterRecipientType::ResizeOneEmailContainsPattern: d->ui->resizeOneEmails->setChecked(true); d->ui->resizeEmailsPattern->setEnabled(true); break; case MessageComposer::MessageComposerSettings::EnumFilterRecipientType::DontResizeEachEmailsContainsPattern: d->ui->doNotResizeEachEmails->setChecked(true); d->ui->doNotResizePattern->setEnabled(true); break; case MessageComposer::MessageComposerSettings::EnumFilterRecipientType::DontResizeOneEmailContainsPattern: d->ui->doNotResizeOneEmails->setChecked(true); d->ui->doNotResizePattern->setEnabled(false); break; } } void ImageScalingWidget::writeConfig() { if (d->ui->EnlargeImageToMinimum->isChecked() && d->ui->ReduceImageToMaximum->isChecked()) { if ((d->ui->customMinimumWidth->value() >= d->ui->customMaximumWidth->value()) || (d->ui->customMinimumHeight->value() >= d->ui->customMaximumHeight->value())) { KMessageBox::error(this, i18n("Please verify minimum and maximum values."), i18n("Error in minimum Maximum value")); return; } } MessageComposer::MessageComposerSettings::self()->setAutoResizeImageEnabled(d->ui->enabledAutoResize->isChecked()); MessageComposer::MessageComposerSettings::self()->setKeepImageRatio(d->ui->KeepImageRatio->isChecked()); MessageComposer::MessageComposerSettings::self()->setAskBeforeResizing(d->ui->AskBeforeResizing->isChecked()); MessageComposer::MessageComposerSettings::self()->setEnlargeImageToMinimum(d->ui->EnlargeImageToMinimum->isChecked()); MessageComposer::MessageComposerSettings::self()->setReduceImageToMaximum(d->ui->ReduceImageToMaximum->isChecked()); MessageComposer::MessageComposerSettings::self()->setCustomMaximumWidth(d->ui->customMaximumWidth->value()); MessageComposer::MessageComposerSettings::self()->setCustomMaximumHeight(d->ui->customMaximumHeight->value()); MessageComposer::MessageComposerSettings::self()->setCustomMinimumWidth(d->ui->customMinimumWidth->value()); MessageComposer::MessageComposerSettings::self()->setCustomMinimumHeight(d->ui->customMinimumHeight->value()); MessageComposer::MessageComposerSettings::self()->setMaximumWidth(d->ui->CBMaximumWidth->itemData(d->ui->CBMaximumWidth->currentIndex()).toInt()); MessageComposer::MessageComposerSettings::self()->setMaximumHeight(d->ui->CBMaximumHeight->itemData(d->ui->CBMaximumHeight->currentIndex()).toInt()); MessageComposer::MessageComposerSettings::self()->setMinimumWidth(d->ui->CBMinimumWidth->itemData(d->ui->CBMinimumWidth->currentIndex()).toInt()); MessageComposer::MessageComposerSettings::self()->setMinimumHeight(d->ui->CBMinimumHeight->itemData(d->ui->CBMinimumHeight->currentIndex()).toInt()); MessageComposer::MessageComposerSettings::self()->setWriteFormat(d->ui->WriteToImageFormat->currentText()); MessageComposer::MessageComposerSettings::self()->setSkipImageLowerSizeEnabled(d->ui->skipImageSizeLower->isChecked()); MessageComposer::MessageComposerSettings::self()->setSkipImageLowerSize(d->ui->imageSize->value()); MessageComposer::MessageComposerSettings::self()->setFilterSourcePattern(d->ui->pattern->text()); MessageComposer::MessageComposerSettings::self()->setFilterSourceType(d->mSourceFilenameFilterGroup->checkedId()); MessageComposer::MessageComposerSettings::self()->setRenameResizedImages(d->ui->renameResizedImage->isChecked()); MessageComposer::MessageComposerSettings::self()->setRenameResizedImagesPattern(d->ui->renameResizedImagePattern->text()); MessageComposer::MessageComposerSettings::self()->setDoNotResizeEmailsPattern(d->ui->doNotResizePattern->text()); MessageComposer::MessageComposerSettings::self()->setResizeEmailsPattern(d->ui->resizeEmailsPattern->text()); MessageComposer::MessageComposerSettings::self()->setFilterRecipientType(d->mRecipientFilterGroup->checkedId()); MessageComposer::MessageComposerSettings::self()->setResizeImagesWithFormats(d->ui->resizeImageWithFormats->isChecked()); MessageComposer::MessageComposerSettings::self()->setResizeImagesWithFormatsType(d->ui->resizeImageWithFormatsType->format()); d->mWasChanged = false; } void ImageScalingWidget::resetToDefault() { const bool bUseDefaults = MessageComposer::MessageComposerSettings::self()->useDefaults(true); updateSettings(); MessageComposer::MessageComposerSettings::self()->useDefaults(bUseDefaults); } diff --git a/messagelist/src/core/widgetbase.cpp b/messagelist/src/core/widgetbase.cpp index 0ceabecb..f1e8da2f 100644 --- a/messagelist/src/core/widgetbase.cpp +++ b/messagelist/src/core/widgetbase.cpp @@ -1,1108 +1,1100 @@ /****************************************************************************** * * Copyright 2008 Szymon Tomasz Stefanek * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * *******************************************************************************/ #include "core/widgetbase.h" #include "core/widgets/quicksearchwarning.h" #include "core/widgets/searchcollectionindexingwarning.h" #include "core/aggregation.h" #include "core/theme.h" #include "core/filter.h" #include "core/manager.h" #include "core/optionset.h" #include "core/view.h" #include "core/model.h" #include "core/messageitem.h" #include "core/storagemodelbase.h" #include "widgets/searchlinestatus.h" #include "messagelistsettings.h" #include "utils/configureaggregationsdialog.h" #include "utils/configurethemesdialog.h" #include #include #include #include #include #include #include #include "messagelist_debug.h" #include #include #include #include #include using namespace MessageList::Core; class Widget::Private { public: Private(Widget *owner) : q(owner) , quickSearchWarning(nullptr) , searchCollectionIndexingWarning(nullptr) , quickSearchLine(nullptr) , mView(nullptr) , mSearchTimer(nullptr) , mStorageModel(nullptr) , mAggregation(nullptr) , mTheme(nullptr) , mFilter(nullptr) , mStorageUsesPrivateTheme(false) , mStorageUsesPrivateAggregation(false) , mStorageUsesPrivateSortOrder(false) , mStatusFilterComboPopulationInProgress(false) { } /** * Small helper for switching SortOrder::MessageSorting and SortOrder::SortDirection * on the fly. * After doing this, the sort indicator in the header is updated. */ void switchMessageSorting(SortOrder::MessageSorting messageSorting, SortOrder::SortDirection sortDirection, int logicalHeaderColumnIndex); /** * Check if our sort order can still be used with this aggregation. * This can happen if the global aggregation changed, for example we can now * have "most recent in subtree" sorting with an aggregation without threading. * If this happens, reset to the default sort order and don't use the global sort * order. */ void checkSortOrder(const StorageModel *storageModel); void setDefaultAggregationForStorageModel(const StorageModel *storageModel); void setDefaultThemeForStorageModel(const StorageModel *storageModel); void setDefaultSortOrderForStorageModel(const StorageModel *storageModel); void applyFilter(); Widget *const q; QuickSearchWarning *quickSearchWarning; SearchCollectionIndexingWarning *searchCollectionIndexingWarning; QuickSearchLine *quickSearchLine; View *mView; QString mLastAggregationId; QString mLastThemeId; QTimer *mSearchTimer; StorageModel *mStorageModel; ///< The currently displayed storage. The storage itself /// is owned by MessageList::Widget. Aggregation *mAggregation; ///< The currently set aggregation mode, a deep copy Theme *mTheme; ///< The currently set theme, a deep copy SortOrder mSortOrder; ///< The currently set sort order Filter *mFilter; ///< The currently applied filter, owned by us. bool mStorageUsesPrivateTheme; ///< true if the current folder does not use the global theme bool mStorageUsesPrivateAggregation; ///< true if the current folder does not use the global aggregation bool mStorageUsesPrivateSortOrder; ///< true if the current folder does not use the global sort order QUrl mCurrentFolderUrl; ///< The Akonadi URL of the current folder Akonadi::Collection mCurrentFolder; ///< The current folder int mCurrentStatusFilterIndex = 0; bool mStatusFilterComboPopulationInProgress; }; Widget::Widget(QWidget *pParent) : QWidget(pParent) , d(new Private(this)) { Manager::registerWidget(this); connect(Manager::instance(), &Manager::aggregationsChanged, this, &Widget::aggregationsChanged); connect(Manager::instance(), &Manager::themesChanged, this, &Widget::themesChanged); setAutoFillBackground(true); setObjectName(QStringLiteral("messagelistwidget")); QVBoxLayout *g = new QVBoxLayout(this); g->setContentsMargins(0, 0, 0, 0); g->setSpacing(0); d->quickSearchLine = new QuickSearchLine; d->quickSearchLine->setObjectName(QStringLiteral("quicksearchline")); connect(d->quickSearchLine, &QuickSearchLine::clearButtonClicked, this, &Widget::searchEditClearButtonClicked); connect(d->quickSearchLine, &QuickSearchLine::searchEditTextEdited, this, &Widget::searchEditTextEdited); connect(d->quickSearchLine, &QuickSearchLine::searchOptionChanged, this, &Widget::searchEditTextEdited); connect(d->quickSearchLine, &QuickSearchLine::statusButtonsClicked, this, &Widget::slotStatusButtonsClicked); connect(d->quickSearchLine, &QuickSearchLine::forceLostFocus, this, &Widget::forceLostFocus); g->addWidget(d->quickSearchLine, 0); d->quickSearchWarning = new QuickSearchWarning(this); g->addWidget(d->quickSearchWarning, 0); d->searchCollectionIndexingWarning = new SearchCollectionIndexingWarning(this); g->addWidget(d->searchCollectionIndexingWarning, 0); d->mView = new View(this); d->mView->setFrameStyle(QFrame::NoFrame); d->mView->setSortOrder(&d->mSortOrder); d->mView->setObjectName(QStringLiteral("messagealistview")); g->addWidget(d->mView, 1); connect(d->mView->header(), &QHeaderView::sectionClicked, this, &Widget::slotViewHeaderSectionClicked); d->mSearchTimer = nullptr; } Widget::~Widget() { d->mView->setStorageModel(nullptr); Manager::unregisterWidget(this); delete d->mSearchTimer; delete d->mTheme; delete d->mAggregation; delete d->mFilter; delete d->mStorageModel; delete d; } void Widget::changeQuicksearchVisibility(bool show) { QLineEdit *const lineEdit = d->quickSearchLine->searchEdit(); if (!show) { //if we hide it we do not want to apply the filter, //otherwise someone is maybe stuck with x new emails //and cannot read it because of filter lineEdit->clear(); //we focus the message list if we hide the searchbar d->mView->setFocus(Qt::OtherFocusReason); } else { // on show: we focus the lineedit for fast filtering lineEdit->setFocus(Qt::OtherFocusReason); if (d->mFilter) { resetFilter(); } } d->quickSearchLine->changeQuicksearchVisibility(show); MessageListSettings::self()->setShowQuickSearch(show); } void Widget::populateStatusFilterCombo() { if (d->mStatusFilterComboPopulationInProgress) { return; } d->mStatusFilterComboPopulationInProgress = true; QComboBox *tagFilterComboBox = d->quickSearchLine->tagFilterComboBox(); d->mCurrentStatusFilterIndex = (tagFilterComboBox->currentIndex() != -1) ? tagFilterComboBox->currentIndex() : 0; -#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) disconnect(tagFilterComboBox, qOverload(&QComboBox::currentIndexChanged), this, &Widget::statusSelected); -#else - disconnect(tagFilterComboBox, qOverload(&QComboBox::currentIndexChanged), this, &Widget::statusSelected); -#endif tagFilterComboBox->clear(); fillMessageTagCombo(); } void Widget::addMessageTagItem(const QPixmap &icon, const QString &text, const QVariant &data) { d->quickSearchLine->tagFilterComboBox()->addItem(icon, text, data); } void Widget::setCurrentStatusFilterItem() { d->quickSearchLine->updateComboboxVisibility(); -#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) connect(d->quickSearchLine->tagFilterComboBox(), qOverload(&QComboBox::currentIndexChanged), this, &Widget::statusSelected); -#else - connect(d->quickSearchLine->tagFilterComboBox(), qOverload(&QComboBox::currentIndexChanged), this, &Widget::statusSelected); -#endif d->quickSearchLine->tagFilterComboBox()->setCurrentIndex(d->mCurrentStatusFilterIndex >= d->quickSearchLine->tagFilterComboBox()->count() ? 0 : d->mCurrentStatusFilterIndex); d->mStatusFilterComboPopulationInProgress = false; } MessageItem *Widget::currentMessageItem() const { return view()->currentMessageItem(); } MessageList::Core::QuickSearchLine::SearchOptions Widget::currentOptions() const { return d->quickSearchLine->searchOptions(); } QVector Widget::currentFilterStatus() const { if (d->mFilter) { return d->mFilter->status(); } return QVector(); } QString Widget::currentFilterSearchString() const { if (d->mFilter) { return d->mFilter->searchString(); } return QString(); } QString Widget::currentFilterTagId() const { if (d->mFilter) { return d->mFilter->tagId(); } return QString(); } void Widget::Private::setDefaultAggregationForStorageModel(const StorageModel *storageModel) { const Aggregation *opt = Manager::instance()->aggregationForStorageModel(storageModel, &mStorageUsesPrivateAggregation); Q_ASSERT(opt); delete mAggregation; mAggregation = new Aggregation(*opt); mView->setAggregation(mAggregation); mLastAggregationId = opt->id(); } void Widget::Private::setDefaultThemeForStorageModel(const StorageModel *storageModel) { const Theme *opt = Manager::instance()->themeForStorageModel(storageModel, &mStorageUsesPrivateTheme); Q_ASSERT(opt); delete mTheme; mTheme = new Theme(*opt); mView->setTheme(mTheme); mLastThemeId = opt->id(); } void Widget::Private::checkSortOrder(const StorageModel *storageModel) { if (storageModel && mAggregation && !mSortOrder.validForAggregation(mAggregation)) { qCDebug(MESSAGELIST_LOG) << "Could not restore sort order for folder" << storageModel->id(); mSortOrder = SortOrder::defaultForAggregation(mAggregation, mSortOrder); // Change the global sort order if the sort order didn't fit the global aggregation. // Otherwise, if it is a per-folder aggregation, make the sort order per-folder too. if (mStorageUsesPrivateAggregation) { mStorageUsesPrivateSortOrder = true; } if (mStorageModel) { Manager::instance()->saveSortOrderForStorageModel(storageModel, mSortOrder, mStorageUsesPrivateSortOrder); } switchMessageSorting(mSortOrder.messageSorting(), mSortOrder.messageSortDirection(), -1); } } void Widget::Private::setDefaultSortOrderForStorageModel(const StorageModel *storageModel) { // Load the sort order from config and update column headers mSortOrder = Manager::instance()->sortOrderForStorageModel(storageModel, &mStorageUsesPrivateSortOrder); switchMessageSorting(mSortOrder.messageSorting(), mSortOrder.messageSortDirection(), -1); checkSortOrder(storageModel); } void Widget::saveCurrentSelection() { if (d->mStorageModel) { // Save the current selection MessageItem *lastSelectedMessageItem = d->mView->currentMessageItem(false); if (lastSelectedMessageItem) { d->mStorageModel->savePreSelectedMessage(lastSelectedMessageItem->uniqueId()); } } } void Widget::setStorageModel(StorageModel *storageModel, PreSelectionMode preSelectionMode) { if (storageModel == d->mStorageModel) { return; // nuthin to do here } d->setDefaultAggregationForStorageModel(storageModel); d->setDefaultThemeForStorageModel(storageModel); d->setDefaultSortOrderForStorageModel(storageModel); if (!d->quickSearchLine->searchEdit()->locked()) { if (d->mSearchTimer) { d->mSearchTimer->stop(); delete d->mSearchTimer; d->mSearchTimer = nullptr; } d->quickSearchLine->searchEdit()->clear(); if (d->mFilter) { resetFilter(); } } StorageModel *oldModel = d->mStorageModel; d->mStorageModel = storageModel; d->mView->setStorageModel(d->mStorageModel, preSelectionMode); delete oldModel; d->quickSearchLine->tagFilterComboBox()->setEnabled(d->mStorageModel); d->quickSearchLine->searchEdit()->setEnabled(d->mStorageModel); d->quickSearchLine->setContainsOutboundMessages(d->mStorageModel->containsOutboundMessages()); } StorageModel *Widget::storageModel() const { return d->mStorageModel; } QLineEdit *Widget::quickSearch() const { return d->quickSearchLine->searchEdit(); } View *Widget::view() const { return d->mView; } void Widget::themeMenuAboutToShow() { if (!d->mStorageModel) { return; } QMenu *menu = qobject_cast< QMenu * >(sender()); if (!menu) { return; } themeMenuAboutToShow(menu); } void Widget::themeMenuAboutToShow(QMenu *menu) { menu->clear(); menu->addSection(i18n("Theme")); QActionGroup *grp = new QActionGroup(menu); QList< Theme * > sortedThemes = Manager::instance()->themes().values(); QAction *act; std::sort(sortedThemes.begin(), sortedThemes.end(), MessageList::Core::Theme::compareName); for (const auto theme : qAsConst(sortedThemes)) { act = menu->addAction(theme->name()); act->setCheckable(true); grp->addAction(act); act->setChecked(d->mLastThemeId == theme->id()); act->setData(QVariant(theme->id())); connect(act, &QAction::triggered, this, &Widget::themeSelected); } menu->addSeparator(); act = menu->addAction(i18n("Configure...")); connect(act, &QAction::triggered, this, &Widget::configureThemes); } void Widget::setPrivateSortOrderForStorage() { if (!d->mStorageModel) { return; } d->mStorageUsesPrivateSortOrder = !d->mStorageUsesPrivateSortOrder; Manager::instance()->saveSortOrderForStorageModel(d->mStorageModel, d->mSortOrder, d->mStorageUsesPrivateSortOrder); } void Widget::configureThemes() { Utils::ConfigureThemesDialog *dialog = new Utils::ConfigureThemesDialog(window()); dialog->selectTheme(d->mLastThemeId); dialog->show(); } void Widget::themeSelected(bool) { if (!d->mStorageModel) { return; // nuthin to do } QAction *act = qobject_cast< QAction * >(sender()); if (!act) { return; } QVariant v = act->data(); const QString id = v.toString(); if (id.isEmpty()) { return; } const Theme *opt = Manager::instance()->theme(id); delete d->mTheme; d->mTheme = new Theme(*opt); d->mView->setTheme(d->mTheme); d->mLastThemeId = opt->id(); //mStorageUsesPrivateTheme = false; Manager::instance()->saveThemeForStorageModel(d->mStorageModel, opt->id(), d->mStorageUsesPrivateTheme); d->mView->reload(); } void Widget::aggregationMenuAboutToShow() { QMenu *menu = qobject_cast< QMenu * >(sender()); if (!menu) { return; } aggregationMenuAboutToShow(menu); } void Widget::aggregationMenuAboutToShow(QMenu *menu) { menu->clear(); menu->addSection(i18n("Aggregation")); QActionGroup *grp = new QActionGroup(menu); QList< Aggregation * > sortedAggregations = Manager::instance()->aggregations().values(); QAction *act; std::sort(sortedAggregations.begin(), sortedAggregations.end(), MessageList::Core::Aggregation::compareName); for (const auto agg : qAsConst(sortedAggregations)) { act = menu->addAction(agg->name()); act->setCheckable(true); grp->addAction(act); act->setChecked(d->mLastAggregationId == agg->id()); act->setData(QVariant(agg->id())); connect(act, &QAction::triggered, this, &Widget::aggregationSelected); } menu->addSeparator(); act = menu->addAction(i18n("Configure...")); act->setData(QVariant(QString())); connect(act, &QAction::triggered, this, &Widget::aggregationSelected); } void Widget::aggregationSelected(bool) { QAction *act = qobject_cast< QAction * >(sender()); if (!act) { return; } QVariant v = act->data(); QString id = v.toString(); if (id.isEmpty()) { Utils::ConfigureAggregationsDialog *dialog = new Utils::ConfigureAggregationsDialog(window()); dialog->selectAggregation(d->mLastAggregationId); dialog->show(); return; } if (!d->mStorageModel) { return; // nuthin to do } const Aggregation *opt = Manager::instance()->aggregation(id); delete d->mAggregation; d->mAggregation = new Aggregation(*opt); d->mView->setAggregation(d->mAggregation); d->mLastAggregationId = opt->id(); //mStorageUsesPrivateAggregation = false; Manager::instance()->saveAggregationForStorageModel(d->mStorageModel, opt->id(), d->mStorageUsesPrivateAggregation); // The sort order might not be valid anymore for this aggregation d->checkSortOrder(d->mStorageModel); d->mView->reload(); } void Widget::sortOrderMenuAboutToShow() { if (!d->mAggregation) { return; } QMenu *menu = qobject_cast< QMenu * >(sender()); if (!menu) { return; } sortOrderMenuAboutToShow(menu); } void Widget::sortOrderMenuAboutToShow(QMenu *menu) { menu->clear(); menu->addSection(i18n("Message Sort Order")); QActionGroup *grp; QAction *act; QVector< QPair< QString, int > > options; grp = new QActionGroup(menu); options = SortOrder::enumerateMessageSortingOptions(d->mAggregation->threading()); for (const auto &opt : qAsConst(options)) { act = menu->addAction(opt.first); act->setCheckable(true); grp->addAction(act); act->setChecked(d->mSortOrder.messageSorting() == opt.second); act->setData(QVariant(opt.second)); } connect(grp, &QActionGroup::triggered, this, &Widget::messageSortingSelected); options = SortOrder::enumerateMessageSortDirectionOptions(d->mSortOrder.messageSorting()); if (options.size() >= 2) { menu->addSection(i18n("Message Sort Direction")); grp = new QActionGroup(menu); for (const auto &opt : qAsConst(options)) { act = menu->addAction(opt.first); act->setCheckable(true); grp->addAction(act); act->setChecked(d->mSortOrder.messageSortDirection() == opt.second); act->setData(QVariant(opt.second)); } connect(grp, &QActionGroup::triggered, this, &Widget::messageSortDirectionSelected); } options = SortOrder::enumerateGroupSortingOptions(d->mAggregation->grouping()); if (options.size() >= 2) { menu->addSection(i18n("Group Sort Order")); grp = new QActionGroup(menu); for (const auto &opt : qAsConst(options)) { act = menu->addAction(opt.first); act->setCheckable(true); grp->addAction(act); act->setChecked(d->mSortOrder.groupSorting() == opt.second); act->setData(QVariant(opt.second)); } connect(grp, &QActionGroup::triggered, this, &Widget::groupSortingSelected); } options = SortOrder::enumerateGroupSortDirectionOptions(d->mAggregation->grouping(), d->mSortOrder.groupSorting()); if (options.size() >= 2) { menu->addSection(i18n("Group Sort Direction")); grp = new QActionGroup(menu); for (const auto &opt : qAsConst(options)) { act = menu->addAction(opt.first); act->setCheckable(true); grp->addAction(act); act->setChecked(d->mSortOrder.groupSortDirection() == opt.second); act->setData(QVariant(opt.second)); } connect(grp, &QActionGroup::triggered, this, &Widget::groupSortDirectionSelected); } menu->addSeparator(); act = menu->addAction(i18n("Folder Always Uses This Sort Order")); act->setCheckable(true); act->setChecked(d->mStorageUsesPrivateSortOrder); connect(act, &QAction::triggered, this, &Widget::setPrivateSortOrderForStorage); } void Widget::Private::switchMessageSorting(SortOrder::MessageSorting messageSorting, SortOrder::SortDirection sortDirection, int logicalHeaderColumnIndex) { mSortOrder.setMessageSorting(messageSorting); mSortOrder.setMessageSortDirection(sortDirection); // If the logicalHeaderColumnIndex was specified then we already know which // column we should set the sort indicator to. If it wasn't specified (it's -1) // then we need to find it out in the theme. if (logicalHeaderColumnIndex == -1) { // try to find the specified message sorting in the theme columns const auto columns = mTheme->columns(); int idx = 0; // First try with a well defined message sorting. for (const auto column : qAsConst(columns)) { if (!mView->header()->isSectionHidden(idx)) { if (column->messageSorting() == messageSorting) { // found a visible column with this message sorting logicalHeaderColumnIndex = idx; break; } } ++idx; } // if still not found, try again with a wider range if (logicalHeaderColumnIndex == -1) { idx = 0; for (const auto column : qAsConst(columns)) { if (!mView->header()->isSectionHidden(idx)) { if ( ( (column->messageSorting() == SortOrder::SortMessagesBySenderOrReceiver) || (column->messageSorting() == SortOrder::SortMessagesByReceiver) || (column->messageSorting() == SortOrder::SortMessagesBySender) ) && ( (messageSorting == SortOrder::SortMessagesBySenderOrReceiver) || (messageSorting == SortOrder::SortMessagesByReceiver) || (messageSorting == SortOrder::SortMessagesBySender) ) ) { // found a visible column with this message sorting logicalHeaderColumnIndex = idx; break; } } ++idx; } } } if (logicalHeaderColumnIndex == -1) { // not found: either not a column-based sorting or the related column is hidden mView->header()->setSortIndicatorShown(false); return; } mView->header()->setSortIndicatorShown(true); if (sortDirection == SortOrder::Ascending) { mView->header()->setSortIndicator(logicalHeaderColumnIndex, Qt::AscendingOrder); } else { mView->header()->setSortIndicator(logicalHeaderColumnIndex, Qt::DescendingOrder); } } void Widget::messageSortingSelected(QAction *action) { if (!d->mAggregation) { return; } if (!action) { return; } if (!d->mStorageModel) { return; } bool ok; auto ord = static_cast< SortOrder::MessageSorting >(action->data().toInt(&ok)); if (!ok) { return; } d->switchMessageSorting(ord, d->mSortOrder.messageSortDirection(), -1); Manager::instance()->saveSortOrderForStorageModel(d->mStorageModel, d->mSortOrder, d->mStorageUsesPrivateSortOrder); d->mView->reload(); } void Widget::messageSortDirectionSelected(QAction *action) { if (!d->mAggregation) { return; } if (!action) { return; } if (!d->mStorageModel) { return; } bool ok; auto ord = static_cast< SortOrder::SortDirection >(action->data().toInt(&ok)); if (!ok) { return; } d->switchMessageSorting(d->mSortOrder.messageSorting(), ord, -1); Manager::instance()->saveSortOrderForStorageModel(d->mStorageModel, d->mSortOrder, d->mStorageUsesPrivateSortOrder); d->mView->reload(); } void Widget::groupSortingSelected(QAction *action) { if (!d->mAggregation) { return; } if (!action) { return; } if (!d->mStorageModel) { return; } bool ok; auto ord = static_cast< SortOrder::GroupSorting >(action->data().toInt(&ok)); if (!ok) { return; } d->mSortOrder.setGroupSorting(ord); Manager::instance()->saveSortOrderForStorageModel(d->mStorageModel, d->mSortOrder, d->mStorageUsesPrivateSortOrder); d->mView->reload(); } void Widget::groupSortDirectionSelected(QAction *action) { if (!d->mAggregation) { return; } if (!action) { return; } if (!d->mStorageModel) { return; } bool ok; auto ord = static_cast< SortOrder::SortDirection >(action->data().toInt(&ok)); if (!ok) { return; } d->mSortOrder.setGroupSortDirection(ord); Manager::instance()->saveSortOrderForStorageModel(d->mStorageModel, d->mSortOrder, d->mStorageUsesPrivateSortOrder); d->mView->reload(); } void Widget::resetFilter() { delete d->mFilter; d->mFilter = nullptr; d->mView->model()->setFilter(nullptr); d->quickSearchLine->resetFilter(); d->quickSearchWarning->animatedHide(); } void Widget::slotViewHeaderSectionClicked(int logicalIndex) { if (!d->mTheme) { return; } if (!d->mAggregation) { return; } if (logicalIndex >= d->mTheme->columns().count()) { return; } if (!d->mStorageModel) { return; } auto column = d->mTheme->column(logicalIndex); if (!column) { return; // should never happen... } if (column->messageSorting() == SortOrder::NoMessageSorting) { return; // this is a null op. } if (d->mSortOrder.messageSorting() == column->messageSorting()) { // switch sort direction if (d->mSortOrder.messageSortDirection() == SortOrder::Ascending) { d->switchMessageSorting(d->mSortOrder.messageSorting(), SortOrder::Descending, logicalIndex); } else { d->switchMessageSorting(d->mSortOrder.messageSorting(), SortOrder::Ascending, logicalIndex); } } else { // keep sort direction but switch sort order d->switchMessageSorting(column->messageSorting(), d->mSortOrder.messageSortDirection(), logicalIndex); } Manager::instance()->saveSortOrderForStorageModel(d->mStorageModel, d->mSortOrder, d->mStorageUsesPrivateSortOrder); d->mView->reload(); } void Widget::themesChanged() { d->setDefaultThemeForStorageModel(d->mStorageModel); d->mView->reload(); } void Widget::aggregationsChanged() { d->setDefaultAggregationForStorageModel(d->mStorageModel); d->checkSortOrder(d->mStorageModel); d->mView->reload(); } void Widget::fillMessageTagCombo() { // nothing here: must be overridden in derived classes setCurrentStatusFilterItem(); } void Widget::tagIdSelected(const QVariant &data) { QString tagId = data.toString(); if (tagId.isEmpty()) { if (d->mFilter) { if (d->mFilter->isEmpty()) { resetFilter(); return; } } } else { if (!d->mFilter) { d->mFilter = new Filter(); } d->mFilter->setTagId(tagId); } d->mView->model()->setFilter(d->mFilter); } void Widget::statusSelected(int index) { if (index == 0) { resetFilter(); return; } tagIdSelected(d->quickSearchLine->tagFilterComboBox()->itemData(index)); d->mView->model()->setFilter(d->mFilter); } void Widget::searchEditTextEdited() { // This slot is called whenever the user edits the search QLineEdit. // Since the user is likely to type more than one character // so we start the real search after a short delay in order to catch // multiple textEdited() signals. if (!d->mSearchTimer) { d->mSearchTimer = new QTimer(this); connect(d->mSearchTimer, &QTimer::timeout, this, &Widget::searchTimerFired); } else { d->mSearchTimer->stop(); // eventually } d->mSearchTimer->setSingleShot(true); d->mSearchTimer->start(1000); } void Widget::slotStatusButtonsClicked() { // We also arbitrarily set tagId to an empty string, though we *could* allow filtering // by status AND tag... if (d->mFilter) { d->mFilter->setTagId(QString()); } auto lst = d->quickSearchLine->status(); if (lst.isEmpty()) { if (d->mFilter) { d->mFilter->setStatus(lst); if (d->mFilter->isEmpty()) { qCDebug(MESSAGELIST_LOG) << " RESET FILTER"; resetFilter(); return; } } } else { // don't have this status bit if (!d->mFilter) { d->mFilter = new Filter(); } d->mFilter->setStatus(lst); } d->mView->model()->setFilter(d->mFilter); } void Widget::searchTimerFired() { // A search is pending. if (d->mSearchTimer) { d->mSearchTimer->stop(); } if (!d->mFilter) { d->mFilter = new Filter(); } const QString text = d->quickSearchLine->searchEdit()->text(); if (!text.isEmpty()) { d->quickSearchLine->addCompletionItem(text); } d->mFilter->setCurrentFolder(d->mCurrentFolder); d->mFilter->setSearchString(text, d->quickSearchLine->searchOptions()); d->quickSearchWarning->setSearchText(text); if (d->mFilter->isEmpty()) { resetFilter(); return; } d->mView->model()->setFilter(d->mFilter); } void Widget::searchEditClearButtonClicked() { if (!d->mFilter) { return; } resetFilter(); d->mView->scrollTo(d->mView->currentIndex(), QAbstractItemView::PositionAtCenter); } void Widget::viewMessageSelected(MessageItem *) { } void Widget::viewMessageActivated(MessageItem *) { } void Widget::viewSelectionChanged() { } void Widget::viewMessageListContextPopupRequest(const QVector< MessageItem * > &, const QPoint &) { } void Widget::viewGroupHeaderContextPopupRequest(GroupHeaderItem *, const QPoint &) { } void Widget::viewDragEnterEvent(QDragEnterEvent *) { } void Widget::viewDragMoveEvent(QDragMoveEvent *) { } void Widget::viewDropEvent(QDropEvent *) { } void Widget::viewStartDragRequest() { } void Widget::viewMessageStatusChangeRequest(MessageItem *msg, Akonadi::MessageStatus set, Akonadi::MessageStatus clear) { Q_UNUSED(msg); Q_UNUSED(set); Q_UNUSED(clear); } void Widget::focusQuickSearch(const QString &selectedText) { d->quickSearchLine->focusQuickSearch(selectedText); } bool Widget::isThreaded() const { return d->mView->isThreaded(); } bool Widget::selectionEmpty() const { return d->mView->selectionEmpty(); } Akonadi::Collection Widget::currentFolder() const { return d->mCurrentFolder; } void Widget::setCurrentFolder(const Akonadi::Collection &collection) { d->mCurrentFolder = collection; d->searchCollectionIndexingWarning->setCollection(collection); } bool Widget::searchEditHasFocus() const { return d->quickSearchLine->searchEdit()->hasFocus(); } diff --git a/messageviewer/src/widgets/configurewidget.cpp b/messageviewer/src/widgets/configurewidget.cpp index f09154e6..7ab89426 100644 --- a/messageviewer/src/widgets/configurewidget.cpp +++ b/messageviewer/src/widgets/configurewidget.cpp @@ -1,126 +1,121 @@ /* Copyright (C) 2009 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.net Copyright (c) 2009 Andras Mantia This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "configurewidget.h" #include "messageviewer_debug.h" #include "ui_settings.h" #include "utils/messageviewerutil.h" #include "settings/messageviewersettings.h" #include #include "MessageCore/MessageCoreSettings" #include using namespace MessageViewer; class MessageViewer::ConfigureWidgetPrivate { public: ConfigureWidgetPrivate() { } ~ConfigureWidgetPrivate() { delete mSettingsUi; mSettingsUi = nullptr; } Ui_Settings *mSettingsUi = nullptr; }; ConfigureWidget::ConfigureWidget(QWidget *parent) : QWidget(parent) , d(new MessageViewer::ConfigureWidgetPrivate) { d->mSettingsUi = new Ui_Settings; d->mSettingsUi->setupUi(this); layout()->setContentsMargins(0, 0, 0, 0); QStringList encodings = MimeTreeParser::NodeHelper::supportedEncodings(false); encodings.prepend(i18n("Auto")); d->mSettingsUi->overrideCharacterEncoding->addItems(encodings); d->mSettingsUi->overrideCharacterEncoding->setCurrentIndex(0); d->mSettingsUi->overrideCharacterEncoding->setWhatsThis( MessageCore::MessageCoreSettings::self()->overrideCharacterEncodingItem()->whatsThis()); d->mSettingsUi->kcfg_ShrinkQuotes->setWhatsThis( MessageViewer::MessageViewerSettings::self()->shrinkQuotesItem()->whatsThis()); d->mSettingsUi->kcfg_ShowExpandQuotesMark->setWhatsThis( MessageViewer::MessageViewerSettings::self()->showExpandQuotesMarkItem()->whatsThis()); -#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) connect(d->mSettingsUi->overrideCharacterEncoding, qOverload(&QComboBox::currentIndexChanged), this, &ConfigureWidget::settingsChanged); -#else - connect(d->mSettingsUi->overrideCharacterEncoding, qOverload(&QComboBox::currentIndexChanged), this, - &ConfigureWidget::settingsChanged); -#endif } ConfigureWidget::~ConfigureWidget() { delete d; } void ConfigureWidget::readConfig() { readCurrentOverrideCodec(); d->mSettingsUi->kcfg_CollapseQuoteLevelSpin->setEnabled( MessageViewer::MessageViewerSettings::self()->showExpandQuotesMark()); } void ConfigureWidget::writeConfig() { MessageCore::MessageCoreSettings::self()->setOverrideCharacterEncoding( d->mSettingsUi->overrideCharacterEncoding->currentIndex() == 0 ? QString() : MimeTreeParser::NodeHelper::encodingForName(d->mSettingsUi->overrideCharacterEncoding-> currentText())); } void ConfigureWidget::readCurrentOverrideCodec() { const QString ¤tOverrideEncoding = MessageCore::MessageCoreSettings::self()->overrideCharacterEncoding(); if (currentOverrideEncoding.isEmpty()) { d->mSettingsUi->overrideCharacterEncoding->setCurrentIndex(0); return; } QStringList encodings = MimeTreeParser::NodeHelper::supportedEncodings(false); encodings.prepend(i18n("Auto")); QStringList::ConstIterator it(encodings.constBegin()); const QStringList::ConstIterator end(encodings.constEnd()); int i = 0; for (; it != end; ++it) { if (MimeTreeParser::NodeHelper::encodingForName(*it) == currentOverrideEncoding) { d->mSettingsUi->overrideCharacterEncoding->setCurrentIndex(i); break; } ++i; } if (i == encodings.size()) { // the current value of overrideCharacterEncoding is an unknown encoding => reset to Auto qCWarning(MESSAGEVIEWER_LOG) << "Unknown override character encoding" << currentOverrideEncoding << ". Resetting to Auto."; d->mSettingsUi->overrideCharacterEncoding->setCurrentIndex(0); MessageCore::MessageCoreSettings::self()->setOverrideCharacterEncoding(QString()); } }