File indexing completed on 2024-05-19 16:09:31

0001 /* This file is part of the KDE project
0002 * Copyright (C) 2011 Paul Mendez <paulestebanms@gmail.com>
0003 *
0004 * This library is free software; you can redistribute it and/or
0005 * modify it under the terms of the GNU Library General Public
0006 * License as published by the Free Software Foundation; either
0007 * version 2 of the License, or (at your option) any later version.
0008 *
0009 * This library is distributed in the hope that it will be useful,
0010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
0011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0012 * Library General Public License for more details.
0013 *
0014 * You should have received a copy of the GNU Library General Public License
0015 * along with this library; see the file COPYING.LIB.  If not, write to
0016 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0017 * Boston, MA 02110-1301, USA.
0018 */
0019 
0020 #include "KPrCustomSlideShowsModel.h"
0021 
0022 //Calligra headers
0023 #include "KPrCustomSlideShows.h"
0024 #include "KPrDocument.h"
0025 #include "KoPAPageBase.h"
0026 #include "commands/KPrEditCustomSlideShowsCommand.h"
0027 #include "commands/KPrAddCustomSlideShowCommand.h"
0028 #include "commands/KPrDelCustomSlideShowCommand.h"
0029 #include "commands/KPrRenameCustomSlideShowCommand.h"
0030 
0031 //KF5 headers
0032 #include <klocalizedstring.h>
0033 
0034 //Qt headers
0035 #include <QIcon>
0036 #include <QMimeData>
0037 #include <QApplication>
0038 #include <QMenu>
0039 
0040 //Other
0041 #include <algorithm>
0042 
0043 KPrCustomSlideShowsModel::KPrCustomSlideShowsModel(KPrDocument *document, QObject *parent)
0044     : QAbstractListModel(parent)
0045     , m_customSlideShows(document->customSlideShows())
0046     , m_iconSize(QSize(200,200))
0047     , m_document(document)
0048 {
0049     connect(m_customSlideShows, SIGNAL(updated()), this, SLOT(updateModel()));
0050 }
0051 
0052 KPrCustomSlideShowsModel::~KPrCustomSlideShowsModel(){
0053 }
0054 
0055 QVariant KPrCustomSlideShowsModel::data(const QModelIndex &index, int role) const
0056 {
0057     if (!index.isValid() || !m_customSlideShows || m_activeCustomSlideShowName.isEmpty()) {
0058         return QVariant();
0059     }
0060     Q_ASSERT(index.model() == this);
0061 
0062     KoPAPageBase *page = m_customSlideShows->pageByIndex(m_activeCustomSlideShowName, index.row());
0063 
0064     switch (role) {
0065         case Qt::DisplayRole:
0066         {
0067             QString name = i18n("Unknown");
0068             if (page) {
0069                 name = page->name();
0070                 if (name.isEmpty()) {
0071                     //Default case
0072                     name = i18n("Slide %1",  index.row());
0073                 }
0074             }
0075             return name;
0076         }
0077         case Qt::DecorationRole:
0078         {
0079             return QIcon(page->thumbnail(m_iconSize));
0080         }
0081         default:
0082             return QVariant();
0083     }
0084 }
0085 
0086 int KPrCustomSlideShowsModel::rowCount(const QModelIndex &parent) const
0087 {
0088     if (!m_activeCustomSlideShowName.isEmpty()) {
0089         if (!parent.isValid()) {
0090             return m_customSlideShows->getByName(m_activeCustomSlideShowName).count();
0091         }
0092     }
0093 
0094     return 0;
0095 }
0096 
0097 Qt::ItemFlags KPrCustomSlideShowsModel::flags(const QModelIndex &index) const
0098 {
0099     if (m_activeCustomSlideShowName.isEmpty()) {
0100         return 0;
0101     }
0102 
0103     Qt::ItemFlags defaultFlags = QAbstractListModel::flags (index);
0104 
0105     if (index.isValid()) {
0106         return Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | defaultFlags;
0107     }
0108     else {
0109         return Qt::ItemIsDropEnabled | defaultFlags;
0110     }
0111 }
0112 
0113 QModelIndex KPrCustomSlideShowsModel::index(int row, int column, const QModelIndex &parent) const
0114 {
0115     if (m_activeCustomSlideShowName.isEmpty()) {
0116         return QModelIndex();
0117     }
0118 
0119     // check if parent is root node
0120     if (!parent.isValid()) {
0121         if (row >= 0 && row < rowCount(QModelIndex())) {
0122             return createIndex(row, column, m_customSlideShows->pageByIndex(m_activeCustomSlideShowName, row));
0123         }
0124     }
0125     return QModelIndex();
0126 }
0127 
0128 QStringList KPrCustomSlideShowsModel::mimeTypes() const
0129 {
0130     return QStringList() << "application/x-calligra-customslideshows";
0131 }
0132 
0133 QMimeData * KPrCustomSlideShowsModel::mimeData(const QModelIndexList &indexes) const
0134 {
0135     // check if there is data to encode
0136     if (! indexes.count()) {
0137         return 0;
0138     }
0139 
0140     // check if we support a format
0141     const QStringList types = mimeTypes();
0142     if (types.isEmpty()) {
0143         return 0;
0144     }
0145 
0146     QMimeData *data = new QMimeData();
0147     QByteArray encoded;
0148     QDataStream stream(&encoded, QIODevice::WriteOnly);
0149 
0150     // encode the data & order slides
0151     QModelIndexList::ConstIterator it = indexes.begin();
0152 
0153     QMap<int, KoPAPageBase*> map;
0154     for( ; it != indexes.end(); ++it) {
0155         map.insert(m_customSlideShows->indexByPage(m_activeCustomSlideShowName, (KoPAPageBase*)it->internalPointer()),
0156                    (KoPAPageBase*)it->internalPointer());
0157     }
0158 
0159     QList<KoPAPageBase *> slides = map.values();
0160 
0161     foreach (KoPAPageBase *slide, slides) {
0162         stream << QVariant::fromValue(qulonglong((void*)slide));
0163     }
0164 
0165     data->setData(types[0], encoded);
0166     return data;
0167 }
0168 
0169 Qt::DropActions KPrCustomSlideShowsModel::supportedDropActions() const
0170 {
0171     return Qt::MoveAction | Qt::CopyAction;
0172 }
0173 
0174 bool KPrCustomSlideShowsModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent)
0175 {
0176     if (action == Qt::IgnoreAction) {
0177         return true;
0178     }
0179 
0180     if (data->hasFormat("application/x-calligra-sliderssorter") || data->hasFormat("application/x-calligra-customslideshows")) {
0181 
0182         if (column > 0) {
0183             return false;
0184         }
0185 
0186         QList<KoPAPageBase *> slides;
0187 
0188         int beginRow = 0;
0189 
0190         if (row != -1) {
0191             beginRow = row;
0192         }
0193         else if (parent.isValid()) {
0194             beginRow = parent.row();
0195         }
0196         else {
0197             beginRow = rowCount(QModelIndex());
0198         }
0199 
0200         if (data->hasFormat("application/x-calligra-sliderssorter")) {
0201             QByteArray encoded = data->data("application/x-calligra-sliderssorter");
0202             slides = decodeSlidesList(encoded);
0203 
0204             if (slides.empty()) {
0205                 return false;
0206             }
0207 
0208             //perform action
0209             doCustomSlideShowAction(KPrCustomSlideShowsModel::SlidesAdd, slides, QList<int>(), beginRow);
0210         }
0211         else if (data->hasFormat("application/x-calligra-customslideshows")) {
0212             QByteArray encoded = data->data("application/x-calligra-customslideshows");
0213             slides = decodeSlidesList(encoded);
0214 
0215             if (slides.empty()) {
0216                 return false;
0217             }
0218 
0219             //perform action
0220             doCustomSlideShowAction(KPrCustomSlideShowsModel::SlidesMove, slides, QList<int>(), beginRow);
0221         }
0222         return true;
0223     }
0224     return false;
0225 }
0226 
0227 QList<KoPAPageBase *> KPrCustomSlideShowsModel::decodeSlidesList(const QByteArray &encoded)
0228 {
0229     QList<KoPAPageBase *> slides;
0230     QDataStream stream(encoded);
0231 
0232     // decode the data
0233     while(!stream.atEnd()) {
0234         QVariant v;
0235         stream >> v;
0236         slides.append(static_cast<KoPAPageBase*>((void*)v.value<qulonglong>()));
0237     }
0238     return slides;
0239 }
0240 
0241 void KPrCustomSlideShowsModel::setCustomSlideShows(KPrCustomSlideShows *customShows)
0242 {
0243     beginResetModel();
0244     m_customSlideShows = customShows;
0245     m_activeCustomSlideShowName.clear();
0246     endResetModel();
0247 }
0248 
0249 
0250 QString KPrCustomSlideShowsModel::activeCustomSlideShow() const
0251 {
0252     return m_activeCustomSlideShowName;
0253 }
0254 
0255 void KPrCustomSlideShowsModel::setActiveSlideShow(const QString &name)
0256 {
0257     if (!m_customSlideShows || (m_activeCustomSlideShowName == name)) {
0258         return;
0259     }
0260     if (m_customSlideShows->names().contains(name)) {
0261         beginResetModel();
0262         m_activeCustomSlideShowName = name;
0263         endResetModel();
0264     }
0265 }
0266 
0267 void KPrCustomSlideShowsModel::setActiveSlideShow(int index)
0268 {
0269     if (!m_customSlideShows) {
0270         return;
0271     }
0272     QString name = m_customSlideShows->names().value(index);
0273     setActiveSlideShow(name);
0274 }
0275 
0276 void KPrCustomSlideShowsModel::setIconSize(const QSize &size)
0277 {
0278     m_iconSize = size;
0279 }
0280 
0281 QStringList KPrCustomSlideShowsModel::customShowsNamesList() const
0282 {
0283     if (m_customSlideShows) {
0284         return m_customSlideShows->names();
0285     }
0286 
0287     return QStringList();
0288 }
0289 
0290 void KPrCustomSlideShowsModel::setDocument(KPrDocument *document)
0291 {
0292     m_document = document;
0293     setCustomSlideShows(document->customSlideShows());
0294 }
0295 
0296 void KPrCustomSlideShowsModel::removeSlidesByIndexes(const QModelIndexList &pageIndexes)
0297 {
0298     QList<KoPAPageBase *> slides;
0299     QList<int> indexesList;
0300 
0301     foreach (const QModelIndex &index, pageIndexes) {
0302         indexesList.append(index.row());
0303     }
0304 
0305     doCustomSlideShowAction(KPrCustomSlideShowsModel::SlidesDelete, slides, indexesList);
0306 }
0307 
0308 void KPrCustomSlideShowsModel::addSlides(const QList<KoPAPageBase *> &pages, const int &row)
0309 {
0310     doCustomSlideShowAction(KPrCustomSlideShowsModel::SlidesAdd, pages, QList<int>(), row);
0311 }
0312 
0313 bool KPrCustomSlideShowsModel::doCustomSlideShowAction(const CustomShowActions &action, const QList<KoPAPageBase *> &slides, QList<int> indexes, int beginRow)
0314 {
0315     bool updated = false;
0316     int start = beginRow;
0317 
0318     //get the slideshow
0319     if (m_activeCustomSlideShowName.isEmpty()) {
0320         return false;
0321     }
0322     QList<KoPAPageBase*> selectedSlideShow = m_customSlideShows->getByName(m_activeCustomSlideShowName);
0323 
0324     if (action == KPrCustomSlideShowsModel::SlidesAdd) {
0325         //insert the slides on the current custom show
0326         int i = beginRow;
0327         foreach(KoPAPageBase *page, slides) {
0328                 selectedSlideShow.insert(i, page);
0329                 i++;
0330         }
0331         updated = true;
0332     }
0333     else if (action == KPrCustomSlideShowsModel::SlidesMove) {
0334         //move the slides on the current custom show
0335         // slides order within the slides list is important to get the expected behaviour
0336         if (beginRow >= selectedSlideShow.count()) {
0337            beginRow = selectedSlideShow.count();
0338         }
0339         int i = 0;
0340         foreach(KoPAPageBase *page, slides)
0341         {
0342             int from = selectedSlideShow.indexOf(page);
0343             if (from < beginRow) {
0344                 selectedSlideShow.move(from, beginRow - 1);
0345                 start--;
0346             }
0347             else {
0348                 selectedSlideShow.move(from, beginRow + i);
0349                 i++;
0350             }
0351         }
0352         updated = true;
0353     }
0354     else if (action == KPrCustomSlideShowsModel::SlidesDelete) {
0355         //delete de slides on the current custom show
0356         //delete command use indexes because the custom show could have
0357         //more than one copy of the same slide.
0358         std::sort(indexes.begin(), indexes.end());
0359         int i = 0;
0360         foreach(int row, indexes) {
0361             selectedSlideShow.removeAt(row - i);
0362             i++;
0363         }
0364         updated = true;
0365     }
0366     else {
0367         updated = false;
0368     }
0369 
0370     if (updated) {
0371         //update the SlideShow with the resulting list
0372         KPrEditCustomSlideShowsCommand *command = new KPrEditCustomSlideShowsCommand(
0373                     m_document, m_activeCustomSlideShowName, selectedSlideShow);
0374         m_document->addCommand(command);
0375         emit selectPages(start, slides.count());
0376     }
0377     return updated;
0378 }
0379 
0380 void KPrCustomSlideShowsModel::addNewCustomShow(const QString &name)
0381 {
0382     KPrAddCustomSlideShowCommand *command = new KPrAddCustomSlideShowCommand(m_document, this, name);
0383     m_document->addCommand(command);
0384 }
0385 
0386 void KPrCustomSlideShowsModel::renameCustomShow(const QString &oldName, const QString &newName)
0387 {
0388     KPrRenameCustomSlideShowCommand *command = new KPrRenameCustomSlideShowCommand(m_document, this, oldName, newName);
0389     m_document->addCommand(command);
0390 }
0391 
0392 void KPrCustomSlideShowsModel::removeCustomShow(const QString &name)
0393 {
0394     KPrDelCustomSlideShowCommand *command = new KPrDelCustomSlideShowCommand(m_document, this, name);
0395     m_document->addCommand(command);
0396 }
0397 
0398 void KPrCustomSlideShowsModel::updateCustomSlideShowsList(const QString &name)
0399 {
0400     m_activeCustomSlideShowName.clear();
0401     setActiveSlideShow(name);
0402     emit customSlideShowsChanged();
0403 }
0404 
0405 void KPrCustomSlideShowsModel::updateModel()
0406 {
0407     emit layoutAboutToBeChanged();
0408     emit layoutChanged();
0409 }