diff --git a/CMakeLists.txt b/CMakeLists.txt index 26d4cfee7..9009fb02d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,161 +1,156 @@ cmake_minimum_required(VERSION 3.1) set(KDEPIM_VERSION_NUMBER "5.9.41") project(kmail VERSION ${KDEPIM_VERSION_NUMBER}) include(CheckIncludeFiles) if (POLICY CMP0063) cmake_policy(SET CMP0063 NEW) endif() set(KF5_VERSION "5.50.0") find_package(ECM ${KF5_VERSION} CONFIG REQUIRED) set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH}) include(ECMOptionalAddSubdirectory) include(ECMInstallIcons) include(ECMSetupVersion) include(ECMAddTests) include(ECMMarkNonGuiExecutable) include(GenerateExportHeader) include(ECMGenerateHeaders) include(CMakePackageConfigHelpers) include(FeatureSummary) include(CheckFunctionExists) include(ECMGeneratePriFile) include(KDEInstallDirs) include(KDECMakeSettings) -include(KDECompilerSettings NO_POLICY_SCOPE) +include(KDEFrameworkCompilerSettings NO_POLICY_SCOPE) include(ECMAddAppIcon) include(ECMQtDeclareLoggingCategory) include(ECMCoverageOption) # Do NOT add quote set(KDEPIM_DEV_VERSION alpha) # add an extra space if(DEFINED KDEPIM_DEV_VERSION) set(KDEPIM_DEV_VERSION " ${KDEPIM_DEV_VERSION}") endif() set(KDEPIM_VERSION "${KDEPIM_VERSION_NUMBER}${KDEPIM_DEV_VERSION}") set(AKONADI_MIMELIB_VERSION "5.9.40") set(AKONADI_CONTACT_VERSION "5.9.40") set(KCONTACTS_LIB_VERSION "5.9.40") set(KCALENDARCORE_LIB_VERSION "5.9.40") set(CALENDARUTILS_LIB_VERSION "5.9.40") set(IDENTITYMANAGEMENT_LIB_VERSION "5.9.40") set(KLDAP_LIB_VERSION "5.9.40") set(KMAILTRANSPORT_LIB_VERSION "5.9.40") set(KONTACTINTERFACE_LIB_VERSION "5.9.40") set(KMIME_LIB_VERSION "5.9.40") set(KPIMTEXTEDIT_LIB_VERSION "5.9.41") set(AKONADI_VERSION "5.9.40") set(KTNEF_LIB_VERSION "5.9.40") set(KDEPIM_LIB_VERSION "${KDEPIM_VERSION_NUMBER}") set(KDEPIM_LIB_SOVERSION "5") set(QT_REQUIRED_VERSION "5.9.0") 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) find_package(Qt5 ${QT_REQUIRED_VERSION} CONFIG REQUIRED DBus Network Test Widgets WebEngine WebEngineWidgets) set(LIBGRAVATAR_VERSION_LIB "5.9.40") set(MAILCOMMON_LIB_VERSION_LIB "5.9.41") set(KDEPIM_APPS_LIB_VERSION_LIB "5.9.40") set(MESSAGELIB_LIB_VERSION_LIB "5.9.50") set(LIBKLEO_LIB_VERSION_LIB "5.9.40") set(PIMCOMMON_LIB_VERSION_LIB "5.9.42") set(LIBKDEPIM_LIB_VERSION_LIB "5.9.40") set(LIBKSIEVE_LIB_VERSION_LIB "5.9.40") find_package(KF5WebEngineViewer ${MESSAGELIB_LIB_VERSION_LIB} CONFIG REQUIRED) find_package(KF5AkonadiSearch "5.9.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") set(GPGMEPP_LIB_VERSION "1.8.0") find_package(Gpgmepp ${GPGMEPP_LIB_VERSION} CONFIG REQUIRED) # Find KF5 package find_package(KF5Bookmarks ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5Codecs ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5Config ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5ConfigWidgets ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5Crash ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5DBusAddons ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5DocTools ${KF5_VERSION} REQUIRED) find_package(KF5GuiAddons ${KF5_VERSION} REQUIRED) find_package(KF5I18n ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5ItemViews ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5JobWidgets ${KF5_VERSION} REQUIRED) find_package(KF5KIO ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5KCMUtils ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5Notifications ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5NotifyConfig ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5Parts ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5Service ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5Sonnet ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5TextWidgets ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5WidgetsAddons ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5WindowSystem ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5XmlGui ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5IconThemes ${KF5_VERSION} CONFIG REQUIRED) # Find KdepimLibs Package find_package(KF5Akonadi ${AKONADI_VERSION} CONFIG REQUIRED) find_package(KF5AkonadiContact ${AKONADI_CONTACT_VERSION} CONFIG REQUIRED) find_package(KF5AkonadiMime ${AKONADI_MIMELIB_VERSION} CONFIG REQUIRED) find_package(KF5Contacts ${KCONTACTS_LIB_VERSION} CONFIG REQUIRED) find_package(KF5CalendarCore ${KCALENDARCORE_LIB_VERSION} CONFIG REQUIRED) find_package(KF5CalendarUtils ${CALENDARUTILS_LIB_VERSION} CONFIG REQUIRED) find_package(KF5IdentityManagement ${IDENTITYMANAGEMENT_LIB_VERSION} CONFIG REQUIRED) find_package(KF5Ldap ${KLDAP_LIB_VERSION} CONFIG REQUIRED) find_package(KF5MailTransportAkonadi ${KMAILTRANSPORT_LIB_VERSION} CONFIG REQUIRED) find_package(KF5PimTextEdit ${KPIMTEXTEDIT_LIB_VERSION} CONFIG REQUIRED) find_package(KF5KontactInterface ${KONTACTINTERFACE_LIB_VERSION} CONFIG REQUIRED) find_package(KF5Mime ${KMIME_LIB_VERSION} CONFIG REQUIRED) find_package(KF5FollowupReminder ${KDEPIM_APPS_LIB_VERSION_LIB} CONFIG REQUIRED) find_package(KF5Gravatar ${LIBGRAVATAR_VERSION_LIB} CONFIG REQUIRED) find_package(KF5KdepimDBusInterfaces ${KDEPIM_APPS_LIB_VERSION_LIB} CONFIG REQUIRED) find_package(KF5LibkdepimAkonadi ${LIBKDEPIM_LIB_VERSION_LIB} CONFIG REQUIRED) find_package(KF5Libkleo ${LIBKLEO_LIB_VERSION_LIB} CONFIG REQUIRED) find_package(KF5LibKSieve ${LIBKSIEVE_LIB_VERSION_LIB} CONFIG REQUIRED) find_package(KF5MailCommon ${MAILCOMMON_LIB_VERSION_LIB} CONFIG REQUIRED) find_package(KF5MessageCore ${MESSAGELIB_LIB_VERSION_LIB} CONFIG REQUIRED) find_package(KF5MessageComposer ${MESSAGELIB_LIB_VERSION_LIB} CONFIG REQUIRED) find_package(KF5MessageList ${MESSAGELIB_LIB_VERSION_LIB} CONFIG REQUIRED) find_package(KF5MessageViewer ${MESSAGELIB_LIB_VERSION_LIB} CONFIG REQUIRED) find_package(KF5PimCommonAkonadi ${PIMCOMMON_LIB_VERSION_LIB} CONFIG REQUIRED) find_package(KF5SendLater ${KDEPIM_APPS_LIB_VERSION_LIB} CONFIG REQUIRED) find_package(KF5TemplateParser ${MESSAGELIB_LIB_VERSION_LIB} CONFIG REQUIRED) find_package(KF5Tnef ${KTNEF_LIB_VERSION} CONFIG REQUIRED) find_package(MailTransportDBusService CONFIG REQUIRED) configure_file(config-enterprise.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-enterprise.h ) include_directories(${kmail_SOURCE_DIR} ${kmail_BINARY_DIR}) configure_file(kmail-version.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/kmail-version.h @ONLY) -add_definitions(-DQT_NO_CAST_FROM_ASCII) -add_definitions(-DQT_NO_CAST_TO_ASCII) -add_definitions(-DQT_NO_NARROWING_CONVERSIONS_IN_CONNECT) -add_definitions(-DQT_NO_URL_CAST_FROM_STRING) -add_definitions(-DQT_USE_QSTRINGBUILDER) add_definitions(-DQT_DISABLE_DEPRECATED_BEFORE=0x060000) add_subdirectory(src) add_subdirectory(agents) add_subdirectory(ktnef) install( FILES kmail.renamecategories kmail.categories DESTINATION ${KDE_INSTALL_CONFDIR} ) add_subdirectory(doc) feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES) diff --git a/ktnef/src/qwmf.cpp b/ktnef/src/qwmf.cpp index 499ece157..b7556841e 100644 --- a/ktnef/src/qwmf.cpp +++ b/ktnef/src/qwmf.cpp @@ -1,1257 +1,1257 @@ /* Windows Meta File Loader/Painter Class Implementation * * Copyright ( C ) 1998 Stefan Taferner * Modified 2002 thierry lorthiois * * 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 * MERCHANTABLILITY 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 // WORDS_BIGENDIAN #include #include #include #include #include #include #include #include #include #include "ktnef_debug.h" bool qwmfDebug = false; #include "qwmf.h" #include "wmfstruct.h" #include "metafuncs.h" #define QWMF_DEBUG 0 class WmfCmd { public: ~WmfCmd() { delete next; } WmfCmd *next; unsigned short funcIndex; long numParm; short *parm; }; class WinObjHandle { public: virtual ~WinObjHandle() { } virtual void apply(QPainter &p) = 0; }; class WinObjBrushHandle : public WinObjHandle { public: void apply(QPainter &p) override; QBrush brush; virtual ~WinObjBrushHandle() { } }; class WinObjPenHandle : public WinObjHandle { public: void apply(QPainter &p) override; QPen pen; virtual ~WinObjPenHandle() { } }; class WinObjPatternBrushHandle : public WinObjHandle { public: void apply(QPainter &p) override; QBrush brush; QImage image; virtual ~WinObjPatternBrushHandle() { } }; class WinObjFontHandle : public WinObjHandle { public: void apply(QPainter &p) override; QFont font; int rotation; virtual ~WinObjFontHandle() { } }; void WinObjBrushHandle::apply(QPainter &p) { p.setBrush(brush); } void WinObjPenHandle::apply(QPainter &p) { p.setPen(pen); } void WinObjPatternBrushHandle::apply(QPainter &p) { p.setBrush(brush); } void WinObjFontHandle::apply(QPainter &p) { p.setFont(font); } #define MAX_OBJHANDLE 64 //----------------------------------------------------------------------------- QWinMetaFile::QWinMetaFile() { mValid = false; mFirstCmd = NULL; mObjHandleTab = NULL; mDpi = 1000; } //----------------------------------------------------------------------------- QWinMetaFile::~QWinMetaFile() { delete mFirstCmd; if (mObjHandleTab) { delete[] mObjHandleTab; } } //----------------------------------------------------------------------------- bool QWinMetaFile::load(const QString &filename) { QFile file(filename); if (!file.exists()) { qCDebug(KTNEFAPPS_LOG) << "File" << QFile::encodeName(filename) << " does not exist"; return false; } if (!file.open(QIODevice::ReadOnly)) { qCDebug(KTNEFAPPS_LOG) << "Cannot open file" << QFile::encodeName(filename); return false; } QByteArray ba = file.readAll(); file.close(); QBuffer buffer(&ba); buffer.open(QIODevice::ReadOnly); return load(buffer); } //----------------------------------------------------------------------------- bool QWinMetaFile::load(QBuffer &buffer) { QDataStream st; WmfEnhMetaHeader eheader; WmfMetaHeader header; WmfPlaceableHeader pheader; WORD checksum; int filePos, idx, i; WmfCmd *cmd, *last; DWORD rdSize; WORD rdFunc; mTextAlign = 0; mRotation = 0; mTextColor = Qt::black; if (mFirstCmd) { delete mFirstCmd; } mFirstCmd = NULL; st.setDevice(&buffer); st.setByteOrder(QDataStream::LittleEndian); // Great, I love Qt ! //----- Read placeable metafile header st >> pheader.key; mIsPlaceable = (pheader.key == (DWORD)APMHEADER_KEY); if (mIsPlaceable) { st >> pheader.hmf; st >> pheader.bbox.left; st >> pheader.bbox.top; st >> pheader.bbox.right; st >> pheader.bbox.bottom; st >> pheader.inch; st >> pheader.reserved; st >> pheader.checksum; checksum = calcCheckSum(&pheader); if (pheader.checksum != checksum) { mIsPlaceable = false; } mDpi = pheader.inch; mBBox.setLeft(pheader.bbox.left); mBBox.setTop(pheader.bbox.top); mBBox.setRight(pheader.bbox.right); mBBox.setBottom(pheader.bbox.bottom); mHeaderBoundingBox = mBBox; if (QWMF_DEBUG) { qCDebug(KTNEFAPPS_LOG) << endl << "-------------------------------------------------"; qCDebug(KTNEFAPPS_LOG) << "WMF Placeable Header (" << static_cast(sizeof(pheader)) << "):"; qCDebug(KTNEFAPPS_LOG) << " bbox=(" << mBBox.left() << ";" << mBBox.top() << ";" << mBBox.width() << "; " << mBBox.height() << ")"; qCDebug(KTNEFAPPS_LOG) << " inch=" << pheader.inch; qCDebug(KTNEFAPPS_LOG) << " checksum=" << pheader.checksum << "(" << (pheader.checksum == checksum ? "ok" : "wrong") << " )"; } } else { buffer.reset(); } //----- Read as enhanced metafile header filePos = buffer.pos(); st >> eheader.iType; st >> eheader.nSize; st >> eheader.rclBounds.left; st >> eheader.rclBounds.top; st >> eheader.rclBounds.right; st >> eheader.rclBounds.bottom; st >> eheader.rclFrame.left; st >> eheader.rclFrame.top; st >> eheader.rclFrame.right; st >> eheader.rclFrame.bottom; st >> eheader.dSignature; mIsEnhanced = (eheader.dSignature == ENHMETA_SIGNATURE); if (mIsEnhanced) { // is it really enhanced ? st >> eheader.nVersion; st >> eheader.nBytes; st >> eheader.nRecords; st >> eheader.nHandles; st >> eheader.sReserved; st >> eheader.nDescription; st >> eheader.offDescription; st >> eheader.nPalEntries; st >> eheader.szlDevice.width; st >> eheader.szlDevice.height; st >> eheader.szlMillimeters.width; st >> eheader.szlMillimeters.height; if (QWMF_DEBUG) { qCDebug(KTNEFAPPS_LOG) << endl << "-------------------------------------------------"; qCDebug(KTNEFAPPS_LOG) << "WMF Extended Header:"; qCDebug(KTNEFAPPS_LOG) << " iType=" << eheader.iType; qCDebug(KTNEFAPPS_LOG) << " nSize=" << eheader.nSize; qCDebug(KTNEFAPPS_LOG) << " rclBounds=(" << eheader.rclBounds.left << ";" << eheader.rclBounds.top << ";" << eheader.rclBounds.right << "; " << eheader.rclBounds.bottom << ")"; qCDebug(KTNEFAPPS_LOG) << " rclFrame=(" << eheader.rclFrame.left << ";" << eheader.rclFrame.top << ";" << eheader.rclFrame.right << "; " << eheader.rclFrame.bottom << ")"; qCDebug(KTNEFAPPS_LOG) << " nBytes=" << eheader.nBytes; qCDebug(KTNEFAPPS_LOG) << "\nNOT YET IMPLEMENTED, SORRY."; } } else { // no, not enhanced //----- Read as standard metafile header buffer.seek(filePos); st >> header.mtType; st >> header.mtHeaderSize; st >> header.mtVersion; st >> header.mtSize; st >> header.mtNoObjects; st >> header.mtMaxRecord; st >> header.mtNoParameters; if (QWMF_DEBUG) { qCDebug(KTNEFAPPS_LOG) << "WMF Header:" << "mtSize=" << header.mtSize; } } //----- Test header validity mValid = ((header.mtHeaderSize == 9) && (header.mtNoParameters == 0)) || mIsEnhanced || mIsPlaceable; if (mValid) { //----- Read Metafile Records last = NULL; rdFunc = -1; while (!st.atEnd() && (rdFunc != 0)) { st >> rdSize; st >> rdFunc; idx = findFunc(rdFunc); rdSize -= 3; cmd = new WmfCmd; cmd->next = NULL; if (last) { last->next = cmd; } else { mFirstCmd = cmd; } cmd->funcIndex = idx; cmd->numParm = rdSize; cmd->parm = new WORD[ rdSize ]; last = cmd; for (i = 0; i < rdSize && !st.atEnd(); ++i) { st >> cmd->parm[ i ]; } if (rdFunc == 0x020B) { // SETWINDOWORG: dimensions mBBox.setLeft(cmd->parm[ 1 ]); mBBox.setTop(cmd->parm[ 0 ]); } if (rdFunc == 0x020C) { // SETWINDOWEXT: dimensions mBBox.setWidth(cmd->parm[ 1 ]); mBBox.setHeight(cmd->parm[ 0 ]); } if (i < rdSize) { qCDebug(KTNEFAPPS_LOG) << "WMF : file truncated !"; return false; } } //----- Test records validities mValid = (rdFunc == 0) && (mBBox.width() != 0) && (mBBox.height() != 0); if (!mValid) { qCDebug(KTNEFAPPS_LOG) << "WMF : incorrect file format !"; } } else { qCDebug(KTNEFAPPS_LOG) << "WMF Header : incorrect header !"; } buffer.close(); return mValid; } //----------------------------------------------------------------------------- bool QWinMetaFile::paint(QPaintDevice *aTarget, bool absolute) { int idx, i; WmfCmd *cmd; if (!mValid) { return false; } assert(aTarget != NULL); if (mPainter.isActive()) { return false; } if (mObjHandleTab) { delete[] mObjHandleTab; } mObjHandleTab = new WinObjHandle * [ MAX_OBJHANDLE ]; for (i = MAX_OBJHANDLE - 1; i >= 0; --i) { mObjHandleTab[ i ] = NULL; } mPainter.resetMatrix(); mWinding = false; mAbsoluteCoord = absolute; mPainter.begin(aTarget); if (QWMF_DEBUG) { qCDebug(KTNEFAPPS_LOG) << "Bounding box :" << mBBox.left() << " " << mBBox.top() << " " << mBBox.right() << " " << mBBox.bottom(); } if (mAbsoluteCoord) { mPainter.setWindow(mBBox.top(), mBBox.left(), mBBox.width(), mBBox.height()); } mInternalWorldMatrix.reset(); for (cmd = mFirstCmd; cmd; cmd = cmd->next) { idx = cmd->funcIndex; (this->*metaFuncTab[ idx ].method)(cmd->numParm, cmd->parm); if (QWMF_DEBUG) { QString str, param; if (metaFuncTab[ idx ].name == NULL) { str += QLatin1String("UNKNOWN "); } if (metaFuncTab[ idx ].method == &QWinMetaFile::noop) { str += QLatin1String("UNIMPLEMENTED "); } str += QLatin1String(metaFuncTab[ idx ].name); str += QLatin1String(" : "); for (i = 0; i < cmd->numParm; ++i) { param.setNum(cmd->parm[ i ]); str += param; str += QLatin1Char(' '); } qCDebug(KTNEFAPPS_LOG) << str; } } /* // TODO: cleanup this code when QPicture::setBoundingBox() is possible in KOClipart (QT31) // because actually QPicture::boundingBox() != mBBox() mWindowsCoord += 1; if ( mWindowsCoord == 2 ) { qCDebug(KTNEFAPPS_LOG) <<"DRAW ANGLES"; mPainter.setPen( Qt::white ); mPainter.drawPoint( mBBox.left(), mBBox.top() ); mPainter.drawPoint( mBBox.right(), mBBox.bottom() ); } */ mPainter.end(); return true; } //----------------s------------------------------------------------------------- // Metafile painter methods //----------------------------------------------------------------------------- void QWinMetaFile::setWindowOrg(long, short *parm) { if (mAbsoluteCoord) { QRect r = mPainter.window(); mPainter.setWindow(parm[ 1 ], parm[ 0 ], r.width(), r.height()); } else { double dx = mInternalWorldMatrix.dx(); double dy = mInternalWorldMatrix.dy(); mInternalWorldMatrix.translate(-dx, -dy); mInternalWorldMatrix.translate(-parm[ 1 ], -parm[ 0 ]); mPainter.translate(-dx, -dy); mPainter.translate(-parm[ 1 ], -parm[ 0 ]); } } //----------------------------------------------------------------------------- void QWinMetaFile::setWindowExt(long, short *parm) { // negative value allowed for width and height : QABS() forbidden if (mAbsoluteCoord) { QRect r = mPainter.window(); mPainter.setWindow(r.left(), r.top(), parm[ 1 ], parm[ 0 ]); } else { if ((parm[ 0 ] != 0) && (parm[ 1 ] != 0)) { QRect r = mPainter.window(); double dx = mInternalWorldMatrix.dx(); double dy = mInternalWorldMatrix.dy(); double sx = mInternalWorldMatrix.m11(); double sy = mInternalWorldMatrix.m22(); mInternalWorldMatrix.translate(-dx, -dy); mInternalWorldMatrix.scale(1 / sx, 1 / sy); mPainter.translate(-dx, -dy); mPainter.scale(1 / sx, 1 / sy); sx = (double)r.width() / (double)parm[ 1 ]; sy = (double)r.height() / (double)parm[ 0 ]; mInternalWorldMatrix.scale(sx, sy); mInternalWorldMatrix.translate(dx, dy); mPainter.scale(sx, sy); mPainter.translate(dx, dy); } } } //----------------------------------------------------------------------------- // Drawing //----------------------------------------------------------------------------- void QWinMetaFile::lineTo(long, short *parm) { mPainter.drawLine(mLastPos, QPoint(parm[1], parm[0])); } //----------------------------------------------------------------------------- void QWinMetaFile::moveTo(long, short *parm) { mLastPos = QPoint(parm[ 1 ], parm[ 0 ]); } //----------------------------------------------------------------------------- void QWinMetaFile::ellipse(long, short *parm) { mPainter.drawEllipse(parm[ 3 ], parm[ 2 ], parm[ 1 ] - parm[ 3 ], parm[ 0 ] - parm[ 2 ]); } //----------------------------------------------------------------------------- void QWinMetaFile::polygon(long, short *parm) { QPolygon *pa; // causing a memleck ??? pa = pointArray(parm[ 0 ], &parm[ 1 ]); if (mWinding) { mPainter.drawPolygon(*pa, Qt::WindingFill); } else { mPainter.drawPolygon(*pa, Qt::OddEvenFill); } delete pa; } //----------------------------------------------------------------------------- void QWinMetaFile::polyPolygon(long, short *parm) { QRegion region; int i, j, startPolygon; mPainter.save(); // define clipping region QRect win = bbox(); startPolygon = 1 + parm[ 0 ]; for (i = 0; i < parm[ 0 ]; ++i) { QPolygon pa1(parm[ 1 + i ]); for (j = 0; j < parm[ 1 + i ]; ++j) { pa1.setPoint(j, parm[ startPolygon ], parm[ startPolygon + 1 ]); startPolygon += 2; } QRegion r(pa1); region = region.xored(r); } mPainter.setClipRegion(region); // fill polygons mPainter.fillRect(win.left(), win.top(), win.width(), win.height(), mPainter.brush()); // draw polygon's border if necessary if (mPainter.pen().style() != Qt::NoPen) { mPainter.setClipping(false); mPainter.setBrush(Qt::NoBrush); QPolygon *pa; int idxPolygon = 1 + parm[ 0 ]; for (i = 0; i < parm[ 0 ]; ++i) { pa = pointArray(parm[ 1 + i ], &parm[ idxPolygon ]); mPainter.drawPolygon(*pa); idxPolygon += parm[ 1 + i ] * 2; } } mPainter.restore(); } //----------------------------------------------------------------------------- void QWinMetaFile::polyline(long, short *parm) { QPolygon *pa; pa = pointArray(parm[ 0 ], &parm[ 1 ]); mPainter.drawPolyline(*pa); } //----------------------------------------------------------------------------- void QWinMetaFile::rectangle(long, short *parm) { mPainter.drawRect(parm[ 3 ], parm[ 2 ], parm[ 1 ] - parm[ 3 ], parm[ 0 ] - parm[ 2 ]); } //----------------------------------------------------------------------------- void QWinMetaFile::roundRect(long, short *parm) { int xRnd = 0, yRnd = 0; // convert (xRound, yRound) in percentage if ((parm[ 3 ] - parm[ 5 ]) != 0) { xRnd = (parm[ 1 ] * 100) / (parm[ 3 ] - parm[ 5 ]); } if ((parm[ 2 ] - parm[ 4 ]) != 0) { yRnd = (parm[ 0 ] * 100) / (parm[ 2 ] - parm[ 4 ]); } mPainter.drawRoundRect(parm[ 5 ], parm[ 4 ], parm[ 3 ] - parm[ 5 ], parm[ 2 ] - parm[ 4 ], xRnd, yRnd); } //----------------------------------------------------------------------------- void QWinMetaFile::arc(long, short *parm) { int xCenter, yCenter, angleStart, aLength; xCenter = parm[ 7 ] + ((parm[ 5 ] - parm[ 7 ]) / 2); yCenter = parm[ 6 ] + ((parm[ 4 ] - parm[ 6 ]) / 2); xyToAngle(parm[ 3 ] - xCenter, yCenter - parm[ 2 ], parm[ 1 ] - xCenter, yCenter - parm[ 0 ], angleStart, aLength); mPainter.drawArc(parm[ 7 ], parm[ 6 ], parm[ 5 ] - parm[ 7 ], parm[ 4 ] - parm[ 6 ], angleStart, aLength); } //----------------------------------------------------------------------------- void QWinMetaFile::chord(long, short *parm) { int xCenter, yCenter, angleStart, aLength; xCenter = parm[ 7 ] + ((parm[ 5 ] - parm[ 7 ]) / 2); yCenter = parm[ 6 ] + ((parm[ 4 ] - parm[ 6 ]) / 2); xyToAngle(parm[ 3 ] - xCenter, yCenter - parm[ 2 ], parm[ 1 ] - xCenter, yCenter - parm[ 0 ], angleStart, aLength); mPainter.drawChord(parm[ 7 ], parm[ 6 ], parm[ 5 ] - parm[ 7 ], parm[ 4 ] - parm[ 6 ], angleStart, aLength); } //----------------------------------------------------------------------------- void QWinMetaFile::pie(long, short *parm) { int xCenter, yCenter, angleStart, aLength; xCenter = parm[ 7 ] + ((parm[ 5 ] - parm[ 7 ]) / 2); yCenter = parm[ 6 ] + ((parm[ 4 ] - parm[ 6 ]) / 2); xyToAngle(parm[ 3 ] - xCenter, yCenter - parm[ 2 ], parm[ 1 ] - xCenter, yCenter - parm[ 0 ], angleStart, aLength); mPainter.drawPie(parm[ 7 ], parm[ 6 ], parm[ 5 ] - parm[ 7 ], parm[ 4 ] - parm[ 6 ], angleStart, aLength); } //----------------------------------------------------------------------------- void QWinMetaFile::setPolyFillMode(long, short *parm) { mWinding = parm[ 0 ]; } //----------------------------------------------------------------------------- void QWinMetaFile::setBkColor(long, short *parm) { mPainter.setBackground(QBrush(color(parm))); } //----------------------------------------------------------------------------- void QWinMetaFile::setBkMode(long, short *parm) { if (parm[ 0 ] == 1) { mPainter.setBackgroundMode(Qt::TransparentMode); } else { mPainter.setBackgroundMode(Qt::OpaqueMode); } } //----------------------------------------------------------------------------- void QWinMetaFile::setPixel(long, short *parm) { QPen pen = mPainter.pen(); mPainter.setPen(color(parm)); mPainter.drawPoint(parm[ 3 ], parm[ 2 ]); mPainter.setPen(pen); } //----------------------------------------------------------------------------- void QWinMetaFile::setRop(long, short *parm) { mPainter.setCompositionMode(winToQtComposition(parm[ 0 ])); } //----------------------------------------------------------------------------- void QWinMetaFile::saveDC(long, short *) { mPainter.save(); } //----------------------------------------------------------------------------- void QWinMetaFile::restoreDC(long, short *parm) { for (int i = 0; i > parm[ 0 ]; i--) { mPainter.restore(); } } //----------------------------------------------------------------------------- void QWinMetaFile::intersectClipRect(long, short *parm) { /* TODO: better implementation : need QT 3.0.2 QRegion region = mPainter.clipRegion(); if ( region.isEmpty() ) region = bbox(); */ QRegion region(bbox()); QRegion newRegion(parm[ 3 ], parm[ 2 ], parm[ 1 ] - parm[ 3 ], parm[ 0 ] - parm[ 2 ]); region = region.intersected(newRegion); mPainter.setClipRegion(region); } //----------------------------------------------------------------------------- void QWinMetaFile::excludeClipRect(long, short *parm) { /* TODO: better implementation : need QT 3.0.2 QRegion region = mPainter.clipRegion(); if ( region.isEmpty() ) region = bbox(); */ QRegion region(bbox()); QRegion newRegion(parm[ 3 ], parm[ 2 ], parm[ 1 ] - parm[ 3 ], parm[ 0 ] - parm[ 2 ]); region = region.subtracted(newRegion); mPainter.setClipRegion(region); } //----------------------------------------------------------------------------- // Text //----------------------------------------------------------------------------- void QWinMetaFile::setTextColor(long, short *parm) { mTextColor = color(parm); } //----------------------------------------------------------------------------- void QWinMetaFile::setTextAlign(long, short *parm) { mTextAlign = parm[ 0 ]; } //----------------------------------------------------------------------------- void QWinMetaFile::textOut(long num, short *parm) { short *copyParm = new short[ num + 1 ]; // re-order parameters int idxOffset = (parm[ 0 ] / 2) + 1 + (parm[ 0 ] & 1); copyParm[ 0 ] = parm[ idxOffset ]; copyParm[ 1 ] = parm[ idxOffset + 1 ]; copyParm[ 2 ] = parm[ 0 ]; copyParm[ 3 ] = 0; memcpy(©Parm[ 4 ], &parm[ 1 ], parm[ 0 ]); extTextOut(num + 1, copyParm); delete [] copyParm; } //----------------------------------------------------------------------------- void QWinMetaFile::extTextOut(long num, short *parm) { char *ptStr; int x, y, width, height; int idxOffset; if (parm[ 3 ] != 0) { // ETO_CLIPPED flag add 4 parameters ptStr = (char *)&parm[ 8 ]; } else { ptStr = (char *)&parm[ 4 ]; } QByteArray text(ptStr, parm[ 2 ] + 1); QFontMetrics fm(mPainter.font()); width = fm.boundingRect(QLatin1String(text)).width() + fm.descent(); // because fm.width(text) isn't rigth with Italic text height = fm.height(); mPainter.save(); if (mTextAlign & 0x01) { // (left, top) position = current logical position x = mLastPos.x(); y = mLastPos.y(); } else { // (left, top) position = parameters x = parm[ 1 ]; y = parm[ 0 ]; } if (mRotation) { mPainter.translate(parm[ 1 ], parm[ 0 ]); mPainter.rotate(mRotation); mPainter.translate(-parm[ 1 ], -parm[ 0 ]); } // alignment if (mTextAlign & 0x06) { x -= (width / 2); } if (mTextAlign & 0x08) { y -= (height - fm.descent()); } mPainter.setPen(mTextColor); idxOffset = (parm[ 2 ] / 2) + 4 + (parm[ 2 ] & 1); if ((parm[ 2 ] > 1) && (num >= (idxOffset + parm[ 2 ])) && (parm[ 3 ] == 0)) { // offset for each char int left = x; mPainter.drawText(left, y, width, height, Qt::AlignLeft | Qt::AlignTop, QLatin1String(text.mid(0, 1))); for (int i = 1; i < parm[ 2 ]; ++i) { left += parm[ idxOffset + i - 1 ]; mPainter.drawText(left, y, width, height, Qt::AlignLeft | Qt::AlignTop, QLatin1String(text.mid(i, 1))); } } else { mPainter.drawText(x, y, width, height, Qt::AlignLeft | Qt::AlignTop, QLatin1String(text)); } mPainter.restore(); } //----------------------------------------------------------------------------- // Bitmap //----------------------------------------------------------------------------- void QWinMetaFile::dibBitBlt(long num, short *parm) { if (num > 9) { // DIB image QImage bmpSrc; if (dibToBmp(bmpSrc, (char *)&parm[ 8 ], (num - 8) * 2)) { long raster = toDWord(parm); mPainter.setCompositionMode(winToQtComposition(raster)); // wmf file allow negative width or height mPainter.save(); if (parm[ 5 ] < 0) { // width < 0 => horizontal flip QMatrix m(-1.0F, 0.0F, 0.0F, 1.0F, 0.0F, 0.0F); mPainter.setMatrix(m, true); } if (parm[ 4 ] < 0) { // height < 0 => vertical flip QMatrix m(1.0F, 0.0F, 0.0F, -1.0F, 0.0F, 0.0F); mPainter.setMatrix(m, true); } mPainter.drawImage(parm[ 7 ], parm[ 6 ], bmpSrc, parm[ 3 ], parm[ 2 ], parm[ 5 ], parm[ 4 ]); mPainter.restore(); } } else { qCDebug(KTNEFAPPS_LOG) << "QWinMetaFile::dibBitBlt without image: not implemented"; } } //----------------------------------------------------------------------------- void QWinMetaFile::dibStretchBlt(long num, short *parm) { QImage bmpSrc; if (dibToBmp(bmpSrc, (char *)&parm[ 10 ], (num - 10) * 2)) { long raster = toDWord(parm); mPainter.setCompositionMode(winToQtComposition(raster)); // wmf file allow negative width or height mPainter.save(); if (parm[ 7 ] < 0) { // width < 0 => horizontal flip QMatrix m(-1.0F, 0.0F, 0.0F, 1.0F, 0.0F, 0.0F); mPainter.setMatrix(m, true); } if (parm[ 6 ] < 0) { // height < 0 => vertical flip QMatrix m(1.0F, 0.0F, 0.0F, -1.0F, 0.0F, 0.0F); mPainter.setMatrix(m, true); } bmpSrc = bmpSrc.copy(parm[ 5 ], parm[ 4 ], parm[ 3 ], parm[ 2 ]); // TODO: scale the bitmap ( QImage::scale(parm[ 7 ], parm[ 6 ]) is actually too slow ) mPainter.drawImage(parm[ 9 ], parm[ 8 ], bmpSrc); mPainter.restore(); } } //----------------------------------------------------------------------------- void QWinMetaFile::stretchDib(long num, short *parm) { QImage bmpSrc; if (dibToBmp(bmpSrc, (char *)&parm[ 11 ], (num - 11) * 2)) { long raster = toDWord(parm); mPainter.setCompositionMode(winToQtComposition(raster)); // wmf file allow negative width or height mPainter.save(); if (parm[ 8 ] < 0) { // width < 0 => horizontal flip QMatrix m(-1.0F, 0.0F, 0.0F, 1.0F, 0.0F, 0.0F); mPainter.setMatrix(m, true); } if (parm[ 7 ] < 0) { // height < 0 => vertical flip QMatrix m(1.0F, 0.0F, 0.0F, -1.0F, 0.0F, 0.0F); mPainter.setMatrix(m, true); } bmpSrc = bmpSrc.copy(parm[ 6 ], parm[ 5 ], parm[ 4 ], parm[ 3 ]); // TODO: scale the bitmap ( QImage::scale(parm[ 8 ], parm[ 7 ]) is actually too slow ) mPainter.drawImage(parm[ 10 ], parm[ 9 ], bmpSrc); mPainter.restore(); } } //----------------------------------------------------------------------------- void QWinMetaFile::dibCreatePatternBrush(long num, short *parm) { WinObjPatternBrushHandle *handle = new WinObjPatternBrushHandle; addHandle(handle); QImage bmpSrc; if (dibToBmp(bmpSrc, (char *)&parm[ 2 ], (num - 2) * 2)) { handle->image = bmpSrc; handle->brush.setTextureImage(handle->image); } } //----------------------------------------------------------------------------- // Object handle //----------------------------------------------------------------------------- void QWinMetaFile::selectObject(long, short *parm) { int idx = parm[ 0 ]; if (idx >= 0 && idx < MAX_OBJHANDLE && mObjHandleTab[ idx ]) { mObjHandleTab[ idx ]->apply(mPainter); } } //----------------------------------------------------------------------------- void QWinMetaFile::deleteObject(long, short *parm) { deleteHandle(parm[ 0 ]); } //----------------------------------------------------------------------------- void QWinMetaFile::createEmptyObject(long, short *) { // allocation of an empty object (to keep object counting in sync) WinObjPenHandle *handle = new WinObjPenHandle; addHandle(handle); qCDebug(KTNEFAPPS_LOG) << "QWinMetaFile: unimplemented createObject"; } //----------------------------------------------------------------------------- void QWinMetaFile::createBrushIndirect(long, short *parm) { static Qt::BrushStyle hatchedStyleTab[] = { Qt::HorPattern, Qt::FDiagPattern, Qt::BDiagPattern, Qt::CrossPattern, Qt::DiagCrossPattern }; static Qt::BrushStyle styleTab[] = { Qt::SolidPattern, Qt::NoBrush, Qt::FDiagPattern, /* hatched */ Qt::Dense4Pattern, /* should be custom bitmap pattern */ Qt::HorPattern, /* should be BS_INDEXED (?) */ Qt::VerPattern, /* should be device-independent bitmap */ Qt::Dense6Pattern, /* should be device-independent packed-bitmap */ Qt::Dense2Pattern, /* should be BS_PATTERN8x8 */ Qt::Dense3Pattern /* should be device-independent BS_DIBPATTERN8x8 */ }; Qt::BrushStyle style; short arg; WinObjBrushHandle *handle = new WinObjBrushHandle; addHandle(handle); arg = parm[ 0 ]; if (arg == 2) { arg = parm[ 3 ]; if (arg >= 0 && arg < 5) { style = hatchedStyleTab[ arg ]; } else { qCDebug(KTNEFAPPS_LOG) << "QWinMetaFile::createBrushIndirect: invalid hatched brush" << arg; style = Qt::SolidPattern; } } else if (arg >= 0 && arg < 9) { style = styleTab[ arg ]; } else { qCDebug(KTNEFAPPS_LOG) << "QWinMetaFile::createBrushIndirect: invalid brush" << arg; style = Qt::SolidPattern; } handle->brush.setStyle(style); handle->brush.setColor(color(parm + 1)); } //----------------------------------------------------------------------------- void QWinMetaFile::createPenIndirect(long, short *parm) { static Qt::PenStyle styleTab[] = { Qt::SolidLine, Qt::DashLine, Qt::DotLine, Qt::DashDotLine, Qt::DashDotDotLine, Qt::NoPen, Qt::SolidLine }; Qt::PenStyle style; WinObjPenHandle *handle = new WinObjPenHandle; addHandle(handle); if (parm[ 0 ] >= 0 && parm[ 0 ] < 6) { style = styleTab[ parm[ 0 ] ]; } else { qCDebug(KTNEFAPPS_LOG) << "QWinMetaFile::createPenIndirect: invalid pen" << parm[ 0 ]; style = Qt::SolidLine; } handle->pen.setStyle(style); handle->pen.setColor(color(parm + 3)); handle->pen.setCapStyle(Qt::RoundCap); //int width = 0; // TODO : width of pen proportional to device context width // DOESN'T WORK /* QRect devRec; devRec = mPainter.transformed( mBBox ); width = ( parm[ 0 ] * devRec.width() ) / mBBox.width() ; qCDebug(KTNEFAPPS_LOG) <<"CreatePenIndirect:"; qCDebug(KTNEFAPPS_LOG) <<" log coord. :" << mBBox.width() <<"" << mBBox.height(); qCDebug(KTNEFAPPS_LOG) <<" log. pen :" << parm[ 1 ] <<"" << parm[ 2 ]; qCDebug(KTNEFAPPS_LOG) <<" dev. pen :" << width; handle->pen.setWidth( width ); */ } //----------------------------------------------------------------------------- void QWinMetaFile::createFontIndirect(long, short *parm) { WinObjFontHandle *handle = new WinObjFontHandle; addHandle(handle); QString family(QLatin1String((const char *)&parm[ 9 ])); mRotation = -parm[ 2 ] / 10; // text rotation (in 1/10 degree) // TODO: memorisation of rotation in object Font handle->font.setFamily(family); handle->font.setFixedPitch(((parm[ 8 ] & 0x01) == 0)); // TODO: investigation why some test case need -2. (size of font in logical point) handle->font.setPointSize(qAbs(parm[ 0 ]) - 2); handle->font.setWeight((parm[ 4 ] >> 3)); handle->font.setItalic((parm[ 5 ] & 0x01)); handle->font.setUnderline((parm[ 5 ] & 0x100)); } //----------------------------------------------------------------------------- // Misc //----------------------------------------------------------------------------- void QWinMetaFile::noop(long, short *) { } void QWinMetaFile::end(long, short *) { // end of file : // qCDebug(KTNEFAPPS_LOG) <<"END bbox=(" << mBBox.left() <<";" << mBBox.top() <<";" << mBBox.width() <<";" << mBBox.height() <<")"; } //----------------------------------------------------------------------------- unsigned short QWinMetaFile::calcCheckSum(WmfPlaceableHeader *apmfh) { WORD *lpWord; WORD wResult, i; // Start with the first word wResult = *(lpWord = (WORD *)(apmfh)); // XOR in each of the other 9 words for (i = 1; i <= 9; ++i) { wResult ^= lpWord[ i ]; } return wResult; } //----------------------------------------------------------------------------- int QWinMetaFile::findFunc(unsigned short aFunc) const { int i; for (i = 0; metaFuncTab[ i ].name; ++i) { if (metaFuncTab[ i ].func == aFunc) { return i; } } // here : unknown function return i; } //----------------------------------------------------------------------------- QPolygon *QWinMetaFile::pointArray(short num, short *parm) { int i; mPoints.resize(num); for (i = 0; i < num; ++i, parm += 2) { mPoints.setPoint(i, parm[ 0 ], parm[ 1 ]); } return &mPoints; } //----------------------------------------------------------------------------- unsigned int QWinMetaFile::toDWord(short *parm) { unsigned int l; #if !defined(WORDS_BIGENDIAN) l = *(unsigned int *)(parm); #else char *bytes; char swap[ 4 ]; bytes = (char *)parm; swap[ 0 ] = bytes[ 2 ]; swap[ 1 ] = bytes[ 3 ]; swap[ 2 ] = bytes[ 0 ]; swap[ 3 ] = bytes[ 1 ]; l = *(unsigned int *)(swap); #endif return l; } //----------------------------------------------------------------------------- QColor QWinMetaFile::color(short *parm) { unsigned int colorRef; int red, green, blue; colorRef = toDWord(parm) & 0xffffff; red = colorRef & 255; green = (colorRef >> 8) & 255; blue = (colorRef >> 16) & 255; return QColor(red, green, blue); } //----------------------------------------------------------------------------- void QWinMetaFile::xyToAngle(int xStart, int yStart, int xEnd, int yEnd, int &angleStart, int &angleLength) { float aStart, aLength; aStart = atan2((double)yStart, (double)xStart); aLength = atan2((double)yEnd, (double)xEnd) - aStart; angleStart = (int)(aStart * 2880 / 3.14166); angleLength = (int)(aLength * 2880 / 3.14166); if (angleLength < 0) { angleLength = 5760 + angleLength; } } //----------------------------------------------------------------------------- void QWinMetaFile::addHandle(WinObjHandle *handle) { int idx; for (idx = 0; idx < MAX_OBJHANDLE; idx++) { if (mObjHandleTab[ idx ] == NULL) { break; } } if (idx < MAX_OBJHANDLE) { mObjHandleTab[ idx ] = handle; } else { qCDebug(KTNEFAPPS_LOG) << "QWinMetaFile error: handle table full !"; } } //----------------------------------------------------------------------------- void QWinMetaFile::deleteHandle(int idx) { if (idx >= 0 && idx < MAX_OBJHANDLE && mObjHandleTab[ idx ]) { delete mObjHandleTab[ idx ]; mObjHandleTab[ idx ] = NULL; } } //----------------------------------------------------------------------------- QPainter::CompositionMode QWinMetaFile::winToQtComposition(short parm) const { static const QPainter::CompositionMode opTab[] = { // ### untested (conversion from Qt::RasterOp) QPainter::CompositionMode_Source, // Qt::CopyROP QPainter::CompositionMode_Clear, // Qt::ClearROP QPainter::CompositionMode_SourceOut, // Qt::NandROP QPainter::CompositionMode_SourceOut, // Qt::NotAndROP QPainter::CompositionMode_DestinationOut, // Qt::NotCopyROP QPainter::CompositionMode_DestinationOut, // Qt::AndNotROP QPainter::CompositionMode_DestinationOut, // Qt::NotROP QPainter::CompositionMode_Xor, // Qt::XorROP QPainter::CompositionMode_Source, // Qt::NorROP QPainter::CompositionMode_SourceIn, // Qt::AndROP QPainter::CompositionMode_SourceIn, // Qt::NotXorROP QPainter::CompositionMode_Destination, // Qt::NopROP QPainter::CompositionMode_Destination, // Qt::NotOrROP QPainter::CompositionMode_Source, // Qt::CopyROP QPainter::CompositionMode_Source, // Qt::OrNotROP QPainter::CompositionMode_SourceOver, // Qt::OrROP QPainter::CompositionMode_Source // Qt::SetROP }; if (parm > 0 && parm <= 16) { return opTab[ parm ]; } else { return QPainter::CompositionMode_Source; } } //----------------------------------------------------------------------------- QPainter::CompositionMode QWinMetaFile::winToQtComposition(long parm) const { /* TODO: Ternary raster operations 0x00C000CA dest = (source AND pattern) 0x00F00021 dest = pattern 0x00FB0A09 dest = DPSnoo 0x005A0049 dest = pattern XOR dest */ static const struct OpTab { long winRasterOp; QPainter::CompositionMode qtRasterOp; } opTab[] = { // ### untested (conversion from Qt::RasterOp) { 0x00CC0020, QPainter::CompositionMode_Source }, // CopyROP { 0x00EE0086, QPainter::CompositionMode_SourceOver }, // OrROP { 0x008800C6, QPainter::CompositionMode_SourceIn }, // AndROP { 0x00660046, QPainter::CompositionMode_Xor }, // XorROP { 0x00440328, QPainter::CompositionMode_DestinationOut }, // AndNotROP { 0x00330008, QPainter::CompositionMode_DestinationOut }, // NotCopyROP { 0x001100A6, QPainter::CompositionMode_SourceOut }, // NandROP { 0x00C000CA, QPainter::CompositionMode_Source }, // CopyROP { 0x00BB0226, QPainter::CompositionMode_Destination }, // NotOrROP { 0x00F00021, QPainter::CompositionMode_Source }, // CopyROP { 0x00FB0A09, QPainter::CompositionMode_Source }, // CopyROP { 0x005A0049, QPainter::CompositionMode_Source }, // CopyROP { 0x00550009, QPainter::CompositionMode_DestinationOut }, // NotROP { 0x00000042, QPainter::CompositionMode_Clear }, // ClearROP { 0x00FF0062, QPainter::CompositionMode_Source } // SetROP }; int i; for (i = 0; i < 15; ++i) { if (opTab[ i ].winRasterOp == parm) { break; } } if (i < 15) { return opTab[ i ].qtRasterOp; } else { return QPainter::CompositionMode_Source; } } //----------------------------------------------------------------------------- bool QWinMetaFile::dibToBmp(QImage &bmp, const char *dib, long size) { typedef struct _BMPFILEHEADER { WORD bmType; DWORD bmSize; WORD bmReserved1; WORD bmReserved2; DWORD bmOffBits; } BMPFILEHEADER; int sizeBmp = size + 14; QByteArray pattern; // BMP header and DIB data pattern.fill(0, sizeBmp); //resize and fill pattern.insert(14, QByteArray::fromRawData(dib, size)); // add BMP header BMPFILEHEADER *bmpHeader; - bmpHeader = (BMPFILEHEADER *)((const char *)pattern); + bmpHeader = (BMPFILEHEADER *)(pattern.constData()); bmpHeader->bmType = 0x4D42; bmpHeader->bmSize = sizeBmp; if (!bmp.loadFromData((const uchar *)bmpHeader, pattern.size(), "BMP")) { qCDebug(KTNEFAPPS_LOG) << "QWinMetaFile::dibToBmp: invalid bitmap"; return false; } else { // if ( bmp.save("/home/software/kde-cvs/qt/examples/wmf/test.bmp", "BMP") ) // if ( bmp.load( "/home/software/kde-cvs/qt/examples/wmf/test.bmp", "BMP" ) ) // fprintf(stderr, "Bitmap ok \n"); return true; } } diff --git a/src/configuredialog/configureaccountpage.cpp b/src/configuredialog/configureaccountpage.cpp index 2a42982f5..99d10bf49 100644 --- a/src/configuredialog/configureaccountpage.cpp +++ b/src/configuredialog/configureaccountpage.cpp @@ -1,381 +1,381 @@ /* Copyright (c) 2013-2018 Montel Laurent This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2, as published by the Free Software Foundation. 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 "configureaccountpage.h" #include "dialog/kmknotify.h" #include "newmailnotifierinterface.h" #include "kmkernel.h" #include "settings/kmailsettings.h" #include "configagentdelegate.h" #include "MessageComposer/MessageComposerSettings" #include "MailCommon/AccountConfigOrderDialog" #include "PimCommon/ConfigureImmutableWidgetUtils" using namespace PimCommon::ConfigureImmutableWidgetUtils; #include using MailTransport::TransportManagementWidget; #include "ui_accountspagereceivingtab.h" #include "MailCommon/MailUtil" #include #include #include #include #include #include #include #include #include #include #include #include "kmail_debug.h" #include #include #include #include #include #include #include QString AccountsPage::helpAnchor() const { return QStringLiteral("configure-accounts"); } AccountsPage::AccountsPage(QWidget *parent) : ConfigModuleWithTabs(parent) { //Identity Tab: KMail::IdentityPage *identityTab = new KMail::IdentityPage(); addTab(identityTab, i18nc("@title:tab Tab page where the user configures identities", "Identities")); // // "Receiving" tab: // ReceivingTab *receivingTab = new ReceivingTab(); addTab(receivingTab, i18nc("@title:tab Tab page where the user configures accounts to receive mail", "Receiving")); connect(receivingTab, &ReceivingTab::accountListChanged, this, &AccountsPage::accountListChanged); // // "Sending" tab: // SendingTab *sendingTab = new SendingTab(); addTab(sendingTab, i18nc("@title:tab Tab page where the user configures accounts to send mail", "Sending")); } AccountsPageSendingTab::~AccountsPageSendingTab() { } QString AccountsPage::SendingTab::helpAnchor() const { return QStringLiteral("configure-accounts-sending"); } AccountsPageSendingTab::AccountsPageSendingTab(QWidget *parent) : ConfigModuleTab(parent) { QVBoxLayout *vlay = new QVBoxLayout(this); // label: zero stretch ### FIXME more vlay->addWidget(new QLabel(i18n("Outgoing accounts (add at least one):"), this)); TransportManagementWidget *tmw = new TransportManagementWidget(this); tmw->layout()->setContentsMargins(0, 0, 0, 0); vlay->addWidget(tmw); // "Common options" groupbox: QGroupBox *group = new QGroupBox(i18n("Common Options"), this); vlay->addWidget(group); // a grid layout for the contents of the "common options" group box QGridLayout *glay = new QGridLayout(); group->setLayout(glay); glay->setColumnStretch(2, 10); // "confirm before send" check box: mConfirmSendCheck = new QCheckBox(i18n("Confirm &before send"), group); glay->addWidget(mConfirmSendCheck, 0, 0, 1, 2); connect(mConfirmSendCheck, &QCheckBox::stateChanged, this, &AccountsPageSendingTab::slotEmitChanged); mCheckSpellingBeforeSending = new QCheckBox(i18n("Check spelling before sending"), group); glay->addWidget(mCheckSpellingBeforeSending, 1, 0, 1, 2); connect(mCheckSpellingBeforeSending, &QCheckBox::stateChanged, this, &AccountsPageSendingTab::slotEmitChanged); // "send on check" combo: mSendOnCheckCombo = new KComboBox(group); mSendOnCheckCombo->setEditable(false); mSendOnCheckCombo->addItems(QStringList() << i18n("Never Automatically") << i18n("On Manual Mail Checks") << i18n("On All Mail Checks")); glay->addWidget(mSendOnCheckCombo, 2, 1); connect(mSendOnCheckCombo, QOverload::of(&KComboBox::activated), this, &AccountsPageSendingTab::slotEmitChanged); // "default send method" combo: mSendMethodCombo = new KComboBox(group); mSendMethodCombo->setEditable(false); mSendMethodCombo->addItems(QStringList() << i18n("Send Now") << i18n("Send Later")); glay->addWidget(mSendMethodCombo, 3, 1); connect(mSendMethodCombo, QOverload::of(&KComboBox::activated), this, &AccountsPageSendingTab::slotEmitChanged); // labels: QLabel *l = new QLabel(i18n("Send &messages in outbox folder:"), group); l->setBuddy(mSendOnCheckCombo); glay->addWidget(l, 2, 0); - QString msg = i18n(KMailSettings::self()->sendOnCheckItem()->whatsThis().toUtf8()); + QString msg = i18n(KMailSettings::self()->sendOnCheckItem()->whatsThis().toUtf8().constData()); l->setWhatsThis(msg); mSendOnCheckCombo->setWhatsThis(msg); l = new QLabel(i18n("Defa&ult send method:"), group); l->setBuddy(mSendMethodCombo); glay->addWidget(l, 3, 0); } void AccountsPage::SendingTab::doLoadFromGlobalSettings() { mSendOnCheckCombo->setCurrentIndex(KMailSettings::self()->sendOnCheck()); } void AccountsPage::SendingTab::doLoadOther() { mSendMethodCombo->setCurrentIndex(MessageComposer::MessageComposerSettings::self()->sendImmediate() ? 0 : 1); loadWidget(mConfirmSendCheck, KMailSettings::self()->confirmBeforeSendItem()); loadWidget(mCheckSpellingBeforeSending, KMailSettings::self()->checkSpellingBeforeSendItem()); } void AccountsPage::SendingTab::save() { KMailSettings::self()->setSendOnCheck(mSendOnCheckCombo->currentIndex()); saveCheckBox(mConfirmSendCheck, KMailSettings::self()->confirmBeforeSendItem()); saveCheckBox(mCheckSpellingBeforeSending, KMailSettings::self()->checkSpellingBeforeSendItem()); MessageComposer::MessageComposerSettings::self()->setSendImmediate(mSendMethodCombo->currentIndex() == 0); } QString AccountsPage::ReceivingTab::helpAnchor() const { return QStringLiteral("configure-accounts-receiving"); } AccountsPageReceivingTab::AccountsPageReceivingTab(QWidget *parent) : ConfigModuleTab(parent) { const auto service = Akonadi::ServerManager::self()->agentServiceName(Akonadi::ServerManager::Agent, QStringLiteral("akonadi_newmailnotifier_agent")); mNewMailNotifierInterface = new OrgFreedesktopAkonadiNewMailNotifierInterface(service, QStringLiteral("/NewMailNotifierAgent"), QDBusConnection::sessionBus(), this); if (!mNewMailNotifierInterface->isValid()) { qCDebug(KMAIL_LOG) << " org.freedesktop.Akonadi.NewMailNotifierAgent not found. Please verify your installation"; delete mNewMailNotifierInterface; mNewMailNotifierInterface = nullptr; } mAccountsReceiving.setupUi(this); mAccountsReceiving.mAccountsReceiving->setMimeTypeFilter(QStringList() << KMime::Message::mimeType()); mAccountsReceiving.mAccountsReceiving->setCapabilityFilter(QStringList() << QStringLiteral("Resource")); mAccountsReceiving.mAccountsReceiving->setExcludeCapabilities(QStringList() << QStringLiteral("MailTransport") << QStringLiteral("Notes") << QStringLiteral("Autostart")); KConfig specialMailCollection(QStringLiteral("specialmailcollectionsrc")); if (specialMailCollection.hasGroup(QStringLiteral("SpecialCollections"))) { KConfigGroup grp = specialMailCollection.group(QStringLiteral("SpecialCollections")); mAccountsReceiving.mAccountsReceiving->setSpecialCollectionIdentifier(grp.readEntry(QStringLiteral("DefaultResourceId"))); } ConfigAgentDelegate *configDelegate = new ConfigAgentDelegate(mAccountsReceiving.mAccountsReceiving->view()); mAccountsReceiving.mAccountsReceiving->setItemDelegate(configDelegate); connect(configDelegate, &ConfigAgentDelegate::optionsClicked, this, &AccountsPageReceivingTab::slotShowMailCheckMenu); connect(mAccountsReceiving.mVerboseNotificationCheck, &QCheckBox::stateChanged, this, &ConfigModuleTab::slotEmitChanged); connect(mAccountsReceiving.mOtherNewMailActionsButton, &QAbstractButton::clicked, this, &AccountsPageReceivingTab::slotEditNotifications); connect(mAccountsReceiving.customizeAccountOrder, &QAbstractButton::clicked, this, &AccountsPageReceivingTab::slotCustomizeAccountOrder); mAccountsReceiving.mAccountsReceiving->disconnectAddAccountButton(); QMenu *accountMenu = new QMenu(this); accountMenu->addAction(i18n("Add Mail Account..."), this, &AccountsPageReceivingTab::slotAddMailAccount); accountMenu->addAction(i18n("Custom Account..."), this, &AccountsPageReceivingTab::slotAddCustomAccount); mAccountsReceiving.mAccountsReceiving->addAccountButton()->setMenu(accountMenu); } AccountsPageReceivingTab::~AccountsPageReceivingTab() { delete mNewMailNotifierInterface; mRetrievalHash.clear(); } void AccountsPageReceivingTab::slotAddCustomAccount() { mAccountsReceiving.mAccountsReceiving->slotAddAccount(); } void AccountsPageReceivingTab::slotAddMailAccount() { const QStringList lst = {QStringLiteral("--type"), QStringLiteral("message/rfc822") }; const QString path = QStandardPaths::findExecutable(QStringLiteral("accountwizard")); if (!QProcess::startDetached(path, lst)) { KMessageBox::error(this, i18n("Could not start the account wizard. " "Please make sure you have AccountWizard properly installed."), i18n("Unable to start account wizard")); } } void AccountsPageReceivingTab::slotCustomizeAccountOrder() { if (KMKernel::self()) { QPointer dlg = new MailCommon::AccountConfigOrderDialog(KMKernel::self()->mailCommonSettings(), this); dlg->exec(); delete dlg; } } void AccountsPageReceivingTab::slotShowMailCheckMenu(const QString &ident, const QPoint &pos) { QMenu menu(this); bool IncludeInManualChecks; bool OfflineOnShutdown; bool CheckOnStartup; if (!mRetrievalHash.contains(ident)) { const QString resourceGroupPattern(QStringLiteral("Resource %1")); KConfigGroup group; KConfig *conf = nullptr; if (KMKernel::self()) { group = KConfigGroup(KMKernel::self()->config(), resourceGroupPattern.arg(ident)); } else { conf = new KConfig(QStringLiteral("kmail2rc")); group = KConfigGroup(conf, resourceGroupPattern.arg(ident)); } IncludeInManualChecks = group.readEntry("IncludeInManualChecks", true); // Keep sync with kmkernel, don't forget to change there. OfflineOnShutdown = group.readEntry("OfflineOnShutdown", ident.startsWith(QLatin1String("akonadi_pop3_resource")) ? true : false); CheckOnStartup = group.readEntry("CheckOnStartup", false); QSharedPointer opts(new RetrievalOptions(IncludeInManualChecks, OfflineOnShutdown, CheckOnStartup)); mRetrievalHash.insert(ident, opts); delete conf; } else { QSharedPointer opts = mRetrievalHash.value(ident); IncludeInManualChecks = opts->IncludeInManualChecks; OfflineOnShutdown = opts->OfflineOnShutdown; CheckOnStartup = opts->CheckOnStartup; } if (!MailCommon::Util::isVirtualCollection(ident)) { QAction *manualMailCheck = new QAction(i18nc("Label to a checkbox, so is either checked/unchecked", "Include in Manual Mail Check"), &menu); manualMailCheck->setCheckable(true); manualMailCheck->setChecked(IncludeInManualChecks); manualMailCheck->setData(ident); menu.addAction(manualMailCheck); connect(manualMailCheck, &QAction::toggled, this, &AccountsPageReceivingTab::slotIncludeInCheckChanged); } QAction *switchOffline = new QAction(i18nc("Label to a checkbox, so is either checked/unchecked", "Switch offline on KMail Shutdown"), &menu); switchOffline->setCheckable(true); switchOffline->setChecked(OfflineOnShutdown); switchOffline->setData(ident); menu.addAction(switchOffline); connect(switchOffline, &QAction::toggled, this, &AccountsPageReceivingTab::slotOfflineOnShutdownChanged); QAction *checkOnStartup = new QAction(i18n("Check mail on startup"), &menu); checkOnStartup->setCheckable(true); checkOnStartup->setChecked(CheckOnStartup); checkOnStartup->setData(ident); menu.addAction(checkOnStartup); connect(checkOnStartup, &QAction::toggled, this, &AccountsPageReceivingTab::slotCheckOnStatupChanged); menu.exec(mAccountsReceiving.mAccountsReceiving->view()->mapToGlobal(pos)); } void AccountsPageReceivingTab::slotCheckOnStatupChanged(bool checked) { QAction *action = qobject_cast< QAction * >(sender()); const QString ident = action->data().toString(); QSharedPointer opts = mRetrievalHash.value(ident); opts->CheckOnStartup = checked; slotEmitChanged(); } void AccountsPageReceivingTab::slotIncludeInCheckChanged(bool checked) { QAction *action = qobject_cast< QAction * >(sender()); const QString ident = action->data().toString(); QSharedPointer opts = mRetrievalHash.value(ident); opts->IncludeInManualChecks = checked; slotEmitChanged(); } void AccountsPageReceivingTab::slotOfflineOnShutdownChanged(bool checked) { QAction *action = qobject_cast< QAction * >(sender()); QString ident = action->data().toString(); QSharedPointer opts = mRetrievalHash.value(ident); opts->OfflineOnShutdown = checked; slotEmitChanged(); } void AccountsPage::ReceivingTab::slotEditNotifications() { if (mNewMailNotifierInterface) { mNewMailNotifierInterface->asyncCall(QStringLiteral("showConfigureDialog"), (qlonglong)winId()); } else { KMessageBox::error(this, i18n("New Mail Notifier Agent not registered. Please contact your administrator.")); } } void AccountsPage::ReceivingTab::doLoadFromGlobalSettings() { if (mNewMailNotifierInterface) { mAccountsReceiving.mVerboseNotificationCheck->setChecked(mNewMailNotifierInterface->verboseMailNotification()); } } void AccountsPage::ReceivingTab::save() { // Save Mail notification settings if (mNewMailNotifierInterface) { mNewMailNotifierInterface->setVerboseMailNotification(mAccountsReceiving.mVerboseNotificationCheck->isChecked()); } const QString resourceGroupPattern(QStringLiteral("Resource %1")); QHash >::const_iterator it = mRetrievalHash.cbegin(); const QHash >::const_iterator itEnd = mRetrievalHash.cend(); for (; it != itEnd; ++it) { KConfigGroup group; KConfig *conf = nullptr; if (KMKernel::self()) { group = KConfigGroup(KMKernel::self()->config(), resourceGroupPattern.arg(it.key())); } else { conf = new KConfig(QStringLiteral("kmail2rc")); group = KConfigGroup(conf, resourceGroupPattern.arg(it.key())); } QSharedPointer opts = it.value(); group.writeEntry("IncludeInManualChecks", opts->IncludeInManualChecks); group.writeEntry("OfflineOnShutdown", opts->OfflineOnShutdown); group.writeEntry("CheckOnStartup", opts->CheckOnStartup); delete conf; } } diff --git a/src/configuredialog/configurecomposerpage.cpp b/src/configuredialog/configurecomposerpage.cpp index b9f6bcc21..596d970ab 100644 --- a/src/configuredialog/configurecomposerpage.cpp +++ b/src/configuredialog/configurecomposerpage.cpp @@ -1,1276 +1,1276 @@ /* Copyright (c) 2013-2018 Montel Laurent This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2, as published by the Free Software Foundation. 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 "configurecomposerpage.h" #include "PimCommon/ConfigureImmutableWidgetUtils" using namespace PimCommon::ConfigureImmutableWidgetUtils; #include "kmkernel.h" #include "kmmainwidget.h" #include "PimCommon/AutoCorrectionWidget" #include "MessageComposer/ImageScalingWidget" #include "MessageComposer/MessageComposerSettings" #include #include "settings/kmailsettings.h" #include "configuredialog/configuredialoglistview.h" #include "PimCommon/SimpleStringListEditor" #include "templatesconfiguration_kfg.h" #include "TemplateParser/TemplatesConfiguration" #include "templateparser/customtemplates.h" #include "globalsettings_templateparser.h" #include "libkdepim/recentaddresses.h" #include #include "libkdepimakonadi/completionordereditor.h" using KPIM::RecentAddresses; #include #include #include #include #include #include #include #include "kmail_debug.h" #include #include #include #include #include #include #include #include #include #include QString ComposerPage::helpAnchor() const { return QStringLiteral("configure-composer"); } ComposerPage::ComposerPage(QWidget *parent) : ConfigModuleWithTabs(parent) { // // "General" tab: // GeneralTab *generalTab = new GeneralTab(); addTab(generalTab, i18nc("General settings for the composer.", "General")); addConfig(KMailSettings::self(), generalTab); // // "Templates" tab: // TemplatesTab *templatesTab = new TemplatesTab(); addTab(templatesTab, i18n("Standard Templates")); // // "Custom Templates" tab: // CustomTemplatesTab *customTemplatesTab = new CustomTemplatesTab(); addTab(customTemplatesTab, i18n("Custom Templates")); // // "Subject" tab: // SubjectTab *subjectTab = new SubjectTab(); addTab(subjectTab, i18nc("Settings regarding the subject when composing a message.", "Subject")); addConfig(KMailSettings::self(), subjectTab); // // "Charset" tab: // CharsetTab *charsetTab = new CharsetTab(); addTab(charsetTab, i18n("Charset")); // // "Headers" tab: // HeadersTab *headersTab = new HeadersTab(); addTab(headersTab, i18n("Headers")); // // "Attachments" tab: // AttachmentsTab *attachmentsTab = new AttachmentsTab(); addTab(attachmentsTab, i18nc("Config->Composer->Attachments", "Attachments")); // // "autocorrection" tab: // AutoCorrectionTab *autoCorrectionTab = new AutoCorrectionTab(); addTab(autoCorrectionTab, i18n("Autocorrection")); // // "autoresize" tab: // AutoImageResizeTab *autoImageResizeTab = new AutoImageResizeTab(); addTab(autoImageResizeTab, i18n("Auto Resize Image")); } QString ComposerPage::GeneralTab::helpAnchor() const { return QStringLiteral("configure-composer-general"); } ComposerPageGeneralTab::ComposerPageGeneralTab(QWidget *parent) : ConfigModuleTab(parent) { // Main layout QGridLayout *grid = new QGridLayout(this); // "Signature" group QGroupBox *groupBox = new QGroupBox(i18nc("@title:group", "Signature")); QVBoxLayout *groupVBoxLayout = new QVBoxLayout(); // "Automatically insert signature" checkbox mAutoAppSignFileCheck = new QCheckBox( MessageComposer::MessageComposerSettings::self()->autoTextSignatureItem()->label(), this); QString helpText = i18n("Automatically insert the configured signature\n" "when starting to compose a message"); mAutoAppSignFileCheck->setToolTip(helpText); mAutoAppSignFileCheck->setWhatsThis(helpText); connect(mAutoAppSignFileCheck, &QCheckBox::stateChanged, this, &ConfigModuleTab::slotEmitChanged); groupVBoxLayout->addWidget(mAutoAppSignFileCheck); // "Insert signature above quoted text" checkbox mTopQuoteCheck = new QCheckBox( MessageComposer::MessageComposerSettings::self()->prependSignatureItem()->label(), this); mTopQuoteCheck->setEnabled(false); helpText = i18n("Insert the signature above any quoted text"); mTopQuoteCheck->setToolTip(helpText); mTopQuoteCheck->setWhatsThis(helpText); connect(mTopQuoteCheck, &QCheckBox::stateChanged, this, &ConfigModuleTab::slotEmitChanged); connect(mAutoAppSignFileCheck, &QAbstractButton::toggled, mTopQuoteCheck, &QWidget::setEnabled); groupVBoxLayout->addWidget(mTopQuoteCheck); // "Prepend separator to signature" checkbox mDashDashCheck = new QCheckBox( MessageComposer::MessageComposerSettings::self()->dashDashSignatureItem()->label(), this); mDashDashCheck->setEnabled(false); helpText = i18n("Insert the RFC-compliant signature separator\n" "(two dashes and a space on a line) before the signature"); mDashDashCheck->setToolTip(helpText); mDashDashCheck->setWhatsThis(helpText); connect(mDashDashCheck, &QCheckBox::stateChanged, this, &ConfigModuleTab::slotEmitChanged); connect(mAutoAppSignFileCheck, &QAbstractButton::toggled, mDashDashCheck, &QWidget::setEnabled); groupVBoxLayout->addWidget(mDashDashCheck); // "Remove signature when replying" checkbox mStripSignatureCheck = new QCheckBox(TemplateParser::TemplateParserSettings::self()->stripSignatureItem()->label(), this); helpText = i18n("When replying, do not quote any existing signature"); mStripSignatureCheck->setToolTip(helpText); mStripSignatureCheck->setWhatsThis(helpText); connect(mStripSignatureCheck, &QCheckBox::stateChanged, this, &ConfigModuleTab::slotEmitChanged); groupVBoxLayout->addWidget(mStripSignatureCheck); groupVBoxLayout->addStretch(1); groupBox->setLayout(groupVBoxLayout); grid->addWidget(groupBox, 0, 0); // "Format" group groupBox = new QGroupBox(i18nc("@title:group", "Format")); QGridLayout *groupGridLayout = new QGridLayout(); int row = 0; // "Only quote selected text when replying" checkbox mQuoteSelectionOnlyCheck = new QCheckBox(MessageComposer::MessageComposerSettings::self()->quoteSelectionOnlyItem()->label(), this); helpText = i18n("When replying, only quote the selected text\n" "(instead of the complete message), if\n" "there is text selected in the message window."); mQuoteSelectionOnlyCheck->setToolTip(helpText); mQuoteSelectionOnlyCheck->setWhatsThis(helpText); connect(mQuoteSelectionOnlyCheck, &QCheckBox::stateChanged, this, &ConfigModuleTab::slotEmitChanged); groupGridLayout->addWidget(mQuoteSelectionOnlyCheck, row, 0, 1, -1); ++row; // "Use smart quoting" checkbox mSmartQuoteCheck = new QCheckBox( TemplateParser::TemplateParserSettings::self()->smartQuoteItem()->label(), this); helpText = i18n("When replying, add quote signs in front of all lines of the quoted text,\n" "even when the line was created by adding an additional line break while\n" "word-wrapping the text."); mSmartQuoteCheck->setToolTip(helpText); mSmartQuoteCheck->setWhatsThis(helpText); connect(mSmartQuoteCheck, &QCheckBox::stateChanged, this, &ConfigModuleTab::slotEmitChanged); groupGridLayout->addWidget(mSmartQuoteCheck, row, 0, 1, -1); ++row; // "Word wrap at column" checkbox/spinbox mWordWrapCheck = new QCheckBox( MessageComposer::MessageComposerSettings::self()->wordWrapItem()->label(), this); helpText = i18n("Enable automatic word wrapping at the specified width"); mWordWrapCheck->setToolTip(helpText); mWordWrapCheck->setWhatsThis(helpText); mWrapColumnSpin = new QSpinBox(this); mWrapColumnSpin->setMaximum(78 /*max*/); mWrapColumnSpin->setMinimum(30 /*min*/); mWrapColumnSpin->setSingleStep(1 /*step*/); mWrapColumnSpin->setValue(78 /*init*/); mWrapColumnSpin->setEnabled(false); // since !mWordWrapCheck->isChecked() helpText = i18n("Set the text width for automatic word wrapping"); mWrapColumnSpin->setToolTip(helpText); mWrapColumnSpin->setWhatsThis(helpText); connect(mWordWrapCheck, &QCheckBox::stateChanged, this, &ConfigModuleTab::slotEmitChanged); connect(mWrapColumnSpin, QOverload::of(&QSpinBox::valueChanged), this, &ComposerPageGeneralTab::slotEmitChanged); // only enable the spinbox if the checkbox is checked connect(mWordWrapCheck, &QAbstractButton::toggled, mWrapColumnSpin, &QWidget::setEnabled); groupGridLayout->addWidget(mWordWrapCheck, row, 0); groupGridLayout->addWidget(mWrapColumnSpin, row, 1); ++row; // Spacing ++row; // "Reply/Forward using HTML if present" checkbox mReplyUsingHtml = new QCheckBox(TemplateParser::TemplateParserSettings::self()->replyUsingHtmlItem()->label(), this); helpText = i18n("When replying or forwarding, quote the message\n" "in the original format it was received.\n" "If unchecked, the reply will be as plain text by default."); mReplyUsingHtml->setToolTip(helpText); mReplyUsingHtml->setWhatsThis(helpText); connect(mReplyUsingHtml, &QCheckBox::stateChanged, this, &ConfigModuleTab::slotEmitChanged); groupGridLayout->addWidget(mReplyUsingHtml, row, 0, 1, -1); ++row; // "Improve plain text of HTML" checkbox mImprovePlainTextOfHtmlMessage = new QCheckBox(MessageComposer::MessageComposerSettings::self()->improvePlainTextOfHtmlMessageItem()->label(), this); // For what is supported see http://www.grantlee.org/apidox/classGrantlee_1_1PlainTextMarkupBuilder.html helpText = i18n("Format the plain text part of a message from the HTML markup.\n" "Bold, italic and underlined text, lists, and external references\n" "are supported."); mImprovePlainTextOfHtmlMessage->setToolTip(helpText); mImprovePlainTextOfHtmlMessage->setWhatsThis(helpText); connect(mImprovePlainTextOfHtmlMessage, &QCheckBox::stateChanged, this, &ConfigModuleTab::slotEmitChanged); groupGridLayout->addWidget(mImprovePlainTextOfHtmlMessage, row, 0, 1, -1); ++row; #ifdef KDEPIM_ENTERPRISE_BUILD ++row; // "Default forwarding type" combobox mForwardTypeCombo = new KComboBox(false, this); mForwardTypeCombo->addItems(QStringList() << i18nc("@item:inlistbox Inline mail forwarding", "Inline") << i18n("As Attachment")); helpText = i18n("Set the default forwarded message format"); mForwardTypeCombo->setToolTip(helpText); mForwardTypeCombo->setWhatsThis(helpText); label = new QLabel(i18n("Default forwarding type:"), this); label->setBuddy(mForwardTypeCombo); connect(mForwardTypeCombo, QOverload::of(&KComboBox::activated), this, &ComposerPageGeneralTab::slotEmitChanged); groupGridLayout->addWidget(label, row, 0); groupGridLayout->addWidget(mForwardTypeCombo, row, 1); #endif groupGridLayout->setRowStretch(row, 1); groupBox->setLayout(groupGridLayout); grid->addWidget(groupBox, 1, 0); // "Recipients" group groupBox = new QGroupBox(i18nc("@title:group", "Recipients")); groupGridLayout = new QGridLayout(); row = 0; // "Automatically request MDNs" checkbox mAutoRequestMDNCheck = new QCheckBox(KMailSettings::self()->requestMDNItem()->label(), this); helpText = i18n("By default, request an MDN when starting to compose a message.\n" "You can select this on a per-message basis using \"Options - Request Disposition Notification\""); mAutoRequestMDNCheck->setToolTip(helpText); mAutoRequestMDNCheck->setWhatsThis(helpText); connect(mAutoRequestMDNCheck, &QCheckBox::stateChanged, this, &ConfigModuleTab::slotEmitChanged); groupGridLayout->addWidget(mAutoRequestMDNCheck, row, 0, 1, -1); ++row; // Spacing ++row; // "Use Baloo search in composer" checkbox mShowAkonadiSearchAddressesInComposer = new QCheckBox( MessageComposer::MessageComposerSettings::self()->showBalooSearchInComposerItem()->label(), this); connect(mShowAkonadiSearchAddressesInComposer, &QCheckBox::stateChanged, this, &ConfigModuleTab::slotEmitChanged); groupGridLayout->addWidget(mShowAkonadiSearchAddressesInComposer, row, 0, 1, -1); ++row; #ifdef KDEPIM_ENTERPRISE_BUILD // "Warn if too many recipients" checkbox/spinbox mRecipientCheck = new QCheckBox( GlobalSettings::self()->tooManyRecipientsItem()->label(), this); mRecipientCheck->setObjectName(QStringLiteral("kcfg_TooManyRecipients")); - helpText = i18n(KMailSettings::self()->tooManyRecipientsItem()->whatsThis().toUtf8()); + helpText = i18n(KMailSettings::self()->tooManyRecipientsItem()->whatsThis().toUtf8().constData()); mRecipientCheck->setWhatsThis(helpText); mRecipientCheck->setToolTip(i18n("Warn if too many recipients are specified")); mRecipientSpin = new QSpinBox(this); mRecipientSpin->setMaximum(100 /*max*/); mRecipientSpin->setMinimum(1 /*min*/); mRecipientSpin->setSingleStep(1 /*step*/); mRecipientSpin->setValue(5 /*init*/); mRecipientSpin->setObjectName(QStringLiteral("kcfg_RecipientThreshold")); mRecipientSpin->setEnabled(false); - helpText = i18n(KMailSettings::self()->recipientThresholdItem()->whatsThis().toUtf8()); + helpText = i18n(KMailSettings::self()->recipientThresholdItem()->whatsThis().toUtf8().constData()); mRecipientSpin->setWhatsThis(helpText); mRecipientSpin->setToolTip(i18n("Set the maximum number of recipients for the warning")); connect(mRecipientCheck, &QCheckBox::stateChanged, this, &ComposerPageGeneralTab::slotEmitChanged); connect(mRecipientSpin, QOverload::of(&QSpinBox::valueChanged), this, &ComposerPageGeneralTab::slotEmitChanged); // only enable the spinbox if the checkbox is checked connect(mRecipientCheck, &QCheckBox::toggled, mRecipientSpin, &QSpinBox::setEnabled); groupGridLayout->addWidget(mRecipientCheck, row, 0, 1, 2); groupGridLayout->addWidget(mRecipientSpin, row, 2); ++row; #endif // "Maximum Reply-to-All recipients" spinbox mMaximumRecipients = new QSpinBox(this); mMaximumRecipients->setMaximum(9999); mMaximumRecipients->setMinimum(0); mMaximumRecipients->setSingleStep(1); mMaximumRecipients->setValue(1); helpText = i18n("Only allow this many recipients to be specified for the message.\n" "This applies to doing a \"Reply to All\", entering recipients manually\n" "or using the \"Select...\" picker. Setting this limit helps you to\n" "avoid accidentally sending a message to too many people. Note,\n" "however, that it does not take account of distribution lists or\n" "mailing lists."); mMaximumRecipients->setToolTip(helpText); mMaximumRecipients->setWhatsThis(helpText); QLabel *label = new QLabel(MessageComposer::MessageComposerSettings::self()->maximumRecipientsItem()->label(), this); label->setBuddy(mMaximumRecipients); connect(mMaximumRecipients, QOverload::of(&QSpinBox::valueChanged), this, &ConfigModuleTab::slotEmitChanged); groupGridLayout->addWidget(label, row, 0, 1, 2); groupGridLayout->addWidget(mMaximumRecipients, row, 2); ++row; // Spacing ++row; // "Use recent addresses for autocompletion" checkbox mShowRecentAddressesInComposer = new QCheckBox( MessageComposer::MessageComposerSettings::self()->showRecentAddressesInComposerItem()->label(), this); helpText = i18n("Remember recent addresses entered,\n" "and offer them for recipient completion"); mShowRecentAddressesInComposer->setToolTip(helpText); mShowRecentAddressesInComposer->setWhatsThis(helpText); connect(mShowRecentAddressesInComposer, &QCheckBox::stateChanged, this, &ConfigModuleTab::slotEmitChanged); groupGridLayout->addWidget(mShowRecentAddressesInComposer, row, 0, 1, -1); ++row; // "Maximum recent addresses retained" spinbox mMaximumRecentAddress = new QSpinBox(this); mMaximumRecentAddress->setMinimum(0); mMaximumRecentAddress->setMaximum(999); mMaximumRecentAddress->setSpecialValueText(i18nc("No addresses are retained", "No save")); mMaximumRecentAddress->setEnabled(false); label = new QLabel(i18n("Maximum recent addresses retained:")); label->setBuddy(mMaximumRecentAddress); label->setEnabled(false); helpText = i18n("The maximum number of recently entered addresses that will\n" "be remembered for completion"); mMaximumRecentAddress->setToolTip(helpText); mMaximumRecentAddress->setWhatsThis(helpText); connect(mMaximumRecentAddress, QOverload::of(&QSpinBox::valueChanged), this, &ConfigModuleTab::slotEmitChanged); connect(mShowRecentAddressesInComposer, &QAbstractButton::toggled, mMaximumRecentAddress, &QWidget::setEnabled); connect(mShowRecentAddressesInComposer, &QAbstractButton::toggled, label, &QWidget::setEnabled); groupGridLayout->addWidget(label, row, 0, 1, 2); groupGridLayout->addWidget(mMaximumRecentAddress, row, 2); ++row; // Configure All Address settings QPushButton *configureCompletionButton = new QPushButton(i18n("Configure Completion..."), this); connect(configureCompletionButton, &QAbstractButton::clicked, this, &ComposerPageGeneralTab::slotConfigureAddressCompletion); groupGridLayout->addWidget(configureCompletionButton, row, 1, 1, 2); groupGridLayout->setRowStretch(row, 1); groupBox->setLayout(groupGridLayout); grid->addWidget(groupBox, 0, 1); groupBox = new QGroupBox(i18nc("@title:group", "Autosave")); groupGridLayout = new QGridLayout(); row = 0; // "Autosave interval" spinbox mAutoSave = new KPluralHandlingSpinBox(this); mAutoSave->setMaximum(60); mAutoSave->setMinimum(0); mAutoSave->setSingleStep(1); mAutoSave->setValue(1); mAutoSave->setObjectName(QStringLiteral("kcfg_AutosaveInterval")); mAutoSave->setSpecialValueText(i18n("No autosave")); mAutoSave->setSuffix(ki18ncp("Interval suffix", " minute", " minutes")); helpText = i18n("Automatically save the message at this specified interval"); mAutoSave->setToolTip(helpText); mAutoSave->setWhatsThis(helpText); label = new QLabel(KMailSettings::self()->autosaveIntervalItem()->label(), this); label->setBuddy(mAutoSave); connect(mAutoSave, QOverload::of(&QSpinBox::valueChanged), this, &ConfigModuleTab::slotEmitChanged); groupGridLayout->addWidget(label, row, 0); groupGridLayout->addWidget(mAutoSave, row, 1); row++; groupGridLayout->setRowStretch(row, 1); groupBox->setLayout(groupGridLayout); grid->addWidget(groupBox, 1, 1); grid->setRowStretch(2, 1); } void ComposerPage::GeneralTab::doResetToDefaultsOther() { const bool bUseDefaults = MessageComposer::MessageComposerSettings::self()->useDefaults(true); const bool autoAppSignFile = MessageComposer::MessageComposerSettings::self()->autoTextSignature() == QLatin1String("auto"); const bool topQuoteCheck = MessageComposer::MessageComposerSettings::self()->prependSignature(); const bool dashDashSignature = MessageComposer::MessageComposerSettings::self()->dashDashSignature(); const bool smartQuoteCheck = MessageComposer::MessageComposerSettings::self()->quoteSelectionOnly(); const bool wordWrap = MessageComposer::MessageComposerSettings::self()->wordWrap(); const int wrapColumn = MessageComposer::MessageComposerSettings::self()->lineWrapWidth(); const bool showRecentAddress = MessageComposer::MessageComposerSettings::self()->showRecentAddressesInComposer(); const int maximumRecipient = MessageComposer::MessageComposerSettings::self()->maximumRecipients(); const bool improvePlainText = MessageComposer::MessageComposerSettings::self()->improvePlainTextOfHtmlMessage(); const bool showBalooSearchInComposer = MessageComposer::MessageComposerSettings::self()->showBalooSearchInComposer(); MessageComposer::MessageComposerSettings::self()->useDefaults(bUseDefaults); mAutoAppSignFileCheck->setChecked(autoAppSignFile); mTopQuoteCheck->setChecked(topQuoteCheck); mDashDashCheck->setChecked(dashDashSignature); mQuoteSelectionOnlyCheck->setChecked(smartQuoteCheck); mWordWrapCheck->setChecked(wordWrap); mWrapColumnSpin->setValue(wrapColumn); mMaximumRecipients->setValue(maximumRecipient); mShowRecentAddressesInComposer->setChecked(showRecentAddress); mShowAkonadiSearchAddressesInComposer->setChecked(showBalooSearchInComposer); mImprovePlainTextOfHtmlMessage->setChecked(improvePlainText); mMaximumRecentAddress->setValue(200); } void ComposerPage::GeneralTab::doLoadFromGlobalSettings() { // various check boxes: mAutoAppSignFileCheck->setChecked( MessageComposer::MessageComposerSettings::self()->autoTextSignature() == QLatin1String("auto")); loadWidget(mTopQuoteCheck, MessageComposer::MessageComposerSettings::self()->prependSignatureItem()); loadWidget(mDashDashCheck, MessageComposer::MessageComposerSettings::self()->dashDashSignatureItem()); loadWidget(mSmartQuoteCheck, TemplateParser::TemplateParserSettings::self()->smartQuoteItem()); loadWidget(mQuoteSelectionOnlyCheck, MessageComposer::MessageComposerSettings::self()->quoteSelectionOnlyItem()); loadWidget(mReplyUsingHtml, TemplateParser::TemplateParserSettings::self()->replyUsingHtmlItem()); loadWidget(mStripSignatureCheck, TemplateParser::TemplateParserSettings::self()->stripSignatureItem()); loadWidget(mAutoRequestMDNCheck, KMailSettings::self()->requestMDNItem()); loadWidget(mWordWrapCheck, MessageComposer::MessageComposerSettings::self()->wordWrapItem()); loadWidget(mWrapColumnSpin, MessageComposer::MessageComposerSettings::self()->lineWrapWidthItem()); loadWidget(mMaximumRecipients, MessageComposer::MessageComposerSettings::self()->maximumRecipientsItem()); mAutoSave->setValue(KMailSettings::self()->autosaveInterval()); loadWidget(mShowRecentAddressesInComposer, MessageComposer::MessageComposerSettings::self()->showRecentAddressesInComposerItem()); loadWidget(mShowAkonadiSearchAddressesInComposer, MessageComposer::MessageComposerSettings::self()->showBalooSearchInComposerItem()); mImprovePlainTextOfHtmlMessage->setChecked(MessageComposer::MessageComposerSettings::self()->improvePlainTextOfHtmlMessage()); #ifdef KDEPIM_ENTERPRISE_BUILD mRecipientCheck->setChecked(KMailSettings::self()->tooManyRecipients()); mRecipientSpin->setValue(KMailSettings::self()->recipientThreshold()); if (KMailSettings::self()->forwardingInlineByDefault()) { mForwardTypeCombo->setCurrentIndex(0); } else { mForwardTypeCombo->setCurrentIndex(1); } #endif mMaximumRecentAddress->setValue(RecentAddresses::self(MessageComposer::MessageComposerSettings::self()->config())->maxCount()); } void ComposerPage::GeneralTab::save() { saveCheckBox(mTopQuoteCheck, MessageComposer::MessageComposerSettings::self()->prependSignatureItem()); saveCheckBox(mDashDashCheck, MessageComposer::MessageComposerSettings::self()->dashDashSignatureItem()); saveCheckBox(mSmartQuoteCheck, TemplateParser::TemplateParserSettings::self()->smartQuoteItem()); saveCheckBox(mQuoteSelectionOnlyCheck, MessageComposer::MessageComposerSettings::self()->quoteSelectionOnlyItem()); saveCheckBox(mReplyUsingHtml, TemplateParser::TemplateParserSettings::self()->replyUsingHtmlItem()); saveCheckBox(mStripSignatureCheck, TemplateParser::TemplateParserSettings::self()->stripSignatureItem()); saveCheckBox(mAutoRequestMDNCheck, KMailSettings::self()->requestMDNItem()); saveCheckBox(mWordWrapCheck, MessageComposer::MessageComposerSettings::self()->wordWrapItem()); MessageComposer::MessageComposerSettings::self()->setAutoTextSignature( mAutoAppSignFileCheck->isChecked() ? QStringLiteral("auto") : QStringLiteral("manual")); saveSpinBox(mWrapColumnSpin, MessageComposer::MessageComposerSettings::self()->lineWrapWidthItem()); saveSpinBox(mMaximumRecipients, MessageComposer::MessageComposerSettings::self()->maximumRecipientsItem()); KMailSettings::self()->setAutosaveInterval(mAutoSave->value()); MessageComposer::MessageComposerSettings::self()->setShowRecentAddressesInComposer(mShowRecentAddressesInComposer->isChecked()); MessageComposer::MessageComposerSettings::self()->setShowBalooSearchInComposer(mShowAkonadiSearchAddressesInComposer->isChecked()); MessageComposer::MessageComposerSettings::self()->setImprovePlainTextOfHtmlMessage(mImprovePlainTextOfHtmlMessage->isChecked()); #ifdef KDEPIM_ENTERPRISE_BUILD KMailSettings::self()->setTooManyRecipients(mRecipientCheck->isChecked()); KMailSettings::self()->setRecipientThreshold(mRecipientSpin->value()); KMailSettings::self()->setForwardingInlineByDefault(mForwardTypeCombo->currentIndex() == 0); #endif RecentAddresses::self(MessageComposer::MessageComposerSettings::self()->config())->setMaxCount(mMaximumRecentAddress->value()); MessageComposer::MessageComposerSettings::self()->requestSync(); } void ComposerPage::GeneralTab::slotConfigureAddressCompletion() { KLDAP::LdapClientSearch search; QPointer dlg(new KPIM::CompletionConfigureDialog(this)); dlg->setRecentAddresses(KPIM::RecentAddresses::self(MessageComposer::MessageComposerSettings::self()->config())->addresses()); dlg->setLdapClientSearch(&search); KSharedConfig::Ptr config = KSharedConfig::openConfig(QStringLiteral("kpimbalooblacklist")); KConfigGroup group(config, "AddressLineEdit"); const QStringList balooBlackList = group.readEntry("BalooBackList", QStringList()); dlg->setEmailBlackList(balooBlackList); dlg->load(); if (dlg->exec()) { if (dlg->recentAddressWasChanged()) { KPIM::RecentAddresses::self(MessageComposer::MessageComposerSettings::self()->config())->clear(); dlg->storeAddresses(MessageComposer::MessageComposerSettings::self()->config()); } } delete dlg; } QString ComposerPage::TemplatesTab::helpAnchor() const { return QStringLiteral("configure-composer-templates"); } ComposerPageTemplatesTab::ComposerPageTemplatesTab(QWidget *parent) : ConfigModuleTab(parent) { QVBoxLayout *vlay = new QVBoxLayout(this); mWidget = new TemplateParser::TemplatesConfiguration(this); vlay->addWidget(mWidget); connect(mWidget, &TemplateParser::TemplatesConfiguration::changed, this, &ConfigModuleTab::slotEmitChanged); } void ComposerPage::TemplatesTab::doLoadFromGlobalSettings() { mWidget->loadFromGlobal(); } void ComposerPage::TemplatesTab::save() { mWidget->saveToGlobal(); } void ComposerPage::TemplatesTab::doResetToDefaultsOther() { mWidget->resetToDefault(); } QString ComposerPage::CustomTemplatesTab::helpAnchor() const { return QStringLiteral("configure-composer-custom-templates"); } ComposerPageCustomTemplatesTab::ComposerPageCustomTemplatesTab(QWidget *parent) : ConfigModuleTab(parent) { QVBoxLayout *vlay = new QVBoxLayout(this); mWidget = new TemplateParser::CustomTemplates(kmkernel->getKMMainWidget() ? kmkernel->getKMMainWidget()->actionCollections() : QList(), this); vlay->addWidget(mWidget); connect(mWidget, &TemplateParser::CustomTemplates::changed, this, &ConfigModuleTab::slotEmitChanged); if (KMKernel::self()) { connect(mWidget, &TemplateParser::CustomTemplates::templatesUpdated, KMKernel::self(), &KMKernel::updatedTemplates); } } void ComposerPage::CustomTemplatesTab::doLoadFromGlobalSettings() { mWidget->load(); } void ComposerPage::CustomTemplatesTab::save() { mWidget->save(); } QString ComposerPage::SubjectTab::helpAnchor() const { return QStringLiteral("configure-composer-subject"); } ComposerPageSubjectTab::ComposerPageSubjectTab(QWidget *parent) : ConfigModuleTab(parent) { QVBoxLayout *vlay = new QVBoxLayout(this); QGroupBox *group = new QGroupBox(i18n("Repl&y Subject Prefixes"), this); QLayout *layout = new QVBoxLayout(group); // row 0: help text: QLabel *label = new QLabel(i18n("Recognize any sequence of the following prefixes\n" "(entries are case-insensitive regular expressions):"), group); label->setWordWrap(true); label->setAlignment(Qt::AlignLeft); // row 1, string list editor: PimCommon::SimpleStringListEditor::ButtonCode buttonCode = static_cast(PimCommon::SimpleStringListEditor::Add | PimCommon::SimpleStringListEditor::Remove | PimCommon::SimpleStringListEditor::Modify); mReplyListEditor = new PimCommon::SimpleStringListEditor(group, buttonCode, i18n("A&dd..."), i18n("Re&move"), i18n("Mod&ify..."), i18n("Enter new reply prefix:")); connect(mReplyListEditor, &PimCommon::SimpleStringListEditor::changed, this, &ConfigModuleTab::slotEmitChanged); // row 2: "replace [...]" check box: mReplaceReplyPrefixCheck = new QCheckBox( MessageCore::MessageCoreSettings::self()->replaceReplyPrefixItem()->label(), group); connect(mReplaceReplyPrefixCheck, &QCheckBox::stateChanged, this, &ConfigModuleTab::slotEmitChanged); layout->addWidget(label); layout->addWidget(mReplyListEditor); layout->addWidget(mReplaceReplyPrefixCheck); vlay->addWidget(group); group = new QGroupBox(i18n("For&ward Subject Prefixes"), this); layout = new QVBoxLayout(group); // row 0: help text: label = new QLabel(i18n("Recognize any sequence of the following prefixes\n" "(entries are case-insensitive regular expressions):"), group); label->setAlignment(Qt::AlignLeft); label->setWordWrap(true); // row 1: string list editor mForwardListEditor = new PimCommon::SimpleStringListEditor(group, buttonCode, i18n("Add..."), i18n("Remo&ve"), i18n("Modify..."), i18n("Enter new forward prefix:")); connect(mForwardListEditor, &PimCommon::SimpleStringListEditor::changed, this, &ConfigModuleTab::slotEmitChanged); // row 3: "replace [...]" check box: mReplaceForwardPrefixCheck = new QCheckBox( MessageCore::MessageCoreSettings::self()->replaceForwardPrefixItem()->label(), group); connect(mReplaceForwardPrefixCheck, &QCheckBox::stateChanged, this, &ConfigModuleTab::slotEmitChanged); layout->addWidget(label); layout->addWidget(mForwardListEditor); layout->addWidget(mReplaceForwardPrefixCheck); vlay->addWidget(group); } void ComposerPage::SubjectTab::doLoadFromGlobalSettings() { loadWidget(mReplyListEditor, MessageCore::MessageCoreSettings::self()->replyPrefixesItem()); loadWidget(mForwardListEditor, MessageCore::MessageCoreSettings::self()->forwardPrefixesItem()); loadWidget(mReplaceForwardPrefixCheck, MessageCore::MessageCoreSettings::self()->replaceForwardPrefixItem()); loadWidget(mReplaceReplyPrefixCheck, MessageCore::MessageCoreSettings::self()->replaceReplyPrefixItem()); } void ComposerPage::SubjectTab::save() { saveSimpleStringListEditor(mReplyListEditor, MessageCore::MessageCoreSettings::self()->replyPrefixesItem()); saveSimpleStringListEditor(mForwardListEditor, MessageCore::MessageCoreSettings::self()->forwardPrefixesItem()); saveCheckBox(mReplaceForwardPrefixCheck, MessageCore::MessageCoreSettings::self()->replaceForwardPrefixItem()); saveCheckBox(mReplaceReplyPrefixCheck, MessageCore::MessageCoreSettings::self()->replaceReplyPrefixItem()); } void ComposerPage::SubjectTab::doResetToDefaultsOther() { const bool bUseDefaults = MessageComposer::MessageComposerSettings::self()->useDefaults(true); loadWidget(mReplyListEditor, MessageCore::MessageCoreSettings::self()->replyPrefixesItem()); loadWidget(mForwardListEditor, MessageCore::MessageCoreSettings::self()->forwardPrefixesItem()); loadWidget(mReplaceForwardPrefixCheck, MessageCore::MessageCoreSettings::self()->replaceForwardPrefixItem()); loadWidget(mReplaceReplyPrefixCheck, MessageCore::MessageCoreSettings::self()->replaceReplyPrefixItem()); MessageComposer::MessageComposerSettings::self()->useDefaults(bUseDefaults); } QString ComposerPage::CharsetTab::helpAnchor() const { return QStringLiteral("configure-composer-charset"); } ComposerPageCharsetTab::ComposerPageCharsetTab(QWidget *parent) : ConfigModuleTab(parent) { QVBoxLayout *vlay = new QVBoxLayout(this); QLabel *label = new QLabel(i18n("This list is checked for every outgoing message " "from the top to the bottom for a charset that " "contains all required characters."), this); label->setWordWrap(true); vlay->addWidget(label); mCharsetListEditor = new PimCommon::SimpleStringListEditor(this, PimCommon::SimpleStringListEditor::All, i18n("A&dd..."), i18n("Remo&ve"), i18n("&Modify..."), i18n("Enter charset:")); mCharsetListEditor->setUpDownAutoRepeat(true); connect(mCharsetListEditor, &PimCommon::SimpleStringListEditor::changed, this, &ConfigModuleTab::slotEmitChanged); vlay->addWidget(mCharsetListEditor, 1); mKeepReplyCharsetCheck = new QCheckBox(i18n("&Keep original charset when " "replying or forwarding (if " "possible)"), this); connect(mKeepReplyCharsetCheck, &QCheckBox::stateChanged, this, &ConfigModuleTab::slotEmitChanged); vlay->addWidget(mKeepReplyCharsetCheck); connect(mCharsetListEditor, &PimCommon::SimpleStringListEditor::aboutToAdd, this, &ComposerPageCharsetTab::slotVerifyCharset); setEnabled(kmkernel); } void ComposerPage::CharsetTab::slotVerifyCharset(QString &charset) { if (charset.isEmpty()) { return; } // KCharsets::codecForName("us-ascii") returns "iso-8859-1" (cf. Bug #49812) // therefore we have to treat this case specially const QString charsetLower = charset.toLower(); if (charsetLower == QLatin1String("us-ascii")) { charset = QStringLiteral("us-ascii"); return; } else if (charsetLower == QLatin1String("locale")) { charset = QStringLiteral("%1 (locale)") .arg(QString::fromLatin1(kmkernel->networkCodec()->name()).toLower()); return; } bool ok = false; QTextCodec *codec = KCharsets::charsets()->codecForName(charset, ok); if (ok && codec) { charset = QString::fromLatin1(codec->name()).toLower(); return; } KMessageBox::sorry(this, i18n("This charset is not supported.")); charset.clear(); } void ComposerPage::CharsetTab::doLoadOther() { if (!kmkernel) { return; } QStringList charsets = MessageComposer::MessageComposerSettings::preferredCharsets(); QStringList::Iterator end(charsets.end()); for (QStringList::Iterator it = charsets.begin(); it != end; ++it) { if ((*it) == QLatin1String("locale")) { QByteArray cset = kmkernel->networkCodec()->name(); cset = cset.toLower(); (*it) = QStringLiteral("%1 (locale)").arg(QString::fromLatin1(cset)); } } mCharsetListEditor->setStringList(charsets); loadWidget(mKeepReplyCharsetCheck, MessageComposer::MessageComposerSettings::self()->forceReplyCharsetItem()); } void ComposerPage::CharsetTab::doResetToDefaultsOther() { const bool bUseDefaults = MessageComposer::MessageComposerSettings::self()->useDefaults(true); mCharsetListEditor->setStringList(MessageComposer::MessageComposerSettings::preferredCharsets()); mKeepReplyCharsetCheck->setChecked(MessageComposer::MessageComposerSettings::forceReplyCharset()); saveCheckBox(mKeepReplyCharsetCheck, MessageComposer::MessageComposerSettings::self()->forceReplyCharsetItem()); MessageComposer::MessageComposerSettings::self()->useDefaults(bUseDefaults); slotEmitChanged(); } void ComposerPage::CharsetTab::save() { if (!kmkernel) { return; } QStringList charsetList = mCharsetListEditor->stringList(); QStringList::Iterator it = charsetList.begin(); QStringList::Iterator end = charsetList.end(); for (; it != end; ++it) { if ((*it).endsWith(QLatin1String("(locale)"))) { (*it) = QStringLiteral("locale"); } } MessageComposer::MessageComposerSettings::setPreferredCharsets(charsetList); saveCheckBox(mKeepReplyCharsetCheck, MessageComposer::MessageComposerSettings::self()->forceReplyCharsetItem()); } QString ComposerPage::HeadersTab::helpAnchor() const { return QStringLiteral("configure-composer-headers"); } ComposerPageHeadersTab::ComposerPageHeadersTab(QWidget *parent) : ConfigModuleTab(parent) { QVBoxLayout *vlay = new QVBoxLayout(this); // "Use custom Message-Id suffix" checkbox: mCreateOwnMessageIdCheck = new QCheckBox(i18n("&Use custom message-id suffix"), this); connect(mCreateOwnMessageIdCheck, &QCheckBox::stateChanged, this, &ConfigModuleTab::slotEmitChanged); vlay->addWidget(mCreateOwnMessageIdCheck); // "Message-Id suffix" line edit and label: QHBoxLayout *hlay = new QHBoxLayout(); // inherits spacing vlay->addLayout(hlay); mMessageIdSuffixEdit = new QLineEdit(this); mMessageIdSuffixEdit->setClearButtonEnabled(true); // only ASCII letters, digits, plus, minus and dots are allowed QRegularExpressionValidator *messageIdSuffixValidator = new QRegularExpressionValidator(QRegularExpression(QStringLiteral("[a-zA-Z0-9+-]+(?:\\.[a-zA-Z0-9+-]+)*")), this); mMessageIdSuffixEdit->setValidator(messageIdSuffixValidator); QLabel *label = new QLabel(i18n("Custom message-&id suffix:"), this); label->setBuddy(mMessageIdSuffixEdit); label->setEnabled(false); // since !mCreateOwnMessageIdCheck->isChecked() mMessageIdSuffixEdit->setEnabled(false); hlay->addWidget(label); hlay->addWidget(mMessageIdSuffixEdit, 1); connect(mCreateOwnMessageIdCheck, &QAbstractButton::toggled, label, &QWidget::setEnabled); connect(mCreateOwnMessageIdCheck, &QAbstractButton::toggled, mMessageIdSuffixEdit, &QWidget::setEnabled); connect(mMessageIdSuffixEdit, &QLineEdit::textChanged, this, &ConfigModuleTab::slotEmitChanged); // horizontal rule and "custom header fields" label: vlay->addWidget(new KSeparator(Qt::Horizontal, this)); vlay->addWidget(new QLabel(i18n("Define custom mime header fields:"), this)); // "custom header fields" listbox: QGridLayout *glay = new QGridLayout(); // inherits spacing vlay->addLayout(glay); glay->setRowStretch(2, 1); glay->setColumnStretch(1, 1); mHeaderList = new ListView(this); mHeaderList->setHeaderLabels(QStringList() << i18nc("@title:column Name of the mime header.", "Name") << i18nc("@title:column Value of the mimeheader.", "Value")); mHeaderList->setSortingEnabled(false); connect(mHeaderList, &QTreeWidget::currentItemChanged, this, &ComposerPageHeadersTab::slotMimeHeaderSelectionChanged); connect(mHeaderList, &ListView::addHeader, this, &ComposerPageHeadersTab::slotNewMimeHeader); connect(mHeaderList, &ListView::removeHeader, this, &ComposerPageHeadersTab::slotRemoveMimeHeader); glay->addWidget(mHeaderList, 0, 0, 3, 2); // "new" and "remove" buttons: QPushButton *button = new QPushButton(i18nc("@action:button Add new mime header field.", "Ne&w"), this); connect(button, &QAbstractButton::clicked, this, &ComposerPageHeadersTab::slotNewMimeHeader); button->setAutoDefault(false); glay->addWidget(button, 0, 2); mRemoveHeaderButton = new QPushButton(i18n("Re&move"), this); connect(mRemoveHeaderButton, &QAbstractButton::clicked, this, &ComposerPageHeadersTab::slotRemoveMimeHeader); button->setAutoDefault(false); glay->addWidget(mRemoveHeaderButton, 1, 2); // "name" and "value" line edits and labels: mTagNameEdit = new QLineEdit(this); mTagNameEdit->setClearButtonEnabled(true); mTagNameEdit->setEnabled(false); mTagNameLabel = new QLabel(i18nc("@label:textbox Name of the mime header.", "&Name:"), this); mTagNameLabel->setBuddy(mTagNameEdit); mTagNameLabel->setEnabled(false); glay->addWidget(mTagNameLabel, 3, 0); glay->addWidget(mTagNameEdit, 3, 1); connect(mTagNameEdit, &QLineEdit::textChanged, this, &ComposerPageHeadersTab::slotMimeHeaderNameChanged); mTagValueEdit = new QLineEdit(this); mTagValueEdit->setClearButtonEnabled(true); mTagValueEdit->setEnabled(false); mTagValueLabel = new QLabel(i18n("&Value:"), this); mTagValueLabel->setBuddy(mTagValueEdit); mTagValueLabel->setEnabled(false); glay->addWidget(mTagValueLabel, 4, 0); glay->addWidget(mTagValueEdit, 4, 1); connect(mTagValueEdit, &QLineEdit::textChanged, this, &ComposerPageHeadersTab::slotMimeHeaderValueChanged); } void ComposerPage::HeadersTab::slotMimeHeaderSelectionChanged() { mEmitChanges = false; QTreeWidgetItem *item = mHeaderList->currentItem(); if (item) { mTagNameEdit->setText(item->text(0)); mTagValueEdit->setText(item->text(1)); } else { mTagNameEdit->clear(); mTagValueEdit->clear(); } mRemoveHeaderButton->setEnabled(item); mTagNameEdit->setEnabled(item); mTagValueEdit->setEnabled(item); mTagNameLabel->setEnabled(item); mTagValueLabel->setEnabled(item); mEmitChanges = true; } void ComposerPage::HeadersTab::slotMimeHeaderNameChanged(const QString &text) { // is called on ::setup(), when clearing the line edits. So be // prepared to not find a selection: QTreeWidgetItem *item = mHeaderList->currentItem(); if (item) { item->setText(0, text); } slotEmitChanged(); } void ComposerPage::HeadersTab::slotMimeHeaderValueChanged(const QString &text) { // is called on ::setup(), when clearing the line edits. So be // prepared to not find a selection: QTreeWidgetItem *item = mHeaderList->currentItem(); if (item) { item->setText(1, text); } slotEmitChanged(); } void ComposerPage::HeadersTab::slotNewMimeHeader() { QTreeWidgetItem *listItem = new QTreeWidgetItem(mHeaderList); mHeaderList->setCurrentItem(listItem); slotEmitChanged(); } void ComposerPage::HeadersTab::slotRemoveMimeHeader() { // calling this w/o selection is a programming error: QTreeWidgetItem *item = mHeaderList->currentItem(); if (!item) { qCDebug(KMAIL_LOG) << "==================================================" << "Error: Remove button was pressed although no custom header was selected\n" << "==================================================\n"; return; } QTreeWidgetItem *below = mHeaderList->itemBelow(item); if (below) { qCDebug(KMAIL_LOG) << "below"; mHeaderList->setCurrentItem(below); delete item; item = nullptr; } else if (mHeaderList->topLevelItemCount() > 0) { delete item; item = nullptr; mHeaderList->setCurrentItem( mHeaderList->topLevelItem(mHeaderList->topLevelItemCount() - 1) ); } slotEmitChanged(); } void ComposerPage::HeadersTab::doLoadOther() { mMessageIdSuffixEdit->setText(MessageComposer::MessageComposerSettings::customMsgIDSuffix()); const bool state = (!MessageComposer::MessageComposerSettings::customMsgIDSuffix().isEmpty() && MessageComposer::MessageComposerSettings::useCustomMessageIdSuffix()); mCreateOwnMessageIdCheck->setChecked(state); mHeaderList->clear(); mTagNameEdit->clear(); mTagValueEdit->clear(); QTreeWidgetItem *item = nullptr; const int count = KMailSettings::self()->customMessageHeadersCount(); for (int i = 0; i < count; ++i) { KConfigGroup config(KMKernel::self()->config(), QLatin1String("Mime #") + QString::number(i)); const QString name = config.readEntry("name"); const QString value = config.readEntry("value"); if (!name.isEmpty()) { item = new QTreeWidgetItem(mHeaderList, item); item->setText(0, name); item->setText(1, value); } } if (mHeaderList->topLevelItemCount() > 0) { mHeaderList->setCurrentItem(mHeaderList->topLevelItem(0)); } else { // disable the "Remove" button mRemoveHeaderButton->setEnabled(false); } } void ComposerPage::HeadersTab::save() { MessageComposer::MessageComposerSettings::self()->setCustomMsgIDSuffix(mMessageIdSuffixEdit->text()); MessageComposer::MessageComposerSettings::self()->setUseCustomMessageIdSuffix(mCreateOwnMessageIdCheck->isChecked()); //Clean config const int oldHeadersCount = KMailSettings::self()->customMessageHeadersCount(); for (int i = 0; i < oldHeadersCount; ++i) { const QString groupMimeName = QStringLiteral("Mime #%1").arg(i); if (KMKernel::self()->config()->hasGroup(groupMimeName)) { KConfigGroup config(KMKernel::self()->config(), groupMimeName); config.deleteGroup(); } } int numValidEntries = 0; QTreeWidgetItem *item = nullptr; const int numberOfEntry = mHeaderList->topLevelItemCount(); for (int i = 0; i < numberOfEntry; ++i) { item = mHeaderList->topLevelItem(i); const QString str = item->text(0).trimmed(); if (!str.isEmpty()) { if (str == QLatin1String("Content-Type")) { KMessageBox::error(this, i18n("\'Content-Type\' is not an authorized string. This header will be not saved."), i18n("Invalid header")); continue; } KConfigGroup config(KMKernel::self()->config(), QStringLiteral("Mime #%1").arg(numValidEntries)); config.writeEntry("name", str); config.writeEntry("value", item->text(1)); numValidEntries++; } } KMailSettings::self()->setCustomMessageHeadersCount(numValidEntries); } void ComposerPage::HeadersTab::doResetToDefaultsOther() { const bool bUseDefaults = MessageComposer::MessageComposerSettings::self()->useDefaults(true); const QString messageIdSuffix = MessageComposer::MessageComposerSettings::customMsgIDSuffix(); const bool useCustomMessageIdSuffix = MessageComposer::MessageComposerSettings::useCustomMessageIdSuffix(); MessageComposer::MessageComposerSettings::self()->useDefaults(bUseDefaults); mMessageIdSuffixEdit->setText(messageIdSuffix); const bool state = (!messageIdSuffix.isEmpty() && useCustomMessageIdSuffix); mCreateOwnMessageIdCheck->setChecked(state); mHeaderList->clear(); mTagNameEdit->clear(); mTagValueEdit->clear(); // disable the "Remove" button mRemoveHeaderButton->setEnabled(false); } QString ComposerPage::AttachmentsTab::helpAnchor() const { return QStringLiteral("configure-composer-attachments"); } ComposerPageAttachmentsTab::ComposerPageAttachmentsTab(QWidget *parent) : ConfigModuleTab(parent) { QVBoxLayout *vlay = new QVBoxLayout(this); // "Outlook compatible attachment naming" check box mOutlookCompatibleCheck = new QCheckBox(i18n("Outlook-compatible attachment naming"), this); mOutlookCompatibleCheck->setChecked(false); mOutlookCompatibleCheck->setToolTip(i18n( "Turn this option on to make Outlook(tm) understand attachment names " "containing non-English characters")); connect(mOutlookCompatibleCheck, &QCheckBox::stateChanged, this, &ConfigModuleTab::slotEmitChanged); connect(mOutlookCompatibleCheck, &QAbstractButton::clicked, this, &ComposerPageAttachmentsTab::slotOutlookCompatibleClicked); vlay->addWidget(mOutlookCompatibleCheck); vlay->addSpacing(5); // "Enable detection of missing attachments" check box mMissingAttachmentDetectionCheck = new QCheckBox(i18n("E&nable detection of missing attachments"), this); mMissingAttachmentDetectionCheck->setChecked(true); connect(mMissingAttachmentDetectionCheck, &QCheckBox::stateChanged, this, &ConfigModuleTab::slotEmitChanged); vlay->addWidget(mMissingAttachmentDetectionCheck); // "Attachment key words" label and string list editor QLabel *label = new QLabel(i18n("Recognize any of the following key words as " "intention to attach a file:"), this); label->setAlignment(Qt::AlignLeft); label->setWordWrap(true); vlay->addWidget(label); PimCommon::SimpleStringListEditor::ButtonCode buttonCode = static_cast(PimCommon::SimpleStringListEditor::Add | PimCommon::SimpleStringListEditor::Remove | PimCommon::SimpleStringListEditor::Modify); mAttachWordsListEditor = new PimCommon::SimpleStringListEditor(this, buttonCode, i18n("A&dd..."), i18n("Re&move"), i18n("Mod&ify..."), i18n("Enter new key word:")); connect(mAttachWordsListEditor, &PimCommon::SimpleStringListEditor::changed, this, &ConfigModuleTab::slotEmitChanged); vlay->addWidget(mAttachWordsListEditor); connect(mMissingAttachmentDetectionCheck, &QAbstractButton::toggled, label, &QWidget::setEnabled); connect(mMissingAttachmentDetectionCheck, &QAbstractButton::toggled, mAttachWordsListEditor, &QWidget::setEnabled); QHBoxLayout *layAttachment = new QHBoxLayout; label = new QLabel(i18n("Maximum Attachment Size:"), this); label->setAlignment(Qt::AlignLeft); layAttachment->addWidget(label); mMaximumAttachmentSize = new QSpinBox(this); mMaximumAttachmentSize->setRange(-1, 99999); mMaximumAttachmentSize->setSingleStep(100); mMaximumAttachmentSize->setSuffix(i18nc("spinbox suffix: unit for kilobyte", " kB")); connect(mMaximumAttachmentSize, QOverload::of(&QSpinBox::valueChanged), this, &ConfigModuleTab::slotEmitChanged); mMaximumAttachmentSize->setSpecialValueText(i18n("No limit")); layAttachment->addWidget(mMaximumAttachmentSize); vlay->addLayout(layAttachment); } void ComposerPage::AttachmentsTab::doLoadFromGlobalSettings() { loadWidget(mOutlookCompatibleCheck, MessageComposer::MessageComposerSettings::self()->outlookCompatibleAttachmentsItem()); loadWidget(mMissingAttachmentDetectionCheck, KMailSettings::self()->showForgottenAttachmentWarningItem()); loadWidget(mAttachWordsListEditor, KMailSettings::self()->attachmentKeywordsItem()); const int maximumAttachmentSize(MessageCore::MessageCoreSettings::self()->maximumAttachmentSize()); mMaximumAttachmentSize->setValue(maximumAttachmentSize == -1 ? -1 : MessageCore::MessageCoreSettings::self()->maximumAttachmentSize() / 1024); } void ComposerPage::AttachmentsTab::save() { saveCheckBox(mOutlookCompatibleCheck, MessageComposer::MessageComposerSettings::self()->outlookCompatibleAttachmentsItem()); saveCheckBox(mMissingAttachmentDetectionCheck, KMailSettings::self()->showForgottenAttachmentWarningItem()); saveSimpleStringListEditor(mAttachWordsListEditor, KMailSettings::self()->attachmentKeywordsItem()); KMime::setUseOutlookAttachmentEncoding(mOutlookCompatibleCheck->isChecked()); const int maximumAttachmentSize(mMaximumAttachmentSize->value()); MessageCore::MessageCoreSettings::self()->setMaximumAttachmentSize(maximumAttachmentSize == -1 ? -1 : maximumAttachmentSize * 1024); } void ComposerPageAttachmentsTab::slotOutlookCompatibleClicked() { if (mOutlookCompatibleCheck->isChecked()) { KMessageBox::information(nullptr, i18n("You have chosen to " "encode attachment names containing non-English characters in a way that " "is understood by Outlook(tm) and other mail clients that do not " "support standard-compliant encoded attachment names.\n" "Note that KMail may create non-standard compliant messages, " "and consequently it is possible that your messages will not be " "understood by standard-compliant mail clients; so, unless you have no " "other choice, you should not enable this option.")); } } ComposerPageAutoCorrectionTab::ComposerPageAutoCorrectionTab(QWidget *parent) : ConfigModuleTab(parent) { QVBoxLayout *vlay = new QVBoxLayout(this); vlay->setSpacing(0); vlay->setMargin(0); autocorrectionWidget = new PimCommon::AutoCorrectionWidget(this); if (KMKernel::self()) { autocorrectionWidget->setAutoCorrection(KMKernel::self()->composerAutoCorrection()); } vlay->addWidget(autocorrectionWidget); connect(autocorrectionWidget, &PimCommon::AutoCorrectionWidget::changed, this, &ConfigModuleTab::slotEmitChanged); } QString ComposerPageAutoCorrectionTab::helpAnchor() const { return QStringLiteral("configure-autocorrection"); } void ComposerPageAutoCorrectionTab::save() { autocorrectionWidget->writeConfig(); } void ComposerPageAutoCorrectionTab::doLoadFromGlobalSettings() { autocorrectionWidget->loadConfig(); } void ComposerPageAutoCorrectionTab::doResetToDefaultsOther() { autocorrectionWidget->resetToDefault(); } ComposerPageAutoImageResizeTab::ComposerPageAutoImageResizeTab(QWidget *parent) : ConfigModuleTab(parent) { QVBoxLayout *vlay = new QVBoxLayout(this); vlay->setSpacing(0); vlay->setMargin(0); autoResizeWidget = new MessageComposer::ImageScalingWidget(this); vlay->addWidget(autoResizeWidget); connect(autoResizeWidget, &MessageComposer::ImageScalingWidget::changed, this, &ConfigModuleTab::slotEmitChanged); } QString ComposerPageAutoImageResizeTab::helpAnchor() const { return QStringLiteral("configure-image-resize"); } void ComposerPageAutoImageResizeTab::save() { autoResizeWidget->writeConfig(); } void ComposerPageAutoImageResizeTab::doLoadFromGlobalSettings() { autoResizeWidget->loadConfig(); } void ComposerPageAutoImageResizeTab::doResetToDefaultsOther() { autoResizeWidget->resetToDefault(); } diff --git a/src/configuredialog/configuremiscpage.cpp b/src/configuredialog/configuremiscpage.cpp index b0c016129..d97442f4f 100644 --- a/src/configuredialog/configuremiscpage.cpp +++ b/src/configuredialog/configuremiscpage.cpp @@ -1,176 +1,176 @@ /* Copyright (c) 2013-2018 Montel Laurent This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2, as published by the Free Software Foundation. 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 "configuremiscpage.h" #include "PimCommon/ConfigureImmutableWidgetUtils" using namespace PimCommon::ConfigureImmutableWidgetUtils; #include "settings/kmailsettings.h" #include #include "MessageViewer/InvitationSettings" #include "MessageViewer/PrintingSettings" #include "messageviewer/messageviewersettings.h" #include "MessageViewer/PrintingSettings" #include #include #include #include #include using namespace MailCommon; QString MiscPage::helpAnchor() const { return QStringLiteral("configure-misc"); } MiscPage::MiscPage(QWidget *parent) : ConfigModuleWithTabs(parent) { FolderTab *folderTab = new FolderTab(); addTab(folderTab, i18n("Folders")); InviteTab *inviteTab = new InviteTab(); addTab(inviteTab, i18n("Invitations")); MiscPagePrintingTab *printingTab = new MiscPagePrintingTab(); addTab(printingTab, i18n("Printing")); } QString MiscPageFolderTab::helpAnchor() const { return QStringLiteral("configure-misc-folders"); } MiscPageFolderTab::MiscPageFolderTab(QWidget *parent) : ConfigModuleTab(parent) { mMMTab.setupUi(this); //replace QWidget with FolderRequester. Promote to doesn't work due to the custom constructor QHBoxLayout *layout = new QHBoxLayout; layout->setContentsMargins(0, 0, 0, 0); mMMTab.mOnStartupOpenFolder->setLayout(layout); mOnStartupOpenFolder = new FolderRequester(mMMTab.mOnStartupOpenFolder); layout->addWidget(mOnStartupOpenFolder); mMMTab.mExcludeImportantFromExpiry->setWhatsThis( - i18n(KMailSettings::self()->excludeImportantMailFromExpiryItem()->whatsThis().toUtf8())); + i18n(KMailSettings::self()->excludeImportantMailFromExpiryItem()->whatsThis().toUtf8().constData())); connect(mMMTab.mExcludeImportantFromExpiry, &QCheckBox::stateChanged, this, &MiscPageFolderTab::slotEmitChanged); connect(mMMTab.mLoopOnGotoUnread, QOverload::of(&KComboBox::activated), this, &MiscPageFolderTab::slotEmitChanged); connect(mMMTab.mActionEnterFolder, QOverload::of(&KComboBox::activated), this, &MiscPageFolderTab::slotEmitChanged); connect(mMMTab.mDelayedMarkTime, QOverload::of(&QSpinBox::valueChanged), this, &MiscPageFolderTab::slotEmitChanged); connect(mMMTab.mDelayedMarkAsRead, &QAbstractButton::toggled, mMMTab.mDelayedMarkTime, &QWidget::setEnabled); connect(mMMTab.mDelayedMarkAsRead, &QAbstractButton::toggled, this, &ConfigModuleTab::slotEmitChanged); connect(mMMTab.mShowPopupAfterDnD, &QCheckBox::stateChanged, this, &MiscPageFolderTab::slotEmitChanged); connect(mOnStartupOpenFolder, &MailCommon::FolderRequester::folderChanged, this, &MiscPageFolderTab::slotEmitChanged); connect(mMMTab.mEmptyTrashCheck, &QCheckBox::stateChanged, this, &MiscPageFolderTab::slotEmitChanged); connect(mMMTab.mStartUpFolderCheck, &QCheckBox::toggled, this, &MiscPageFolderTab::slotEmitChanged); connect(mMMTab.mStartUpFolderCheck, &QCheckBox::toggled, mOnStartupOpenFolder, &MailCommon::FolderRequester::setEnabled); connect(mMMTab.mDeleteMessagesWithoutConfirmation, &QCheckBox::toggled, this, &MiscPageFolderTab::slotEmitChanged); } void MiscPage::FolderTab::doLoadFromGlobalSettings() { loadWidget(mMMTab.mExcludeImportantFromExpiry, KMailSettings::self()->excludeImportantMailFromExpiryItem()); // default = "Loop in current folder" loadWidget(mMMTab.mLoopOnGotoUnread, KMailSettings::self()->loopOnGotoUnreadItem()); loadWidget(mMMTab.mActionEnterFolder, KMailSettings::self()->actionEnterFolderItem()); loadWidget(mMMTab.mDelayedMarkAsRead, MessageViewer::MessageViewerSettings::self()->delayedMarkAsReadItem()); loadWidget(mMMTab.mDelayedMarkTime, MessageViewer::MessageViewerSettings::self()->delayedMarkTimeItem()); loadWidget(mMMTab.mShowPopupAfterDnD, KMailSettings::self()->showPopupAfterDnDItem()); loadWidget(mMMTab.mStartUpFolderCheck, KMailSettings::self()->startSpecificFolderAtStartupItem()); mOnStartupOpenFolder->setEnabled(KMailSettings::self()->startSpecificFolderAtStartup()); loadWidget(mMMTab.mDeleteMessagesWithoutConfirmation, KMailSettings::self()->deleteMessageWithoutConfirmationItem()); doLoadOther(); } void MiscPage::FolderTab::doLoadOther() { loadWidget(mMMTab.mEmptyTrashCheck, KMailSettings::self()->emptyTrashOnExitItem()); mOnStartupOpenFolder->setCollection(Akonadi::Collection(KMailSettings::self()->startupFolder())); } void MiscPage::FolderTab::save() { saveCheckBox(mMMTab.mEmptyTrashCheck, KMailSettings::self()->emptyTrashOnExitItem()); saveComboBox(mMMTab.mActionEnterFolder, KMailSettings::self()->actionEnterFolderItem()); KMailSettings::self()->setStartupFolder(mOnStartupOpenFolder->collection().id()); saveCheckBox(mMMTab.mDelayedMarkAsRead, MessageViewer::MessageViewerSettings::self()->delayedMarkAsReadItem()); saveSpinBox(mMMTab.mDelayedMarkTime, MessageViewer::MessageViewerSettings::self()->delayedMarkTimeItem()); saveComboBox(mMMTab.mLoopOnGotoUnread, KMailSettings::self()->loopOnGotoUnreadItem()); saveCheckBox(mMMTab.mExcludeImportantFromExpiry, KMailSettings::self()->excludeImportantMailFromExpiryItem()); saveCheckBox(mMMTab.mShowPopupAfterDnD, KMailSettings::self()->showPopupAfterDnDItem()); saveCheckBox(mMMTab.mStartUpFolderCheck, KMailSettings::self()->startSpecificFolderAtStartupItem()); saveCheckBox(mMMTab.mDeleteMessagesWithoutConfirmation, KMailSettings::self()->deleteMessageWithoutConfirmationItem()); } MiscPageInviteTab::MiscPageInviteTab(QWidget *parent) : ConfigModuleTab(parent) { mInvitationUi = new MessageViewer::InvitationSettings(this); QHBoxLayout *l = new QHBoxLayout(this); l->setContentsMargins(0, 0, 0, 0); l->addWidget(mInvitationUi); connect(mInvitationUi, &MessageViewer::InvitationSettings::changed, this, &MiscPageInviteTab::slotEmitChanged); } void MiscPage::InviteTab::doLoadFromGlobalSettings() { mInvitationUi->doLoadFromGlobalSettings(); } void MiscPage::InviteTab::save() { mInvitationUi->save(); } void MiscPage::InviteTab::doResetToDefaultsOther() { mInvitationUi->doResetToDefaultsOther(); } MiscPagePrintingTab::MiscPagePrintingTab(QWidget *parent) : ConfigModuleTab(parent) { mPrintingUi = new MessageViewer::PrintingSettings(this); QHBoxLayout *l = new QHBoxLayout(this); l->setContentsMargins(0, 0, 0, 0); l->addWidget(mPrintingUi); connect(mPrintingUi, &MessageViewer::PrintingSettings::changed, this, &MiscPagePrintingTab::slotEmitChanged); } void MiscPagePrintingTab::doLoadFromGlobalSettings() { mPrintingUi->doLoadFromGlobalSettings(); } void MiscPagePrintingTab::doResetToDefaultsOther() { mPrintingUi->doResetToDefaultsOther(); } void MiscPagePrintingTab::save() { mPrintingUi->save(); }