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 */