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 175 176 177
    Media* media = m_temporaryMedias->addMedia( filePath );
    if ( media )
        connect( media, SIGNAL( metaDataComputed( const Media* ) ),
                 this, SLOT( metaDataComputed( const Media* ) ) );
Thomas Boquet's avatar
Thomas Boquet committed
178 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
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 );
}

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

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

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

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

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

274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289
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();
}
290 291

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

}
309 310 311 312

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

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

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