File indexing completed on 2024-05-05 17:09:09

0001 /*
0002  * This file is part of the KDE project
0003  *
0004  * Copyright 2014  Dan Leinir Turthra Jensen <admin@leinir.dk>
0005  *
0006  * This program is free software; you can redistribute it and/or
0007  * modify it under the terms of the GNU General Public License as
0008  * published by the Free Software Foundation; either version 2 of
0009  * the License or (at your option) version 3 or any later version
0010  * accepted by the membership of KDE e.V. (or its successor approved
0011  * by the membership of KDE e.V.), which shall act as a proxy
0012  * defined in Section 14 of version 3 of the license.
0013  *
0014  * This program is distributed in the hope that it will be useful,
0015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0017  * GNU General Public License for more details.
0018  *
0019  * You should have received a copy of the GNU General Public License
0020  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
0021  *
0022  */
0023 
0024 #include "CQTextDocumentNotesModel.h"
0025 
0026 #include <QColor>
0027 
0028 struct Entry {
0029     Entry() : colorCount(1), shape(0), expanded(false) {};
0030     QString text;
0031     QString image;
0032     QString color;
0033     QString categoryName;
0034     int colorCount;
0035     KoShape* shape;
0036     bool expanded;
0037 };
0038 
0039 class CQTextDocumentNotesModel::Private {
0040 public:
0041     Private() {}
0042     ~Private() {
0043         qDeleteAll(entries);
0044     }
0045     QList<Entry*> entries;
0046 };
0047 
0048 CQTextDocumentNotesModel::CQTextDocumentNotesModel(QObject* parent)
0049     : QAbstractListModel(parent)
0050     , d(new Private)
0051 {
0052     QHash<int, QByteArray> roles;
0053     roles[Text] = "text";
0054     roles[Image] = "image";
0055     roles[Color] = "color";
0056     roles[ColorCount] = "colorCount";
0057     roles[CategoryName] = "categoryName";
0058     roles[FirstOfThisColor] = "firstOfThisColor";
0059     roles[Position] = "position";
0060     roles[Expanded] = "expanded";
0061     setRoleNames(roles);
0062 }
0063 
0064 CQTextDocumentNotesModel::~CQTextDocumentNotesModel()
0065 {
0066     delete d;
0067 }
0068 
0069 QVariant CQTextDocumentNotesModel::data(const QModelIndex& index, int role) const
0070 {
0071     QVariant data;
0072     if (index.isValid() && index.row() < d->entries.count()) {
0073         Entry* entry = d->entries.at(index.row());
0074         switch(role) {
0075             case Text:
0076                 data = entry->text;
0077                 break;
0078             case Image:
0079                 data = entry->image;
0080                 break;
0081             case Color:
0082                 data = entry->color;
0083                 break;
0084             case ColorCount:
0085                 data = entry->colorCount;
0086                 break;
0087             case CategoryName:
0088                 data = entry->categoryName;
0089                 break;
0090             case FirstOfThisColor:
0091                 data = true;
0092                 if (index.row() > 0 && d->entries.at(index.row() - 1)->color == entry->color) {
0093                     data = false;
0094                 }
0095                 break;
0096             case Position:
0097                 data = entry->shape->absolutePosition();
0098                 break;
0099             case Expanded:
0100                 data = entry->expanded;
0101                 break;
0102             default:
0103                 data = QLatin1String("No such role. Supported roles are text, image, color, colorCount and position.");
0104                 break;
0105         }
0106     }
0107     return data;
0108 }
0109 
0110 int CQTextDocumentNotesModel::rowCount(const QModelIndex& parent) const
0111 {
0112     if (parent.isValid()) {
0113         return 0;
0114     }
0115     return d->entries.count();
0116 }
0117 
0118 int CQTextDocumentNotesModel::count() const
0119 {
0120     return d->entries.count();
0121 }
0122 
0123 void CQTextDocumentNotesModel::toggleExpanded(int index)
0124 {
0125     if (index > -1 && index < d->entries.count()) {
0126         QColor color = d->entries.at(index)->color;
0127         foreach(Entry* entry, d->entries) {
0128             if (color == entry->color) {
0129                 entry->expanded = !entry->expanded;
0130             }
0131         }
0132     }
0133     dataChanged(this->index(0), this->index(d->entries.count() - 1));
0134 }
0135 
0136 void CQTextDocumentNotesModel::addEntry(const QString& text, const QString& image, const QString& color, KoShape* shape)
0137 {
0138     Entry* entry = new Entry();
0139     entry->text = text;
0140     entry->image = image;
0141     entry->shape = shape;
0142     entry->color = color;
0143     entry->categoryName = "Others";
0144     if (color == "#fd5134") {
0145         entry->categoryName = "Major Errors";
0146     } else if (color == "#ffb20c") {
0147         entry->categoryName = "Minor Errors";
0148     } else if (color == "#29b618") {
0149         entry->categoryName = "Successes";
0150     }
0151 
0152     QList<Entry*>::iterator before = d->entries.begin();
0153     bool reachedColor = false;
0154     int colorCount = 0, position = 0;
0155     for(; before != d->entries.end(); ++before) {
0156         if ((*before)->color == entry->color)
0157         {
0158             // We are now in the current entry's section as defined by colour
0159             // and we grab the current colour count for that section from
0160             // this item. Could just increase, but that's cause a double-loop
0161             // to update all the other entries.
0162             reachedColor = true;
0163             colorCount = (*before)->colorCount + 1;
0164             (*before)->colorCount = colorCount;
0165             entry->colorCount = colorCount;
0166             entry->expanded = (*before)->expanded;
0167         }
0168         if (reachedColor)
0169         {
0170             // If we find a new colour, that means we're out of the current
0171             // section, and we break out. This also conveniently leaves us
0172             // with the entry we want to insert the item before.
0173             if ((*before)->color != entry->color) {
0174                 break;
0175             }
0176             (*before)->colorCount = colorCount;
0177         }
0178         ++position;
0179     }
0180 
0181     // By default, the Neutral category is supposed to be expanded
0182     if (color == "Neutral" && colorCount == 1) {
0183         entry->expanded = true;
0184     }
0185 
0186     beginInsertRows(QModelIndex(), position, position);
0187     d->entries.insert(before, entry);
0188     endInsertRows();
0189     dataChanged(index(position - colorCount), index(position - 1));
0190     emit countChanged();
0191 }