File indexing completed on 2024-04-21 08:39:56

0001 /*
0002     SPDX-FileCopyrightText: 1998-2008 Sebastian Trueg <trueg@k3b.org>
0003     SPDX-License-Identifier: GPL-2.0-or-later
0004 */
0005 
0006 #include "k3bplacesmodel.h"
0007 #include "k3bdevicemodel.h"
0008 
0009 #include "k3bcore.h"
0010 #include "k3bdevice.h"
0011 #include "k3bdevicemanager.h"
0012 #include "k3bmediacache.h"
0013 #include "k3bmedium.h"
0014 
0015 #include <KDirSortFilterProxyModel>
0016 #include <KFilePlacesModel>
0017 #include <KDirModel>
0018 #include <KDirLister>
0019 #include <Solid/StorageAccess>
0020 
0021 #include <QIcon>
0022 
0023 typedef QMap<KDirModel*, KDirSortFilterProxyModel*> DirModels;
0024 
0025 
0026 class K3b::PlacesModel::Private
0027 {
0028 public:
0029     K3b::DeviceModel* deviceModel;
0030     KFilePlacesModel* filePlacesModel;
0031     DirModels dirModels;
0032 };
0033 
0034 
0035 
0036 K3b::PlacesModel::PlacesModel( QObject* parent )
0037     : K3b::MetaItemModel( parent ),
0038       d( new Private() )
0039 {
0040     d->deviceModel = new K3b::DeviceModel( this );
0041     d->filePlacesModel = new KFilePlacesModel( this );
0042     addSubModel( "Devices", QIcon::fromTheme( "media-optical" ), d->deviceModel, true );
0043     
0044     // TODO: Currently our place list doesn't follow changes KFilePlacesModel.
0045     //       This needs to be changed. Adding, removing and editing places would be also nice.
0046     for( int i = 0; i < d->filePlacesModel->rowCount(); ++i ) {
0047         QModelIndex place = d->filePlacesModel->index( i, 0 );
0048         QUrl url = d->filePlacesModel->url( place );
0049         
0050         // Let's filter out device-related places
0051         // and custom protocols (we doesn't support burning from them)
0052         if( !d->filePlacesModel->isDevice( place ) && url.isLocalFile() ) {
0053             addPlace(
0054                 d->filePlacesModel->text( place ),
0055                 d->filePlacesModel->icon( place ),
0056                 url );
0057         }
0058     }
0059 
0060     connect( d->deviceModel, SIGNAL(modelAboutToBeReset()),
0061              this, SIGNAL(modelAboutToBeReset()) );
0062     connect( d->deviceModel, SIGNAL(modelReset()),
0063              this, SIGNAL(modelReset()) );
0064     connect( k3bcore->deviceManager(), SIGNAL(changed(K3b::Device::DeviceManager*)),
0065              this, SLOT(slotDevicesChanged(K3b::Device::DeviceManager*)) );
0066     slotDevicesChanged( k3bcore->deviceManager() );
0067 }
0068 
0069 
0070 K3b::PlacesModel::~PlacesModel()
0071 {
0072     delete d;
0073 }
0074 
0075 
0076 KFileItem K3b::PlacesModel::itemForIndex( const QModelIndex& index ) const
0077 {
0078     // KDirSortFilterProxyModel does not have the Q_OBJECT macro. Thus, we need to use dynamic_cast
0079     KDirSortFilterProxyModel* proxy = dynamic_cast<KDirSortFilterProxyModel*>( subModelForIndex( index ) );
0080     if ( proxy ) {
0081         KDirModel* model = qobject_cast<KDirModel*>( proxy->sourceModel() );
0082         return model->itemForIndex( proxy->mapToSource( mapToSubModel( index ) ) );
0083     }
0084     return KFileItem();
0085 }
0086 
0087 
0088 K3b::Device::Device* K3b::PlacesModel::deviceForIndex( const QModelIndex& index ) const
0089 {
0090     if ( qobject_cast<K3b::DeviceModel*>( subModelForIndex( index ) ) == d->deviceModel ) {
0091         return d->deviceModel->deviceForIndex( mapToSubModel( index ) );
0092     }
0093     return 0;
0094 }
0095 
0096 
0097 QModelIndex K3b::PlacesModel::indexForDevice( K3b::Device::Device* dev ) const
0098 {
0099     return mapFromSubModel( d->deviceModel->indexForDevice( dev ) );
0100 }
0101 
0102 
0103 void K3b::PlacesModel::expandToUrl( const QUrl& url )
0104 {
0105     qDebug() << url;
0106     
0107     // Check if url is not device's
0108     Q_FOREACH( Device::Device* device, d->deviceModel->devices() )
0109     {
0110         if( Solid::StorageAccess* solidStorage = device->solidStorage() ) {
0111             QUrl parent = QUrl::fromLocalFile( solidStorage->filePath() );
0112             if( parent.isParentOf( url ) ) {
0113                 qDebug() << url << "will be expanded to device" << device->description();
0114                 emit expand( mapFromSubModel( d->deviceModel->indexForDevice( device ) ) );
0115                 return;
0116             }
0117         }
0118         else if( url.scheme() == "audiocd" )
0119         {
0120             const Medium& medium = k3bcore->mediaCache()->medium( device );
0121             if( medium.content() & Medium::ContentAudio )
0122             {
0123                 qDebug() << url << "will be expanded to device" << device->description();
0124                 emit expand( mapFromSubModel( d->deviceModel->indexForDevice( device ) ) );
0125                 return;
0126             }
0127         }
0128     }
0129 
0130     // search for the best suited place that contains this URL
0131     int maxDepth = 0;
0132     KDirModel* modelToExpand = 0;
0133 
0134     for( DirModels::iterator it = d->dirModels.begin(); it != d->dirModels.end(); ++it ) {
0135         KDirModel* model = it.key();
0136         QUrl parent = model->dirLister()->url();
0137         if ( parent.isParentOf( url ) ) {
0138             if ( parent.path().length() > maxDepth ) {
0139                 maxDepth = parent.path().length();
0140                 modelToExpand = model;
0141             }
0142         }
0143     }
0144 
0145     if ( modelToExpand ) {
0146         qDebug() << modelToExpand->dirLister()->url() << " will be expanded.";
0147         if( modelToExpand->dirLister()->url().matches( url, QUrl::StripTrailingSlash ) ) {
0148             emit expand( indexForSubModel( d->dirModels[ modelToExpand ] ) );
0149         }
0150         else {
0151             modelToExpand->expandToUrl( url );
0152         }
0153     }
0154 }
0155 
0156 
0157 void K3b::PlacesModel::addPlace( const QString& name, const QIcon& icon, const QUrl& rootUrl )
0158 {
0159     KDirModel* model = new KDirModel( this );
0160     connect( model, SIGNAL(expand(QModelIndex)), this, SLOT(slotExpand(QModelIndex)) );
0161     model->dirLister()->setAutoErrorHandlingEnabled( false );
0162     model->dirLister()->setDirOnlyMode( true );
0163     model->dirLister()->openUrl( rootUrl, KDirLister::Keep );
0164 
0165     KDirSortFilterProxyModel* proxy = new KDirSortFilterProxyModel( model );
0166     proxy->setSourceModel( model );
0167     d->dirModels.insert( model, proxy );
0168     addSubModel( name, icon, proxy );
0169 }
0170 
0171 
0172 void K3b::PlacesModel::slotExpand( const QModelIndex& index )
0173 {
0174     qDebug() << index;
0175     KDirModel* model = ( KDirModel* )index.model();
0176     emit expand( mapFromSubModel( d->dirModels[model]->mapFromSource( index ) ) );
0177 }
0178 
0179 
0180 void K3b::PlacesModel::slotDevicesChanged( K3b::Device::DeviceManager* dm )
0181 {
0182     qDebug();
0183     d->deviceModel->setDevices( dm->allDevices() );
0184 }
0185 
0186 #include "moc_k3bplacesmodel.cpp"