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

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
    m_nameFilters << Media::AudioExtensions.split(' ', QString::SkipEmptyParts)
62 63 64
            << Media::VideoExtensions.split(' ', QString::SkipEmptyParts)
            << Media::ImageExtensions.split(' ', QString::SkipEmptyParts);
    m_filesModel->setFilter( QDir::AllDirs | QDir::AllEntries | QDir::NoDotAndDotDot );
65
    m_filesModel->setNameFilters( m_nameFilters );
66
    m_filesModel->setRootPath( "/" );
67
    m_filesModel->setNameFilterDisables( false );
68 69 70

    restoreCurrentPath();

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

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 QUuid& ) ),
             m_clipRenderer, SLOT( clipUnloaded( const QUuid& ) ) );
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
    setUIMetaData( clip->rootClip() );
136 137
    m_preview->stop();
    m_currentUuid = uuid;
Hugo Beauzee-Luyssen's avatar
Hugo Beauzee-Luyssen committed
138 139
    m_tag->clipSelected( clip );
    emit clipSelected( clip );
Geoffroy Lacarriere's avatar
Geoffroy Lacarriere committed
140 141
}

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

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

177
    Media*  media = m_temporaryMedias->addMedia( filePath );
178 179 180 181 182
    if ( media == NULL )
    {
        qCritical() << "An error occured while loading media:" << filePath;
        return ;
    }
183 184 185
    Clip*   clip = new Clip( media );
    media->setBaseClip( clip );
    m_temporaryMedias->addClip( clip );
186 187 188 189
    ++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
190 191
}

192 193 194 195
void
ImportController::importDir( const QString &path )
{
    QDir            dir( path );
196
    QFileInfoList   files = dir.entryInfoList( m_nameFilters, QDir::NoDotAndDotDot | QDir::Readable
197 198 199 200 201
                                               | QDir::AllEntries );

    foreach ( QFileInfo fInfo, files )
    {
        if ( fInfo.isDir() == true )
202
            importDir( fInfo.absoluteFilePath() );
203
        else
204
            importMedia( fInfo.absoluteFilePath() );
205 206 207 208 209 210 211 212 213 214 215 216 217 218 219
    }
}

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

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

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

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

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

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

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

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

}
312 313 314 315

void
ImportController::failedToLoad( Media *media )
{
316
    m_ui->errorLabel->setText( tr( "Failed to load %1").arg(
317
            media->fileInfo()->fileName() ) );
318 319 320
    m_ui->errorLabelImg->show();
    m_ui->errorLabel->show();
    QTimer::singleShot( 3000, this, SLOT( hideErrors() ) );
321
    m_temporaryMedias->deleteClip( media->baseClip()->uuid() );
322
}
323 324 325 326 327 328 329

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

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