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 }