ImportController.cpp 11.7 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>
8
 *          Clement Chavance <chavance.c@gmail.com>
Hugo Beauzee-Luyssen's avatar
Hugo Beauzee-Luyssen committed
9
 *          Hugo Beauzée-Luyssen <hugo@vlmc.org>
Geoffroy Lacarriere's avatar
Geoffroy Lacarriere committed
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
 *
 * 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.
 *****************************************************************************/

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

Thomas Boquet's avatar
Thomas Boquet committed
28
#include "ClipRenderer.h"
29
#include "ImportController.h"
Geoffroy Lacarriere's avatar
Geoffroy Lacarriere committed
30
#include "Library.h"
Hugo Beauzee-Luyssen's avatar
Hugo Beauzee-Luyssen committed
31
#include "MetaDataManager.h"
32
#include "MediaCellView.h"
33 34

#include <QPalette>
35
#include <QSettings>
36
#include <QTime>
37
#include <QTimer>
Thomas Boquet's avatar
Thomas Boquet committed
38 39 40

ImportController::ImportController(QWidget *parent) :
    QDialog(parent),
41 42
    m_ui(new Ui::ImportController),
    m_clipListController( 0 ),
43 44
    m_nbMediaToLoad( 0 ),
    m_nbMediaLoaded( 0 )
Thomas Boquet's avatar
Thomas Boquet committed
45 46 47 48
{
    m_ui->setupUi(this);
    m_preview = new PreviewWidget( new ClipRenderer, m_ui->previewContainer );
    m_stackNav = new StackViewController( m_ui->stackViewContainer, false );
49 50
    m_temporaryMedias = new MediaContainer;
    m_mediaListController = new MediaListViewController( m_stackNav, m_temporaryMedias );
Thomas Boquet's avatar
Thomas Boquet committed
51
    m_tag = new TagWidget( m_ui->tagContainer, 6 );
52
    m_filesModel = new QFileSystemModel( this );
Thomas Boquet's avatar
Thomas Boquet committed
53 54 55
    m_stackNav->pushViewController( m_mediaListController );

    QStringList filters;
56 57 58 59
    filters << Media::AudioExtensions.split(' ', QString::SkipEmptyParts)
            << Media::VideoExtensions.split(' ', QString::SkipEmptyParts)
            << Media::ImageExtensions.split(' ', QString::SkipEmptyParts);
    m_filesModel->setFilter( QDir::AllDirs | QDir::AllEntries | QDir::NoDotAndDotDot );
Thomas Boquet's avatar
Thomas Boquet committed
60 61 62
    m_filesModel->sort( 2, Qt::AscendingOrder );
    m_filesModel->sort( 0, Qt::AscendingOrder );
    m_filesModel->setNameFilters( filters );
63
    m_filesModel->setRootPath( "/" );
64
    m_filesModel->setNameFilterDisables( false );
65 66 67

    restoreCurrentPath();

Thomas Boquet's avatar
Thomas Boquet committed
68
    m_ui->treeView->setModel( m_filesModel );
69
    m_ui->treeView->setHeaderHidden( true );
70
    m_ui->treeView->setCurrentIndex( m_filesModel->index( m_currentlyWatchedDir ) );
Thomas Boquet's avatar
Thomas Boquet committed
71
    m_ui->treeView->setExpanded( m_ui->treeView->currentIndex() , true );
72 73
    m_ui->treeView->header()->setStretchLastSection( false );
    m_ui->treeView->header()->setResizeMode( QHeaderView::ResizeToContents );
Thomas Boquet's avatar
Thomas Boquet committed
74 75 76
    m_ui->treeView->setColumnHidden( 1, true );
    m_ui->treeView->setColumnHidden( 2, true );
    m_ui->treeView->setColumnHidden( 3, true );
77
    m_ui->forwardButton->setEnabled( true );
Thomas Boquet's avatar
Thomas Boquet committed
78

79
    m_ui->progressBar->setHidden( true );
80 81
    m_ui->errorLabelImg->hide();
    m_ui->errorLabel->hide();
82

83 84 85 86 87 88 89
    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() ) );

90
    connect( m_mediaListController, SIGNAL( clipSelected( Clip* ) ),
91
             qobject_cast<const ClipRenderer*>( m_preview->getGenericRenderer() ),
92 93 94
             SLOT( setClip( Clip* ) ) );
    connect( m_mediaListController, SIGNAL( clipSelected( Clip* ) ),
             this, SLOT( mediaSelection( Clip* ) ) );
95

96
    connect( m_mediaListController, SIGNAL( clipDeleted( const QUuid& ) ),
97 98 99 100
             this, SLOT( mediaDeletion( const QUuid& ) ) );

    connect( m_stackNav, SIGNAL( previousButtonPushed() ),
             this, SLOT( restoreContext() ) );
101 102 103

    connect( MetaDataManager::getInstance(), SIGNAL( failedToCompute( Media* ) ),
             this, SLOT( failedToLoad( Media* ) ) );
Thomas Boquet's avatar
Thomas Boquet committed
104 105 106 107
}

ImportController::~ImportController()
{
108
    delete m_preview;
Thomas Boquet's avatar
Thomas Boquet committed
109 110 111 112 113
    delete m_ui;
    delete m_stackNav;
    delete m_tag;
}

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

128
void
129
ImportController::mediaSelection( Clip* clip )
Geoffroy Lacarriere's avatar
Geoffroy Lacarriere committed
130
{
131
    const QUuid& uuid = clip->uuid();
132 133
    if ( m_currentUuid == uuid )
        return ;
134 135
    Media*  media = m_temporaryMedias->media( uuid );
    setUIMetaData( media->baseClip() );
136 137
    m_preview->stop();
    m_currentUuid = uuid;
138 139
    m_tag->mediaSelected( media );
    emit clipSelected( media->baseClip() );
Geoffroy Lacarriere's avatar
Geoffroy Lacarriere committed
140 141
}

142 143
void
ImportController::clipSelection( const QUuid& uuid )
Geoffroy Lacarriere's avatar
Geoffroy Lacarriere committed
144
{
145 146
    if ( uuid == m_currentUuid )
        return ;
147
    Clip*   clip = m_temporaryMedias->clip( uuid );
148 149

    if ( clip == NULL )
150
        return ;
151
    setUIMetaData( clip );
152
    m_preview->stop();
153
    emit clipSelected( clip );
Thomas Boquet's avatar
Thomas Boquet committed
154 155
}

156
void
157
ImportController::setUIMetaData( Clip* clip )
Geoffroy Lacarriere's avatar
Geoffroy Lacarriere committed
158
{
159
    if ( clip != NULL )
Geoffroy Lacarriere's avatar
Geoffroy Lacarriere committed
160 161 162
    {
        //Duration
        QTime   duration;
163
        duration = duration.addSecs( clip->lengthSecond() );
Geoffroy Lacarriere's avatar
Geoffroy Lacarriere committed
164 165
        m_ui->durationValueLabel->setText( duration.toString( "hh:mm:ss" ) );
        //Filename || title
166
        m_ui->nameValueLabel->setText( clip->getParent()->fileInfo()->fileName() );
Geoffroy Lacarriere's avatar
Geoffroy Lacarriere committed
167
        m_ui->nameValueLabel->setWordWrap( true );
168
        setWindowTitle( clip->getParent()->fileInfo()->fileName() + " " + tr( "properties" ) );
Geoffroy Lacarriere's avatar
Geoffroy Lacarriere committed
169
        //Resolution
170 171
        m_ui->resolutionValueLabel->setText( QString::number( clip->getParent()->width() )
                                        + " x " + QString::number( clip->getParent()->height() ) );
Geoffroy Lacarriere's avatar
Geoffroy Lacarriere committed
172
        //FPS
173
        m_ui->fpsValueLabel->setText( QString::number( clip->getParent()->fps() ) );
Geoffroy Lacarriere's avatar
Geoffroy Lacarriere committed
174 175 176
    }
    else
    {
177 178 179 180
        m_ui->durationValueLabel->setText( "--:--:--" );
        m_ui->nameValueLabel->setText( "none" );
        m_ui->resolutionValueLabel->setText( "-- x --" );
        m_ui->fpsValueLabel->setText( "--" );
Geoffroy Lacarriere's avatar
Geoffroy Lacarriere committed
181
    }
Geoffroy Lacarriere's avatar
Geoffroy Lacarriere committed
182 183
}

184
void
185
ImportController::importMedia( const QString &filePath )
Thomas Boquet's avatar
Thomas Boquet committed
186
{
187
    ++m_nbMediaToLoad;
188
    m_ui->progressBar->setMaximum( m_nbMediaToLoad );
189 190
    if ( m_temporaryMedias->mediaAlreadyLoaded( filePath ) == true ||
         Library::getInstance()->mediaAlreadyLoaded( filePath ) == true )
Hugo Beauzee-Luyssen's avatar
Hugo Beauzee-Luyssen committed
191 192
        return ;

Hugo Beauzee-Luyssen's avatar
Hugo Beauzee-Luyssen committed
193
    Media*          media = new Media( filePath );
194
    connect( media, SIGNAL( snapshotComputed( const Media* ) ),
195
             this, SLOT( mediaLoaded() ) );
196
    m_temporaryMedias->addMedia( media );
Hugo Beauzee-Luyssen's avatar
Hugo Beauzee-Luyssen committed
197
    MetaDataManager::getInstance()->computeMediaMetadata( media );
Thomas Boquet's avatar
Thomas Boquet committed
198 199
}

200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236
void
ImportController::importDir( const QString &path )
{
    QDir            dir( path );
    QFileInfoList   files = dir.entryInfoList( QDir::NoDotAndDotDot | QDir::Readable
                                               | QDir::AllEntries );

    foreach ( QFileInfo fInfo, files )
    {
        if ( fInfo.isDir() == true )
            importDir( fInfo.absolutePath() );
        else
        {
            QString ext = fInfo.suffix();

            if ( Media::AudioExtensions.contains( ext ) ||
                 Media::VideoExtensions.contains( ext ) ||
                 Media::ImageExtensions.contains( ext ) )
            {
                importMedia( fInfo.absoluteFilePath() );
            }
        }
    }
}

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 );
}

237 238
void
ImportController::treeViewClicked( const QModelIndex& index )
Thomas Boquet's avatar
Thomas Boquet committed
239 240 241 242
{
    if ( m_filesModel->isDir( index ) )
    {
        m_currentlyWatchedDir = m_filesModel->filePath( index );
243
        saveCurrentPath();
Thomas Boquet's avatar
Thomas Boquet committed
244 245 246 247
    }
    m_ui->forwardButton->setEnabled( true );
}

248 249
void
ImportController::treeViewDoubleClicked( const QModelIndex& index )
Thomas Boquet's avatar
Thomas Boquet committed
250
{
251 252
    if ( m_filesModel->isDir( index ) == false )
        forwardButtonClicked();
Thomas Boquet's avatar
Thomas Boquet committed
253
}
Geoffroy Lacarriere's avatar
Geoffroy Lacarriere committed
254

255 256
void
ImportController::reject()
257 258
{
    m_preview->stop();
259
    m_mediaListController->clear();
260
    m_temporaryMedias->clear();
261
    collapseAllButCurrentPath();
262
    done( Rejected );
263 264
}

265 266
void
ImportController::accept()
Geoffroy Lacarriere's avatar
Geoffroy Lacarriere committed
267
{
268
    m_mediaListController->clear();
269
    m_preview->stop();
270
    collapseAllButCurrentPath();
271
    foreach ( Media* media, m_temporaryMedias->medias().values() )
272
        Library::getInstance()->addMedia( media );
273
    m_temporaryMedias->removeAll();
Geoffroy Lacarriere's avatar
Geoffroy Lacarriere committed
274 275
    done( Accepted );
}
Geoffroy Lacarriere's avatar
Geoffroy Lacarriere committed
276

277 278 279 280 281 282 283 284 285 286 287 288
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 );
    }
289
    m_ui->forwardButton->setEnabled( true );
290 291
}

292 293
void
ImportController::mediaDeletion( const QUuid& uuid )
Geoffroy Lacarriere's avatar
Geoffroy Lacarriere committed
294
{
295
    m_temporaryMedias->deleteMedia( uuid );
296

Geoffroy Lacarriere's avatar
Geoffroy Lacarriere committed
297
    if ( uuid == m_currentUuid )
Geoffroy Lacarriere's avatar
Geoffroy Lacarriere committed
298
    {
299
        setUIMetaData( NULL );
Geoffroy Lacarriere's avatar
Geoffroy Lacarriere committed
300
        m_currentUuid = QUuid();
301
        m_preview->stop();
Geoffroy Lacarriere's avatar
Geoffroy Lacarriere committed
302
    }
Geoffroy Lacarriere's avatar
Geoffroy Lacarriere committed
303 304
}

305 306
void
ImportController::clipDeletion( const QUuid& uuid )
Geoffroy Lacarriere's avatar
Geoffroy Lacarriere committed
307
{
308
    m_temporaryMedias->removeClip( uuid );
Geoffroy Lacarriere's avatar
Geoffroy Lacarriere committed
309
}
310

311 312
void
ImportController::showClipList( const QUuid& uuid )
313
{
314 315
    Media* media = m_temporaryMedias->media( uuid );
    if ( media == NULL || media->clipsCount() == 0 )
316
        return ;
317

318
    m_clipListController = new MediaListViewController( m_stackNav, m_temporaryMedias );
319 320 321 322
    connect( m_clipListController, SIGNAL( clipSelected( const QUuid& ) ),
             this, SLOT( clipSelection( const QUuid& ) ) );
    connect( m_clipListController, SIGNAL( clipDeleted( const QUuid& ) ),
             this, SLOT( clipDeletion( const QUuid& ) ) );
323 324 325 326 327
    if ( !m_currentUuid.isNull() )
        m_savedUuid = m_currentUuid;
    m_stackNav->pushViewController( m_clipListController );
}

328 329
void
ImportController::restoreContext()
330
{
331 332
    qDebug() << "FIXME: update clip count";
    m_currentUuid = m_savedUuid;
333
}
334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350

void
ImportController::saveCurrentPath()
{
    QSettings s;
    s.setValue( "ImportPreviouslySelectPath", m_currentlyWatchedDir );
    s.sync();
}

void
ImportController::restoreCurrentPath()
{
    QSettings s;
    QVariant path = s.value( "ImportPreviouslySelectPath", QDir::homePath() );
    QFileInfo info = path.toString();
    m_currentlyWatchedDir = info.absoluteFilePath();
}
351 352

void
353
ImportController::mediaLoaded()
354
{
355 356 357 358 359
    ++m_nbMediaLoaded;
    if ( m_nbMediaLoaded == m_nbMediaToLoad )
    {
        m_nbMediaLoaded = 0;
        m_nbMediaToLoad = 0;
360
        m_ui->progressBar->hide();
361 362
    }
    else
363 364 365 366 367
    {
        if ( m_nbMediaToLoad > 3 )
            m_ui->progressBar->show();
        m_ui->progressBar->setValue( m_nbMediaLoaded );
    }
368 369

}
370 371 372 373

void
ImportController::failedToLoad( Media *media )
{
374
    m_ui->errorLabel->setText( tr( "Failed to load %1").arg(
375
            media->fileInfo()->fileName() ) );
376 377 378
    m_ui->errorLabelImg->show();
    m_ui->errorLabel->show();
    QTimer::singleShot( 3000, this, SLOT( hideErrors() ) );
379
    mediaDeletion( media->baseClip()->uuid() );
380
}
381 382 383 384 385 386 387

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