Warning, file /office/calligra/libs/text/KoSectionModel.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 #include "KoSectionModel.h"
0002 
0003 #include <climits>
0004 #include <KoTextDocument.h>
0005 #include <KLocalizedString>
0006 
0007 KoSectionModel::KoSectionModel(QTextDocument *doc)
0008     : QAbstractItemModel()
0009     , m_doc(doc)
0010 {
0011     KoTextDocument(m_doc).setSectionModel(this);
0012 }
0013 
0014 KoSectionModel::~KoSectionModel()
0015 {
0016     foreach(KoSection *sec, m_registeredSections) {
0017         delete sec; // This will delete associated KoSectionEnd in KoSection destructor
0018     }
0019 }
0020 
0021 KoSection *KoSectionModel::createSection(const QTextCursor &cursor, KoSection *parent, const QString &name)
0022 {
0023     if (!isValidNewName(name)) {
0024         return 0;
0025     }
0026 
0027     KoSection *result = new KoSection(cursor, name, parent);
0028 
0029     // Lets find our number in parent's children by cursor position
0030     QVector<KoSection *> children = (parent ? parent->children() : m_rootSections);
0031     int childrenId = children.size();
0032     for (int i = 0; i < children.size(); i++) {
0033         if (cursor.position() < children[i]->bounds().first) {
0034             childrenId = i;
0035             break;
0036         }
0037     }
0038     // We need to place link from parent to children in childId place
0039     // Also need to find corresponding index and declare operations in terms of model
0040     insertToModel(result, childrenId);
0041 
0042     return result;
0043 }
0044 
0045 KoSection *KoSectionModel::createSection(const QTextCursor &cursor, KoSection *parent)
0046 {
0047     return createSection(cursor, parent, possibleNewName());
0048 }
0049 
0050 KoSectionEnd *KoSectionModel::createSectionEnd(KoSection *section)
0051 {
0052     return new KoSectionEnd(section);
0053 }
0054 
0055 KoSection *KoSectionModel::sectionAtPosition(int pos) const
0056 {
0057     // TODO: Rewrite it by traversing Model as tree
0058     KoSection *result = 0;
0059     int level = -1; // Seeking the section with maximum level
0060     QHash<QString, KoSection *>::ConstIterator it = m_sectionNames.begin();
0061     for (; it != m_sectionNames.end(); ++it) {
0062         QPair<int, int> bounds = it.value()->bounds();
0063         if (bounds.first > pos || bounds.second < pos) {
0064             continue;
0065         }
0066 
0067         if (it.value()->level() > level) {
0068             result = it.value();
0069             level = it.value()->level();
0070         }
0071     }
0072 
0073     return result;
0074 }
0075 
0076 bool KoSectionModel::isValidNewName(const QString &name) const
0077 {
0078     return (m_sectionNames.constFind(name) == m_sectionNames.constEnd());
0079 }
0080 
0081 QString KoSectionModel::possibleNewName()
0082 {
0083     QString newName;
0084     int i = m_registeredSections.count();
0085     do {
0086         i++;
0087         newName = i18nc("new numbered section name", "New section %1", i);
0088     } while (!isValidNewName(newName));
0089 
0090     return newName;
0091 }
0092 
0093 bool KoSectionModel::setName(KoSection *section, const QString &name)
0094 {
0095     if (section->name() == name || isValidNewName(name)) {
0096         section->setName(name);
0097         //TODO: we don't have name in columns, but need something to notify views about change
0098         emit dataChanged(m_modelIndex[section], m_modelIndex[section]);
0099         return true;
0100     }
0101     return false;
0102 }
0103 
0104 void KoSectionModel::allowMovingEndBound()
0105 {
0106     QSet<KoSection *>::ConstIterator it = m_registeredSections.constBegin();
0107     for (; it != m_registeredSections.constEnd(); ++it) {
0108         (*it)->setKeepEndBound(false);
0109     }
0110 }
0111 
0112 int KoSectionModel::findRowOfChild(KoSection *section) const
0113 {
0114     QVector<KoSection *> lookOn;
0115     if (!section->parent()) {
0116         lookOn = m_rootSections;
0117     } else {
0118         lookOn = section->parent()->children();
0119     }
0120 
0121     int result = lookOn.indexOf(section);
0122     Q_ASSERT(result != -1);
0123     return result;
0124 }
0125 
0126 QModelIndex KoSectionModel::index(int row, int column, const QModelIndex &parentIdx) const
0127 {
0128     if (!hasIndex(row, column, parentIdx)) {
0129         return QModelIndex();
0130     }
0131 
0132     if (!parentIdx.isValid()) {
0133         return createIndex(row, column, m_rootSections[row]);
0134     }
0135 
0136     KoSection *parent = static_cast<KoSection *>(parentIdx.internalPointer());
0137     return createIndex(row, column, parent->children().at(row));
0138 }
0139 
0140 QModelIndex KoSectionModel::parent(const QModelIndex &child) const
0141 {
0142     if (!child.isValid()) {
0143         return QModelIndex();
0144     }
0145 
0146     KoSection *section = static_cast<KoSection *>(child.internalPointer());
0147     KoSection *parent = section->parent();
0148     if (parent) {
0149         return createIndex(findRowOfChild(parent), 0, parent);
0150     }
0151     return QModelIndex();
0152 }
0153 
0154 int KoSectionModel::rowCount(const QModelIndex &parent) const
0155 {
0156     if (!parent.isValid()) {
0157         return m_rootSections.size();
0158     }
0159     return static_cast<KoSection *>(parent.internalPointer())->children().size();
0160 }
0161 
0162 int KoSectionModel::columnCount(const QModelIndex &/*parent*/) const
0163 {
0164     return 1;
0165 }
0166 
0167 QVariant KoSectionModel::data(const QModelIndex &index, int role) const
0168 {
0169     if (!index.isValid()) {
0170         return QVariant();
0171     }
0172 
0173     if (index.column() == 0 && role == PointerRole) {
0174         QVariant v;
0175         v.setValue(static_cast<KoSection *>(index.internalPointer()));
0176         return v;
0177     }
0178     return QVariant();
0179 }
0180 
0181 void KoSectionModel::insertToModel(KoSection *section, int childIdx)
0182 {
0183     Q_ASSERT(isValidNewName(section->name()));
0184 
0185     KoSection *parent = section->parent();
0186     if (parent) { // Inserting to some section
0187         beginInsertRows(m_modelIndex[parent], childIdx, childIdx);
0188         parent->insertChild(childIdx, section);
0189         endInsertRows();
0190         m_modelIndex[section] = QPersistentModelIndex(index(childIdx, 0, m_modelIndex[parent]));
0191     } else { // It will be root section
0192         beginInsertRows(QModelIndex(), childIdx, childIdx);
0193         m_rootSections.insert(childIdx, section);
0194         endInsertRows();
0195         m_modelIndex[section] = QPersistentModelIndex(index(childIdx, 0, QModelIndex()));
0196     }
0197 
0198     m_registeredSections.insert(section);
0199     m_sectionNames[section->name()] = section;
0200 }
0201 
0202 void KoSectionModel::deleteFromModel(KoSection *section)
0203 {
0204     KoSection *parent = section->parent();
0205     int childIdx = findRowOfChild(section);
0206     if (parent) { // Deleting non root section
0207         beginRemoveRows(m_modelIndex[parent], childIdx, childIdx);
0208         parent->removeChild(childIdx);
0209         endRemoveRows();
0210     } else { // Deleting root section
0211         beginRemoveRows(QModelIndex(), childIdx, childIdx);
0212         m_rootSections.remove(childIdx);
0213         endRemoveRows();
0214     }
0215     m_modelIndex.remove(section);
0216     m_sectionNames.remove(section->name());
0217 }