ImportController.cpp 10.5 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.
 *****************************************************************************/

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

27
#include "Clip.h"
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"
31
#include "Media.h"
32
#include "MediaCellView.h"
33
#include "MediaListView.h"
34 35 36
#include "MetaDataManager.h"
#include "PreviewWidget.h"
#include "TagWidget.h"
37

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

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

    QStringList filters;
62 63 64 65
    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
66
    m_filesModel->setNameFilters( filters );
67
    m_filesModel->setRootPath( "/" );
68
    m_filesModel->setNameFilterDisables( false );
69 70 71

    restoreCurrentPath();

Thomas Boquet's avatar
Thomas Boquet committed
72
    m_ui->treeView->setModel( m_filesModel );
73
    m_ui->treeView->setHeaderHidden( true );
74
    m_ui->treeView->setCurrentIndex( m_filesModel->index( m_currentlyWatchedDir ) );
Thomas Boquet's avatar
Thomas Boquet committed
75
    m_ui->treeView->setExpanded( m_ui->treeView->currentIndex() , true );
76 77
    m_ui->treeView->header()->setStretchLastSection( false );
    m_ui->treeView->header()->setResizeMode( QHeaderView::ResizeToContents );
Thomas Boquet's avatar
Thomas Boquet committed
78 79 80
    m_ui->treeView->setColumnHidden( 1, true );
    m_ui->treeView->setColumnHidden( 2, true );
    m_ui->treeView->setColumnHidden( 3, true );
81 82 83
    for ( int i = 0; i < m_filesModel->columnCount(); ++i )
        m_ui->treeView->sortByColumn( i );

84
    m_ui->forwardButton->setEnabled( true );
Thomas Boquet's avatar
Thomas Boquet committed
85

86
    m_ui->progressBar->setHidden( true );
87 88
    m_ui->errorLabelImg->hide();
    m_ui->errorLabel->hide();
89

90 91 92 93 94 95 96
    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() ) );

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

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

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

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

130
void
131
ImportController::clipSelection( Clip* clip )
Geoffroy Lacarriere's avatar
Geoffroy Lacarriere committed
132
{
133
    const QUuid& uuid = clip->uuid();
134 135
    if ( m_currentUuid == uuid )
        return ;
Hugo Beauzee-Luyssen's avatar
Hugo Beauzee-Luyssen committed
136
    setUIMetaData( clip->rootClip() );
137 138
    m_preview->stop();
    m_currentUuid = uuid;
Hugo Beauzee-Luyssen's avatar
Hugo Beauzee-Luyssen committed
139 140
    m_tag->clipSelected( clip );
    emit clipSelected( clip );
Geoffroy Lacarriere's avatar
Geoffroy Lacarriere committed
141 142
}

143
void
144
ImportController::setUIMetaData( const Clip* clip )
Geoffroy Lacarriere's avatar
Geoffroy Lacarriere committed
145
{
146
    if ( clip != NULL )
Geoffroy Lacarriere's avatar
Geoffroy Lacarriere committed
147 148 149
    {
        //Duration
        QTime   duration;
150
        duration = duration.addSecs( clip->lengthSecond() );
Geoffroy Lacarriere's avatar
Geoffroy Lacarriere committed
151 152
        m_ui->durationValueLabel->setText( duration.toString( "hh:mm:ss" ) );
        //Filename || title
Hugo Beauzee-Luyssen's avatar
Hugo Beauzee-Luyssen committed
153
        m_ui->nameValueLabel->setText( clip->getMedia()->fileInfo()->fileName() );
Geoffroy Lacarriere's avatar
Geoffroy Lacarriere committed
154
        m_ui->nameValueLabel->setWordWrap( true );
Hugo Beauzee-Luyssen's avatar
Hugo Beauzee-Luyssen committed
155
        setWindowTitle( clip->getMedia()->fileInfo()->fileName() + " " + tr( "properties" ) );
Geoffroy Lacarriere's avatar
Geoffroy Lacarriere committed
156
        //Resolution
Hugo Beauzee-Luyssen's avatar
Hugo Beauzee-Luyssen committed
157 158
        m_ui->resolutionValueLabel->setText( QString::number( clip->getMedia()->width() )
                                        + " x " + QString::number( clip->getMedia()->height() ) );
Geoffroy Lacarriere's avatar
Geoffroy Lacarriere committed
159
        //FPS
Hugo Beauzee-Luyssen's avatar
Hugo Beauzee-Luyssen committed
160
        m_ui->fpsValueLabel->setText( QString::number( clip->getMedia()->fps() ) );
Geoffroy Lacarriere's avatar
Geoffroy Lacarriere committed
161 162 163
    }
    else
    {
164 165 166 167
        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
168
    }
Geoffroy Lacarriere's avatar
Geoffroy Lacarriere committed
169 170
}

171
void
172
ImportController::importMedia( const QString &filePath )
Thomas Boquet's avatar
Thomas Boquet committed
173
{
174 175
    if ( Library::getInstance()->mediaAlreadyLoaded( filePath ) == true ||
         m_temporaryMedias->mediaAlreadyLoaded( filePath ) == true )
176
        return ;
Hugo Beauzee-Luyssen's avatar
Hugo Beauzee-Luyssen committed
177

178
    Media*  media = m_temporaryMedias->addMedia( filePath );
179 180 181 182 183
    if ( media == NULL )
    {
        qCritical() << "An error occured while loading media:" << filePath;
        return ;
    }
184 185 186
    Clip*   clip = new Clip( media );
    media->setBaseClip( clip );
    m_temporaryMedias->addClip( clip );
187 188 189 190
    ++m_nbMediaToLoad;
    m_ui->progressBar->setMaximum( m_nbMediaToLoad );
    connect( media, SIGNAL( metaDataComputed( const Media* ) ),
             this, SLOT( metaDataComputed( const Media* ) ) );
Thomas Boquet's avatar
Thomas Boquet committed
191 192
}

193 194 195 196 197 198 199 200 201 202
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 )
203
            importDir( fInfo.absoluteFilePath() );
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
        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 );
}

230 231
void
ImportController::treeViewClicked( const QModelIndex& index )
Thomas Boquet's avatar
Thomas Boquet committed
232 233 234 235
{
    if ( m_filesModel->isDir( index ) )
    {
        m_currentlyWatchedDir = m_filesModel->filePath( index );
236
        saveCurrentPath();
Thomas Boquet's avatar
Thomas Boquet committed
237 238 239 240
    }
    m_ui->forwardButton->setEnabled( true );
}

241 242
void
ImportController::treeViewDoubleClicked( const QModelIndex& index )
Thomas Boquet's avatar
Thomas Boquet committed
243
{
244 245
    if ( m_filesModel->isDir( index ) == false )
        forwardButtonClicked();
Thomas Boquet's avatar
Thomas Boquet committed
246
}
Geoffroy Lacarriere's avatar
Geoffroy Lacarriere committed
247

248 249
void
ImportController::reject()
250 251
{
    m_preview->stop();
252
    m_mediaListView->clear();
253
    m_temporaryMedias->clear();
254
    collapseAllButCurrentPath();
255
    m_clipRenderer->setClip( NULL );
256
    done( Rejected );
257 258
}

259 260
void
ImportController::accept()
Geoffroy Lacarriere's avatar
Geoffroy Lacarriere committed
261
{
262
    m_mediaListView->clear();
263
    m_preview->stop();
264
    collapseAllButCurrentPath();
Hugo Beauzee-Luyssen's avatar
Hugo Beauzee-Luyssen committed
265
    foreach ( Clip* clip, m_temporaryMedias->clips().values() )
266
        Library::getInstance()->addClip( clip );
267
    m_temporaryMedias->removeAll();
268
    m_clipRenderer->setClip( NULL );
Geoffroy Lacarriere's avatar
Geoffroy Lacarriere committed
269 270
    done( Accepted );
}
Geoffroy Lacarriere's avatar
Geoffroy Lacarriere committed
271

272 273 274 275 276 277 278 279 280 281 282 283
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 );
    }
284
    m_ui->forwardButton->setEnabled( true );
285 286
}

287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302
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();
}
303 304

void
305
ImportController::mediaLoaded()
306
{
307 308 309 310 311
    ++m_nbMediaLoaded;
    if ( m_nbMediaLoaded == m_nbMediaToLoad )
    {
        m_nbMediaLoaded = 0;
        m_nbMediaToLoad = 0;
312
        m_ui->progressBar->hide();
313 314
    }
    else
315 316 317 318 319
    {
        if ( m_nbMediaToLoad > 3 )
            m_ui->progressBar->show();
        m_ui->progressBar->setValue( m_nbMediaLoaded );
    }
320 321

}
322 323 324 325

void
ImportController::failedToLoad( Media *media )
{
326
    m_ui->errorLabel->setText( tr( "Failed to load %1").arg(
327
            media->fileInfo()->fileName() ) );
328 329 330
    m_ui->errorLabelImg->show();
    m_ui->errorLabel->show();
    QTimer::singleShot( 3000, this, SLOT( hideErrors() ) );
331
    m_temporaryMedias->deleteClip( media->baseClip()->uuid() );
332
}
333 334 335 336 337 338 339

void
ImportController::hideErrors()
{
    m_ui->errorLabelImg->hide();
    m_ui->errorLabel->hide();
}
340 341 342 343 344 345

void
ImportController::metaDataComputed( const Media *media )
{
    setUIMetaData( media->baseClip() );
}