ImportController.cpp 10.4 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 67 68
    m_filesModel->sort( 2, Qt::AscendingOrder );
    m_filesModel->sort( 0, Qt::AscendingOrder );
    m_filesModel->setNameFilters( filters );
69
    m_filesModel->setRootPath( "/" );
70
    m_filesModel->setNameFilterDisables( false );
71 72 73

    restoreCurrentPath();

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

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

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

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

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

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

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

129
void
130
ImportController::clipSelection( Clip* clip )
Geoffroy Lacarriere's avatar
Geoffroy Lacarriere committed
131
{
132
    const QUuid& uuid = clip->uuid();
133 134
    if ( m_currentUuid == uuid )
        return ;
Hugo Beauzee-Luyssen's avatar
Hugo Beauzee-Luyssen committed
135 136
    Media*  media = clip->rootClip()->getMedia();
    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 )
        return ;
176
    ++m_nbMediaToLoad;
177
    m_ui->progressBar->setMaximum( m_nbMediaToLoad );
Hugo Beauzee-Luyssen's avatar
Hugo Beauzee-Luyssen committed
178

179 180 181 182
    Media*  media = m_temporaryMedias->addMedia( filePath );
    Clip*   clip = new Clip( media );
    media->setBaseClip( clip );
    m_temporaryMedias->addClip( clip );
183 184 185
    if ( media )
        connect( media, SIGNAL( metaDataComputed( const Media* ) ),
                 this, SLOT( metaDataComputed( const Media* ) ) );
Thomas Boquet's avatar
Thomas Boquet committed
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 218 219 220 221 222 223 224
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 );
}

225 226
void
ImportController::treeViewClicked( const QModelIndex& index )
Thomas Boquet's avatar
Thomas Boquet committed
227 228 229 230
{
    if ( m_filesModel->isDir( index ) )
    {
        m_currentlyWatchedDir = m_filesModel->filePath( index );
231
        saveCurrentPath();
Thomas Boquet's avatar
Thomas Boquet committed
232 233 234 235
    }
    m_ui->forwardButton->setEnabled( true );
}

236 237
void
ImportController::treeViewDoubleClicked( const QModelIndex& index )
Thomas Boquet's avatar
Thomas Boquet committed
238
{
239 240
    if ( m_filesModel->isDir( index ) == false )
        forwardButtonClicked();
Thomas Boquet's avatar
Thomas Boquet committed
241
}
Geoffroy Lacarriere's avatar
Geoffroy Lacarriere committed
242

243 244
void
ImportController::reject()
245 246
{
    m_preview->stop();
247
    m_mediaListView->clear();
248
    m_temporaryMedias->clear();
249
    collapseAllButCurrentPath();
250
    m_clipRenderer->setClip( NULL );
251
    done( Rejected );
252 253
}

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

267 268 269 270 271 272 273 274 275 276 277 278
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 );
    }
279
    m_ui->forwardButton->setEnabled( true );
280 281
}

282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297
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();
}
298 299

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

}
317 318 319 320

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

void
ImportController::hideErrors()
{
    m_ui->errorLabelImg->hide();
    m_ui->errorLabel->hide();
}
336 337 338 339 340 341

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