ImportController.cpp 10.3 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 96
    connect( m_mediaListView, SIGNAL( clipRemoved( const Clip* ) ),
             m_clipRenderer, SLOT( clipUnloaded( const Clip* ) ) );
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 );
    Clip*   clip = new Clip( media );
    media->setBaseClip( clip );
    m_temporaryMedias->addClip( clip );
178 179 180
    if ( media )
        connect( media, SIGNAL( metaDataComputed( const Media* ) ),
                 this, SLOT( metaDataComputed( const Media* ) ) );
Thomas Boquet's avatar
Thomas Boquet committed
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 218 219
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 );
}

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() ) );
Hugo Beauzee-Luyssen's avatar
Hugo Beauzee-Luyssen committed
321 322
    delete m_temporaryMedias->removeClip( media->baseClip() );
    delete media;
323
}
324 325 326 327 328 329 330

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

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