diff --git a/CMakeLists.txt b/CMakeLists.txt index 822aa613..e780722a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,133 +1,134 @@ cmake_minimum_required(VERSION 3.5) set(PIM_VERSION "5.11.42") if (POLICY CMP0053) cmake_policy(SET CMP0053 NEW) endif() project(Messagelib VERSION ${PIM_VERSION}) option(MIMETREEPARSER_ONLY_BUILD "Build only mimetreeparser" FALSE) option(KDEPIM_ENTERPRISE_BUILD "Enable features specific to the enterprise branch, which are normally disabled. Also, it disables many components not needed for Kontact such as the Kolab client." FALSE) option(KDEPIM_RUN_AKONADI_TEST "Enable autotest based on Akonadi." TRUE) option(DKIM_CHECKER_BUILD "DKIM CHECKER (experimental)" FALSE) -set(KF5_MIN_VERSION "5.57.0") +set(KF5_MIN_VERSION "5.58.0") set(MESSAGELIB_LIB_VERSION ${PIM_VERSION}) set(AKONADIMIME_LIB_VERSION "5.11.40") set(QT_REQUIRED_VERSION "5.10.0") set(AKONADI_VERSION "5.11.40") set(GRANTLEETHEME_LIB_VERSION "5.11.40") set(GRAVATAR_LIB_VERSION "5.11.40") set(IDENTITYMANAGEMENT_LIB_VERSION "5.11.40") set(KCONTACTS_LIB_VERSION "5.11.40") set(KDEPIM_APPS_LIB_VERSION "5.11.40") set(KLDAP_LIB_VERSION "5.11.40") set(KMAILTRANSPORT_LIB_VERSION "5.11.40") set(KMBOX_LIB_VERSION "5.11.40") set(KMIME_LIB_VERSION "5.11.40") set(KPIMTEXTEDIT_LIB_VERSION "5.11.40") set(LIBKDEPIM_LIB_VERSION "5.11.40") set(LIBKLEO_LIB_VERSION "5.11.40") set(PIMCOMMON_LIB_VERSION "5.11.40") set(GPGME_LIB_VERSION "1.11.1") set(AKONADI_CONTACT_VERSION "5.11.40") if (${MIMETREEPARSER_ONLY_BUILD}) set(ECM_VERSION "5.26.0") set(KMIME_LIB_VERSION "5.1.40") else() set(ECM_VERSION ${KF5_MIN_VERSION}) endif() find_package(ECM ${ECM_VERSION} CONFIG REQUIRED) set(CMAKE_MODULE_PATH ${Messagelib_SOURCE_DIR}/cmake/modules ${ECM_MODULE_PATH}) set(LIBRARY_NAMELINK) include(GenerateExportHeader) include(ECMSetupVersion) include(ECMGenerateHeaders) include(ECMGeneratePriFile) include(FeatureSummary) include(KDEInstallDirs) include(KDECMakeSettings) include(KDEFrameworkCompilerSettings NO_POLICY_SCOPE) include(ECMQtDeclareLoggingCategory) include(ECMAddTests) find_package(Qt5 ${QT_REQUIRED_VERSION} CONFIG REQUIRED Gui Test) find_package(KF5Codecs ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5I18n ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5Mime ${KMIME_LIB_VERSION} CONFIG REQUIRED) +find_package(KF5NewStuff ${KMIME_LIB_VERSION} CONFIG REQUIRED) find_package(QGpgme ${GPGME_LIB_VERSION} CONFIG REQUIRED) message(STATUS "GPGME Version ${QGpgme_VERSION}") if (NOT ${MIMETREEPARSER_ONLY_BUILD}) find_package(Qt5 ${QT_REQUIRED_VERSION} CONFIG REQUIRED Widgets Network PrintSupport WebEngine WebEngineWidgets) find_package(KF5Archive ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5Completion ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5Config ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5ConfigWidgets ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5IconThemes ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5ItemViews ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5JobWidgets ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5KIO ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5Service ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5Sonnet ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5TextWidgets ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5WidgetsAddons ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5WindowSystem ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5XmlGui ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5SyntaxHighlighting ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5DBusAddons ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(Grantlee5 "5.1" CONFIG REQUIRED) find_package(KF5Akonadi ${AKONADI_VERSION} CONFIG REQUIRED) find_package(KF5AkonadiMime ${AKONADIMIME_LIB_VERSION} CONFIG REQUIRED) find_package(KF5Contacts ${KCONTACTS_LIB_VERSION} CONFIG REQUIRED) find_package(KF5AkonadiContact ${AKONADI_CONTACT_VERSION} CONFIG REQUIRED) find_package(KF5FollowupReminder ${KDEPIM_APPS_LIB_VERSION} CONFIG REQUIRED) find_package(KF5GrantleeTheme ${GRANTLEETHEME_LIB_VERSION} CONFIG REQUIRED) find_package(KF5Gravatar ${GRAVATAR_LIB_VERSION} CONFIG REQUIRED) find_package(KF5IdentityManagement ${IDENTITYMANAGEMENT_LIB_VERSION} CONFIG REQUIRED) find_package(KF5KaddressbookGrantlee ${KDEPIM_APPS_LIB_VERSION} CONFIG REQUIRED) find_package(KF5Ldap ${KLDAP_LIB_VERSION} CONFIG REQUIRED) find_package(KF5LibkdepimAkonadi ${LIBKDEPIM_LIB_VERSION} CONFIG REQUIRED) find_package(KF5Libkleo ${LIBKLEO_LIB_VERSION} CONFIG REQUIRED) find_package(KF5MailTransportAkonadi ${KMAILTRANSPORT_LIB_VERSION} CONFIG REQUIRED) find_package(KF5Mbox ${KMBOX_LIB_VERSION} CONFIG REQUIRED) find_package(KF5PimCommonAkonadi ${PIMCOMMON_LIB_VERSION} CONFIG REQUIRED) find_package(KF5PimTextEdit ${KPIMTEXTEDIT_LIB_VERSION} CONFIG REQUIRED) find_package(KF5SendLater ${KDEPIM_APPS_LIB_VERSION} CONFIG REQUIRED) find_package(KF5AkonadiSearch "5.11.40" CONFIG REQUIRED) set_package_properties(KF5AkonadiSearch PROPERTIES DESCRIPTION "The Akonadi Search libraries" URL "http://www.kde.org" TYPE REQUIRED PURPOSE "Provides search capabilities in KMail and Akonadi") endif() set(CMAKE_CXX_STANDARD 14) #add_definitions(-DQT_DISABLE_DEPRECATED_BEFORE=0x060000) if(BUILD_TESTING) add_definitions(-DBUILD_TESTING) endif() add_subdirectory(mimetreeparser) if (NOT ${MIMETREEPARSER_ONLY_BUILD}) add_subdirectory(messageviewer) add_subdirectory(templateparser) add_subdirectory(messagecomposer) add_subdirectory(messagecore) add_subdirectory(messagelist) add_subdirectory(webengineviewer) endif() install( FILES messagelib.renamecategories messagelib.categories DESTINATION ${KDE_INSTALL_CONFDIR} ) feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES) diff --git a/messagecomposer/src/recipient/distributionlistdialog.cpp b/messagecomposer/src/recipient/distributionlistdialog.cpp index a86cb85d..23896453 100644 --- a/messagecomposer/src/recipient/distributionlistdialog.cpp +++ b/messagecomposer/src/recipient/distributionlistdialog.cpp @@ -1,360 +1,364 @@ /* Copyright (c) 2010 Volker Krause This file was part of KMail. Copyright (c) 2005 Cornelius Schumacher 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 "distributionlistdialog.h" #include #include #include #include #include #include #include "messagecomposer_debug.h" #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace MessageComposer; namespace MessageComposer { class DistributionListItem : public QTreeWidgetItem { public: explicit DistributionListItem(QTreeWidget *tree) : QTreeWidgetItem(tree) { setFlags(flags() | Qt::ItemIsUserCheckable); } void setAddressee(const KContacts::Addressee &a, const QString &email) { init(a, email); } void init(const KContacts::Addressee &a, const QString &email) { mAddressee = a; mEmail = email; mId = -1; setText(0, mAddressee.realName()); setText(1, mEmail); } KContacts::Addressee addressee() const { return mAddressee; } QString email() const { return mEmail; } bool isTransient() const { return mId == -1; } void setId(Akonadi::Item::Id id) { mId = id; } Akonadi::Item::Id id() const { return mId; } private: KContacts::Addressee mAddressee; QString mEmail; Akonadi::Item::Id mId = -1; }; } DistributionListDialog::DistributionListDialog(QWidget *parent) : QDialog(parent) { setWindowTitle(i18nc("@title:window", "Save Distribution List")); + setModal(false); + QVBoxLayout *mainLayout = new QVBoxLayout(this); + + QWidget *topFrame = new QWidget(this); mainLayout->addWidget(topFrame); QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Cancel, this); - mUser1Button = new QPushButton; + mUser1Button = new QPushButton(this); buttonBox->addButton(mUser1Button, QDialogButtonBox::ActionRole); mUser1Button->setText(i18nc("@action:button", "Save List")); mUser1Button->setEnabled(false); mUser1Button->setDefault(true); connect(buttonBox, &QDialogButtonBox::accepted, this, &DistributionListDialog::accept); connect(buttonBox, &QDialogButtonBox::rejected, this, &DistributionListDialog::reject); + mainLayout->addWidget(buttonBox); - setModal(false); QBoxLayout *topLayout = new QVBoxLayout(topFrame); topLayout->setContentsMargins(0, 0, 0, 0); QBoxLayout *titleLayout = new QHBoxLayout(); topLayout->addItem(titleLayout); QLabel *label = new QLabel( i18nc("@label:textbox Name of the distribution list.", "&Name:"), topFrame); titleLayout->addWidget(label); mTitleEdit = new QLineEdit(topFrame); titleLayout->addWidget(mTitleEdit); mTitleEdit->setFocus(); mTitleEdit->setClearButtonEnabled(true); label->setBuddy(mTitleEdit); mRecipientsList = new QTreeWidget(topFrame); mRecipientsList->setHeaderLabels( QStringList() << i18nc("@title:column Name of the recipient", "Name") << i18nc("@title:column Email of the recipient", "Email") ); mRecipientsList->setRootIsDecorated(false); mRecipientsList->header()->setSectionsMovable(false); topLayout->addWidget(mRecipientsList); connect(mUser1Button, &QPushButton::clicked, this, &DistributionListDialog::slotUser1); connect(mTitleEdit, &QLineEdit::textChanged, this, &DistributionListDialog::slotTitleChanged); readConfig(); } DistributionListDialog::~DistributionListDialog() { writeConfig(); } // This starts one ContactSearchJob for each of the specified recipients. void DistributionListDialog::setRecipients(const Recipient::List &recipients) { Recipient::List::ConstIterator end(recipients.constEnd()); for (Recipient::List::ConstIterator it = recipients.constBegin(); it != end; ++it) { const QStringList emails = KEmailAddress::splitAddressList((*it)->email()); QStringList::ConstIterator end2(emails.constEnd()); for (QStringList::ConstIterator it2 = emails.constBegin(); it2 != end2; ++it2) { QString name; QString email; KContacts::Addressee::parseEmailAddress(*it2, name, email); if (!email.isEmpty()) { Akonadi::ContactSearchJob *job = new Akonadi::ContactSearchJob(this); job->setQuery(Akonadi::ContactSearchJob::Email, email.toLower(), Akonadi::ContactSearchJob::ExactMatch); job->setProperty("name", name); job->setProperty("email", email); connect(job, &Akonadi::ContactSearchJob::result, this, &DistributionListDialog::slotDelayedSetRecipients); } } } } // This result slot will be called once for each of the original recipients. // There could potentially be more than one Akonadi item returned per // recipient, in the case where email addresses are duplicated between contacts. void DistributionListDialog::slotDelayedSetRecipients(KJob *job) { const Akonadi::ContactSearchJob *searchJob = qobject_cast(job); const Akonadi::Item::List akItems = searchJob->items(); const QString email = searchJob->property("email").toString(); QString name = searchJob->property("name").toString(); if (name.isEmpty()) { const int index = email.indexOf(QLatin1Char('@')); if (index != -1) { name = email.left(index); } else { name = email; } } if (akItems.isEmpty()) { KContacts::Addressee contact; contact.setNameFromString(name); contact.insertEmail(email); DistributionListItem *item = new DistributionListItem(mRecipientsList); item->setAddressee(contact, email); item->setCheckState(0, Qt::Checked); } else { bool isFirst = true; for (const Akonadi::Item &akItem : qAsConst(akItems)) { if (akItem.hasPayload()) { const KContacts::Addressee contact = akItem.payload(); DistributionListItem *item = new DistributionListItem(mRecipientsList); item->setAddressee(contact, email); // Need to record the Akonadi ID of the contact, so that // it can be added as a reference later. Setting an ID // makes the item non-transient. item->setId(akItem.id()); // If there were multiple contacts returned for an email address, // then check the first one and uncheck any subsequent ones. if (isFirst) { item->setCheckState(0, Qt::Checked); isFirst = false; } else { // Need this to create an unchecked item, as otherwise the // item will have no checkbox at all. item->setCheckState(0, Qt::Unchecked); } } } } } void DistributionListDialog::slotUser1() { bool isEmpty = true; const int numberOfTopLevel(mRecipientsList->topLevelItemCount()); for (int i = 0; i < numberOfTopLevel; ++i) { DistributionListItem *item = static_cast( mRecipientsList->topLevelItem(i)); if (item && item->checkState(0) == Qt::Checked) { isEmpty = false; break; } } if (isEmpty) { KMessageBox::information(this, i18nc("@info", "There are no recipients in your list. " "First select some recipients, " "then try again.")); return; } QString name = mTitleEdit->text(); if (name.isEmpty()) { bool ok = false; name = QInputDialog::getText(this, i18nc("@title:window", "New Distribution List"), i18nc("@label:textbox", "Please enter name:"), QLineEdit::Normal, QString(), &ok); if (!ok || name.isEmpty()) { return; } } Akonadi::ContactGroupSearchJob *job = new Akonadi::ContactGroupSearchJob(); job->setQuery(Akonadi::ContactGroupSearchJob::Name, name); job->setProperty("name", name); qDebug() << " name " << name; connect(job, &Akonadi::ContactSearchJob::result, this, &DistributionListDialog::slotDelayedUser1); } void DistributionListDialog::slotDelayedUser1(KJob *job) { const Akonadi::ContactGroupSearchJob *searchJob = qobject_cast(job); const QString name = searchJob->property("name").toString(); if (!searchJob->contactGroups().isEmpty()) { qDebug() << " searchJob->contactGroups()" << searchJob->contactGroups().count(); KMessageBox::information(this, xi18nc("@info", "Distribution list with the given name %1 " "already exists. Please select a different name.", name)); return; } QPointer dlg = new Akonadi::CollectionDialog(Akonadi::CollectionDialog::KeepTreeExpanded, nullptr, this); dlg->setMimeTypeFilter(QStringList() << KContacts::Addressee::mimeType() << KContacts::ContactGroup::mimeType()); dlg->setAccessRightsFilter(Akonadi::Collection::CanCreateItem); dlg->setWindowTitle(i18nc("@title:window", "Select Address Book")); dlg->setDescription(i18n("Select the address book folder to store the contact group in:")); if (dlg->exec()) { const Akonadi::Collection targetCollection = dlg->selectedCollection(); delete dlg; KContacts::ContactGroup group(name); const int numberOfTopLevel(mRecipientsList->topLevelItemCount()); for (int i = 0; i < numberOfTopLevel; ++i) { DistributionListItem *item = static_cast(mRecipientsList->topLevelItem(i)); if (item && item->checkState(0) == Qt::Checked) { qCDebug(MESSAGECOMPOSER_LOG) << item->addressee().fullEmail() << item->addressee().uid(); if (item->isTransient()) { group.append(KContacts::ContactGroup::Data(item->addressee().realName(), item->email())); } else { KContacts::ContactGroup::ContactReference reference(QString::number(item->id())); if (item->email() != item->addressee().preferredEmail()) { reference.setPreferredEmail(item->email()); } group.append(reference); } } } Akonadi::Item groupItem(KContacts::ContactGroup::mimeType()); groupItem.setPayload(group); Akonadi::Job *createJob = new Akonadi::ItemCreateJob(groupItem, targetCollection); connect(createJob, &Akonadi::ItemCreateJob::result, this, &DistributionListDialog::slotContactGroupCreateJobResult); } delete dlg; } void DistributionListDialog::slotContactGroupCreateJobResult(KJob *job) { if (job->error()) { KMessageBox::information(this, i18n("Unable to create distribution list: %1", job->errorString())); qCWarning(MESSAGECOMPOSER_LOG) << "Unable to create distribution list:" << job->errorText(); } else { accept(); } } void DistributionListDialog::slotTitleChanged(const QString &text) { mUser1Button->setEnabled(!text.trimmed().isEmpty()); } void DistributionListDialog::readConfig() { KSharedConfig::Ptr cfg = KSharedConfig::openConfig(); KConfigGroup group(cfg, "DistributionListDialog"); const QSize size = group.readEntry("Size", QSize()); if (!size.isEmpty()) { resize(size); } mRecipientsList->header()->restoreState(group.readEntry("Header", QByteArray())); } void DistributionListDialog::writeConfig() { KSharedConfig::Ptr cfg = KSharedConfig::openConfig(); KConfigGroup group(cfg, "DistributionListDialog"); group.writeEntry("Size", size()); group.writeEntry("Header", mRecipientsList->header()->saveState()); } diff --git a/messageviewer/src/CMakeLists.txt b/messageviewer/src/CMakeLists.txt index fd19af49..2ec5d209 100644 --- a/messageviewer/src/CMakeLists.txt +++ b/messageviewer/src/CMakeLists.txt @@ -1,503 +1,503 @@ add_definitions(-DTRANSLATION_DOMAIN=\"libmessageviewer\") add_subdirectory(messagepartthemes/grantlee) # KCFG files: # The main messageviewer.kcfg is configured by CMake and put in the build directory. if(KDEPIM_ENTERPRISE_BUILD) set(LEGACY_MANGLE_FROM_TO_HEADERS true) set(LEGACY_BODY_INVITES true) set(EXCHANGE_COMPATIBLE_INVITATIONS true) else() set(LEGACY_MANGLE_FROM_TO_HEADERS false) set(LEGACY_BODY_INVITES false) set(EXCHANGE_COMPATIBLE_INVITATIONS false) endif() configure_file(settings/messageviewer.kcfg.cmake ${CMAKE_CURRENT_BINARY_DIR}/messageviewer.kcfg) include(CheckIncludeFiles) find_package(Inotify) set_package_properties(Inotify PROPERTIES PURPOSE "Filesystem alteration notifications using inotify") if(Inotify_FOUND) set(HAVE_SYS_INOTIFY_H 1) else() set(HAVE_SYS_INOTIFY_H 0) endif() configure_file(config-messageviewer.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-messageviewer.h) # target_include_directories does not handle empty include paths include_directories(${GPGME_INCLUDES}) if(BUILD_TESTING) add_subdirectory(header/autotests) add_subdirectory(scamdetection/autotests) add_subdirectory(scamdetection/tests) add_subdirectory(viewerplugins/tests/) add_subdirectory(htmlwriter/autotests) add_subdirectory(viewer/webengine/tests) add_subdirectory(messagepartthemes/default/autotests) add_subdirectory(widgets/autotests/) add_subdirectory(utils/autotests) endif() add_subdirectory(pics) add_subdirectory(kconf_update) add_subdirectory(about) add_subdirectory(messageviewerheaderplugins) if (DKIM_CHECKER_BUILD) add_subdirectory(dkim-verify) set(dkim_verify_SRCS dkim-verify/dkiminfo.cpp dkim-verify/dkimmanagerkey.cpp dkim-verify/dkimmanagerkeywidget.cpp dkim-verify/dkimmanagerkeydialog.cpp dkim-verify/dkimdownloadkeyjob.cpp dkim-verify/dkimchecksignaturejob.cpp dkim-verify/dkimcheckauthenticationstatusjob.cpp dkim-verify/dkimauthenticationstatusinfo.cpp dkim-verify/dkimutil.cpp ) endif() if(DEBUG_SIGNATURE) add_definitions(-DDEBUG_SIGNATURE) endif() set(libmessageviewer_mailviewer_SRCS viewer/webengine/mailwebengineview.cpp viewer/webengine/mailwebenginepage.cpp viewer/webengine/loadexternalreferencesurlinterceptor/loadexternalreferencesurlinterceptor.cpp viewer/webengine/cidreferencesurlinterceptor/cidreferencesurlinterceptor.cpp viewer/webengine/blockexternalresourcesurlinterceptor/blockexternalresourcesurlinterceptor.cpp viewer/webengine/blockmailtrackingurlinterceptor/blockmailtrackingurlinterceptor.cpp ) set(libmessageviewer_viewer_SRCS viewer/attachmentstrategy.cpp viewer/csshelper.cpp viewer/csshelperbase.cpp viewer/editorwatcher.cpp viewer/objecttreeemptysource.cpp viewer/objecttreeviewersource.cpp viewer/viewer.cpp viewer/viewer_p.cpp viewer/messagedisplayformatattribute.cpp viewer/urlhandlermanager.cpp viewer/mimeparttree/mimeparttreeview.cpp viewer/mimeparttree/mimetreemodel.cpp ) set(libmessageviewer_widgets_SRCS widgets/attachmentdialog.cpp widgets/configurewidget.cpp widgets/printingsettings.cpp widgets/htmlstatusbar.cpp widgets/vcardviewer.cpp widgets/invitationsettings.cpp widgets/openattachmentfolderwidget.cpp widgets/mailsourceviewtextbrowserwidget.cpp widgets/submittedformwarningwidget.cpp widgets/mailtrackingwarningwidget.cpp widgets/mailtrackingdetailsdialog.cpp widgets/shownextmessagewidget.cpp ) set(libmessageviewer_widgets_webengine_SRCS widgets/mailsourcewebengineviewer.cpp ) set(libmessageviewer_header_SRCS header/contactdisplaymessagememento.cpp header/headerstrategy.cpp header/richheaderstrategy.cpp header/headerstyle.cpp header/grantleeheaderstyle.cpp header/plainheaderstyle.cpp header/headerstyle_util.cpp header/grantleeheaderformatter.cpp header/grantleeheaderteststyle.cpp header/kxface.cpp header/headerstyleplugin.cpp header/headerstylepluginmanager.cpp header/headerstyleinterface.cpp header/headerstylemenumanager.cpp ) set(libmessageviewer_scamdetection_SRCS scamdetection/scamdetectionwarningwidget.cpp scamdetection/scamdetectiondetailsdialog.cpp scamdetection/scamattribute.cpp scamdetection/scamcheckshorturl.cpp scamdetection/scamexpandurljob.cpp scamdetection/scamcheckshorturlmanager.cpp ) set(libmessageviewer_scamdetection_webengine_SRCS scamdetection/scamdetectionwebengine.cpp ) set(libmessageviewer_findbar_SRCS findbar/findbarsourceview.cpp ) set(libmessageviewer_utils_SRCS utils/iconnamecache.cpp utils/markmessagereadhandler.cpp utils/messageviewerutil.cpp utils/mimetype.cpp ) set(libmessageviewer_htmlwriter_webengine_SRCS htmlwriter/webengineparthtmlwriter.cpp htmlwriter/webengineembedpart.cpp ) set(libmessageviewer_htmlwriter_SRCS ${libmessageviewer_htmlwriter_webengine_SRCS} htmlwriter/bufferedhtmlwriter.cpp htmlwriter/filehtmlwriter.cpp ) set(libmessageviewer_antispam_SRCS antispam/spamheaderanalyzer.cpp antispam/antispamconfig.cpp ) set(libmessageviewer_job_SRCS job/modifymessagedisplayformatjob.cpp ) set(libmessageviewer_viewerplugins_SRCS viewerplugins/viewerpluginmanager.cpp viewerplugins/viewerplugin.cpp viewerplugins/viewerplugininterface.cpp viewerplugins/viewerplugintoolmanager.cpp ) set(libmessageviewer_configureplugins_SRCS messageviewerconfigureplugins/messageviewerconfiguresettingsplugin.cpp messageviewerconfigureplugins/messageviewerconfiguresettingspluginmanager.cpp messageviewerconfigureplugins/messageviewerconfiguresettingspluginwidget.cpp ) set(libmessageviewer_messagepartthemes_default_SRCS messagepartthemes/default/converthtmltoplaintext.cpp messagepartthemes/default/defaultrenderer.cpp messagepartthemes/default/htmlblock.cpp messagepartthemes/default/messagepartrenderermanager.cpp messagepartthemes/default/plugins/attachmentmessagepartrenderer.cpp messagepartthemes/default/plugins/messagepartrenderer.cpp messagepartthemes/default/plugins/textmessagepartrenderer.cpp messagepartthemes/default/plugins/quotehtml.cpp messagepartthemes/default/messagepartrenderbase.cpp messagepartthemes/default/messagepartrenderplugin.cpp messagepartthemes/default/messagepartrendererfactory.cpp ) set(libmessageviewer_interfaces_SRCS interfaces/htmlwriter.cpp ) set(libmessageviewer_SRCS ${dkim_verify_SRCS} ${libmessageviewer_messagepartthemes_default_SRCS} ${libmessageviewer_htmlwriter_SRCS} ${libmessageviewer_messagepartthemes_SRCS} ${libmessageviewer_scamdetection_webengine_SRCS} ${libmessageviewer_widgets_webengine_SRCS} ${libmessageviewer_viewer_SRCS} ${libmessageviewer_widgets_SRCS} ${libmessageviewer_header_SRCS} ${libmessageviewer_scamdetection_SRCS} ${libmessageviewer_findbar_SRCS} ${libmessageviewer_utils_SRCS} ${libmessageviewer_antispam_SRCS} ${libmessageviewer_job_SRCS} ${libmessageviewer_viewerplugins_SRCS} settings/messageviewersettings.cpp ${libmessageviewer_mailviewer_SRCS} ${libmessageviewer_interfaces_SRCS} ${libmessageviewer_configureplugins_SRCS} ) qt5_add_resources(libmessageviewer_SRCS messagepartthemes.qrc) ecm_qt_declare_logging_category(libmessageviewer_SRCS HEADER messageviewer_debug.h IDENTIFIER MESSAGEVIEWER_LOG CATEGORY_NAME org.kde.pim.messageviewer) kconfig_add_kcfg_files(libmessageviewer_SRCS settings/globalsettings_messageviewer.kcfgc ) ki18n_wrap_ui(libmessageviewer_SRCS ui/settings.ui ui/invitationsettings.ui ui/printingsettings.ui ) add_library(KF5MessageViewer ${libmessageviewer_SRCS}) generate_export_header(KF5MessageViewer BASE_NAME messageviewer) add_library(KF5::MessageViewer ALIAS KF5MessageViewer) target_include_directories(KF5MessageViewer INTERFACE "$;${Inotify_INCLUDE_DIRS}") target_link_libraries(KF5MessageViewer PUBLIC KF5::MessageCore KF5::PimCommon KF5::AkonadiCore KF5::AkonadiMime KF5::Contacts KF5::Libkleo KF5::MimeTreeParser PRIVATE KF5::SyntaxHighlighting KF5::ItemViews Qt5::Network KF5::WebEngineViewer KF5::LibkdepimAkonadi KF5::GrantleeTheme KF5::KaddressbookGrantlee KF5::MailTransportAkonadi KF5::Mime KF5::Mbox KF5::PimTextEdit KF5::Gravatar KF5::IconThemes KF5::I18n KF5::KIOFileWidgets KF5::KIOWidgets KF5::WindowSystem KF5::XmlGui Grantlee5::TextDocument Grantlee5::Templates Qt5::PrintSupport QGpgme ${Inotify_LIBRARIES} ) set_target_properties(KF5MessageViewer PROPERTIES VERSION ${MESSAGEVIEWER_VERSION_STRING} SOVERSION ${MESSAGEVIEWER_SOVERSION} EXPORT_NAME MessageViewer ) install(TARGETS KF5MessageViewer EXPORT KF5MessageViewerTargets ${KF5_INSTALL_TARGETS_DEFAULT_ARGS} ${LIBRARY_NAMELINK} ) ecm_generate_headers(MessageViewer_Camelblockmailtrackingurlinterceptor_HEADERS HEADER_NAMES BlockMailTrackingUrlInterceptor REQUIRED_HEADERS MessageViewer_blockmailtrackingurlinterceptor_HEADERS PREFIX MessageViewer RELATIVE viewer/webengine/blockmailtrackingurlinterceptor ) ecm_generate_headers(MessageViewer_Camelcasewebengine_HEADERS HEADER_NAMES MailWebEnginePage MailWebEngineView REQUIRED_HEADERS MessageViewer_webengine_HEADERS PREFIX MessageViewer RELATIVE viewer/webengine ) ecm_generate_headers(MessageViewer_Camelcasescam_HEADERS HEADER_NAMES ScamExpandUrlJob ScamCheckShortUrlManager ScamCheckShortUrl REQUIRED_HEADERS MessageViewer_scam_HEADERS PREFIX MessageViewer RELATIVE scamdetection ) ecm_generate_headers(MessageViewer_Camelcaseviewer_HEADERS HEADER_NAMES AttachmentStrategy Viewer CSSHelperBase CSSHelper ObjectTreeEmptySource EditorWatcher Stl_Util REQUIRED_HEADERS MessageViewer_viewer_HEADERS PREFIX MessageViewer RELATIVE viewer ) ecm_generate_headers(MessageViewer_Camelcasewidgets_HEADERS HEADER_NAMES InvitationSettings PrintingSettings ConfigureWidget REQUIRED_HEADERS MessageViewer_widgets_HEADERS PREFIX MessageViewer RELATIVE widgets ) ecm_generate_headers(MessageViewer_Camelcaseutils_HEADERS HEADER_NAMES IconNameCache MarkMessageReadHandler MessageViewerUtil MimeType REQUIRED_HEADERS MessageViewer_utils_HEADERS PREFIX MessageViewer RELATIVE utils ) ecm_generate_headers(MessageViewer_Camelcaseantispam_HEADERS HEADER_NAMES SpamHeaderAnalyzer REQUIRED_HEADERS MessageViewer_antispam_HEADERS PREFIX MessageViewer RELATIVE antispam ) ecm_generate_headers(MessageViewer_Camelcaseinterfaces_HEADERS HEADER_NAMES HtmlWriter BodyPartURLHandler URLHandler REQUIRED_HEADERS MessageViewer_interfaces_HEADERS PREFIX MessageViewer RELATIVE interfaces ) ecm_generate_headers(MessageViewer_Camelcasehtmlwriter_HEADERS HEADER_NAMES BufferedHtmlWriter FileHtmlWriter REQUIRED_HEADERS MessageViewer_htmlwriter_HEADERS PREFIX MessageViewer RELATIVE htmlwriter ) ecm_generate_headers(MessageViewer_Camelcasesettings_HEADERS HEADER_NAMES MessageViewerSettings REQUIRED_HEADERS MessageViewer_settings_HEADERS PREFIX MessageViewer RELATIVE settings ) ecm_generate_headers(MessageViewer_CamelcaseConfigurePlugins_HEADERS HEADER_NAMES MessageViewerConfigureSettingsPluginManager MessageViewerConfigureSettingsPlugin MessageViewerConfigureSettingsPluginWidget REQUIRED_HEADERS MessageViewer_ConfigurePlugins_HEADERS PREFIX MessageViewer RELATIVE messageviewerconfigureplugins ) ecm_generate_headers(MessageViewer_Camelcaseheader_HEADERS HEADER_NAMES HeaderStrategy GrantleeHeaderTestStyle GrantleeHeaderStyle HeaderStyle KXFace HeaderStyle_Util HeaderStylePlugin HeaderStyleInterface PlainHeaderStyle RichHeaderStrategy HeaderStylePluginManager HeaderStyleMenuManager REQUIRED_HEADERS MessageViewer_header_HEADERS PREFIX MessageViewer RELATIVE header ) ecm_generate_headers(MessageViewer_Camelcaseviewerplugin_HEADERS HEADER_NAMES ViewerPluginManager ViewerPlugin ViewerPluginInterface ViewerPluginToolManager REQUIRED_HEADERS MessageViewer_viewerplugin_HEADERS PREFIX MessageViewer RELATIVE viewerplugins ) ecm_generate_headers(MessageViewer_Camelcaserenderer_HEADERS HEADER_NAMES HtmlBlock MessagePartRendererBase MessagePartRendererManager MessagePartRenderPlugin REQUIRED_HEADERS MessageViewer_renderer_HEADERS PREFIX MessageViewer RELATIVE messagepartthemes/default ) ecm_generate_pri_file(BASE_NAME MessageViewer LIB_NAME KF5MessageViewer DEPS "PimCommon MessageCore AkonadiCore AkonadiMime Contacts Libkleo MimeTreeParser" FILENAME_VAR PRI_FILENAME INCLUDE_INSTALL_DIR ${KDE_INSTALL_INCLUDEDIR_KF5}/MessageViewer ) install(FILES ${MessageViewer_CamelcaseConfigurePlugins_HEADERS} ${MessageViewer_Camelcasewebengine_HEADERS} ${MessageViewer_Camelcaseheader_HEADERS} ${MessageViewer_Camelcaseviewerplugin_HEADERS} ${MessageViewer_Camelcasesettings_HEADERS} ${MessageViewer_Camelcaseutils_HEADERS} ${MessageViewer_Camelcaseinterfaces_HEADERS} ${MessageViewer_Camelcasehtmlwriter_HEADERS} ${MessageViewer_Camelcaseviewer_HEADERS} ${MessageViewer_Camelcasewidgets_HEADERS} ${MessageViewer_Camelcaseantispam_HEADERS} ${MessageViewer_Camelfindbar_HEADERS} ${MessageViewer_Camelcasescam_HEADERS} ${MessageViewer_Camelcaserenderer_HEADERS} ${MessageViewer_Camelblockmailtrackingurlinterceptor_HEADERS} DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF5}/MessageViewer COMPONENT Devel ) install(FILES ${MessageViewer_ConfigurePlugins_HEADERS} ${MessageViewer_webengine_HEADERS} ${MessageViewer_scam_HEADERS} ${MessageViewer_viewerplugin_HEADERS} ${MessageViewer_settings_HEADERS} ${MessageViewer_header_HEADERS} ${MessageViewer_utils_HEADERS} ${MessageViewer_interfaces_HEADERS} ${MessageViewer_htmlwriter_HEADERS} ${MessageViewer_HEADERS} ${MessageViewer_viewer_HEADERS} ${MessageViewer_widgets_HEADERS} ${MessageViewer_antispam_HEADERS} ${MessageViewer_findbar_HEADERS} ${MessageViewer_renderer_HEADERS} ${MessageViewer_blockmailtrackingurlinterceptor_HEADERS} ${CMAKE_CURRENT_BINARY_DIR}/messageviewer_export.h ${CMAKE_CURRENT_BINARY_DIR}/globalsettings_messageviewer.h ${CMAKE_CURRENT_BINARY_DIR}/messageviewer_debug.h ${CMAKE_CURRENT_BINARY_DIR}/config-messageviewer.h DESTINATION ${KDE_INSTALL_INCLUDEDIR_KF5}/messageviewer COMPONENT Devel ) install(FILES ${PRI_FILENAME} DESTINATION ${ECM_MKSPECS_INSTALL_DIR}) -install(FILES header/data/messageviewer_header_themes.knsrc DESTINATION ${KDE_INSTALL_CONFDIR} ) +install(FILES header/data/messageviewer_header_themes.knsrc DESTINATION ${KDE_INSTALL_KNSRCDIR} ) install(FILES notify/messageviewer.notifyrc DESTINATION ${KDE_INSTALL_KNOTIFY5RCDIR} ) install(FILES scamdetection/data/longurlServices.json DESTINATION ${KDE_INSTALL_DATADIR}/messageviewer ) diff --git a/webengineviewer/src/findbar/findbarbase.cpp b/webengineviewer/src/findbar/findbarbase.cpp index a7aaeb92..136e2189 100644 --- a/webengineviewer/src/findbar/findbarbase.cpp +++ b/webengineviewer/src/findbar/findbarbase.cpp @@ -1,273 +1,273 @@ /* Copyright (C) 2010 Torgny Nyblom * Copyright (C) 2010-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 "findbarbase.h" #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace WebEngineViewer; FindBarBase::FindBarBase(QWidget *parent) : QWidget(parent) { QHBoxLayout *lay = new QHBoxLayout(this); - lay->setContentsMargins(2, 2, 2, 2); + lay->setContentsMargins(0, 0, 0, 0); QToolButton *closeBtn = new QToolButton(this); closeBtn->setIcon(QIcon::fromTheme(QStringLiteral("dialog-close"))); closeBtn->setObjectName(QStringLiteral("close")); closeBtn->setIconSize(QSize(16, 16)); closeBtn->setToolTip(i18n("Close")); #ifndef QT_NO_ACCESSIBILITY closeBtn->setAccessibleName(i18n("Close")); #endif closeBtn->setAutoRaise(true); lay->addWidget(closeBtn); QLabel *label = new QLabel(i18nc("Find text", "F&ind:"), this); lay->addWidget(label); mSearch = new PimCommon::LineEditWithCompleterNg(this); mSearch->setObjectName(QStringLiteral("searchline")); mSearch->setToolTip(i18n("Text to search for")); mSearch->setClearButtonEnabled(true); label->setBuddy(mSearch); lay->addWidget(mSearch); mFindNextBtn = new QPushButton(QIcon::fromTheme(QStringLiteral("go-down-search")), i18nc("Find and go to the next search match", "Next"), this); mFindNextBtn->setToolTip(i18n("Jump to next match")); mFindNextBtn->setObjectName(QStringLiteral("findnext")); lay->addWidget(mFindNextBtn); mFindNextBtn->setEnabled(false); mFindPrevBtn = new QPushButton(QIcon::fromTheme(QStringLiteral("go-up-search")), i18nc("Find and go to the previous search match", "Previous"), this); mFindPrevBtn->setToolTip(i18n("Jump to previous match")); mFindPrevBtn->setObjectName(QStringLiteral("findprevious")); lay->addWidget(mFindPrevBtn); mFindPrevBtn->setEnabled(false); QPushButton *optionsBtn = new QPushButton(this); optionsBtn->setText(i18n("Options")); optionsBtn->setToolTip(i18n("Modify search behavior")); mOptionsMenu = new QMenu(optionsBtn); mCaseSensitiveAct = mOptionsMenu->addAction(i18n("Case sensitive")); mCaseSensitiveAct->setCheckable(true); optionsBtn->setMenu(mOptionsMenu); lay->addWidget(optionsBtn); connect(closeBtn, &QToolButton::clicked, this, &FindBarBase::closeBar); connect(mFindNextBtn, &QPushButton::clicked, this, &FindBarBase::findNext); connect(mFindPrevBtn, &QPushButton::clicked, this, &FindBarBase::findPrev); connect(mCaseSensitiveAct, &QAction::toggled, this, &FindBarBase::caseSensitivityChanged); connect(mSearch, &QLineEdit::textChanged, this, &FindBarBase::autoSearch); mStatus = new QLabel; mStatus->setObjectName(QStringLiteral("status")); mStatus->setTextFormat(Qt::PlainText); QFontMetrics fm(mStatus->font()); mNotFoundString = i18n("Phrase not found"); mStatus->setFixedWidth(fm.boundingRect(mNotFoundString).width()); lay->addWidget(mStatus); setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed)); hide(); } FindBarBase::~FindBarBase() { } QMenu *FindBarBase::optionsMenu() { return mOptionsMenu; } QString FindBarBase::text() const { return mSearch->text(); } void FindBarBase::setText(const QString &text) { mSearch->setText(text); } void FindBarBase::focusAndSetCursor() { setFocus(); mStatus->clear(); mSearch->selectAll(); mSearch->setFocus(); } void FindBarBase::slotClearSearch() { clearSelections(); } void FindBarBase::autoSearch(const QString &str) { const bool isNotEmpty = (!str.isEmpty()); mFindPrevBtn->setEnabled(isNotEmpty); mFindNextBtn->setEnabled(isNotEmpty); if (isNotEmpty) { QTimer::singleShot(0, this, [this]() { slotSearchText(); }); } else { clearSelections(); } } void FindBarBase::slotSearchText(bool backward, bool isAutoSearch) { searchText(backward, isAutoSearch); } void FindBarBase::setFoundMatch(bool match) { #ifndef QT_NO_STYLE_STYLESHEET QString styleSheet; if (!mSearch->text().isEmpty()) { if (mNegativeBackground.isEmpty()) { KStatefulBrush bgBrush(KColorScheme::View, KColorScheme::PositiveBackground); mPositiveBackground = QStringLiteral("QLineEdit{ background-color:%1 }").arg(bgBrush.brush(mSearch).color().name()); bgBrush = KStatefulBrush(KColorScheme::View, KColorScheme::NegativeBackground); mNegativeBackground = QStringLiteral("QLineEdit{ background-color:%1 }").arg(bgBrush.brush(mSearch).color().name()); } if (match) { styleSheet = mPositiveBackground; mStatus->clear(); } else { styleSheet = mNegativeBackground; mStatus->setText(mNotFoundString); } } mSearch->setStyleSheet(styleSheet); #endif } void FindBarBase::searchText(bool backward, bool isAutoSearch) { Q_UNUSED(backward); Q_UNUSED(isAutoSearch); } void FindBarBase::addToCompletion(const QString &text) { mSearch->addCompletionItem(text); } void FindBarBase::findNext() { searchText(false, false); addToCompletion(mLastSearchStr); } void FindBarBase::findPrev() { searchText(true, false); addToCompletion(mLastSearchStr); } void FindBarBase::caseSensitivityChanged(bool b) { updateSensitivity(b); } void FindBarBase::updateSensitivity(bool) { } void FindBarBase::slotHighlightAllChanged(bool b) { updateHighLight(b); } void FindBarBase::updateHighLight(bool) { } void FindBarBase::clearSelections() { setFoundMatch(false); } void FindBarBase::closeBar() { // Make sure that all old searches are cleared mSearch->clear(); clearSelections(); mSearch->clearFocus(); Q_EMIT hideFindBar(); } bool FindBarBase::event(QEvent *e) { // Close the bar when pressing Escape. // Not using a QShortcut for this because it could conflict with // window-global actions (e.g. Emil Sedgh binds Esc to "close tab"). // With a shortcut override we can catch this before it gets to kactions. const bool shortCutOverride = (e->type() == QEvent::ShortcutOverride); if (shortCutOverride || e->type() == QEvent::KeyPress) { QKeyEvent *kev = static_cast(e); if (kev->key() == Qt::Key_Escape) { if (shortCutOverride) { e->accept(); return true; } e->accept(); closeBar(); return true; } else if (kev->key() == Qt::Key_Enter || kev->key() == Qt::Key_Return) { e->accept(); if (shortCutOverride) { return true; } if (mSearch->text().isEmpty()) { return true; } if (kev->modifiers() & Qt::ShiftModifier) { findPrev(); } else if (kev->modifiers() == Qt::NoModifier) { findNext(); } return true; } } return QWidget::event(e); }