File indexing completed on 2025-02-09 05:31:50
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