File indexing completed on 2024-05-05 05:40:34

0001 /***************************************************************************
0002  *  Copyright (C) 2009 by Renaud Guezennec                             *
0003  *   https://rolisteam.org/contact                   *
0004  *                                                                         *
0005  *   Rolisteam is free software; you can redistribute it and/or modify     *
0006  *   it under the terms of the GNU General Public License as published by  *
0007  *   the Free Software Foundation; either version 2 of the License, or     *
0008  *   (at your option) any later version.                                   *
0009  *                                                                         *
0010  *   This program is distributed in the hope that it will be useful,       *
0011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
0012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
0013  *   GNU General Public License for more details.                          *
0014  *                                                                         *
0015  *   You should have received a copy of the GNU General Public License     *
0016  *   along with this program; if not, write to the                         *
0017  *   Free Software Foundation, Inc.,                                       *
0018  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
0019  ***************************************************************************/
0020 #include "session/sessionitemmodel.h"
0021 
0022 #include <QDebug>
0023 #include <QFileInfo>
0024 #include <QIcon>
0025 #include <QUrl>
0026 
0027 //////////////////////////////////////
0028 /// SessionItemModel
0029 /////////////////////////////////////
0030 namespace session
0031 {
0032 SessionItemModel::SessionItemModel() : m_rootItem(new SessionItem())
0033 {
0034     m_header << tr("Name") << tr("Path");
0035 
0036     m_rootItem->setParentNode(nullptr);
0037 }
0038 
0039 SessionItemModel::~SessionItemModel()= default;
0040 QModelIndex SessionItemModel::index(int row, int column, const QModelIndex& parent) const
0041 {
0042     if(row < 0)
0043         return QModelIndex();
0044 
0045     SessionItem* parentItem= nullptr;
0046 
0047     if(!parent.isValid())
0048         parentItem= m_rootItem.get();
0049     else
0050         parentItem= static_cast<SessionItem*>(parent.internalPointer());
0051 
0052     SessionItem* childItem= parentItem->childAt(row);
0053     if(childItem)
0054         return createIndex(row, column, childItem);
0055     else
0056         return QModelIndex();
0057 }
0058 bool SessionItemModel::setData(const QModelIndex& index, const QVariant& value, int role)
0059 {
0060     if(!index.isValid())
0061         return false;
0062 
0063     if(Qt::EditRole == role)
0064     {
0065         SessionItem* childItem= static_cast<SessionItem*>(index.internalPointer());
0066         childItem->setName(value.toString());
0067         return true;
0068     }
0069     return false;
0070 }
0071 Qt::ItemFlags SessionItemModel::flags(const QModelIndex& index) const
0072 {
0073     if(!index.isValid())
0074         return Qt::NoItemFlags | Qt::ItemIsDropEnabled;
0075 
0076     SessionItem* childItem= static_cast<SessionItem*>(index.internalPointer());
0077     if(!childItem->isLeaf())
0078         return Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable | Qt::ItemIsDropEnabled;
0079     else
0080         return Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled;
0081 }
0082 QStringList SessionItemModel::mimeTypes() const
0083 {
0084     QStringList types;
0085     types << "rolisteam/cleverurilist"
0086           << "text/uri-list";
0087     return types;
0088 }
0089 
0090 QMimeData* SessionItemModel::mimeData(const QModelIndexList& indexes) const
0091 {
0092     Q_UNUSED(indexes)
0093     /*CleverUriMimeData* mimeData= new CleverUriMimeData();
0094 
0095     for(const QModelIndex& index : indexes)
0096     {
0097         if((index.isValid()) && (index.column() == 0))
0098         {
0099             ResourcesNode* item= static_cast<ResourcesNode*>(index.internalPointer());
0100             mimeData->addResourceNode(item, index);
0101         }
0102     }
0103     return mimeData;*/
0104     return nullptr;
0105 }
0106 
0107 /*void SessionItemModel::updateNode(ResourcesNode* node)
0108 {
0109     QModelIndex nodeIndex;
0110     QModelIndex parent;
0111     QList<ResourcesNode*> path;
0112     if(m_rootItem->seekNode(path, node))
0113     {
0114         ResourcesNode* parentItem= nullptr;
0115         for(auto& i : path)
0116         {
0117             if(nullptr != parentItem)
0118             {
0119                 nodeIndex= index(parentItem->indexOf(i), 0, parent);
0120                 parent= nodeIndex;
0121             }
0122             parentItem= i;
0123         }
0124     }
0125     emit dataChanged(nodeIndex, nodeIndex);
0126 }*/
0127 
0128 Qt::DropActions SessionItemModel::supportedDropActions() const
0129 {
0130     return Qt::CopyAction | Qt::MoveAction;
0131 }
0132 bool SessionItemModel::dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column,
0133                                     const QModelIndex& parent)
0134 {
0135     Q_UNUSED(column);
0136 
0137     if(action == Qt::IgnoreAction)
0138         return false;
0139 
0140     bool added= false;
0141 
0142     if(data->hasFormat("rolisteam/cleverurilist"))
0143     {
0144         // const CleverUriMimeData* mediaData= qobject_cast<const CleverUriMimeData*>(data);
0145 
0146         // if(nullptr != mediaData)
0147         {
0148             /*  QList<ResourcesNode*> mediaList= mediaData->getList().values();
0149               QList<QModelIndex> indexList= mediaData->getList().keys();
0150               {
0151                   if(action == Qt::MoveAction)
0152                   {
0153                       added= moveMediaItem(mediaList, parent, row, indexList);
0154                   }
0155               }*/
0156         }
0157     }
0158     else if((data->hasUrls()) && (!added))
0159     {
0160         QList<QUrl> list= data->urls();
0161         for(QUrl& url : list)
0162         {
0163             if(url.isLocalFile())
0164             {
0165                 QFileInfo fileInfo(url.toLocalFile());
0166                 if(fileInfo.isFile())
0167                 {
0168                 }
0169                 // addChildMediaTo(medium,parent);
0170             }
0171             // else if(url.isLocalFile())
0172         }
0173     }
0174     return added;
0175 }
0176 
0177 bool SessionItemModel::moveMediaItem(QList<SessionItem*> items, const QModelIndex& parentToBe, int row,
0178                                      QList<QModelIndex>& formerPosition)
0179 {
0180     SessionItem* parentItem= static_cast<SessionItem*>(parentToBe.internalPointer());
0181 
0182     if(nullptr == parentItem)
0183     {
0184         parentItem= m_rootItem.get();
0185     }
0186     int orignRow= row;
0187 
0188     QList<int> listRow;
0189 
0190     if((!items.isEmpty()) && (!formerPosition.isEmpty()))
0191     {
0192         SessionItem* item= items.at(0);
0193         SessionItem* parent= item->parentNode();
0194         QModelIndex formerPositionIndex= formerPosition.at(0);
0195         QModelIndex sourceParent= formerPositionIndex.parent();
0196         QModelIndex destinationParent= parentToBe;
0197 
0198         int sourceFirst= parent->indexOf(item);
0199         int sourceLast= parent->indexOf(item) + items.size() - 1;
0200 
0201         int destinationRow= orignRow < 0 ? parentItem->childrenCount() : orignRow;
0202         if((sourceParent == destinationParent)
0203            && ((destinationRow == parentItem->childrenCount()) || (destinationRow > sourceFirst)))
0204         {
0205             destinationRow-= items.size() - 1;
0206         }
0207         if((sourceParent == destinationParent) && (sourceFirst == destinationRow))
0208         {
0209             destinationRow-= items.size();
0210             return false;
0211         }
0212 
0213         if(!beginMoveRows(sourceParent, sourceFirst, sourceLast, destinationParent, destinationRow))
0214             return false;
0215     }
0216 
0217     for(int i= items.size() - 1; i >= 0; --i)
0218     {
0219         while(listRow.contains(row))
0220         {
0221             ++row;
0222         }
0223 
0224         SessionItem* item= items.at(i);
0225         SessionItem* parent= item->parentNode();
0226         QModelIndex formerPositionIndex= formerPosition.at(i);
0227 
0228         if(nullptr != parent)
0229         {
0230             parent->removeChild(item);
0231             if((orignRow == -1 && parentItem == m_rootItem.get()))
0232             {
0233                 orignRow= parentItem->childrenCount();
0234                 row= orignRow;
0235             }
0236             else if(formerPositionIndex.row() < orignRow && parentToBe == formerPositionIndex.parent())
0237             {
0238                 orignRow-= 1;
0239                 row= orignRow;
0240             }
0241 
0242             parentItem->insertChildAt(orignRow, item); // row
0243             //---
0244             int oldRow= formerPositionIndex.row();
0245             if(oldRow > orignRow && parentItem == m_rootItem.get() && parent == m_rootItem.get())
0246             {
0247                 oldRow+= items.size() - 1 - i;
0248             }
0249             listRow.append(row);
0250         }
0251     }
0252 
0253     endMoveRows();
0254     return true;
0255 }
0256 QModelIndex SessionItemModel::parent(const QModelIndex& index) const
0257 {
0258     if(!index.isValid())
0259         return QModelIndex();
0260 
0261     SessionItem* childItem= static_cast<SessionItem*>(index.internalPointer());
0262     SessionItem* parentItem= childItem->parentNode();
0263 
0264     if(parentItem == m_rootItem.get())
0265         return QModelIndex();
0266 
0267     SessionItem* grandParent= parentItem->parentNode();
0268 
0269     if(grandParent == nullptr)
0270         return QModelIndex();
0271 
0272     return createIndex(grandParent->indexOf(parentItem), 0, parentItem);
0273 }
0274 int SessionItemModel::rowCount(const QModelIndex& index) const
0275 {
0276     if(index.isValid())
0277     {
0278         SessionItem* tmp= static_cast<SessionItem*>(index.internalPointer());
0279         return tmp->childrenCount();
0280     }
0281     else
0282     {
0283         return m_rootItem->childrenCount();
0284     }
0285 }
0286 int SessionItemModel::columnCount(const QModelIndex&) const
0287 {
0288     return m_header.size();
0289 }
0290 QVariant SessionItemModel::data(const QModelIndex& index, int role) const
0291 {
0292     if(!index.isValid())
0293         return QVariant();
0294 
0295     SessionItem* tmp= static_cast<SessionItem*>(index.internalPointer());
0296     if(!tmp)
0297         return {};
0298 
0299     auto sessionData= tmp->data();
0300 
0301     QVariant var;
0302     switch(role)
0303     {
0304     case Qt::DisplayRole:
0305     case Qt::EditRole:
0306         var= sessionData->name();
0307         break;
0308     case Qt::DecorationRole:
0309         if(index.column() == Name)
0310         {
0311         }
0312         break;
0313     case Qt::BackgroundRole:
0314     {
0315         /*        if(tmp->type() != ResourcesNode::Cleveruri)
0316                     break;
0317                 auto const& cleverUri= dynamic_cast<CleverURI*>(tmp);
0318                 if(!cleverUri)
0319                     break;
0320                 if(cleverUri->hasData() || cleverUri->exists() || cleverUri->contentType() ==
0321            Core::ContentType::WEBVIEW) break;
0322 
0323                 var= QColor(Qt::red).lighter();*/
0324     }
0325     break;
0326     }
0327     return var;
0328 }
0329 
0330 void SessionItemModel::addResource(SessionItem* node, const QModelIndex& parent)
0331 {
0332     if(!node)
0333         return;
0334 
0335     if(m_rootItem->contains(node->uuid()))
0336         return;
0337 
0338     SessionItem* parentItem= nullptr;
0339     auto parentbis= parent;
0340     if(!parent.isValid())
0341     {
0342         parentItem= m_rootItem.get();
0343     }
0344     else
0345     {
0346         SessionItem* node= static_cast<SessionItem*>(parent.internalPointer());
0347         if(node->isLeaf())
0348         {
0349             node= node->parentNode(); // leaf's parent is not a leaf indeed
0350             parentbis= parentbis.parent();
0351         }
0352         parentItem= dynamic_cast<SessionItem*>(node); // nullptr when it is not a chapter.
0353     }
0354 
0355     if(nullptr == parentItem)
0356         return;
0357 
0358     beginInsertRows(parentbis, parentItem->childrenCount(), parentItem->childrenCount());
0359     parentItem->insertChildAt(parentItem->childrenCount(), node);
0360     endInsertRows();
0361 }
0362 
0363 void SessionItemModel::remove(QModelIndex& index)
0364 {
0365     if(!index.isValid())
0366         return;
0367     SessionItem* indexItem= static_cast<SessionItem*>(index.internalPointer());
0368     QModelIndex parent= index.parent();
0369     SessionItem* parentItem= nullptr;
0370 
0371     if(!parent.isValid())
0372         parentItem= m_rootItem.get();
0373     else
0374         parentItem= static_cast<SessionItem*>(parent.internalPointer());
0375 
0376     beginRemoveRows(index.parent(), index.row(), index.row());
0377     parentItem->removeChild(indexItem);
0378     endRemoveRows();
0379 }
0380 
0381 void SessionItemModel::removeNode(SessionItem* node)
0382 {
0383     if(nullptr == node)
0384         return;
0385 
0386     auto parent= node->parentNode();
0387     if(parent == nullptr)
0388         return;
0389 
0390     auto idx= createIndex(parent->indexOf(node), 0, node);
0391     remove(idx);
0392 }
0393 
0394 void SessionItemModel::removeMedia(const QString& id)
0395 {
0396     auto item= m_rootItem->find(id);
0397     // auto idx= createIndex(item->rowInParent(), 0, item);
0398 
0399     removeNode(item);
0400 }
0401 
0402 void SessionItemModel::addMedia(const QString& id, const QString& path, Core::ContentType type, const QString& name)
0403 {
0404     auto uri= new SessionItem();
0405     auto data= uri->data();
0406     data->setUuid(id);
0407     data->setData(QVariant::fromValue(type));
0408     data->setName(name);
0409     data->setType(SessionItemType::Media);
0410     addResource(uri, QModelIndex());
0411 }
0412 
0413 void SessionItemModel::clearData()
0414 {
0415     if(!m_rootItem)
0416         return;
0417 
0418     m_rootItem->clear();
0419 }
0420 
0421 QVariant SessionItemModel::headerData(int section, Qt::Orientation orientation, int role) const
0422 {
0423     QVariant var;
0424     if(orientation == Qt::Horizontal)
0425     {
0426         switch(role)
0427         {
0428         case Qt::DisplayRole:
0429             var= m_header.at(section);
0430             break;
0431         case Qt::TextAlignmentRole:
0432             var= Qt::AlignHCenter;
0433             break;
0434         default:
0435             break;
0436         }
0437     }
0438     return var;
0439 }
0440 ////////////////////////
0441 ////////////////////////
0442 
0443 SessionData::SessionData() {}
0444 
0445 void SessionData::setUuid(const QString& uuid)
0446 {
0447     m_uuid= uuid;
0448 }
0449 
0450 QString SessionData::uuid() const
0451 {
0452     return m_uuid;
0453 }
0454 
0455 void SessionData::setName(const QString& name)
0456 {
0457     m_name= name;
0458 }
0459 
0460 QString SessionData::name() const
0461 {
0462     return m_name;
0463 }
0464 
0465 void SessionData::setPath(const QString& path)
0466 {
0467     m_path= path;
0468 }
0469 
0470 QString SessionData::path() const
0471 {
0472     return m_path;
0473 }
0474 
0475 void SessionData::setData(const QVariant& data)
0476 {
0477     m_data= data;
0478 }
0479 
0480 QVariant SessionData::data() const
0481 {
0482     return m_data;
0483 }
0484 
0485 SessionItemType SessionData::type() const
0486 {
0487     return m_type;
0488 }
0489 
0490 void SessionData::setType(SessionItemType type)
0491 {
0492     m_type= type;
0493 }
0494 
0495 ////////////////////////
0496 ////////////////////////
0497 
0498 SessionItem::SessionItem() : m_data(new SessionData) {}
0499 
0500 bool SessionItem::isLeaf() const
0501 {
0502     return (m_data->type() != Chapter);
0503 }
0504 
0505 int SessionItem::childrenCount() const
0506 {
0507     return static_cast<int>(m_children.size());
0508 }
0509 
0510 SessionData* SessionItem::data() const
0511 {
0512     return m_data.get();
0513 }
0514 
0515 int SessionItem::indexOf(SessionItem* item) const
0516 {
0517     auto it= std::find_if(std::begin(m_children), std::end(m_children),
0518                           [item](const std::unique_ptr<SessionItem>& child) { return item == child.get(); });
0519 
0520     if(it == std::end(m_children))
0521         return -1;
0522 
0523     return std::distance(std::begin(m_children), it);
0524 }
0525 
0526 void SessionItem::insertChildAt(int row, SessionItem* item)
0527 {
0528     std::unique_ptr<SessionItem> child(item);
0529     child->setParentNode(this);
0530     m_children.insert(m_children.begin() + row, std::move(child));
0531 }
0532 
0533 SessionItem* SessionItem::childAt(int i) const
0534 {
0535     if(m_children.size() <= i && i < 0)
0536         return nullptr;
0537 
0538     auto it= m_children.begin() + i;
0539     return it->get();
0540 }
0541 
0542 void SessionItem::setParentNode(SessionItem* parent)
0543 {
0544     m_parent= parent;
0545 }
0546 
0547 SessionItem* SessionItem::parentNode() const
0548 {
0549     return m_parent;
0550 }
0551 
0552 void SessionItem::removeChild(SessionItem* item)
0553 {
0554     auto it= std::find_if(std::begin(m_children), std::end(m_children),
0555                           [item](const std::unique_ptr<SessionItem>& child) { return item == child.get(); });
0556 
0557     if(it == std::end(m_children))
0558         return;
0559 
0560     m_children.erase(it);
0561 }
0562 
0563 void SessionItem::setName(const QString& name)
0564 {
0565     if(m_data)
0566         m_data->setName(name);
0567 }
0568 
0569 bool SessionItem::contains(const QString& id) const
0570 {
0571     auto it= std::find_if(std::begin(m_children), std::end(m_children),
0572                           [id](const std::unique_ptr<SessionItem>& child) { return id == child->uuid(); });
0573 
0574     return it != m_children.end();
0575 }
0576 
0577 QString SessionItem::uuid() const
0578 {
0579     if(m_data)
0580         return m_data->uuid();
0581 
0582     return {};
0583 }
0584 
0585 void SessionItem::clear()
0586 {
0587     m_children.clear();
0588 }
0589 
0590 SessionItem* SessionItem::find(const QString& id) const
0591 {
0592     auto it= std::find_if(std::begin(m_children), std::end(m_children),
0593                           [id](const std::unique_ptr<SessionItem>& child) { return id == child->uuid(); });
0594 
0595     if(it != m_children.end())
0596         return it->get();
0597 
0598     SessionItem* item= nullptr;
0599     for(auto const& child : m_children)
0600     {
0601         item= child->find(id);
0602         if(item != nullptr)
0603             break;
0604     }
0605     return item;
0606 }
0607 } // namespace session