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.
 *****************************************************************************/

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

Thomas Boquet's avatar
Thomas Boquet committed
27
#include "ClipRenderer.h"
28
#include "ImportController.h"
Geoffroy Lacarriere's avatar
Geoffroy Lacarriere committed
29
#include "Library.h"
Hugo Beauzee-Luyssen's avatar
Hugo Beauzee-Luyssen committed
30
#include "MetaDataManager.h"
31
#include "MediaCellView.h"
32
#include "MediaListView.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
    m_ui(new Ui::ImportController),
42 43
    m_nbMediaToLoad( 0 ),
    m_nbMediaLoaded( 0 )
Thomas Boquet's avatar
Thomas Boquet committed
44 45
{
    m_ui->setupUi(this);
46 47 48
    //The renderer will be deleted by the PreviewWidget
    m_clipRenderer = new ClipRenderer;
    m_preview = new PreviewWidget( m_clipRenderer, m_ui->previewContainer );
49
    m_stackNav = new StackViewController( m_ui->stackViewContainer );
50
    m_temporaryMedias = new MediaContainer;
51
    m_mediaListView = new MediaListView( m_stackNav, m_temporaryMedias );
Thomas Boquet's avatar
Thomas Boquet committed
52
    m_tag = new TagWidget( m_ui->tagContainer, 6 );
53
    m_filesModel = new QFileSystemModel( this );
54
    m_stackNav->pushViewController( m_mediaListView );
Thomas Boquet's avatar
Thomas Boquet committed
55 56

    QStringList filters;
57 58 59 60
    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
61 62 63
    m_filesModel->sort( 2, Qt::AscendingOrder );
    m_filesModel->sort( 0, Qt::AscendingOrder );
    m_filesModel->setNameFilters( filters );
64
    m_filesModel->setRootPath( "/" );
65
    m_filesModel->setNameFilterDisables( false );
66 67 68

    restoreCurrentPath();

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

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

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

91
    connect( this, SIGNAL( clipSelected( Clip* ) ),
92
             m_clipRenderer, SLOT( setClip( Clip* ) ) );
93
    connect( m_mediaListView, SIGNAL( clipSelected( Clip* ) ),
94
             this, SLOT( clipSelection( Clip* ) ) );
95
    connect( m_mediaListView, SIGNAL( clipDeleted( const QUuid& ) ),
96
             m_clipRenderer, SLOT( clipUnloaded( const QUuid& ) ) );
97 98 99

    connect( MetaDataManager::getInstance(), SIGNAL( failedToCompute( Media* ) ),
             this, SLOT( failedToLoad( Media* ) ) );
Thomas Boquet's avatar
Thomas Boquet committed
100 101 102 103
}

ImportController::~ImportController()
{
104
    delete m_preview;
Thomas Boquet's avatar
Thomas Boquet committed
105 106 107 108 109
    delete m_ui;
    delete m_stackNav;
    delete m_tag;
}

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

124
void
125
ImportController::clipSelection( Clip* clip )
Geoffroy Lacarriere's avatar
Geoffroy Lacarriere committed
126
{
127
    const QUuid& uuid = clip->uuid();
128 129
    if ( m_currentUuid == uuid )
        return ;
Hugo Beauzee-Luyssen's avatar
Hugo Beauzee-Luyssen committed
130 131
    Media*  media = clip->rootClip()->getMedia();
    setUIMetaData( clip->rootClip() );
132 133
    m_preview->stop();
    m_currentUuid = uuid;
Hugo Beauzee-Luyssen's avatar
Hugo Beauzee-Luyssen committed
134 135
    m_tag->clipSelected( clip );
    emit clipSelected( clip );
Geoffroy Lacarriere's avatar
Geoffroy Lacarriere committed
136 137
}

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

166
void
167
ImportController::importMedia( const QString &filePath )
Thomas Boquet's avatar
Thomas Boquet committed
168
{
169 170
    if ( Library::getInstance()->mediaAlreadyLoaded( filePath ) == true )
        return ;
171
    ++m_nbMediaToLoad;
172
    m_ui->progressBar->setMaximum( m_nbMediaToLoad );
Hugo Beauzee-Luyssen's avatar
Hugo Beauzee-Luyssen committed
173

174
    Media* media = m_temporaryMedias->addMedia( filePath );
175
    m_temporaryMedias->addClip( media->baseClip() );
176 177 178
    if ( media )
        connect( media, SIGNAL( metaDataComputed( const Media* ) ),
                 this, SLOT( metaDataComputed( const Media* ) ) );
Thomas Boquet's avatar
Thomas Boquet committed
179 180
}

181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217
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 );
}

218 219
void
ImportController::treeViewClicked( const QModelIndex& index )
Thomas Boquet's avatar
Thomas Boquet committed
220 221 222 223
{
    if ( m_filesModel->isDir( index ) )
    {
        m_currentlyWatchedDir = m_filesModel->filePath( index );
224
        saveCurrentPath();
Thomas Boquet's avatar
Thomas Boquet committed
225 226 227 228
    }
    m_ui->forwardButton->setEnabled( true );
}

229 230
void
ImportController::treeViewDoubleClicked( const QModelIndex& index )
Thomas Boquet's avatar
Thomas Boquet committed
231
{
232 233
    if ( m_filesModel->isDir( index ) == false )
        forwardButtonClicked();
Thomas Boquet's avatar
Thomas Boquet committed
234
}
Geoffroy Lacarriere's avatar
Geoffroy Lacarriere committed
235

236 237
void
ImportController::reject()
238 239
{
    m_preview->stop();
240
    m_mediaListView->clear();
241
    m_temporaryMedias->clear();
242
    collapseAllButCurrentPath();
243
    m_clipRenderer->setClip( NULL );
244
    done( Rejected );
245 246
}

247 248
void
ImportController::accept()
Geoffroy Lacarriere's avatar
Geoffroy Lacarriere committed
249
{
250
    m_mediaListView->clear();
251
    m_preview->stop();
252
    collapseAllButCurrentPath();
Hugo Beauzee-Luyssen's avatar
Hugo Beauzee-Luyssen committed
253
    foreach ( Clip* clip, m_temporaryMedias->clips().values() )
254
        Library::getInstance()->addClip( clip );
255
    m_temporaryMedias->removeAll();
256
    m_clipRenderer->setClip( NULL );
Geoffroy Lacarriere's avatar
Geoffroy Lacarriere committed
257 258
    done( Accepted );
}
Geoffroy Lacarriere's avatar
Geoffroy Lacarriere committed
259

260 261 262 263 264 265 266 267 268 269 270 271
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 );
    }
272
    m_ui->forwardButton->setEnabled( true );
273 274
}

275 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() );
    QFileInfo info = path.toString();
    m_currentlyWatchedDir = info.absoluteFilePath();
}
291 292

void
293
ImportController::mediaLoaded()
294
{
295 296 297 298 299
    ++m_nbMediaLoaded;
    if ( m_nbMediaLoaded == m_nbMediaToLoad )
    {
        m_nbMediaLoaded = 0;
        m_nbMediaToLoad = 0;
300
        m_ui->progressBar->hide();
301 302
    }
    else
303 304 305 306 307
    {
        if ( m_nbMediaToLoad > 3 )
            m_ui->progressBar->show();
        m_ui->progressBar->setValue( m_nbMediaLoaded );
    }
308 309

}
310 311 312 313

void
ImportController::failedToLoad( Media *media )
{
314
    m_ui->errorLabel->setText( tr( "Failed to load %1").arg(
315
            media->fileInfo()->fileName() ) );
316 317 318
    m_ui->errorLabelImg->show();
    m_ui->errorLabel->show();
    QTimer::singleShot( 3000, this, SLOT( hideErrors() ) );
Hugo Beauzee-Luyssen's avatar
Hugo Beauzee-Luyssen committed
319 320
    delete m_temporaryMedias->removeClip( media->baseClip() );
    delete media;
321
}
322 323 324 325 326 327 328

void
ImportController::hideErrors()
{
    m_ui->errorLabelImg->hide();
    m_ui->errorLabel->hide();
}
329 330 331 332 333 334

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