File indexing completed on 2024-05-26 16:15:52
0001 /* This file is part of the KDE project 0002 * Copyright (C) 2006 Thomas Zander <zander@kde.org> 0003 * Copyright (C) 2010 C. Boemann <cbo@boemann.dk> 0004 * Copyright (C) 2011 Boudewijn Rempt <boud@kogmbh.com> 0005 * 0006 * This library is free software; you can redistribute it and/or 0007 * modify it under the terms of the GNU Library General Public 0008 * License as published by the Free Software Foundation; either 0009 * version 2 of the License, or (at your option) any later version. 0010 * 0011 * This library is distributed in the hope that it will be useful, 0012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0014 * Library General Public License for more details. 0015 * 0016 * You should have received a copy of the GNU Library General Public License 0017 * along with this library; see the file COPYING.LIB. If not, write to 0018 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0019 * Boston, MA 02110-1301, USA. 0020 */ 0021 0022 #include "KoTextBlockData.h" 0023 0024 #include "KoTextBlockBorderData.h" 0025 #include "KoTextBlockPaintStrategyBase.h" 0026 0027 class Q_DECL_HIDDEN KoTextBlockData::Private : public QTextBlockUserData 0028 { 0029 public: 0030 Private() 0031 : counterWidth(-1.0) 0032 , counterSpacing(0) 0033 , counterIsImage(false) 0034 , counterIndex(1) 0035 , border(0) 0036 , paintStrategy(0) 0037 { 0038 layoutedMarkupRanges[KoTextBlockData::Misspell] = false; 0039 layoutedMarkupRanges[KoTextBlockData::Grammar] = false; 0040 } 0041 0042 ~Private() override { 0043 if (border && !border->deref()) 0044 delete border; 0045 delete paintStrategy; 0046 } 0047 qreal counterWidth; 0048 qreal counterSpacing; 0049 QString counterPrefix; 0050 QString counterPlainText; 0051 QString counterSuffix; 0052 QString partialCounterText; 0053 bool counterIsImage; 0054 int counterIndex; 0055 QPointF counterPos; 0056 QTextCharFormat labelFormat; 0057 KoTextBlockBorderData *border; 0058 KoTextBlockPaintStrategyBase *paintStrategy; 0059 QMap<KoTextBlockData::MarkupType, QVector<MarkupRange> > markupRangesMap; 0060 QMap<KoTextBlockData::MarkupType, bool> layoutedMarkupRanges; 0061 }; 0062 0063 KoTextBlockData::KoTextBlockData(QTextBlock &block) 0064 : d(block.userData() ? dynamic_cast<KoTextBlockData::Private *>(block.userData()) 0065 : new Private()) 0066 { 0067 block.setUserData(d); 0068 } 0069 0070 KoTextBlockData::KoTextBlockData(QTextBlockUserData *userData) 0071 : d(dynamic_cast<KoTextBlockData::Private *>(userData)) 0072 { 0073 Q_ASSERT(d); 0074 } 0075 0076 KoTextBlockData::~KoTextBlockData() 0077 { 0078 // explicitly do not delete the d-pointer here 0079 } 0080 0081 0082 void KoTextBlockData::appendMarkup(MarkupType type, int firstChar, int lastChar) 0083 { 0084 Q_ASSERT(d->markupRangesMap[type].isEmpty() || firstChar > d->markupRangesMap[type].last().lastChar + d->markupRangesMap[type].last().lastRebased); 0085 0086 MarkupRange range; 0087 range.firstChar = firstChar; 0088 range.lastChar = lastChar; 0089 range.firstRebased = 0; 0090 range.lastRebased = 0; 0091 if (!d->markupRangesMap[type].isEmpty()) { 0092 // The document may have been changed (and thus markup has moved) while 0093 // the plugin has done its job in the background 0094 range.firstChar += d->markupRangesMap[type].last().firstRebased; 0095 range.lastChar += d->markupRangesMap[type].last().lastRebased; 0096 } 0097 d->layoutedMarkupRanges[type] = false; 0098 0099 d->markupRangesMap[type].append(range); 0100 } 0101 0102 void KoTextBlockData::clearMarkups(MarkupType type) 0103 { 0104 d->markupRangesMap[type].clear(); 0105 d->layoutedMarkupRanges[type] = false; 0106 } 0107 0108 KoTextBlockData::MarkupRange KoTextBlockData::findMarkup(MarkupType type, int positionWithin) const 0109 { 0110 foreach (const MarkupRange &range, d->markupRangesMap[type]) { 0111 if (positionWithin <= range.lastChar + range.lastRebased) { 0112 // possible hit 0113 if (positionWithin >= range.firstChar + range.firstRebased) { 0114 return range; 0115 } else { 0116 return MarkupRange(); // we have passed it without finding 0117 } 0118 } 0119 } 0120 return MarkupRange(); // either no ranges or not in last either 0121 } 0122 0123 void KoTextBlockData::rebaseMarkups(MarkupType type, int fromPosition, int delta) 0124 { 0125 QVector<MarkupRange>::Iterator markIt = markupsBegin(type); 0126 QVector<MarkupRange>::Iterator markEnd = markupsEnd(type); 0127 while (markIt != markEnd) { 0128 if (fromPosition <= markIt->lastChar) { 0129 // we need to modify the end of this 0130 markIt->lastChar += delta; 0131 markIt->lastRebased += delta; 0132 } 0133 if (fromPosition < markIt->firstChar) { 0134 // we need to modify the end of this 0135 markIt->firstChar += delta; 0136 markIt->firstRebased += delta; 0137 } 0138 ++markIt; 0139 } 0140 } 0141 0142 void KoTextBlockData::setMarkupsLayoutValidity(MarkupType type, bool valid) 0143 { 0144 d->layoutedMarkupRanges[type] = valid; 0145 } 0146 0147 bool KoTextBlockData::isMarkupsLayoutValid(MarkupType type) const 0148 { 0149 return d->layoutedMarkupRanges[type]; 0150 } 0151 0152 QVector<KoTextBlockData::MarkupRange>::Iterator KoTextBlockData::markupsBegin(MarkupType type) 0153 { 0154 return d->markupRangesMap[type].begin(); 0155 } 0156 0157 QVector<KoTextBlockData::MarkupRange>::Iterator KoTextBlockData::markupsEnd(MarkupType type) 0158 { 0159 return d->markupRangesMap[type].end(); 0160 } 0161 0162 bool KoTextBlockData::hasCounterData() const 0163 { 0164 return d->counterWidth >= 0 && (!d->counterPlainText.isNull() || d->counterIsImage); 0165 } 0166 0167 qreal KoTextBlockData::counterWidth() const 0168 { 0169 return qMax(qreal(0), d->counterWidth); 0170 } 0171 0172 void KoTextBlockData::setBorder(KoTextBlockBorderData *border) 0173 { 0174 if (d->border && !d->border->deref()) 0175 delete d->border; 0176 d->border = border; 0177 if (d->border) 0178 d->border->ref(); 0179 } 0180 0181 void KoTextBlockData::setCounterWidth(qreal width) 0182 { 0183 d->counterWidth = width; 0184 } 0185 0186 qreal KoTextBlockData::counterSpacing() const 0187 { 0188 return d->counterSpacing; 0189 } 0190 0191 void KoTextBlockData::setCounterSpacing(qreal spacing) 0192 { 0193 d->counterSpacing = spacing; 0194 } 0195 0196 QString KoTextBlockData::counterText() const 0197 { 0198 return d->counterPrefix + d->counterPlainText + d->counterSuffix; 0199 } 0200 0201 void KoTextBlockData::clearCounter() 0202 { 0203 d->partialCounterText.clear(); 0204 d->counterPlainText.clear(); 0205 d->counterPrefix.clear(); 0206 d->counterSuffix.clear(); 0207 d->counterSpacing = 0.0; 0208 d->counterWidth = 0.0; 0209 d->counterIsImage = false; 0210 } 0211 0212 void KoTextBlockData::setPartialCounterText(const QString &text) 0213 { 0214 d->partialCounterText = text; 0215 } 0216 0217 QString KoTextBlockData::partialCounterText() const 0218 { 0219 return d->partialCounterText; 0220 } 0221 0222 void KoTextBlockData::setCounterPlainText(const QString &text) 0223 { 0224 d->counterPlainText = text; 0225 } 0226 0227 QString KoTextBlockData::counterPlainText() const 0228 { 0229 return d->counterPlainText; 0230 } 0231 0232 void KoTextBlockData::setCounterPrefix(const QString &text) 0233 { 0234 d->counterPrefix = text; 0235 } 0236 0237 QString KoTextBlockData::counterPrefix() const 0238 { 0239 return d->counterPrefix; 0240 } 0241 0242 void KoTextBlockData::setCounterSuffix(const QString &text) 0243 { 0244 d->counterSuffix = text; 0245 } 0246 0247 QString KoTextBlockData::counterSuffix() const 0248 { 0249 return d->counterSuffix; 0250 } 0251 0252 void KoTextBlockData::setCounterIsImage(bool isImage) 0253 { 0254 d->counterIsImage = isImage; 0255 } 0256 0257 bool KoTextBlockData::counterIsImage() const 0258 { 0259 return d->counterIsImage; 0260 } 0261 0262 void KoTextBlockData::setCounterIndex(int index) 0263 { 0264 d->counterIndex = index; 0265 } 0266 0267 int KoTextBlockData::counterIndex() const 0268 { 0269 return d->counterIndex; 0270 } 0271 0272 void KoTextBlockData::setCounterPosition(const QPointF &position) 0273 { 0274 d->counterPos = position; 0275 } 0276 0277 QPointF KoTextBlockData::counterPosition() const 0278 { 0279 return d->counterPos; 0280 } 0281 0282 void KoTextBlockData::setLabelFormat(const QTextCharFormat &format) 0283 { 0284 d->labelFormat = format; 0285 } 0286 0287 QTextCharFormat KoTextBlockData::labelFormat() const 0288 { 0289 return d->labelFormat; 0290 } 0291 0292 KoTextBlockBorderData *KoTextBlockData::border() const 0293 { 0294 return d->border; 0295 } 0296 0297 void KoTextBlockData::setPaintStrategy(KoTextBlockPaintStrategyBase *paintStrategy) 0298 { 0299 delete d->paintStrategy; 0300 d->paintStrategy = paintStrategy; 0301 } 0302 0303 KoTextBlockPaintStrategyBase *KoTextBlockData::paintStrategy() const 0304 { 0305 return d->paintStrategy; 0306 } 0307 0308 bool KoTextBlockData::saveXmlID() const 0309 { 0310 // as suggested by boemann, http://lists.kde.org/?l=calligra-devel&m=132396354701553&w=2 0311 return d->paintStrategy != 0; 0312 }