mainwindow.cpp 29.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
/***************************************************************************
 *   Copyright (C) 2007 by Jean-Baptiste Mardelle (jb@kdenlive.org)        *
 *                                                                         *
 *   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          *
 ***************************************************************************/

Jean-Baptiste Mardelle's avatar
Jean-Baptiste Mardelle committed
20

21 22

#include <QTextStream>
23
#include <QTimer>
24
#include <QAction>
Marco Gittler's avatar
Marco Gittler committed
25 26
#include <QtTest>
#include <QtCore>
27

Jean-Baptiste Mardelle's avatar
Jean-Baptiste Mardelle committed
28 29 30 31 32 33 34 35 36 37 38
#include <KApplication>
#include <KAction>
#include <KLocale>
#include <KActionCollection>
#include <KStandardAction>
#include <KFileDialog>
#include <KMessageBox>
#include <KDebug>
#include <KIO/NetAccess>
#include <KSaveFile>
#include <KRuler>
39
#include <KConfigDialog>
40
#include <KXMLGUIFactory>
41
#include <KStatusBar>
42 43
#include <kstandarddirs.h>
#include <KUrlRequesterDialog>
44
#include <KTemporaryFile>
45
#include <ktogglefullscreenaction.h>
Jean-Baptiste Mardelle's avatar
Jean-Baptiste Mardelle committed
46 47 48 49

#include <mlt++/Mlt.h>

#include "mainwindow.h"
50
#include "kdenlivesettings.h"
51
#include "kdenlivesettingsdialog.h"
52
#include "initeffects.h"
53 54
#include "profilesdialog.h"
#include "projectsettings.h"
55
#include "events.h"
56
#include "renderjob.h"
57 58 59 60

#define ID_STATUS_MSG 1
#define ID_EDITMODE_MSG 2
#define ID_TIMELINE_MSG 3
61 62 63
#define ID_TIMELINE_BUTTONS 5
#define ID_TIMELINE_POS 6
#define ID_TIMELINE_FORMAT 7
64

Jean-Baptiste Mardelle's avatar
Jean-Baptiste Mardelle committed
65
MainWindow::MainWindow(QWidget *parent)
66
        : KXmlGuiWindow(parent),
67
        m_activeDocument(NULL), m_activeTimeline(NULL), m_renderWidget(NULL) {
68
    parseProfiles();
69 70

    m_commandStack = new QUndoGroup;
71 72 73
    m_timelineArea = new KTabWidget(this);
    m_timelineArea->setHoverCloseButton(true);
    m_timelineArea->setTabReorderingEnabled(true);
74
    m_timelineArea->setTabBarHidden(true);
75
    connect(m_timelineArea, SIGNAL(currentChanged(int)), this, SLOT(activateDocument()));
76 77
    connect(m_timelineArea, SIGNAL(closeRequest(QWidget *)), this, SLOT(closeDocument(QWidget *)));

78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124

    initEffects::parseEffectFiles(&m_audioEffects, &m_videoEffects);
    m_monitorManager = new MonitorManager();

    projectListDock = new QDockWidget(i18n("Project Tree"), this);
    projectListDock->setObjectName("project_tree");
    m_projectList = new ProjectList(this);
    projectListDock->setWidget(m_projectList);
    addDockWidget(Qt::TopDockWidgetArea, projectListDock);

    effectListDock = new QDockWidget(i18n("Effect List"), this);
    effectListDock->setObjectName("effect_list");
    m_effectList = new EffectsListView(&m_audioEffects, &m_videoEffects, &m_customEffects);

    //m_effectList = new KListWidget(this);
    effectListDock->setWidget(m_effectList);
    addDockWidget(Qt::TopDockWidgetArea, effectListDock);

    effectStackDock = new QDockWidget(i18n("Effect Stack"), this);
    effectStackDock->setObjectName("effect_stack");
    effectStack = new EffectStackView(&m_audioEffects, &m_videoEffects, &m_customEffects, this);
    effectStackDock->setWidget(effectStack);
    addDockWidget(Qt::TopDockWidgetArea, effectStackDock);

    transitionConfigDock = new QDockWidget(i18n("Transition"), this);
    transitionConfigDock->setObjectName("transition");
    transitionConfig = new KListWidget(this);
    transitionConfigDock->setWidget(transitionConfig);
    addDockWidget(Qt::TopDockWidgetArea, transitionConfigDock);


    clipMonitorDock = new QDockWidget(i18n("Clip Monitor"), this);
    clipMonitorDock->setObjectName("clip_monitor");
    m_clipMonitor = new Monitor("clip", m_monitorManager, this);
    clipMonitorDock->setWidget(m_clipMonitor);
    addDockWidget(Qt::TopDockWidgetArea, clipMonitorDock);
    //m_clipMonitor->stop();

    projectMonitorDock = new QDockWidget(i18n("Project Monitor"), this);
    projectMonitorDock->setObjectName("project_monitor");
    m_projectMonitor = new Monitor("project", m_monitorManager, this);
    projectMonitorDock->setWidget(m_projectMonitor);
    addDockWidget(Qt::TopDockWidgetArea, projectMonitorDock);

    undoViewDock = new QDockWidget(i18n("Undo History"), this);
    undoViewDock->setObjectName("undo_history");
    m_undoView = new QUndoView(this);
125 126
    m_undoView->setCleanIcon(KIcon("edit-clear"));
    m_undoView->setEmptyLabel(i18n("Clean"));
127
    undoViewDock->setWidget(m_undoView);
128
    m_undoView->setGroup(m_commandStack);
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
    addDockWidget(Qt::TopDockWidgetArea, undoViewDock);

    overviewDock = new QDockWidget(i18n("Project Overview"), this);
    overviewDock->setObjectName("project_overview");
    m_overView = new CustomTrackView(NULL, NULL, this);
    overviewDock->setWidget(m_overView);
    addDockWidget(Qt::TopDockWidgetArea, overviewDock);

    setupActions();
    tabifyDockWidget(projectListDock, effectListDock);
    tabifyDockWidget(projectListDock, effectStackDock);
    tabifyDockWidget(projectListDock, transitionConfigDock);
    tabifyDockWidget(projectListDock, undoViewDock);
    projectListDock->raise();

    tabifyDockWidget(clipMonitorDock, projectMonitorDock);
    setCentralWidget(m_timelineArea);

    m_timecodeFormat = new KComboBox(this);
    m_timecodeFormat->addItem(i18n("hh:mm:ss::ff"));
    m_timecodeFormat->addItem(i18n("Frames"));

    statusProgressBar = new QProgressBar(this);
    statusProgressBar->setMinimum(0);
    statusProgressBar->setMaximum(100);
    statusProgressBar->setMaximumWidth(150);
    statusProgressBar->setVisible(false);
    statusLabel = new QLabel(this);

158 159 160 161 162 163 164
    QWidget *w = new QWidget;
    timeline_buttons_ui.setupUi(w);
    timeline_buttons_ui.buttonVideo->setDown(KdenliveSettings::videothumbnails());
    timeline_buttons_ui.buttonAudio->setDown(KdenliveSettings::audiothumbnails());
    connect(timeline_buttons_ui.buttonVideo, SIGNAL(clicked()), this, SLOT(slotSwitchVideoThumbs()));
    connect(timeline_buttons_ui.buttonAudio, SIGNAL(clicked()), this, SLOT(slotSwitchAudioThumbs()));

165 166
    statusBar()->insertPermanentWidget(0, statusProgressBar, 1);
    statusBar()->insertPermanentWidget(1, statusLabel, 1);
167
    statusBar()->insertPermanentWidget(ID_TIMELINE_BUTTONS, w);
168 169
    statusBar()->insertPermanentFixedItem("00:00:00:00", ID_TIMELINE_POS);
    statusBar()->insertPermanentWidget(ID_TIMELINE_FORMAT, m_timecodeFormat);
170 171 172 173 174 175
    statusBar()->setMaximumHeight(statusBar()->font().pointSize() * 4);

    timeline_buttons_ui.buttonVideo->setIcon(KIcon("display-video"));
    timeline_buttons_ui.buttonVideo->setToolTip(i18n("Show video thumbnails"));
    timeline_buttons_ui.buttonAudio->setIcon(KIcon("display-audio"));
    timeline_buttons_ui.buttonAudio->setToolTip(i18n("Show audio thumbnails"));
176 177 178 179 180

    setupGUI(Default, "kdenliveui.rc");

    connect(projectMonitorDock, SIGNAL(visibilityChanged(bool)), m_projectMonitor, SLOT(refreshMonitor(bool)));
    connect(clipMonitorDock, SIGNAL(visibilityChanged(bool)), m_clipMonitor, SLOT(refreshMonitor(bool)));
181
    //connect(m_monitorManager, SIGNAL(connectMonitors()), this, SLOT(slotConnectMonitors()));
182 183 184
    connect(m_monitorManager, SIGNAL(raiseClipMonitor(bool)), this, SLOT(slotRaiseMonitor(bool)));
    connect(m_effectList, SIGNAL(addEffect(QDomElement)), this, SLOT(slotAddEffect(QDomElement)));
    m_monitorManager->initMonitors(m_clipMonitor, m_projectMonitor);
185
    slotConnectMonitors();
186 187 188

    setAutoSaveSettings();
    newFile();
189
}
Jean-Baptiste Mardelle's avatar
Jean-Baptiste Mardelle committed
190

191
//virtual
192 193 194 195 196 197 198 199 200 201 202
bool MainWindow::queryClose() {
    saveOptions();
    switch (KMessageBox::warningYesNoCancel(this, i18n("Save changes to document ?"))) {
    case KMessageBox::Yes :
        // save document here. If saving fails, return false;
        return true;
    case KMessageBox::No :
        return true;
    default: // cancel
        return false;
    }
203 204
}

205 206 207 208
void MainWindow::slotFullScreen() {
    KToggleFullScreenAction::setFullScreen(this, actionCollection()->action("fullscreen")->isChecked());
}

209 210 211 212 213 214 215 216
void MainWindow::slotAddEffect(QDomElement effect, GenTime pos, int track) {
    if (!m_activeDocument) return;
    if (effect.isNull()) {
        kDebug() << "--- ERROR, TRYING TO APPEND NULL EFFECT";
        return;
    }
    TrackView *currentTimeLine = (TrackView *) m_timelineArea->currentWidget();
    currentTimeLine->projectView()->slotAddEffect(effect, pos, track);
Jean-Baptiste Mardelle's avatar
Jean-Baptiste Mardelle committed
217 218
}

219 220 221
void MainWindow::slotRaiseMonitor(bool clipMonitor) {
    if (clipMonitor) clipMonitorDock->raise();
    else projectMonitorDock->raise();
Jean-Baptiste Mardelle's avatar
Jean-Baptiste Mardelle committed
222
}
223

224 225 226
void MainWindow::slotSetClipDuration(int id, int duration) {
    if (!m_activeDocument) return;
    m_activeDocument->setProducerDuration(id, duration);
227 228
}

229
void MainWindow::slotConnectMonitors() {
230

231 232 233 234 235 236
    m_projectList->setRenderer(m_clipMonitor->render);
    connect(m_projectList, SIGNAL(clipSelected(const QDomElement &)), m_clipMonitor, SLOT(slotSetXml(const QDomElement &)));
    connect(m_projectList, SIGNAL(receivedClipDuration(int, int)), this, SLOT(slotSetClipDuration(int, int)));
    connect(m_projectList, SIGNAL(getFileProperties(const QDomElement &, int)), m_clipMonitor->render, SLOT(getFileProperties(const QDomElement &, int)));
    connect(m_clipMonitor->render, SIGNAL(replyGetImage(int, int, const QPixmap &, int, int)), m_projectList, SLOT(slotReplyGetImage(int, int, const QPixmap &, int, int)));
    connect(m_clipMonitor->render, SIGNAL(replyGetFileProperties(int, const QMap < QString, QString > &, const QMap < QString, QString > &)), m_projectList, SLOT(slotReplyGetFileProperties(int, const QMap < QString, QString > &, const QMap < QString, QString > &)));
237 238
}

239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259
void MainWindow::setupActions() {
    KAction* clearAction = new KAction(this);
    clearAction->setText(i18n("Clear"));
    clearAction->setIcon(KIcon("document-new"));
    clearAction->setShortcut(Qt::CTRL + Qt::Key_W);
    actionCollection()->addAction("clear", clearAction);
    /*connect(clearAction, SIGNAL(triggered(bool)),
            textArea, SLOT(clear()));*/

    KAction* profilesAction = new KAction(this);
    profilesAction->setText(i18n("Manage Profiles"));
    profilesAction->setIcon(KIcon("document-new"));
    actionCollection()->addAction("manage_profiles", profilesAction);
    connect(profilesAction, SIGNAL(triggered(bool)), this, SLOT(slotEditProfiles()));

    KAction* projectAction = new KAction(this);
    projectAction->setText(i18n("Project Settings"));
    projectAction->setIcon(KIcon("document-new"));
    actionCollection()->addAction("project_settings", projectAction);
    connect(projectAction, SIGNAL(triggered(bool)), this, SLOT(slotEditProjectSettings()));

260 261 262 263 264 265
    KAction* projectRender = new KAction(this);
    projectRender->setText(i18n("Render Project"));
    projectRender->setIcon(KIcon("document-new"));
    actionCollection()->addAction("project_render", projectRender);
    connect(projectRender, SIGNAL(triggered(bool)), this, SLOT(slotRenderProject()));

266 267 268 269 270 271
    KAction* monitorPlay = new KAction(this);
    monitorPlay->setText(i18n("Play"));
    monitorPlay->setIcon(KIcon("media-playback-start"));
    monitorPlay->setShortcut(Qt::Key_Space);
    actionCollection()->addAction("monitor_play", monitorPlay);
    connect(monitorPlay, SIGNAL(triggered(bool)), m_monitorManager, SLOT(slotPlay()));
272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293

    KStandardAction::quit(kapp, SLOT(quit()),
                          actionCollection());

    KStandardAction::open(this, SLOT(openFile()),
                          actionCollection());

    m_fileOpenRecent = KStandardAction::openRecent(this, SLOT(openFile(const KUrl &)),
                       actionCollection());

    KStandardAction::save(this, SLOT(saveFile()),
                          actionCollection());

    KStandardAction::saveAs(this, SLOT(saveFileAs()),
                            actionCollection());

    KStandardAction::openNew(this, SLOT(newFile()),
                             actionCollection());

    KStandardAction::preferences(this, SLOT(slotPreferences()),
                                 actionCollection());

294
    KStandardAction::undo(this, SLOT(undo()),
295 296 297
                          actionCollection());

    KStandardAction::redo(this, SLOT(redo()),
298
                          actionCollection());
299

300 301 302
    KStandardAction::fullScreen(this, SLOT(slotFullScreen()), this, actionCollection());

    connect(actionCollection(), SIGNAL(actionHovered(QAction*)),
303 304
            this, SLOT(slotDisplayActionMessage(QAction*)));
    //connect(actionCollection(), SIGNAL( clearStatusText() ),
305 306
    //statusBar(), SLOT( clear() ) );

307
    readOptions();
308
}
309

310 311 312 313 314 315
void MainWindow::undo() {
    m_commandStack->undo();
}

void MainWindow::redo() {
    m_commandStack->redo();
Jean-Baptiste Mardelle's avatar
Jean-Baptiste Mardelle committed
316
}
317

318 319
void MainWindow::slotDisplayActionMessage(QAction *a) {
    statusBar()->showMessage(a->data().toString(), 3000);
320 321
}

322 323 324 325
void MainWindow::saveOptions() {
    KSharedConfigPtr config = KGlobal::config();
    m_fileOpenRecent->saveEntries(KConfigGroup(config, "Recent Files"));
    config->sync();
326 327
}

328 329 330
void MainWindow::readOptions() {
    KSharedConfigPtr config = KGlobal::config();
    m_fileOpenRecent->loadEntries(KConfigGroup(config, "Recent Files"));
331
}
332 333

void MainWindow::newFile() {
334 335 336 337 338 339 340 341 342
    QString profileName;
    if (m_timelineArea->count() == 0) profileName = KdenliveSettings::default_profile();
    else {
        ProjectSettings *w = new ProjectSettings;
        w->exec();
        profileName = w->selectedProfile();
        delete w;
    }
    MltVideoProfile prof = ProfilesDialog::getVideoProfile(profileName);
343
    if (prof.width == 0) prof = ProfilesDialog::getVideoProfile("dv_pal");
344
    KdenliveDoc *doc = new KdenliveDoc(KUrl(), prof, m_commandStack);
345
    TrackView *trackView = new TrackView(doc);
346
    m_timelineArea->addTab(trackView, KIcon("kdenlive"), i18n("Untitled") + " / " + prof.description);
347 348
    if (m_timelineArea->count() == 1)
        connectDocument(trackView, doc);
349
    else m_timelineArea->setTabBarHidden(false);
Jean-Baptiste Mardelle's avatar
Jean-Baptiste Mardelle committed
350 351
}

352 353 354 355
void MainWindow::activateDocument() {
    TrackView *currentTab = (TrackView *) m_timelineArea->currentWidget();
    KdenliveDoc *currentDoc = currentTab->document();
    connectDocument(currentTab, currentDoc);
Jean-Baptiste Mardelle's avatar
Jean-Baptiste Mardelle committed
356
}
357

358 359 360 361 362 363 364 365 366 367 368 369 370 371 372
void MainWindow::closeDocument(QWidget *w) {
    if (w == m_timelineArea->currentWidget()) {
        // closing current document
        int ix = m_timelineArea->currentIndex() + 1;
        if (ix == m_timelineArea->count()) ix = 0;
        m_timelineArea->setCurrentIndex(ix);
    }

    TrackView *tabToClose = (TrackView *) w;
    KdenliveDoc *docToClose = tabToClose->document();
    m_timelineArea->removeTab(m_timelineArea->indexOf(w));
    delete docToClose;
    delete w;
}

373
void MainWindow::saveFileAs(const QString &outputFileName) {
374 375 376 377 378
    m_projectMonitor->saveSceneList(outputFileName, m_activeDocument->documentInfoXml());
    m_activeDocument->setUrl(KUrl(outputFileName));
    setCaption(m_activeDocument->description());
    m_timelineArea->setTabText(m_timelineArea->currentIndex(), m_activeDocument->description());
    m_timelineArea->setTabToolTip(m_timelineArea->currentIndex(), m_activeDocument->url().path());
379
    m_activeDocument->setModified(false);
Jean-Baptiste Mardelle's avatar
Jean-Baptiste Mardelle committed
380
}
381

382
void MainWindow::saveFileAs() {
383 384 385 386 387
    QString outputFile = KFileDialog::getSaveFileName();
    if (QFile::exists(outputFile)) {
        if (KMessageBox::questionYesNo(this, i18n("File already exists.\nDo you want to overwrite it ?")) == KMessageBox::No) return;
    }
    saveFileAs(outputFile);
Jean-Baptiste Mardelle's avatar
Jean-Baptiste Mardelle committed
388
}
389 390

void MainWindow::saveFile() {
391 392
    if (!m_activeDocument) return;
    if (m_activeDocument->url().isEmpty()) {
393
        saveFileAs();
394 395
    } else {
        saveFileAs(m_activeDocument->url().path());
396
    }
Jean-Baptiste Mardelle's avatar
Jean-Baptiste Mardelle committed
397
}
398 399

void MainWindow::openFile() { //changed
400 401
    KUrl url = KFileDialog::getOpenUrl(KUrl(), "application/vnd.kde.kdenlive;*.kdenlive");
    if (url.isEmpty()) return;
402
    m_fileOpenRecent->addUrl(url);
403
    openFile(url);
Jean-Baptiste Mardelle's avatar
Jean-Baptiste Mardelle committed
404
}
405 406

void MainWindow::openFile(const KUrl &url) { //new
407 408 409
    //TODO: get video profile from url before opening it
    MltVideoProfile prof = ProfilesDialog::getVideoProfile(KdenliveSettings::default_profile());
    if (prof.width == 0) prof = ProfilesDialog::getVideoProfile("dv_pal");
410
    KdenliveDoc *doc = new KdenliveDoc(url, prof, m_commandStack);
411
    TrackView *trackView = new TrackView(doc);
412
    m_timelineArea->setCurrentIndex(m_timelineArea->addTab(trackView, KIcon("kdenlive"), doc->description()));
413
    m_timelineArea->setTabToolTip(m_timelineArea->currentIndex(), doc->url().path());
414
    if (m_timelineArea->count() > 1) m_timelineArea->setTabBarHidden(false);
415
    //connectDocument(trackView, doc);
Jean-Baptiste Mardelle's avatar
Jean-Baptiste Mardelle committed
416 417
}

418

419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450
void MainWindow::parseProfiles() {
    //kdDebug()<<" + + YOUR MLT INSTALL WAS FOUND IN: "<< MLT_PREFIX <<endl;
    if (KdenliveSettings::mltpath().isEmpty()) {
        KdenliveSettings::setMltpath(QString(MLT_PREFIX) + QString("/share/mlt/profiles/"));
    }
    if (KdenliveSettings::rendererpath().isEmpty()) {
        KdenliveSettings::setRendererpath(KStandardDirs::findExe("inigo"));
    }
    QStringList profilesFilter;
    profilesFilter << "*";
    QStringList profilesList = QDir(KdenliveSettings::mltpath()).entryList(profilesFilter, QDir::Files);

    if (profilesList.isEmpty()) {
        // Cannot find MLT path, try finding inigo
        QString profilePath = KdenliveSettings::rendererpath();
        if (!profilePath.isEmpty()) {
            profilePath = profilePath.section('/', 0, -3);
            KdenliveSettings::setMltpath(profilePath + "/share/mlt/profiles/");
            QStringList profilesList = QDir(KdenliveSettings::mltpath()).entryList(profilesFilter, QDir::Files);
        }

        if (profilesList.isEmpty()) {
            // Cannot find the MLT profiles, ask for location
            KUrlRequesterDialog *getUrl = new KUrlRequesterDialog(KdenliveSettings::mltpath(), i18n("Cannot find your Mlt profiles, please give the path"), this);
            getUrl->fileDialog()->setMode(KFile::Directory);
            getUrl->exec();
            KUrl mltPath = getUrl->selectedUrl();
            delete getUrl;
            if (mltPath.isEmpty()) exit(1);
            KdenliveSettings::setMltpath(mltPath.path());
            QStringList profilesList = QDir(KdenliveSettings::mltpath()).entryList(profilesFilter, QDir::Files);
        }
451 452
    }

453 454 455 456 457 458 459 460 461 462 463
    if (KdenliveSettings::rendererpath().isEmpty()) {
        // Cannot find the MLT inigo renderer, ask for location
        KUrlRequesterDialog *getUrl = new KUrlRequesterDialog(KdenliveSettings::mltpath(), i18n("Cannot find the inigo program required for rendering (part of Mlt)"), this);
        getUrl->exec();
        KUrl rendererPath = getUrl->selectedUrl();
        delete getUrl;
        if (rendererPath.isEmpty()) exit(1);
        KdenliveSettings::setRendererpath(rendererPath.path());
    }

    kDebug() << "RESULTING MLT PATH: " << KdenliveSettings::mltpath();
464

465 466
    // Parse MLT profiles to build a list of available video formats
    if (profilesList.isEmpty()) parseProfiles();
467 468
}

469 470 471 472 473

void MainWindow::slotEditProfiles() {
    ProfilesDialog *w = new ProfilesDialog;
    w->exec();
    delete w;
474 475
}

476 477
void MainWindow::slotEditProjectSettings() {
    ProjectSettings *w = new ProjectSettings;
478 479 480 481 482 483 484 485 486 487 488 489 490
    if (w->exec() == QDialog::Accepted) {
        QString profile = w->selectedProfile();
        m_activeDocument->setProfilePath(profile);
        m_monitorManager->resetProfiles(profile);
        setCaption(m_activeDocument->description());
        KdenliveSettings::setCurrent_profile(m_activeDocument->profilePath());
        if (m_renderWidget) m_renderWidget->setDocumentStandard(m_activeDocument->getDocumentStandard());
        m_monitorManager->setTimecode(m_activeDocument->timecode());
        m_timelineArea->setTabText(m_timelineArea->currentIndex(), m_activeDocument->description());

        // We need to desactivate & reactivate monitors to get a refresh
        m_monitorManager->switchMonitors();
    }
491 492
    delete w;
}
493

494
void MainWindow::slotRenderProject() {
Jean-Baptiste Mardelle's avatar
Jean-Baptiste Mardelle committed
495 496
    if (!m_renderWidget) {
        m_renderWidget = new RenderWidget(this);
497
        connect(m_renderWidget, SIGNAL(doRender(const QString&, const QString&, const QStringList &, bool, bool)), this, SLOT(slotDoRender(const QString&, const QString&, const QStringList &, bool, bool)));
Jean-Baptiste Mardelle's avatar
Jean-Baptiste Mardelle committed
498 499 500 501 502 503 504
    }
    /*TrackView *currentTab = (TrackView *) m_timelineArea->currentWidget();
    if (currentTab) m_renderWidget->setTimeline(currentTab);
    m_renderWidget->setDocument(m_activeDocument);*/
    m_renderWidget->show();
}

505
void MainWindow::slotDoRender(const QString &dest, const QString &render, const QStringList &avformat_args, bool zoneOnly, bool playAfter) {
Jean-Baptiste Mardelle's avatar
Jean-Baptiste Mardelle committed
506
    if (dest.isEmpty()) return;
Jean-Baptiste Mardelle's avatar
Jean-Baptiste Mardelle committed
507 508 509
    int in;
    int out;
    TrackView *currentTab = (TrackView *) m_timelineArea->currentWidget();
Jean-Baptiste Mardelle's avatar
Jean-Baptiste Mardelle committed
510
    if (currentTab && zoneOnly) {
Jean-Baptiste Mardelle's avatar
Jean-Baptiste Mardelle committed
511 512 513
        in = currentTab->inPoint();
        out = currentTab->outPoint();
    }
514
    KTemporaryFile temp;
515
    temp.setAutoRemove(false);
516 517 518
    temp.setSuffix(".westley");
    if (temp.open()) {
        m_projectMonitor->saveSceneList(temp.fileName());
519
        QStringList args;
520
        args << "-erase";
Jean-Baptiste Mardelle's avatar
Jean-Baptiste Mardelle committed
521 522 523
        if (zoneOnly) args << "in=" + QString::number(in) << "out=" + QString::number(out);
        QString videoPlayer = "-";
        if (playAfter) videoPlayer = "kmplayer";
524
        args << "inigo" << render << videoPlayer << temp.fileName() << dest << avformat_args;
525
        QProcess::startDetached("kdenlive_render", args);
526 527
    }
}
528 529 530 531 532 533 534 535 536 537

void MainWindow::slotUpdateMousePosition(int pos) {
    if (m_activeDocument)
        switch (m_timecodeFormat->currentIndex()) {
        case 0:
            statusBar()->changeItem(m_activeDocument->timecode().getTimecodeFromFrames(pos), ID_TIMELINE_POS);
            break;
        default:
            statusBar()->changeItem(QString::number(pos), ID_TIMELINE_POS);
        }
538 539
}

540 541 542 543 544 545 546 547 548 549
void MainWindow::slotUpdateDocumentState(bool modified) {
    if (modified) {
        m_timelineArea->setTabTextColor(m_timelineArea->currentIndex(), palette().color(QPalette::Link));
        m_timelineArea->setTabIcon(m_timelineArea->currentIndex(), KIcon("document-save"));
    } else {
        m_timelineArea->setTabTextColor(m_timelineArea->currentIndex(), palette().color(QPalette::Text));
        m_timelineArea->setTabIcon(m_timelineArea->currentIndex(), KIcon("kdenlive"));
    }
}

550 551 552 553 554
void MainWindow::connectDocument(TrackView *trackView, KdenliveDoc *doc) { //changed
    //m_projectMonitor->stop();
    kDebug() << "///////////////////   CONNECTING DOC TO PROJECT VIEW ////////////////";
    if (m_activeDocument) {
        if (m_activeDocument == doc) return;
555 556 557 558 559 560 561 562 563 564
        m_activeDocument->backupMltPlaylist();
        if (m_activeTimeline) {
            disconnect(m_projectMonitor, SIGNAL(renderPosition(int)), m_activeTimeline, SLOT(moveCursorPos(int)));
            disconnect(m_projectMonitor, SIGNAL(durationChanged(int)), m_activeTimeline->projectView(), SLOT(setDuration(int)));
            disconnect(m_activeDocument, SIGNAL(addProjectClip(DocClipBase *)), m_projectList, SLOT(slotAddClip(DocClipBase *)));
            disconnect(m_activeDocument, SIGNAL(signalDeleteProjectClip(int)), m_projectList, SLOT(slotDeleteClip(int)));
            disconnect(m_activeDocument, SIGNAL(updateClipDisplay(int)), m_projectList, SLOT(slotUpdateClip(int)));
            disconnect(m_activeDocument, SIGNAL(deletTimelineClip(int)), m_activeTimeline, SLOT(slotDeleteClip(int)));
            disconnect(m_activeDocument, SIGNAL(thumbsProgress(KUrl, int)), this, SLOT(slotGotProgressInfo(KUrl, int)));
            disconnect(m_activeTimeline, SIGNAL(clipItemSelected(ClipItem*)), effectStack, SLOT(slotClipItemSelected(ClipItem*)));
565
            disconnect(m_activeDocument, SIGNAL(docModified(bool)), this, SLOT(slotUpdateDocumentState(bool)));
566 567 568 569
            disconnect(effectStack, SIGNAL(updateClipEffect(ClipItem*, QDomElement, QDomElement)), m_activeTimeline->projectView(), SLOT(slotUpdateClipEffect(ClipItem*, QDomElement, QDomElement)));
            disconnect(effectStack, SIGNAL(removeEffect(ClipItem*, QDomElement)), m_activeTimeline->projectView(), SLOT(slotDeleteEffect(ClipItem*, QDomElement)));
            disconnect(effectStack, SIGNAL(changeEffectState(ClipItem*, QDomElement, bool)), m_activeTimeline->projectView(), SLOT(slotChangeEffectState(ClipItem*, QDomElement, bool)));
            disconnect(effectStack, SIGNAL(refreshEffectStack(ClipItem*)), m_activeTimeline->projectView(), SLOT(slotRefreshEffects(ClipItem*)));
570
            disconnect(m_activeTimeline->projectView(), SIGNAL(activateDocumentMonitor()), m_projectMonitor, SLOT(activateMonitor()));
571
        }
572
        m_activeDocument->setRenderer(NULL);
573 574
        disconnect(m_projectList, SIGNAL(clipSelected(const QDomElement &)), m_clipMonitor, SLOT(slotSetXml(const QDomElement &)));
        m_clipMonitor->stop();
575
    }
576 577
    m_monitorManager->resetProfiles(doc->profilePath());
    m_projectList->setDocument(doc);
578
    connect(m_projectList, SIGNAL(clipSelected(const QDomElement &)), m_clipMonitor, SLOT(slotSetXml(const QDomElement &)));
579 580 581 582 583 584 585 586 587
    connect(trackView, SIGNAL(cursorMoved()), m_projectMonitor, SLOT(activateMonitor()));
    connect(trackView, SIGNAL(mousePosition(int)), this, SLOT(slotUpdateMousePosition(int)));
    connect(m_projectMonitor, SIGNAL(renderPosition(int)), trackView, SLOT(moveCursorPos(int)));
    connect(m_projectMonitor, SIGNAL(durationChanged(int)), trackView->projectView(), SLOT(setDuration(int)));
    connect(doc, SIGNAL(addProjectClip(DocClipBase *)), m_projectList, SLOT(slotAddClip(DocClipBase *)));
    connect(doc, SIGNAL(signalDeleteProjectClip(int)), m_projectList, SLOT(slotDeleteClip(int)));
    connect(doc, SIGNAL(updateClipDisplay(int)), m_projectList, SLOT(slotUpdateClip(int)));
    connect(doc, SIGNAL(deletTimelineClip(int)), trackView, SLOT(slotDeleteClip(int)));
    connect(doc, SIGNAL(thumbsProgress(KUrl, int)), this, SLOT(slotGotProgressInfo(KUrl, int)));
588
    connect(doc, SIGNAL(docModified(bool)), this, SLOT(slotUpdateDocumentState(bool)));
589 590 591 592 593 594

    connect(trackView, SIGNAL(clipItemSelected(ClipItem*)), effectStack, SLOT(slotClipItemSelected(ClipItem*)));
    connect(effectStack, SIGNAL(updateClipEffect(ClipItem*, QDomElement, QDomElement)), trackView->projectView(), SLOT(slotUpdateClipEffect(ClipItem*, QDomElement, QDomElement)));
    connect(effectStack, SIGNAL(removeEffect(ClipItem*, QDomElement)), trackView->projectView(), SLOT(slotDeleteEffect(ClipItem*, QDomElement)));
    connect(effectStack, SIGNAL(changeEffectState(ClipItem*, QDomElement, bool)), trackView->projectView(), SLOT(slotChangeEffectState(ClipItem*, QDomElement, bool)));
    connect(effectStack, SIGNAL(refreshEffectStack(ClipItem*)), trackView->projectView(), SLOT(slotRefreshEffects(ClipItem*)));
595 596 597
    connect(trackView->projectView(), SIGNAL(activateDocumentMonitor()), m_projectMonitor, SLOT(activateMonitor()));


598
    m_activeTimeline = trackView;
599
    KdenliveSettings::setCurrent_profile(doc->profilePath());
600
    if (m_renderWidget) m_renderWidget->setDocumentStandard(doc->getDocumentStandard());
601 602
    m_monitorManager->setTimecode(doc->timecode());
    doc->setRenderer(m_projectMonitor->render);
603
    m_commandStack->setActiveStack(doc->commandStack());
604 605 606 607

    m_overView->setScene(trackView->projectScene());
    m_overView->scale(m_overView->width() / trackView->duration(), m_overView->height() / (50 * trackView->tracksNumber()));
    //m_overView->fitInView(m_overView->itemAt(0, 50), Qt::KeepAspectRatio);
608

609
    setCaption(doc->description());
610
    m_activeDocument = doc;
Jean-Baptiste Mardelle's avatar
Jean-Baptiste Mardelle committed
611 612
}

613 614 615 616 617 618 619 620 621 622
void MainWindow::slotPreferences() {
    //An instance of your dialog could be already created and could be
    // cached, in which case you want to display the cached dialog
    // instead of creating another one
    if (KConfigDialog::showDialog("settings"))
        return;

    // KConfigDialog didn't find an instance of this dialog, so lets
    // create it :
    KdenliveSettingsDialog* dialog = new KdenliveSettingsDialog(this);
623
    connect(dialog, SIGNAL(settingsChanged(const QString&)), this, SLOT(updateConfiguration()));
624
    dialog->show();
625
}
626

627
void MainWindow::updateConfiguration() {
628
    //TODO: we should apply settings to all projects, not only the current one
629
    TrackView *currentTab = (TrackView *) m_timelineArea->currentWidget();
630 631 632
    if (currentTab) {
        currentTab->refresh();
        currentTab->projectView()->checkAutoScroll();
633
        if (m_activeDocument) m_activeDocument->clipManager()->checkAudioThumbs();
634
    }
635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656
    timeline_buttons_ui.buttonAudio->setDown(KdenliveSettings::audiothumbnails());
    timeline_buttons_ui.buttonVideo->setDown(KdenliveSettings::videothumbnails());
}

void MainWindow::slotSwitchVideoThumbs() {
    KdenliveSettings::setVideothumbnails(!KdenliveSettings::videothumbnails());
    TrackView *currentTab = (TrackView *) m_timelineArea->currentWidget();
    if (currentTab) {
        currentTab->refresh();
    }
    timeline_buttons_ui.buttonVideo->setDown(KdenliveSettings::videothumbnails());
}

void MainWindow::slotSwitchAudioThumbs() {
    KdenliveSettings::setAudiothumbnails(!KdenliveSettings::audiothumbnails());
    TrackView *currentTab = (TrackView *) m_timelineArea->currentWidget();
    if (currentTab) {
        currentTab->refresh();
        currentTab->projectView()->checkAutoScroll();
        if (m_activeDocument) m_activeDocument->clipManager()->checkAudioThumbs();
    }
    timeline_buttons_ui.buttonAudio->setDown(KdenliveSettings::audiothumbnails());
657 658
}

659 660 661 662 663 664 665 666 667
void MainWindow::slotGotProgressInfo(KUrl url, int progress) {
    statusProgressBar->setValue(progress);
    if (progress > 0) {
        statusLabel->setText(tr("Creating Audio Thumbs"));
        statusProgressBar->setVisible(true);
    } else {
        statusLabel->setText("");
        statusProgressBar->setVisible(false);
    }
668
}
669

Jean-Baptiste Mardelle's avatar
Jean-Baptiste Mardelle committed
670
#include "mainwindow.moc"