You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
k3b/src/k3bprojectmanager.cpp

654 lines
18 KiB

/*
*
* $Id$
* Copyright (C) 2003 Sebastian Trueg <trueg@k3b.org>
*
* This file is part of the K3b project.
* Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.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.
* See the file "COPYING" for the exact licensing terms.
*/
#include "k3bprojectmanager.h"
#include "k3bprojectinterface.h"
#include "k3bdataprojectinterface.h"
#include "k3baudioprojectinterface.h"
#include "k3bmixedprojectinterface.h"
#include "kostore/koStore.h"
#include "kostore/koStoreDevice.h"
#include "k3bapplication.h"
#include "k3binteractiondialog.h"
#include <k3baudiodoc.h>
#include <k3baudiodatasourceiterator.h>
#include <k3baudiocdtracksource.h>
#include <k3bdatadoc.h>
#include <k3bdvddoc.h>
#include <k3bvideodvddoc.h>
#include <k3bmixeddoc.h>
#include <k3bvcddoc.h>
#include <k3bmovixdoc.h>
#include <k3bmovixdvddoc.h>
#include <k3bglobals.h>
#include <k3bisooptions.h>
#include <k3bdevicemanager.h>
#include <tqptrlist.h>
#include <tqmap.h>
#include <tqtextstream.h>
#include <tqdom.h>
#include <tqfile.h>
#include <tqapplication.h>
#include <tqcursor.h>
#include <kurl.h>
#include <kdebug.h>
#include <kconfig.h>
#include <kio/netaccess.h>
#include <klocale.h>
#include <kmessagebox.h>
class K3bProjectManager::Private
{
public:
TQPtrList<K3bDoc> projects;
K3bDoc* activeProject;
TQMap<K3bDoc*, K3bProjectInterface*> projectInterfaceMap;
int audioUntitledCount;
int dataUntitledCount;
int mixedUntitledCount;
int vcdUntitledCount;
int movixUntitledCount;
int movixDvdUntitledCount;
int dvdUntitledCount;
int videoDvdUntitledCount;
};
K3bProjectManager::K3bProjectManager( TQObject* parent, const char* name )
: TQObject( parent, name )
{
d = new Private();
d->activeProject = 0;
d->audioUntitledCount = 0;
d->dataUntitledCount = 0;
d->mixedUntitledCount = 0;
d->vcdUntitledCount = 0;
d->movixUntitledCount = 0;
d->movixDvdUntitledCount = 0;
d->dvdUntitledCount = 0;
d->videoDvdUntitledCount = 0;
}
K3bProjectManager::~K3bProjectManager()
{
delete d;
}
const TQPtrList<K3bDoc>& K3bProjectManager::projects() const
{
return d->projects;
}
void K3bProjectManager::addProject( K3bDoc* doc )
{
if( !d->projects.containsRef( doc ) ) {
kdDebug() << "(K3bProjectManager) adding doc " << doc->URL().path() << endl;
d->projects.append(doc);
connect( doc, TQT_SIGNAL(changed(K3bDoc*)),
this, TQT_SLOT(slotProjectChanged(K3bDoc*)) );
emit newProject( doc );
}
}
void K3bProjectManager::removeProject( K3bDoc* doc )
{
//
// TQPtrList.findRef seems to be buggy. Everytime we search for the
// first added item it is not found!
//
for( TQPtrListIterator<K3bDoc> it( d->projects );
it.current(); ++it ) {
if( it.current() == doc ) {
// remove the DCOP interface
TQMap<K3bDoc*, K3bProjectInterface*>::iterator it = d->projectInterfaceMap.find( doc );
if( it != d->projectInterfaceMap.end() ) {
// delete the interface
delete it.data();
d->projectInterfaceMap.remove( it );
}
d->projects.removeRef(doc);
emit closingProject(doc);
return;
}
}
kdDebug() << "(K3bProjectManager) unable to find doc: " << doc->URL().path() << endl;
}
K3bDoc* K3bProjectManager::findByUrl( const KURL& url )
{
for( TQPtrListIterator<K3bDoc> it( d->projects );
it.current(); ++it ) {
K3bDoc* doc = it.current();
if( doc->URL() == url )
return doc;
}
return 0;
}
bool K3bProjectManager::isEmpty() const
{
return d->projects.isEmpty();
}
void K3bProjectManager::setActive( K3bDoc* doc )
{
if( !doc ) {
d->activeProject = 0L;
emit activeProjectChanged( 0L );
return;
}
//
// TQPtrList.findRef seems to be buggy. Everytime we search for the
// first added item it is not found!
//
for( TQPtrListIterator<K3bDoc> it( d->projects );
it.current(); ++it ) {
if( it.current() == doc ) {
d->activeProject = doc;
emit activeProjectChanged(doc);
}
}
}
K3bDoc* K3bProjectManager::activeProject() const
{
return d->activeProject;
}
K3bDoc* K3bProjectManager::createEmptyProject( K3bDoc::DocType type )
{
K3bDoc* doc = 0;
TQString fileName;
switch( type ) {
case K3bDoc::AUDIO: {
doc = new K3bAudioDoc( this );
fileName = i18n("AudioCD%1").arg(d->audioUntitledCount++);
break;
}
case K3bDoc::DATA: {
doc = new K3bDataDoc( this );
fileName = i18n("DataCD%1").arg(d->dataUntitledCount++);
break;
}
case K3bDoc::MIXED: {
doc = new K3bMixedDoc( this );
fileName=i18n("MixedCD%1").arg(d->mixedUntitledCount++);
break;
}
case K3bDoc::VCD: {
doc = new K3bVcdDoc( this );
fileName=i18n("VideoCD%1").arg(d->vcdUntitledCount++);
break;
}
case K3bDoc::MOVIX: {
doc = new K3bMovixDoc( this );
fileName=i18n("eMovixCD%1").arg(d->movixUntitledCount++);
break;
}
case K3bDoc::MOVIX_DVD: {
doc = new K3bMovixDvdDoc( this );
fileName=i18n("eMovixDVD%1").arg(d->movixDvdUntitledCount++);
break;
}
case K3bDoc::DVD: {
doc = new K3bDvdDoc( this );
fileName = i18n("DataDVD%1").arg(d->dvdUntitledCount++);
break;
}
case K3bDoc::VIDEODVD: {
doc = new K3bVideoDvdDoc( this );
fileName = i18n("VideoDVD%1").arg(d->videoDvdUntitledCount++);
break;
}
}
KURL url;
url.setFileName(fileName);
doc->setURL(url);
doc->newDocument();
loadDefaults( doc );
return doc;
}
K3bDoc* K3bProjectManager::createProject( K3bDoc::DocType type )
{
K3bDoc* doc = createEmptyProject( type );
// create the dcop interface
dcopInterface( doc );
addProject( doc );
return doc;
}
void K3bProjectManager::loadDefaults( K3bDoc* doc )
{
TDEConfig* c = kapp->config();
TQString oldGroup = c->group();
TQString cg = "default " + doc->typeString() + " settings";
// earlier K3b versions loaded the saved settings
// so that is what we do as a default
int i = TDEConfigGroup( c, "General Options" ).readNumEntry( "action dialog startup settings",
K3bInteractionDialog::LOAD_SAVED_SETTINGS );
if( i == K3bInteractionDialog::LOAD_K3B_DEFAULTS )
return; // the default k3b settings are the ones everyone starts with
else if( i == K3bInteractionDialog::LOAD_LAST_SETTINGS )
cg = "last used " + cg;
c->setGroup( cg );
TQString mode = c->readEntry( "writing_mode" );
if ( mode == "dao" )
doc->setWritingMode( K3b::DAO );
else if( mode == "tao" )
doc->setWritingMode( K3b::TAO );
else if( mode == "raw" )
doc->setWritingMode( K3b::RAW );
else
doc->setWritingMode( K3b::WRITING_MODE_AUTO );
doc->setDummy( c->readBoolEntry( "simulate", false ) );
doc->setOnTheFly( c->readBoolEntry( "on_the_fly", true ) );
doc->setRemoveImages( c->readBoolEntry( "remove_image", true ) );
doc->setOnlyCreateImages( c->readBoolEntry( "only_create_image", false ) );
doc->setBurner( k3bcore->deviceManager()->findDevice( c->readEntry( "writer_device" ) ) );
// Default = 0 (Auto)
doc->setSpeed( c->readNumEntry( "writing_speed", 0 ) );
doc->setWritingApp( K3b::writingAppFromString( c->readEntry( "writing_app" ) ) );
switch( doc->type() ) {
case K3bDoc::AUDIO: {
K3bAudioDoc* audioDoc = static_cast<K3bAudioDoc*>(doc);
audioDoc->writeCdText( c->readBoolEntry( "cd_text", true ) );
audioDoc->setHideFirstTrack( c->readBoolEntry( "hide_first_track", false ) );
audioDoc->setNormalize( c->readBoolEntry( "normalize", false ) );
audioDoc->setAudioRippingParanoiaMode( c->readNumEntry( "paranoia mode", 0 ) );
audioDoc->setAudioRippingRetries( c->readNumEntry( "read retries", 128 ) );
audioDoc->setAudioRippingIgnoreReadErrors( c->readBoolEntry( "ignore read errors", false ) );
break;
}
case K3bDoc::MOVIX:
case K3bDoc::MOVIX_DVD: {
K3bMovixDoc* movixDoc = static_cast<K3bMovixDoc*>(doc);
movixDoc->setSubtitleFontset( c->readEntry("subtitle_fontset") );
movixDoc->setLoopPlaylist( c->readNumEntry("loop", 1 ) );
movixDoc->setAdditionalMPlayerOptions( c->readEntry( "additional_mplayer_options" ) );
movixDoc->setUnwantedMPlayerOptions( c->readEntry( "unwanted_mplayer_options" ) );
movixDoc->setBootMessageLanguage( c->readEntry("boot_message_language") );
movixDoc->setDefaultBootLabel( c->readEntry( "default_boot_label" ) );
movixDoc->setShutdown( c->readBoolEntry( "shutdown", false) );
movixDoc->setReboot( c->readBoolEntry( "reboot", false ) );
movixDoc->setEjectDisk( c->readBoolEntry( "eject", false ) );
movixDoc->setRandomPlay( c->readBoolEntry( "random_play", false ) );
movixDoc->setNoDma( c->readBoolEntry( "no_dma", false ) );
// fallthrough
}
case K3bDoc::DATA:
case K3bDoc::DVD: {
K3bDataDoc* dataDoc = static_cast<K3bDataDoc*>(doc);
dataDoc->setIsoOptions( K3bIsoOptions::load( c, false ) );
TQString datamode = c->readEntry( "data_track_mode" );
if( datamode == "mode1" )
dataDoc->setDataMode( K3b::MODE1 );
else if( datamode == "mode2" )
dataDoc->setDataMode( K3b::MODE2 );
else
dataDoc->setDataMode( K3b::DATA_MODE_AUTO );
dataDoc->setVerifyData( c->readBoolEntry( "verify data", false ) );
TQString s = c->readEntry( "multisession mode" );
if( s == "none" )
dataDoc->setMultiSessionMode( K3bDataDoc::NONE );
else if( s == "start" )
dataDoc->setMultiSessionMode( K3bDataDoc::START );
else if( s == "continue" )
dataDoc->setMultiSessionMode( K3bDataDoc::CONTINUE );
else if( s == "finish" )
dataDoc->setMultiSessionMode( K3bDataDoc::FINISH );
else
dataDoc->setMultiSessionMode( K3bDataDoc::AUTO );
break;
}
case K3bDoc::VIDEODVD: {
// the only defaults we need here are the volume id and stuff
K3bDataDoc* dataDoc = static_cast<K3bDataDoc*>(doc);
dataDoc->setIsoOptions( K3bIsoOptions::load( c, false ) );
dataDoc->setVerifyData( c->readBoolEntry( "verify data", false ) );
break;
}
case K3bDoc::MIXED: {
K3bMixedDoc* mixedDoc = static_cast<K3bMixedDoc*>(doc);
mixedDoc->audioDoc()->writeCdText( c->readBoolEntry( "cd_text", true ) );
mixedDoc->audioDoc()->setNormalize( c->readBoolEntry( "normalize", false ) );
// load mixed type
if( c->readEntry( "mixed_type" ) == "last_track" )
mixedDoc->setMixedType( K3bMixedDoc::DATA_LAST_TRACK );
else if( c->readEntry( "mixed_type" ) == "first_track" )
mixedDoc->setMixedType( K3bMixedDoc::DATA_FIRST_TRACK );
else
mixedDoc->setMixedType( K3bMixedDoc::DATA_SECOND_SESSION );
TQString datamode = c->readEntry( "data_track_mode" );
if( datamode == "mode1" )
mixedDoc->dataDoc()->setDataMode( K3b::MODE1 );
else if( datamode == "mode2" )
mixedDoc->dataDoc()->setDataMode( K3b::MODE2 );
else
mixedDoc->dataDoc()->setDataMode( K3b::DATA_MODE_AUTO );
mixedDoc->dataDoc()->setIsoOptions( K3bIsoOptions::load( c, false ) );
if( mixedDoc->dataDoc()->isoOptions().volumeID().isEmpty() )
mixedDoc->dataDoc()->setVolumeID( doc->URL().fileName() );
break;
}
case K3bDoc::VCD: {
K3bVcdDoc* vcdDoc = static_cast<K3bVcdDoc*>(doc);
// FIXME: I think we miss a lot here!
vcdDoc->vcdOptions()->setPbcEnabled( c->readBoolEntry( "Use Playback Control", false ) );
vcdDoc->vcdOptions()->setPbcNumkeysEnabled( c->readBoolEntry( "Use numeric keys to navigate chapters", false ) );
vcdDoc->vcdOptions()->setPbcPlayTime( c->readNumEntry( "Play each Sequence/Segment", 1 ) );
vcdDoc->vcdOptions()->setPbcWaitTime( c->readNumEntry( "Time to wait after each Sequence/Segment", 2 ) );
if( vcdDoc->vcdOptions()->volumeId().isEmpty() )
vcdDoc->vcdOptions()->setVolumeId( doc->URL().fileName() );
break;
}
}
if( doc->type() == K3bDoc::DATA ||
doc->type() == K3bDoc::MOVIX ||
doc->type() == K3bDoc::MOVIX_DVD ||
doc->type() == K3bDoc::VIDEODVD ||
doc->type() == K3bDoc::DVD ) {
if( static_cast<K3bDataDoc*>(doc)->isoOptions().volumeID().isEmpty() )
static_cast<K3bDataDoc*>(doc)->setVolumeID( doc->URL().fileName() );
}
doc->setModified( false );
c->setGroup( oldGroup );
}
K3bProjectInterface* K3bProjectManager::dcopInterface( K3bDoc* doc )
{
TQMap<K3bDoc*, K3bProjectInterface*>::iterator it = d->projectInterfaceMap.find( doc );
if( it == d->projectInterfaceMap.end() ) {
K3bProjectInterface* dcopInterface = 0;
if( doc->type() == K3bDoc::DATA || doc->type() == K3bDoc::DVD )
dcopInterface = new K3bDataProjectInterface( static_cast<K3bDataDoc*>(doc) );
else if( doc->type() == K3bDoc::AUDIO )
dcopInterface = new K3bAudioProjectInterface( static_cast<K3bAudioDoc*>(doc) );
else if( doc->type() == K3bDoc::MIXED )
dcopInterface = new K3bMixedProjectInterface( static_cast<K3bMixedDoc*>(doc) );
else
dcopInterface = new K3bProjectInterface( doc );
d->projectInterfaceMap[doc] = dcopInterface;
return dcopInterface;
}
else
return it.data();
}
K3bDoc* K3bProjectManager::openProject( const KURL& url )
{
TQApplication::setOverrideCursor( TQCursor(TQt::WaitCursor) );
TQString tmpfile;
TDEIO::NetAccess::download( url, tmpfile, 0L );
// ///////////////////////////////////////////////
// first check if it's a store or an old plain xml file
bool success = false;
TQDomDocument xmlDoc;
// try opening a store
KoStore* store = KoStore::createStore( tmpfile, KoStore::Read );
if( store ) {
if( !store->bad() ) {
// try opening the document inside the store
if( store->open( "maindata.xml" ) ) {
TQIODevice* dev = store->device();
dev->open( IO_ReadOnly );
if( xmlDoc.setContent( dev ) )
success = true;
dev->close();
store->close();
}
}
delete store;
}
if( !success ) {
// try reading an old plain document
TQFile f( tmpfile );
if ( f.open( IO_ReadOnly ) ) {
//
// First check if this is really an xml file beacuse if this is a very big file
// the setContent method blocks for a very long time
//
char test[5];
if( f.readBlock( test, 5 ) ) {
if( ::strncmp( test, "<?xml", 5 ) ) {
kdDebug() << "(K3bDoc) " << url.path() << " seems to be no xml file." << endl;
TQApplication::restoreOverrideCursor();
return 0;
}
f.reset();
}
else {
kdDebug() << "(K3bDoc) could not read from file." << endl;
TQApplication::restoreOverrideCursor();
return 0;
}
if( xmlDoc.setContent( &f ) )
success = true;
f.close();
}
}
// ///////////////////////////////////////////////
TDEIO::NetAccess::removeTempFile( tmpfile );
if( !success ) {
kdDebug() << "(K3bDoc) could not open file " << url.path() << endl;
TQApplication::restoreOverrideCursor();
return 0;
}
// check the documents DOCTYPE
K3bDoc::DocType type = K3bDoc::AUDIO;
if( xmlDoc.doctype().name() == "k3b_audio_project" )
type = K3bDoc::AUDIO;
else if( xmlDoc.doctype().name() == "k3b_data_project" )
type = K3bDoc::DATA;
else if( xmlDoc.doctype().name() == "k3b_vcd_project" )
type = K3bDoc::VCD;
else if( xmlDoc.doctype().name() == "k3b_mixed_project" )
type = K3bDoc::MIXED;
else if( xmlDoc.doctype().name() == "k3b_movix_project" )
type = K3bDoc::MOVIX;
else if( xmlDoc.doctype().name() == "k3b_movixdvd_project" )
type = K3bDoc::MOVIX_DVD;
else if( xmlDoc.doctype().name() == "k3b_dvd_project" )
type = K3bDoc::DVD;
else if( xmlDoc.doctype().name() == "k3b_video_dvd_project" )
type = K3bDoc::VIDEODVD;
else {
kdDebug() << "(K3bDoc) unknown doc type: " << xmlDoc.doctype().name() << endl;
TQApplication::restoreOverrideCursor();
return 0;
}
// we do not know yet if we will be able to actually open the project, so don't inform others yet
K3bDoc* newDoc = createEmptyProject( type );
// ---------
// load the data into the document
TQDomElement root = xmlDoc.documentElement();
if( newDoc->loadDocumentData( &root ) ) {
newDoc->setURL( url );
newDoc->setSaved( true );
newDoc->setModified( false );
// ok, finish the doc setup, inform the others about the new project
dcopInterface( newDoc );
addProject( newDoc );
// FIXME: find a better way to tell everyone (especially the projecttabwidget)
// that the doc is not changed
emit projectSaved( newDoc );
kdDebug() << "(K3bProjectManager) loading project done." << endl;
}
else {
delete newDoc;
newDoc = 0;
}
TQApplication::restoreOverrideCursor();
return newDoc;
}
bool K3bProjectManager::saveProject( K3bDoc* doc, const KURL& url )
{
TQString tmpfile;
TDEIO::NetAccess::download( url, tmpfile, 0L );
bool success = false;
// create the store
KoStore* store = KoStore::createStore( tmpfile, KoStore::Write, "application/x-k3b" );
if( store ) {
if( store->bad() ) {
delete store;
}
else {
// open the document inside the store
store->open( "maindata.xml" );
// save the data in the document
TQDomDocument xmlDoc( "k3b_" + doc->typeString() + "_project" );
xmlDoc.appendChild( xmlDoc.createProcessingInstruction( "xml", "version=\"1.0\" encoding=\"UTF-8\"" ) );
TQDomElement docElem = xmlDoc.createElement( "k3b_" + doc->typeString() + "_project" );
xmlDoc.appendChild( docElem );
success = doc->saveDocumentData( &docElem );
if( success ) {
KoStoreDevice dev(store);
dev.open( IO_WriteOnly );
TQTextStream xmlStream( &dev );
xmlDoc.save( xmlStream, 0 );
doc->setURL( url );
doc->setModified( false );
}
// close the document inside the store
store->close();
// remove the store (destructor writes the store to disk)
delete store;
doc->setSaved( success );
if( success ) {
emit projectSaved( doc );
}
}
}
TDEIO::NetAccess::removeTempFile( tmpfile );
return success;
}
void K3bProjectManager::slotProjectChanged( K3bDoc* doc )
{
emit projectChanged( doc );
}
#include "k3bprojectmanager.moc"