1
/****************************************************************************************
2
 * Copyright (c) 2007-2008 Ian Monroe <ian@monroe.nu>                                   *
3
 *                                                                                      *
4
 * This program is free software; you can redistribute it and/or modify it under        *
5
 * the terms of the GNU General Public License as published by the Free Software        *
6
 * Foundation; either version 2 of the License, or (at your option) version 3 or        *
7
 * any later version accepted by the membership of KDE e.V. (or its successor approved  *
8
 * by the membership of KDE e.V.), which shall act as a proxy defined in Section 14 of  *
9
 * version 3 of the license.                                                            *
10
 *                                                                                      *
11
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY      *
12
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A      *
13
 * PARTICULAR PURPOSE. See the GNU General Public License for more details.             *
14
 *                                                                                      *
15
 * You should have received a copy of the GNU General Public License along with         *
16
 * this program.  If not, see <http://www.gnu.org/licenses/>.                           *
17
 ****************************************************************************************/
18
19
#include "DirectoryLoader.h"
20
21
#include "core/support/Debug.h"
22
#include "core-impl/collections/support/CollectionManager.h"
23
#include "core-impl/playlists/types/file/PlaylistFileSupport.h"
24
#include "core/playlists/PlaylistFormat.h"
25
#include "playlist/PlaylistModelStack.h"
26
#include "playlistmanager/PlaylistManager.h"
27
28
#include <kio/job.h> // KIO::listRecursive
29
30
31
DirectoryLoader::DirectoryLoader()
32
    : QObject( 0 )
33
        , m_listOperations( 0 )
34
        , m_localConnection( false )
35
        , m_row( 0 )
36
{}
37
38
DirectoryLoader::~DirectoryLoader()
39
{}
40
41
void
42
DirectoryLoader::insertAtRow( int row )
43
{
44
    m_row = row;
45
    m_localConnection = true;
46
    connect( this, SIGNAL( finished( const Meta::TrackList& ) ), this, SLOT( doInsertAtRow() ) );
47
}
48
49
void
50
DirectoryLoader::doInsertAtRow()
51
{
52
    The::playlistController()->insertTracks( m_row, m_tracks );
53
    deleteLater();
54
}
55
56
void
57
DirectoryLoader::init( const QList<QUrl>& qurls )
58
{
59
    QList<KUrl> kurls;
60
    foreach( const QUrl &qurl, qurls )
61
        kurls << KUrl( qurl );
62
63
    init( kurls );
64
}
65
66
void
67
DirectoryLoader::init( const QList<KUrl>& urls )
68
{
69
    //drop from an external source or the file browser
70
    debug() << "Drop from external source or file browser";
71
    QList<KIO::ListJob*> jobs;
72
73
    foreach( const KUrl &kurl, urls )
74
    {
75
        KFileItem kitem( KFileItem::Unknown, KFileItem::Unknown, kurl, true );
76
        if( kitem.isDir() )
77
        {
78
            m_listOperations++;
79
            KIO::ListJob* lister = KIO::listRecursive( kurl ); //kjob's delete themselves
80
            connect( lister, SIGNAL( finished( KJob*) ),
81
                     SLOT( listJobFinished( KJob*) ) );
82
            connect( lister, SIGNAL( entries( KIO::Job*, const KIO::UDSEntryList& ) ),
83
                     SLOT( directoryListResults( KIO::Job*, const KIO::UDSEntryList& ) ) );
84
        }
85
        else
86
        {
87
            if( Playlists::isPlaylist( kurl ) )
88
            {
89
                Playlists::PlaylistFilePtr playlist = Playlists::loadPlaylistFile( kurl );
90
                if( playlist )
91
                    m_tracks << playlist->tracks();
92
            }
93
            else
94
            {
95
                Meta::TrackPtr track = CollectionManager::instance()->trackForUrl( kurl );
96
                if( track )
97
                    m_tracks << track;
98
            }
99
        }
100
        //else TODO: notify user if can't decode, see also MyDirLister::matchesFilter       
101
    }
102
    if( m_listOperations == 0 )
103
    {
104
        finishUrlList();
105
    }
106
}
107
108
void
109
DirectoryLoader::directoryListResults( KIO::Job *job, const KIO::UDSEntryList &list )
110
{
111
    DEBUG_BLOCK
112
    //dfaure says that job->redirectionUrl().isValid() ? job->redirectionUrl() : job->url(); might be needed
113
    //but to wait until an issue is actually found, since it might take more work
114
    const KUrl dir = static_cast<KIO::SimpleJob*>( job )->url();
115
    foreach( const KIO::UDSEntry &entry, list )
116
    {
117
        KFileItem item( entry, dir, true, true );
118
        m_expanded.append( item );
119
    }
120
}
121
122
void
123
DirectoryLoader::listJobFinished(KJob*)
124
{
125
    m_listOperations--;
126
    if( m_listOperations < 1 )
127
        finishUrlList();
128
}
129
130
void
131
DirectoryLoader::finishUrlList()
132
{
133
    if( !m_expanded.isEmpty() )
134
    {
135
        qStableSort( m_expanded.begin(), m_expanded.end(), DirectoryLoader::directorySensitiveLessThan );
136
        foreach( const KFileItem& item, m_expanded )
137
        {
138
            if( !item.isDir() )
139
            {
140
                Meta::TrackPtr track = CollectionManager::instance()->trackForUrl( item.url() );
141
                if( track )
142
                    m_tracks.append( track );
143
            }
144
        }
145
        qStableSort( m_tracks.begin(), m_tracks.end(), Meta::Track::lessThan );
146
    }
147
    emit finished( m_tracks );
148
    if( !m_localConnection )
149
        deleteLater();
150
}
151
152
bool
153
DirectoryLoader::directorySensitiveLessThan( const KFileItem& item1, const KFileItem& item2 )
154
{
155
    QString dir1 =  item1.url().directory();
156
    QString dir2 =  item2.url().directory();
157
158
    debug() << "dir1: " << dir1;
159
    debug() << "dir2: " << dir2;
160
    if(dir1 == dir2)
161
    {
162
        debug() << "dir1==dir2";
163
        return item1.url().url() < item2.url().url();
164
    }
165
    else if( dir1 < dir2 )
166
    {
167
        debug() << "dir1<dir2";
168
        return true;
169
    } else {
170
        debug() << "dir1>dir2";
171
        return false;
172
    }
173
}