File indexing completed on 2024-04-21 04:43:18

0001 /*  This file is part of the KDE project
0002     Copyright (C) 2006-2007 Matthias Kretz <kretz@kde.org>
0003 
0004     This library is free software; you can redistribute it and/or
0005     modify it under the terms of the GNU Lesser General Public
0006     License as published by the Free Software Foundation; either
0007     version 2.1 of the License, or (at your option) version 3, or any
0008     later version accepted by the membership of KDE e.V. (or its
0009     successor approved by the membership of KDE e.V.), Nokia Corporation 
0010     (or its successors, if any) and the KDE Free Qt Foundation, which shall
0011     act as a proxy defined in Section 6 of version 3 of the license.
0012 
0013     This library is distributed in the hope that it will be useful,
0014     but WITHOUT ANY WARRANTY; without even the implied warranty of
0015     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0016     Lesser General Public License for more details.
0017 
0018     You should have received a copy of the GNU Lesser General Public 
0019     License along with this library.  If not, see <http://www.gnu.org/licenses/>.
0020 
0021 */
0022 
0023 #include "objectdescriptionmodel.h"
0024 #include "objectdescriptionmodel_p.h"
0025 #include "phonondefs_p.h"
0026 #include "platform_p.h"
0027 #include "objectdescription.h"
0028 #include "phononnamespace_p.h"
0029 #include "factory_p.h"
0030 #include <QIcon>
0031 #include <QPainter>
0032 #include <QList>
0033 #include <QMimeData>
0034 #include <QStringList>
0035 
0036 #ifndef QT_NO_PHONON_OBJECTDESCRIPTIONMODEL
0037 
0038 // If this wasn't so terrible ...
0039 // ObjectDescriptionModel is a template class. Moc however cannot handle
0040 // templates so the solution done here is to *manually* do whatever moc does.
0041 
0042 static const uint qt_meta_data_Phonon__ObjectDescriptionModel[] = {
0043 
0044  // content:
0045        7,       // revision
0046        0,       // classname
0047        0,    0, // classinfo
0048        0,    0, // methods
0049        0,    0, // properties
0050        0,    0, // enums/sets
0051        0,    0, // constructors
0052        0,       // flags
0053        0,       // signalCount
0054 
0055        0        // eod
0056 };
0057 
0058 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
0059     #define P_STATIC_META_STRINGDATA(name, string, stringlen, stringlenplustwo) \
0060         struct qt_meta_stringdata_Phonon__ObjectDescriptionModel_##name##_t { QByteArrayData data[1]; char stringdata[stringlenplustwo]; }; \
0061         static const qt_meta_stringdata_Phonon__ObjectDescriptionModel_##name##_t qt_meta_stringdata_Phonon__ObjectDescriptionModel_##name = { \
0062             { \
0063                 Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(stringlen, offsetof(qt_meta_stringdata_Phonon__ObjectDescriptionModel_ ## name ## _t, stringdata) + 0 - 0 * sizeof(QByteArrayData)) \
0064             }, \
0065             string \
0066         };
0067 #else
0068     #define P_STATIC_META_STRINGDATA(name, string, stringlen, stringlenplustwo) \
0069         struct qt_meta_stringdata_Phonon__ObjectDescriptionModel_##name##_t { const uint offsetsAndSize[2]; char stringdata[stringlenplustwo]; }; \
0070         static const qt_meta_stringdata_Phonon__ObjectDescriptionModel_##name##_t qt_meta_stringdata_Phonon__ObjectDescriptionModel_##name = { \
0071             { \
0072                 uint(offsetof(qt_meta_stringdata_Phonon__ObjectDescriptionModel_ ## name ## _t, stringdata)), stringlen \
0073             }, \
0074             string \
0075         };
0076 #endif
0077 
0078     P_STATIC_META_STRINGDATA(AudioOutputDeviceType,     "Phonon::AudioOutputDeviceModel\0",  30, 32)
0079     P_STATIC_META_STRINGDATA(AudioCaptureDeviceType,    "Phonon::AudioCaptureDeviceModel\0", 31, 33)
0080     P_STATIC_META_STRINGDATA(VideoCaptureDeviceType,    "Phonon::VideoCaptureDeviceModel\0", 31, 33)
0081     P_STATIC_META_STRINGDATA(EffectType,                "Phonon::EffectModel\0",             19, 21)
0082     P_STATIC_META_STRINGDATA(AudioChannelType,          "Phonon::AudioChannelModel\0",       25, 27)
0083     P_STATIC_META_STRINGDATA(SubtitleType,              "Phonon::SubtitleModel\0",           21, 23)
0084 
0085     #undef P_STATIC_META_STRINGDATA
0086 
0087 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
0088     #define OBJECT_DESCRIPTION_MODEL_STATIC_META_OBJECT(X) { \
0089         &QAbstractListModel::staticMetaObject, \
0090         qt_meta_stringdata_Phonon__ObjectDescriptionModel_##X.data, \
0091         qt_meta_data_Phonon__ObjectDescriptionModel, \
0092         nullptr, nullptr, nullptr }
0093 #else
0094     #define OBJECT_DESCRIPTION_MODEL_STATIC_META_OBJECT(X) { \
0095         &QAbstractListModel::staticMetaObject, \
0096         qt_meta_stringdata_Phonon__ObjectDescriptionModel_##X.offsetsAndSize, \
0097         qt_meta_data_Phonon__ObjectDescriptionModel, \
0098         nullptr, nullptr, nullptr }
0099 #endif
0100 
0101 namespace Phonon
0102 {
0103 
0104 template<> const QMetaObject ObjectDescriptionModel<AudioOutputDeviceType>::staticMetaObject = {
0105     OBJECT_DESCRIPTION_MODEL_STATIC_META_OBJECT(AudioOutputDeviceType)
0106 };
0107 template<> const QMetaObject ObjectDescriptionModel<AudioCaptureDeviceType>::staticMetaObject = {
0108     OBJECT_DESCRIPTION_MODEL_STATIC_META_OBJECT(AudioCaptureDeviceType)
0109 };
0110 template<> const QMetaObject ObjectDescriptionModel<VideoCaptureDeviceType>::staticMetaObject = {
0111     OBJECT_DESCRIPTION_MODEL_STATIC_META_OBJECT(VideoCaptureDeviceType)
0112 };
0113 template<> const QMetaObject ObjectDescriptionModel<EffectType>::staticMetaObject = {
0114     OBJECT_DESCRIPTION_MODEL_STATIC_META_OBJECT(EffectType)
0115 };
0116 template<> const QMetaObject ObjectDescriptionModel<AudioChannelType>::staticMetaObject = {
0117     OBJECT_DESCRIPTION_MODEL_STATIC_META_OBJECT(AudioChannelType)
0118 };
0119 template<> const QMetaObject ObjectDescriptionModel<SubtitleType>::staticMetaObject = {
0120     OBJECT_DESCRIPTION_MODEL_STATIC_META_OBJECT(SubtitleType)
0121 };
0122 
0123 template<ObjectDescriptionType type>
0124 const QMetaObject *ObjectDescriptionModel<type>::metaObject() const
0125 {
0126     return &staticMetaObject;
0127 }
0128 
0129 template<ObjectDescriptionType type>
0130 void *ObjectDescriptionModel<type>::qt_metacast(const char *_clname)
0131 {
0132     qWarning("WARNING: Phonon4Qt5 has not been verified to successfully qt_metacast ObjectDescriptionModels.");
0133     if (!_clname) {
0134         return nullptr;
0135     }
0136     if (!strcmp(_clname, ObjectDescriptionModel<type>::staticMetaObject.className())) {
0137         return static_cast<void *>(const_cast<ObjectDescriptionModel<type> *>(this));
0138     }
0139     return QAbstractListModel::qt_metacast(_clname);
0140 }
0141 
0142 /*
0143 template<ObjectDescriptionType type>
0144 int ObjectDescriptionModel<type>::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
0145 {
0146     return QAbstractListModel::qt_metacall(_c, _id, _a);
0147 }
0148 */
0149 
0150 int ObjectDescriptionModelData::rowCount(const QModelIndex &parent) const
0151 {
0152     if (parent.isValid())
0153         return 0;
0154 
0155     return d->data.size();
0156 }
0157 
0158 QVariant ObjectDescriptionModelData::data(const QModelIndex &index, int role) const
0159 {
0160     if (!index.isValid() || index.row() >= d->data.size() || index.column() != 0)
0161         return QVariant();
0162 
0163     switch(role)
0164     {
0165     case Qt::EditRole:
0166     case Qt::DisplayRole:
0167         return d->data.at(index.row())->name();
0168         break;
0169     case Qt::ToolTipRole:
0170         return d->data.at(index.row())->description();
0171         break;
0172     case Qt::DecorationRole:
0173         {
0174             /* Returns an icon if available. Paint a subicon representing the entity (platform
0175              * plugin or backend) which discovered this object, if it is specified */
0176             QVariant icon = d->data.at(index.row())->property("icon");
0177             QVariant discovererIcon = d->data.at(index.row())->property("discovererIcon");
0178             if (icon.isValid()) {
0179                 if (icon.type() == QVariant::String) {
0180                     icon = Platform::icon(icon.toString());
0181                 }
0182                 if (discovererIcon.type() == QVariant::String) {
0183                     discovererIcon = Platform::icon(discovererIcon.toString());
0184                 }
0185                 if (icon.type() == QVariant::Icon) {
0186                     if (discovererIcon.type() == QVariant::Icon) {
0187                         // Insert the subicon in the top-right corner of the icon
0188                         QPixmap pixmap = icon.value<QIcon>().pixmap(QSize(64, 64));
0189                         QPixmap subPixmap = discovererIcon.value<QIcon>().pixmap(QSize(22, 22));
0190                         QPainter painter(&pixmap);
0191                         painter.drawPixmap(42, 0, subPixmap);
0192                         return QIcon(pixmap);
0193                     } else {
0194                         return icon;
0195                     }
0196                 }
0197             }
0198         }
0199         return QVariant();
0200     default:
0201         return QVariant();
0202 }
0203 }
0204 
0205 Qt::ItemFlags ObjectDescriptionModelData::flags(const QModelIndex &index) const
0206 {
0207     if(!index.isValid() || index.row() >= d->data.size() || index.column() != 0) {
0208         return Qt::ItemIsDropEnabled;
0209     }
0210 
0211     QVariant available = d->data.at(index.row())->property("available");
0212     if (available.isValid() && available.type() == QVariant::Bool && !available.toBool()) {
0213         return Qt::ItemIsSelectable | Qt::ItemIsDragEnabled;
0214     }
0215     return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled;
0216 }
0217 
0218 QList<int> ObjectDescriptionModelData::tupleIndexOrder() const
0219 {
0220     QList<int> ret;
0221     for (int i = 0; i < d->data.size(); ++i) {
0222         ret.append(d->data.at(i)->index());
0223     }
0224     return ret;
0225 }
0226 
0227 int ObjectDescriptionModelData::tupleIndexAtPositionIndex(int positionIndex) const
0228 {
0229     return d->data.at(positionIndex)->index();
0230 }
0231 
0232 QMimeData *ObjectDescriptionModelData::mimeData(ObjectDescriptionType type, const QModelIndexList &indexes) const
0233 {
0234     QMimeData *mimeData = new QMimeData;
0235     QByteArray encodedData;
0236     QDataStream stream(&encodedData, QIODevice::WriteOnly);
0237     QModelIndexList::const_iterator end = indexes.constEnd();
0238     QModelIndexList::const_iterator index = indexes.constBegin();
0239     for(; index!=end; ++index) {
0240         if ((*index).isValid()) {
0241             stream << d->data.at((*index).row())->index();
0242         }
0243     }
0244     //pDebug() << Q_FUNC_INFO << "setting mimeData to" << mimeTypes(type).first() << "=>" << encodedData.toHex();
0245     mimeData->setData(mimeTypes(type).first(), encodedData);
0246     return mimeData;
0247 }
0248 
0249 void ObjectDescriptionModelData::moveUp(const QModelIndex &index)
0250 {
0251     if (!index.isValid() || index.row() >= d->data.size() || index.row() < 1 || index.column() != 0)
0252         return;
0253 
0254     emit d->model->layoutAboutToBeChanged();
0255     QModelIndex above = index.sibling(index.row() - 1, index.column());
0256 #if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)
0257     d->data.swapItemsAt(index.row(), above.row());
0258 #else
0259     d->data.swap(index.row(), above.row());
0260 #endif
0261     QModelIndexList from, to;
0262     from << index << above;
0263     to << above << index;
0264     d->model->changePersistentIndexList(from, to);
0265     emit d->model->layoutChanged();
0266 }
0267 
0268 void ObjectDescriptionModelData::moveDown(const QModelIndex &index)
0269 {
0270     if (!index.isValid() || index.row() >= d->data.size() - 1 || index.column() != 0)
0271         return;
0272 
0273     emit d->model->layoutAboutToBeChanged();
0274     QModelIndex below = index.sibling(index.row() + 1, index.column());
0275 #if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0)
0276     d->data.swapItemsAt(index.row(), below.row());
0277 #else
0278     d->data.swap(index.row(), below.row());
0279 #endif
0280     QModelIndexList from, to;
0281     from << index << below;
0282     to << below << index;
0283     d->model->changePersistentIndexList(from, to);
0284     emit d->model->layoutChanged();
0285 }
0286 
0287 ObjectDescriptionModelData::ObjectDescriptionModelData(QAbstractListModel *model)
0288     : d(new ObjectDescriptionModelDataPrivate(model))
0289 {
0290 }
0291 
0292 ObjectDescriptionModelData::~ObjectDescriptionModelData()
0293 {
0294     delete d;
0295 }
0296 
0297 void ObjectDescriptionModelData::setModelData(const QList<QExplicitlySharedDataPointer<ObjectDescriptionData> > &newData)
0298 {
0299     d->model->beginResetModel();
0300     d->data = newData;
0301     d->model->endResetModel();
0302 }
0303 
0304 QList<QExplicitlySharedDataPointer<ObjectDescriptionData> > ObjectDescriptionModelData::modelData() const
0305 {
0306     return d->data;
0307 }
0308 
0309 QExplicitlySharedDataPointer<ObjectDescriptionData> ObjectDescriptionModelData::modelData(const QModelIndex &index) const
0310 {
0311     if (!index.isValid() || index.row() >= d->data.size() || index.column() != 0) {
0312         return QExplicitlySharedDataPointer<ObjectDescriptionData>(new ObjectDescriptionData(nullptr));
0313     }
0314     return d->data.at(index.row());
0315 }
0316 
0317 Qt::DropActions ObjectDescriptionModelData::supportedDropActions() const
0318 {
0319     //pDebug() << Q_FUNC_INFO;
0320     return Qt::MoveAction;
0321 }
0322 
0323 bool ObjectDescriptionModelData::dropMimeData(ObjectDescriptionType type, const QMimeData *data, Qt::DropAction action,
0324         int row, int column, const QModelIndex &parent)
0325 {
0326     Q_UNUSED(action);
0327     Q_UNUSED(column);
0328     Q_UNUSED(parent);
0329     //pDebug() << Q_FUNC_INFO << data << action << row << column << parent;
0330 
0331     QString format = mimeTypes(type).first();
0332     if (!data->hasFormat(format)) {
0333         return false;
0334     }
0335 
0336     if (row == -1) {
0337         row = d->data.size();
0338     }
0339 
0340     QByteArray encodedData = data->data(format);
0341     QDataStream stream(&encodedData, QIODevice::ReadOnly);
0342     QList<QExplicitlySharedDataPointer<ObjectDescriptionData> > toInsert;
0343     while (!stream.atEnd()) {
0344         int otherIndex;
0345         stream >> otherIndex;
0346         ObjectDescriptionData *obj = ObjectDescriptionData::fromIndex(type, otherIndex);
0347 
0348         if (obj->isValid()) {
0349             toInsert << QExplicitlySharedDataPointer<ObjectDescriptionData>(obj);
0350         } else {
0351             delete obj;
0352         }
0353     }
0354     d->model->beginInsertRows(QModelIndex(), row, row + toInsert.size() - 1);
0355     for (int i = 0 ; i < toInsert.count(); ++i) {
0356         d->data.insert(row, toInsert.at(i));
0357     }
0358     d->model->endInsertRows();
0359     return true;
0360 }
0361 
0362 
0363 bool ObjectDescriptionModelData::removeRows(int row, int count, const QModelIndex &parent)
0364 {
0365     //pDebug() << Q_FUNC_INFO << row << count << parent;
0366     if (parent.isValid() || row + count > d->data.size()) {
0367         return false;
0368     }
0369     d->model->beginRemoveRows(parent, row, row + count - 1);
0370     for (;count > 0; --count) {
0371         d->data.removeAt(row);
0372     }
0373     d->model->endRemoveRows();
0374     return true;
0375 }
0376 
0377 /*
0378 template<ObjectDescriptionType type>
0379 bool ObjectDescriptionModel<type>::insertRows(int row, int count, const QModelIndex &parent)
0380 {
0381     pDebug() << Q_FUNC_INFO << row << count << parent;
0382     if (parent.isValid() || row < 0 || row > d->data.size()) {
0383         return false;
0384     }
0385     beginInsertRows(parent, row, row + count - 1);
0386     for (;count > 0; --count) {
0387         d->data.insert(row, ObjectDescription<type>());
0388     }
0389     endInsertRows();
0390     return true;
0391 }
0392 */
0393 
0394 QStringList ObjectDescriptionModelData::mimeTypes(ObjectDescriptionType type) const
0395 {
0396     return QStringList(QLatin1String("application/x-phonon-objectdescription") + QString::number(static_cast<int>(type)));
0397 }
0398 
0399 #if !defined(Q_CC_MSVC) || _MSC_VER > 1300 || defined(Q_CC_INTEL) || defined(Q_CC_MINGW)
0400 #define INSTANTIATE_META_FUNCTIONS(type) \
0401 template const QMetaObject *ObjectDescriptionModel<type>::metaObject() const; \
0402 template void *ObjectDescriptionModel<type>::qt_metacast(const char *)
0403 
0404 INSTANTIATE_META_FUNCTIONS(AudioOutputDeviceType);
0405 INSTANTIATE_META_FUNCTIONS(AudioCaptureDeviceType);
0406 INSTANTIATE_META_FUNCTIONS(VideoCaptureDeviceType);
0407 INSTANTIATE_META_FUNCTIONS(EffectType);
0408 INSTANTIATE_META_FUNCTIONS(AudioChannelType);
0409 INSTANTIATE_META_FUNCTIONS(SubtitleType);
0410 #endif
0411 /*INSTANTIATE_META_FUNCTIONS(VideoOutputDeviceType);
0412 INSTANTIATE_META_FUNCTIONS(AudioCodecType);
0413 INSTANTIATE_META_FUNCTIONS(VideoCodecType);
0414 INSTANTIATE_META_FUNCTIONS(ContainerFormatType);
0415 INSTANTIATE_META_FUNCTIONS(VisualizationType);
0416 */
0417 } // namespace Phonon
0418 
0419 #endif //QT_NO_PHONON_OBJECTDESCRIPTIONMODEL