File indexing completed on 2024-05-12 15:56:14

0001 /*
0002  *  SPDX-FileCopyrightText: 2014 Dmitry Kazakov <dimula73@gmail.com>
0003  *  SPDX-FileCopyrightText: 2014 Alexander Potashev <aspotashev@gmail.com>
0004  *
0005  *  SPDX-License-Identifier: LGPL-2.0-or-later
0006  */
0007 
0008 #ifndef KUNDO2MAGICSTRING_H
0009 #define KUNDO2MAGICSTRING_H
0010 
0011 #include <QString>
0012 #include <QDebug>
0013 
0014 #include <klocalizedstring.h>
0015 
0016 #include "kritacommand_export.h"
0017 
0018 /**
0019  * \class KUndo2MagicString is a special wrapper for a string that is
0020  * going to passed to a KUndo2Command and be later shown in the undo
0021  * history and undo action in menu. The strings like that must have
0022  * (qtundo-format) context to let translators know that they are
0023  * allowed to use magic split in them.
0024  *
0025  * Magic split is used in some languages to split the message in the
0026  * undo history docker (which is either verb or <a
0027  * href="https://en.wikipedia.org/wiki/Nominative_case">noun in
0028  * nominative</a>) and the message in undo/redo actions (which is
0029  * usually a <a href="https://en.wikipedia.org/wiki/Accusative_case">noun
0030  * in accusative</a>). When the translator needs it he, splits two
0031  * translations with '\n' symbol and the magic string will recognize
0032  * it.
0033  *
0034  * \note KUndo2MagicString will never support concatenation operators,
0035  *       because in many languages you cannot combine words without
0036  *       knowing the proper case.
0037  */
0038 class KRITACOMMAND_EXPORT KUndo2MagicString
0039 {
0040 public:
0041     /**
0042      * Construct an empty string. Note that you cannot create a
0043      * non-empy string without special functions, all the calls to which
0044      * are processed by xgettext.
0045      */
0046     KUndo2MagicString();
0047 
0048     /**
0049      * Fetch the main translated string. That is the one that goes to
0050      * undo history and resembles the action name in verb/nominative
0051      */
0052     QString toString() const;
0053 
0054     /**
0055      * Fetch the secondary string which will go to the undo/redo
0056      * action.  This is usually a noun in accusative. If the
0057      * translator didn't provide a secondary string, toString() and
0058      * toSecondaryString() return the same values.
0059      */
0060     QString toSecondaryString() const;
0061 
0062     /**
0063      * \return true if the contained string is empty
0064      */
0065     bool isEmpty() const;
0066 
0067     bool operator==(const KUndo2MagicString &rhs) const;
0068     bool operator!=(const KUndo2MagicString &rhs) const;
0069 
0070 private:
0071     /**
0072      * Construction of a magic string is allowed only with the means
0073      * of special macros which resemble their kde-wide counterparts
0074      */
0075     explicit KUndo2MagicString(const QString &text);
0076 
0077 
0078     friend KUndo2MagicString kundo2_noi18n(const QString &text);
0079     template <typename A1>
0080     friend KUndo2MagicString kundo2_noi18n(const char *text, const A1 &a1);
0081     template <typename A1, typename A2>
0082     friend KUndo2MagicString kundo2_noi18n(const char *text, const A1 &a1, const A2 &a2);
0083     template <typename A1, typename A2, typename A3>
0084     friend KUndo2MagicString kundo2_noi18n(const char *text, const A1 &a1, const A2 &a2, const A3 &a3);
0085     template <typename A1, typename A2, typename A3, typename A4>
0086     friend KUndo2MagicString kundo2_noi18n(const char *text, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4);
0087 
0088 
0089     friend KUndo2MagicString kundo2_i18n(const char *text);
0090     template <typename A1>
0091     friend KUndo2MagicString kundo2_i18n(const char *text, const A1 &a1);
0092     template <typename A1, typename A2>
0093     friend KUndo2MagicString kundo2_i18n(const char *text, const A1 &a1, const A2 &a2);
0094     template <typename A1, typename A2, typename A3>
0095     friend KUndo2MagicString kundo2_i18n(const char *text, const A1 &a1, const A2 &a2, const A3 &a3);
0096     template <typename A1, typename A2, typename A3, typename A4>
0097     friend KUndo2MagicString kundo2_i18n(const char *text, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4);
0098 
0099 
0100     friend KUndo2MagicString kundo2_i18nc(const char *ctxt, const char *text);
0101     template <typename A1>
0102     friend KUndo2MagicString kundo2_i18nc(const char *ctxt, const char *text, const A1 &a1);
0103     template <typename A1, typename A2>
0104     friend KUndo2MagicString kundo2_i18nc(const char *ctxt, const char *text, const A1 &a1, const A2 &a2);
0105     template <typename A1, typename A2, typename A3>
0106     friend KUndo2MagicString kundo2_i18nc(const char *ctxt, const char *text, const A1 &a1, const A2 &a2, const A3 &a3);
0107 
0108 
0109     template <typename A1>
0110     friend KUndo2MagicString kundo2_i18np(const char *sing, const char *plur, const A1 &a1);
0111     template <typename A1, typename A2>
0112     friend KUndo2MagicString kundo2_i18np(const char *sing, const char *plur, const A1 &a1, const A2 &a2);
0113     template <typename A1, typename A2, typename A3>
0114     friend KUndo2MagicString kundo2_i18np(const char *sing, const char *plur, const A1 &a1, const A2 &a2, const A3 &a3);
0115 
0116 
0117     template <typename A1>
0118     friend KUndo2MagicString kundo2_i18ncp(const char *ctxt, const char *sing, const char *plur, const A1 &a1);
0119     template <typename A1, typename A2>
0120     friend KUndo2MagicString kundo2_i18ncp(const char *ctxt, const char *sing, const char *plur, const A1 &a1, const A2 &a2);
0121     template <typename A1, typename A2, typename A3>
0122     friend KUndo2MagicString kundo2_i18ncp(const char *ctxt, const char *sing, const char *plur, const A1 &a1, const A2 &a2, const A3 &a3);
0123 
0124 private:
0125     QString m_text;
0126 };
0127 
0128 inline QDebug operator<<(QDebug dbg, const KUndo2MagicString &v)
0129 {
0130     if (v.toString() != v.toSecondaryString()) {
0131         dbg.nospace() << v.toString() << "(" << v.toSecondaryString() << ")";
0132     } else {
0133         dbg.nospace() << v.toString();
0134     }
0135 
0136     return dbg.space();
0137 }
0138 
0139 
0140 /**
0141  * This is a special wrapper to a string which tells explicitly
0142  * that we don't need a translation for a given string. It is used
0143  * either in testing or internal commands, which don't go to the
0144  * stack directly.
0145  */
0146 inline KUndo2MagicString kundo2_noi18n(const QString &text)
0147 {
0148     return KUndo2MagicString(text);
0149 }
0150 
0151 template <typename A1>
0152 inline KUndo2MagicString kundo2_noi18n(const char *text, const A1 &a1)
0153 {
0154     return KUndo2MagicString(QString(text).arg(a1));
0155 }
0156 
0157 template <typename A1, typename A2>
0158 inline KUndo2MagicString kundo2_noi18n(const char *text, const A1 &a1, const A2 &a2)
0159 {
0160     return KUndo2MagicString(QString(text).arg(a1).arg(a2));
0161 }
0162 
0163 template <typename A1, typename A2, typename A3>
0164 inline KUndo2MagicString kundo2_noi18n(const char *text, const A1 &a1, const A2 &a2, const A3 &a3)
0165 {
0166     return KUndo2MagicString(QString(text).arg(a1).arg(a2).arg(a3));
0167 }
0168 
0169 template <typename A1, typename A2, typename A3, typename A4>
0170 inline KUndo2MagicString kundo2_noi18n(const char *text, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4)
0171 {
0172     return KUndo2MagicString(QString(text).arg(a1).arg(a2).arg(a3).arg(a4));
0173 }
0174 
0175 /**
0176  * Same as ki18n, but is supposed to work with strings going to
0177  * undo stack
0178  */
0179 
0180 inline KUndo2MagicString kundo2_i18n(const char *text)
0181 {
0182     return KUndo2MagicString(i18nc("(qtundo-format)", text));
0183 }
0184 
0185 template <typename A1>
0186 inline KUndo2MagicString kundo2_i18n(const char *text, const A1 &a1)
0187 {
0188     return KUndo2MagicString(i18nc("(qtundo-format)", text, a1));
0189 }
0190 
0191 template <typename A1, typename A2>
0192 inline KUndo2MagicString kundo2_i18n(const char *text, const A1 &a1, const A2 &a2)
0193 {
0194     return KUndo2MagicString(i18nc("(qtundo-format)", text, a1, a2));
0195 }
0196 
0197 template <typename A1, typename A2, typename A3>
0198 inline KUndo2MagicString kundo2_i18n(const char *text, const A1 &a1, const A2 &a2, const A3 &a3)
0199 {
0200     return KUndo2MagicString(i18nc("(qtundo-format)", text, a1, a2, a3));
0201 }
0202 
0203 template <typename A1, typename A2, typename A3, typename A4>
0204 inline KUndo2MagicString kundo2_i18n(const char *text, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4)
0205 {
0206     return KUndo2MagicString(i18nc("(qtundo-format)", text, a1, a2, a3, a4));
0207 }
0208 
0209 inline QString prependContext(const char *ctxt)
0210 {
0211     return QString("(qtundo-format) %1").arg(ctxt);
0212 }
0213 
0214 /**
0215  * Same as ki18nc, but is supposed to work with strings going to
0216  * undo stack
0217  */
0218 inline KUndo2MagicString kundo2_i18nc(const char *ctxt, const char *text)
0219 {
0220     return KUndo2MagicString(i18nc(prependContext(ctxt).toLatin1().data(), text));
0221 }
0222 
0223 template <typename A1>
0224 inline KUndo2MagicString kundo2_i18nc(const char *ctxt, const char *text, const A1 &a1)
0225 {
0226     return KUndo2MagicString(i18nc(prependContext(ctxt).toLatin1().data(), text, a1));
0227 }
0228 
0229 template <typename A1, typename A2>
0230 inline KUndo2MagicString kundo2_i18nc(const char *ctxt, const char *text, const A1 &a1, const A2 &a2)
0231 {
0232     return KUndo2MagicString(i18nc(prependContext(ctxt).toLatin1().data(), text, a1, a2));
0233 }
0234 
0235 template <typename A1, typename A2, typename A3>
0236 inline KUndo2MagicString kundo2_i18nc(const char *ctxt, const char *text, const A1 &a1, const A2 &a2, const A3 &a3)
0237 {
0238     return KUndo2MagicString(i18nc(prependContext(ctxt).toLatin1().data(), text, a1, a2, a3));
0239 }
0240 
0241 template <typename A1, typename A2, typename A3, typename A4>
0242 inline KUndo2MagicString kundo2_i18nc(const char *ctxt, const char *text, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4)
0243 {
0244     return KUndo2MagicString(i18nc(prependContext(ctxt).toLatin1().data(), text, a1, a2, a3, a4));
0245 }
0246 
0247 /**
0248  * Same as ki18np, but is supposed to work with strings going to
0249  * undo stack
0250  */
0251 
0252 template <typename A1>
0253 inline KUndo2MagicString kundo2_i18np(const char *sing, const char *plur, const A1 &a1)
0254 {
0255     return KUndo2MagicString(i18ncp("(qtundo-format)", sing, plur, a1));
0256 }
0257 
0258 template <typename A1, typename A2>
0259 inline KUndo2MagicString kundo2_i18np(const char *sing, const char *plur, const A1 &a1, const A2 &a2)
0260 {
0261     return i18ncp("(qtundo-format)", sing, plur, a1, a2);
0262 }
0263 
0264 template <typename A1, typename A2, typename A3>
0265 inline KUndo2MagicString kundo2_i18np(const char *sing, const char *plur, const A1 &a1, const A2 &a2, const A3 &a3)
0266 {
0267     return i18ncp("(qtundo-format)", sing, plur, a1, a2, a3);
0268 }
0269 
0270 template <typename A1, typename A2, typename A3, typename A4>
0271 inline KUndo2MagicString kundo2_i18np(const char *sing, const char *plur, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4)
0272 {
0273     return i18ncp("(qtundo-format)", sing, plur, a1, a2, a3, a4);
0274 }
0275 
0276 
0277 /**
0278  * Same as ki18ncp, but is supposed to work with strings going to
0279  * undo stack
0280  */
0281 template <typename A1>
0282 inline KUndo2MagicString kundo2_i18ncp(const char *ctxt, const char *sing, const char *plur, const A1 &a1)
0283 {
0284     return KUndo2MagicString(i18ncp(prependContext(ctxt).toLatin1().data(), sing, plur, a1));
0285 }
0286 
0287 template <typename A1, typename A2>
0288 inline KUndo2MagicString kundo2_i18ncp(const char *ctxt, const char *sing, const char *plur, const A1 &a1, const A2 &a2)
0289 {
0290     return i18ncp(prependContext(ctxt).toLatin1().data(), sing, plur, a1, a2);
0291 }
0292 
0293 template <typename A1, typename A2, typename A3>
0294 inline KUndo2MagicString kundo2_i18ncp(const char *ctxt, const char *sing, const char *plur, const A1 &a1, const A2 &a2, const A3 &a3)
0295 {
0296     return i18ncp(prependContext(ctxt).toLatin1().data(), sing, plur, a1, a2, a3);
0297 }
0298 
0299 template <typename A1, typename A2, typename A3, typename A4>
0300 inline KUndo2MagicString kundo2_i18ncp(const char *ctxt, const char *sing, const char *plur, const A1 &a1, const A2 &a2, const A3 &a3, const A4 &a4)
0301 {
0302     return i18ncp(prependContext(ctxt).toLatin1().data(), sing, plur, a1, a2, a3, a4);
0303 }
0304 
0305 #endif /* KUNDO2MAGICSTRING_H */