ImportController.cpp 10.2 KB
Newer Older
Geoffroy Lacarriere's avatar
Geoffroy Lacarriere committed
1 2 3
/*****************************************************************************
 * ImportController.cpp
 *****************************************************************************
Ludovic Fauvet's avatar
Ludovic Fauvet committed
4
 * Copyright (C) 2008-2010 VideoLAN
Geoffroy Lacarriere's avatar
Geoffroy Lacarriere committed
5 6 7
 *
 * Authors: Geoffroy Lacarriere <geoffroylaca@gmail.com>
 *          Thomas Boquet <thomas.boquet@gmail.com>
Hugo Beauzee-Luyssen's avatar
Hugo Beauzee-Luyssen committed
8
 *          Hugo Beauzée-Luyssen <hugo@vlmc.org>
Geoffroy Lacarriere's avatar
Geoffroy Lacarriere committed
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/

25
#include "ImportController.h"
Thomas Boquet's avatar
Thomas Boquet committed
26
#include "ui_ImportController.h"
27

28
#include "Clip.h"
29
#include "ClipMetadataDisplayer.h"
Thomas Boquet's avatar
Thomas Boquet committed
30
#include "ClipRenderer.h"
Geoffroy Lacarriere's avatar
Geoffroy Lacarriere committed
31
#include "Library.h"
32
#include "Media.h"
33
#include "MediaCellView.h"
34
#include "MediaListView.h"
35 36 37
#include "MetaDataManager.h"
#include "PreviewWidget.h"
#include "TagWidget.h"
38
#include "Transcoder.h"
39

40
#include <QFileSystemModel>
41
#include <QMessageBox>
42
#include <QPalette>
43
#include <QSettings>
44
#include <QTime>
45
#include <QTimer>
Thomas Boquet's avatar
Thomas Boquet committed
46

47 48
#include <QtDebug>

Thomas Boquet's avatar
Thomas Boquet committed
49 50
ImportController::ImportController(QWidget *parent) :
    QDialog(parent),
51
    m_ui(new Ui::ImportController),
52 53
    m_nbMediaToLoad( 0 ),
    m_nbMediaLoaded( 0 )
Thomas Boquet's avatar
Thomas Boquet committed
54 55
{
    m_ui->setupUi(this);
56 57
    //The renderer will be deleted by the PreviewWidget
    m_clipRenderer = new ClipRenderer;
58
    m_ui->previewContainer->setRenderer( m_clipRenderer );
59
    m_stackNav = new StackViewController( m_ui->stackViewContainer );
60
    m_temporaryMedias = new MediaContainer;
61
    m_mediaListView = new MediaListView( m_stackNav, m_temporaryMedias );
62
//    m_tag = new TagWidget( m_ui->tagContainer, 6 );
63
    m_filesModel = new QFileSystemModel( this );
64
    m_stackNav->pushViewController( m_mediaListView );
Thomas Boquet's avatar
Thomas Boquet committed
65

66
    m_nameFilters << Media::AudioExtensions.split(' ', QString::SkipEmptyParts)
67 68 69
            << Media::VideoExtensions.split(' ', QString::SkipEmptyParts)
            << Media::ImageExtensions.split(' ', QString::SkipEmptyParts);
    m_filesModel->setFilter( QDir::AllDirs | QDir::AllEntries | QDir::NoDotAndDotDot );
70
    m_filesModel->setNameFilters( m_nameFilters );
71
    m_filesModel->setRootPath( "/" );
72
    m_filesModel->setNameFilterDisables( false );
73
    restoreCurrentPath();
74
    m_filesModel->sort( 0 );
75

Thomas Boquet's avatar
Thomas Boquet committed
76
    m_ui->treeView->setModel( m_filesModel );
77
    m_ui->treeView->setHeaderHidden( true );
78
    m_ui->treeView->setCurrentIndex( m_filesModel->index( m_currentlyWatchedDir ) );
Thomas Boquet's avatar
Thomas Boquet committed
79
    m_ui->treeView->setExpanded( m_ui->treeView->currentIndex() , true );
80 81
    m_ui->treeView->header()->setStretchLastSection( false );
    m_ui->treeView->header()->setResizeMode( QHeaderView::ResizeToContents );
Thomas Boquet's avatar
Thomas Boquet committed
82 83 84
    m_ui->treeView->setColumnHidden( 1, true );
    m_ui->treeView->setColumnHidden( 2, true );
    m_ui->treeView->setColumnHidden( 3, true );
85

86
    m_ui->forwardButton->setEnabled( true );
Thomas Boquet's avatar
Thomas Boquet committed
87

88
    m_ui->progressBar->setHidden( true );
89 90
    m_ui->errorLabelImg->hide();
    m_ui->errorLabel->hide();
91

92 93 94 95 96 97 98
    connect( m_ui->treeView, SIGNAL( clicked( QModelIndex ) ),
             this, SLOT( treeViewClicked( QModelIndex ) ) );
    connect( m_ui->treeView, SIGNAL( doubleClicked( QModelIndex ) ),
             this, SLOT( treeViewDoubleClicked( QModelIndex ) ) );
    connect( m_ui->forwardButton, SIGNAL( clicked() ),
             this, SLOT( forwardButtonClicked() ) );

99
    connect( this, SIGNAL( clipSelected( Clip* ) ),
100
             m_clipRenderer, SLOT( setClip( Clip* ) ) );
101
    connect( m_mediaListView, SIGNAL( clipSelected( Clip* ) ),
102
             this, SLOT( clipSelection( Clip* ) ) );
103 104
    connect( m_mediaListView, SIGNAL( clipRemoved( const QUuid& ) ),
             m_clipRenderer, SLOT( clipUnloaded( const QUuid& ) ) );
105 106 107

    connect( MetaDataManager::getInstance(), SIGNAL( failedToCompute( Media* ) ),
             this, SLOT( failedToLoad( Media* ) ) );
Thomas Boquet's avatar
Thomas Boquet committed
108 109 110 111 112 113
}

ImportController::~ImportController()
{
    delete m_ui;
    delete m_stackNav;
114
//    delete m_tag;
Thomas Boquet's avatar
Thomas Boquet committed
115 116
}

117 118
void
ImportController::changeEvent( QEvent *e )
Thomas Boquet's avatar
Thomas Boquet committed
119 120
{
    QDialog::changeEvent( e );
Geoffroy Lacarriere's avatar
Geoffroy Lacarriere committed
121 122 123 124 125 126 127
    switch ( e->type() )
    {
        case QEvent::LanguageChange:
            m_ui->retranslateUi( this );
            break;
        default:
            break;
Thomas Boquet's avatar
Thomas Boquet committed
128 129 130
    }
}

131
void
132
ImportController::clipSelection( Clip* clip )
Geoffroy Lacarriere's avatar
Geoffroy Lacarriere committed
133
{
134
    const QUuid& uuid = clip->uuid();
135 136
    if ( m_currentUuid == uuid )
        return ;
Hugo Beauzée-Luyssen's avatar
Hugo Beauzée-Luyssen committed
137
    m_ui->metadataContainer->setWatchedClip( clip );
138
    m_clipRenderer->stop();
139
    m_currentUuid = uuid;
140
//    m_tag->clipSelected( clip );
Hugo Beauzee-Luyssen's avatar
Hugo Beauzee-Luyssen committed
141
    emit clipSelected( clip );
Geoffroy Lacarriere's avatar
Geoffroy Lacarriere committed
142 143
}

144
void
145
ImportController::importMedia( const QString &filePath )
Thomas Boquet's avatar
Thomas Boquet committed
146
{
147 148
    if ( Library::getInstance()->mediaAlreadyLoaded( filePath ) == true ||
         m_temporaryMedias->mediaAlreadyLoaded( filePath ) == true )
149
        return ;
Hugo Beauzee-Luyssen's avatar
Hugo Beauzee-Luyssen committed
150

151
    Media*  media = m_temporaryMedias->addMedia( filePath );
152 153
    if ( media == NULL )
    {
Nikoli's avatar
Nikoli committed
154
        qCritical() << "An error occurred while loading media:" << filePath;
155 156
        return ;
    }
157 158 159
    Clip*   clip = new Clip( media );
    media->setBaseClip( clip );
    m_temporaryMedias->addClip( clip );
160 161
    ++m_nbMediaToLoad;
    m_ui->progressBar->setMaximum( m_nbMediaToLoad );
Thomas Boquet's avatar
Thomas Boquet committed
162 163
}

164 165 166 167
void
ImportController::importDir( const QString &path )
{
    QDir            dir( path );
168
    QFileInfoList   files = dir.entryInfoList( m_nameFilters, QDir::NoDotAndDotDot | QDir::Readable
169 170 171 172 173
                                               | QDir::AllEntries );

    foreach ( QFileInfo fInfo, files )
    {
        if ( fInfo.isDir() == true )
174
            importDir( fInfo.absoluteFilePath() );
175
        else
176
            importMedia( fInfo.absoluteFilePath() );
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
    }
}

void
ImportController::forwardButtonClicked()
{
    QModelIndex     index = m_ui->treeView->selectionModel()->currentIndex();
    QString         filePath = m_filesModel->fileInfo( index ).filePath();

    if ( !m_filesModel->isDir( index ) )
        importMedia( filePath );
    else
        importDir( filePath );
}

192 193
void
ImportController::treeViewClicked( const QModelIndex& index )
Thomas Boquet's avatar
Thomas Boquet committed
194 195 196 197
{
    if ( m_filesModel->isDir( index ) )
    {
        m_currentlyWatchedDir = m_filesModel->filePath( index );
198
        saveCurrentPath();
Thomas Boquet's avatar
Thomas Boquet committed
199 200 201 202
    }
    m_ui->forwardButton->setEnabled( true );
}

203 204
void
ImportController::treeViewDoubleClicked( const QModelIndex& index )
Thomas Boquet's avatar
Thomas Boquet committed
205
{
206 207
    if ( m_filesModel->isDir( index ) == false )
        forwardButtonClicked();
Thomas Boquet's avatar
Thomas Boquet committed
208
}
Geoffroy Lacarriere's avatar
Geoffroy Lacarriere committed
209

210 211
void
ImportController::reject()
212
{
213
    m_clipRenderer->stop();
214
    m_mediaListView->clear();
215
    m_temporaryMedias->clear();
216
    collapseAllButCurrentPath();
217
    m_clipRenderer->setClip( NULL );
218
    done( Rejected );
219 220
}

221 222
void
ImportController::accept()
Geoffroy Lacarriere's avatar
Geoffroy Lacarriere committed
223
{
224 225
    bool    invalidMedias = false;

226
    m_mediaListView->clear();
227
    m_clipRenderer->stop();
228
    collapseAllButCurrentPath();
Hugo Beauzee-Luyssen's avatar
Hugo Beauzee-Luyssen committed
229
    foreach ( Clip* clip, m_temporaryMedias->clips().values() )
230 231 232
    {
        if ( clip->getMedia()->lengthMS() == 0 && clip->getMedia()->inputType() == Media::File )
            invalidMedias = true;
233
        Library::getInstance()->addClip( clip );
234 235 236
    }
    if ( invalidMedias == true )
        handleInvalidMedias();
237
    m_temporaryMedias->removeAll();
238
    m_clipRenderer->setClip( NULL );
Geoffroy Lacarriere's avatar
Geoffroy Lacarriere committed
239 240
    done( Accepted );
}
Geoffroy Lacarriere's avatar
Geoffroy Lacarriere committed
241

242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262
void
ImportController::handleInvalidMedias()
{
    QMessageBox::StandardButton res = QMessageBox::question( NULL, tr( "Invalid medias" ),
                                                             tr( "Some of the medias you loaded can't be used for video editing. Do you want VLMC to convert them"
                                                                 " so you can use them in your project?" ),
                           QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes );
    if ( res == QMessageBox::Yes )
    {
        foreach ( Clip* clip, m_temporaryMedias->clips().values() )
        {
            if ( clip->getMedia()->lengthMS() == 0 && clip->getMedia()->inputType() == Media::File )
            {
                Transcoder  *transcoder = new Transcoder( clip->getMedia() );
                connect( transcoder, SIGNAL( done() ), transcoder, SLOT( deleteLater() ) );
                transcoder->transcodeToPs();
            }
        }
    }
}

263 264 265 266 267 268 269 270 271 272 273 274
void
ImportController::collapseAllButCurrentPath()
{
    m_ui->treeView->collapseAll();
    QStringList paths;
    for ( QDir directory( m_currentlyWatchedDir ); !directory.isRoot(); directory.cdUp() )
        paths.prepend( directory.absolutePath() );
    while ( paths.count() > 0 )
    {
        m_ui->treeView->setCurrentIndex( m_filesModel->index( paths.takeFirst() ) );
        m_ui->treeView->setExpanded( m_ui->treeView->currentIndex() , true );
    }
275
    m_ui->forwardButton->setEnabled( true );
276 277
}

278 279 280 281 282 283 284 285 286 287 288 289 290
void
ImportController::saveCurrentPath()
{
    QSettings s;
    s.setValue( "ImportPreviouslySelectPath", m_currentlyWatchedDir );
    s.sync();
}

void
ImportController::restoreCurrentPath()
{
    QSettings s;
    QVariant path = s.value( "ImportPreviouslySelectPath", QDir::homePath() );
291 292
    if ( QFile::exists( path.toString() ) == false )
        path = QDir::homePath();
293 294 295
    QFileInfo info = path.toString();
    m_currentlyWatchedDir = info.absoluteFilePath();
}
296 297

void
298
ImportController::mediaLoaded()
299
{
300 301 302 303 304
    ++m_nbMediaLoaded;
    if ( m_nbMediaLoaded == m_nbMediaToLoad )
    {
        m_nbMediaLoaded = 0;
        m_nbMediaToLoad = 0;
305
        m_ui->progressBar->hide();
306 307
    }
    else
308 309 310 311 312
    {
        if ( m_nbMediaToLoad > 3 )
            m_ui->progressBar->show();
        m_ui->progressBar->setValue( m_nbMediaLoaded );
    }
313 314

}
315 316 317 318

void
ImportController::failedToLoad( Media *media )
{
319
    m_ui->errorLabel->setText( tr( "Failed to load %1").arg(
320
            media->fileInfo()->fileName() ) );
321 322 323
    m_ui->errorLabelImg->show();
    m_ui->errorLabel->show();
    QTimer::singleShot( 3000, this, SLOT( hideErrors() ) );
324
    m_temporaryMedias->deleteClip( media->baseClip()->uuid() );
325
}
326 327 328 329 330 331 332

void
ImportController::hideErrors()
{
    m_ui->errorLabelImg->hide();
    m_ui->errorLabel->hide();
}