#include "soundkonverter.h" #include "config.h" #include "configdialog.h" #include "logger.h" #include "logviewer.h" #include "options.h" #include "filelist.h" #include "progressindicator.h" #include "cdmanager.h" #include "cdopener.h" #include "tagengine.h" #include "combobutton.h" #include "convert.h" #include "progressindicator.h" #include "replaygainscanner.h" #include "cuesheeteditor.h" // ### #include "aboutplugins.h" delayed to a future soundkonverter version #include "optionsrequester.h" #include "dirdialog.h" #include #include #include #include #include #include #include //#include #include #include #include #include #include #include #include #include #include #include #include #include #include // TODO stop all processes on exit / clean tmp up // ### soundkonverter 0.4: save file list when kde session gets terminated soundKonverter::soundKonverter() : KMainWindow( 0, "soundkonverter-mainwindow", WType_TopLevel | WDestructiveClose | WStyle_ContextHelp ), DCOPObject( "soundkonverter-app" ) { // this is our first startup, set instances to zero instances = 0; replayGainScanner = 0; cuesheetEditor = 0; logViewer = 0; device = ""; visible = true; autoclose = false; configStartPage = ConfigDialog::GeneralPage; logger = new Logger(); logger->log( 1000, "This is soundKonverter 0.3.7" ); #ifdef HAVE_MP4V2 logger->log( 1000, "MP4v2 is enabled" ); #else logger->log( 1000, "MP4v2 is disabled" ); #endif config = new Config( logger ); config->read(); // (re)move the 0.2 config file if( config->data.app.configVersion < 280 ) { KIO::rename( locateLocal("config","soundkonverterrc"), locateLocal("config","soundkonverterrc.back"), true ); // KMessageBox::information( this, "You are using a pre-release of soundKonverter. This version is designed for testing only.\nThere are a few things not implemented at the moment but it should run without crashes and big problems. So feel free to report such an error if you find one.\nPlease have a look at the README.\n\nYour old configuration file has been moved to soundkonverterrc.back." ); } // if( config->data.app.configVersion < 290 ) { // QFile plugin_dir( locateLocal("data","soundkonverter/plugins") ); // if( plugin_dir.exists() ) { // KIO::rename( locateLocal("data","soundkonverter/plugins"), locateLocal("data","soundkonverter/plugins.back"), true ); // int ret = KMessageBox::questionYesNo( this, i18n("soundKonverter has cleaned up it's old installation. It seems to be necessary to restart soundKonverter!\n\nDo you want to restart soundKonverter now?") ); // if( ret == KMessageBox::Yes ) { // config->write(); // // TODO parameters are lost // KProcess restart; // restart << "soundkonverter"; // restart.start( KProcess::DontCare ); // kapp->quit(); // return; // } // } // } cdManager = new CDManager(); tagEngine = new TagEngine(); resize( 640, 470 ); systemTray = new KSystemTray( this, "systemTray" ); systemTray->hide(); // create an icon loader object for loading icons KIconLoader *iconLoader = new KIconLoader(); QWidget* widget = new QWidget( this, "widget" ); setCentralWidget( widget ); // NOTE created here because of some dependences options = new Options( config, i18n("Choose your prefered output options and click on \"Add files ...\"!"), widget, "options" ); fileList = new FileList( cdManager, tagEngine, config, options, logger, widget, "fileList" ); startAction = new KAction( i18n("&Start conversion"), "run", 0, fileList, SLOT(startConversion()), actionCollection(), "start" ); startAction->setEnabled( false ); new KAction( i18n("&Replay Gain Tool ..."), "soundkonverter_replaygain", CTRL+Key_R, this, SLOT(showReplayGainScanner()), actionCollection(), "replaygainscanner" ); //new KAction( i18n("R&epair Tool ..."), "soundkonverter_repair", CTRL+Key_E, this, SLOT(showRepairTool()), actionCollection(), "repairtool" ); new KAction( i18n("C&uesheet Editor ..."), "kwrite", CTRL+Key_U, this, SLOT(showCuesheetEditor()), actionCollection(), "cuesheeteditor" ); new KAction( i18n("Show &Log ..."), "view_text", CTRL+Key_L, this, SLOT(showLogViewer()), actionCollection(), "log" ); // new KAction( i18n("About &Plugins ..."), "connect_creating", CTRL+Key_P, this, SLOT(showAboutPlugins()), actionCollection(), "about_plugins" ); stopAction = new KAction( i18n("S&top after current file is complete"), "stop", CTRL+Key_O, fileList, SLOT(stopConversion()), actionCollection(), "stop" ); continueAction = new KAction( i18n("&Continue after current file is complete"), "run", CTRL+Key_T, fileList, SLOT(continueConversion()), actionCollection(), "continue" ); killAction = new KAction( i18n("Stop &immediately"), "exit", CTRL+Key_K, fileList, SLOT(killConversion()), actionCollection(), "kill" ); stopActionMenu = new KActionMenu( i18n("Stop"), "stop", actionCollection(), "stopMenu" ); stopActionMenu->setDelayed( false ); stopActionMenu->setEnabled( false ); // stopActionMenu->insert( stopAction ); // stopActionMenu->insert( continueAction ); // stopActionMenu->insert( killAction ); /* veryHighPriorityAction = new KToggleAction( i18n("Very hi&gh"), CTRL+Key_1, this, SLOT(priorityChanged()), actionCollection(), "veryhigh" ); veryHighPriorityAction->setExclusiveGroup("priorityActionMenu"); highPriorityAction = new KToggleAction( i18n("&High"), CTRL+Key_2, this, SLOT(priorityChanged()), actionCollection(), "high" ); highPriorityAction->setExclusiveGroup("priorityActionMenu"); normalPriorityAction = new KToggleAction( i18n("&Normal"), CTRL+Key_3, this, SLOT(priorityChanged()), actionCollection(), "nomal" ); normalPriorityAction->setExclusiveGroup("priorityActionMenu"); normalPriorityAction->setChecked(true); lowPriorityAction = new KToggleAction( i18n("&Low"), CTRL+Key_4, this, SLOT(priorityChanged()), actionCollection(), "low" ); lowPriorityAction->setExclusiveGroup("priorityActionMenu"); veryLowPriorityAction = new KToggleAction( i18n("Very lo&w"), CTRL+Key_5, this, SLOT(priorityChanged()), actionCollection(), "verylow" ); veryLowPriorityAction->setExclusiveGroup("priorityActionMenu"); priorityActionMenu = new KActionMenu( i18n("En-/Decoder priority"), "ksysguard", actionCollection(), "priorityMenu" ); priorityActionMenu->setDelayed( false ); priorityActionMenu->insert(veryHighPriorityAction); priorityActionMenu->insert(highPriorityAction); priorityActionMenu->insert(normalPriorityAction); priorityActionMenu->insert(lowPriorityAction); priorityActionMenu->insert(veryLowPriorityAction);*/ //priorityChanged(); new KAction( i18n("A&dd Files ..."), "sound", CTRL+Key_D, this, SLOT(showFileDialog()), actionCollection(), "add_files" ); new KAction( i18n("Add &Folder ..."), "folder", CTRL+Key_F, this, SLOT(showDirDialog()), actionCollection(), "add_folder" ); new KAction( i18n("Add CD &tracks ..."), "cdaudio_unmount", CTRL+Key_T, this, SLOT(showCdDialog()), actionCollection(), "add_audiocd" ); new KAction( i18n("Add &URL ..."), "browser", CTRL+Key_U, this, SLOT(showUrlDialog()), actionCollection(), "add_url" ); KStdAction::quit(this, SLOT(close()), actionCollection()); new KAction( i18n("L&oad file list"), "fileopen", 0, fileList, SLOT(load()), actionCollection(), "load" ); new KAction( i18n("Sa&ve file list"), "filesave", 0, fileList, SLOT(save()), actionCollection(), "save" ); // TODO //KStdAction::paste( this, SLOT(pasteFiles()), actionCollection() ); KStdAction::preferences( this, SLOT(showConfigDialog()), actionCollection() ); showToolBarAction = KStdAction::showToolbar( this, SLOT(showToolbar()), actionCollection() ); //KStdAction::showStatusbar( 0, 0, actionCollection() ); KStdAction::configureToolbars( this, SLOT(editToolbar()), actionCollection() ); createGUI(); if( config->data.general.showToolBar ) { toolBar()->show(); showToolBarAction->setChecked( true ); } else { toolBar()->hide(); showToolBarAction->setChecked( false ); } // the grid for all widgets in the main window QGridLayout* gridLayout = new QGridLayout( widget, 1, 1, 6, 6, "gridLayout" ); // generate the options input area // NOTE created above because of some dependences //options = new Options( config, i18n("Choose your prefered output options and click on \"Add files ...\"!"), this, "options" ); connect( options, SIGNAL(showConfigPluginsPage()), this, SLOT(showConfigPluginsPage()) ); connect( options, SIGNAL(showConfigEnvironmentPage()), this, SLOT(showConfigEnvironmentPage()) ); gridLayout->addWidget( options, 0, 0 ); // generate the list view for the file list // NOTE created above because of some dependences //fileList = new FileList( cdManager, tagEngine, config, options, this, "fileList" ); gridLayout->addWidget( fileList, 1, 0 ); gridLayout->setRowStretch( 1, 1 ); /*connect( this, SIGNAL(windowMoved(int,int)), fileList, SLOT(moveOptionsEditor(int,int)) );*/ connect( fileList, SIGNAL(fileCountChanged(int)), this, SLOT(fileCountChanged(int)) ); connect( fileList, SIGNAL(startedConversion()), this, SLOT(startedConversion()) ); connect( fileList, SIGNAL(stopClicked()), this, SLOT(stopClicked()) ); connect( fileList, SIGNAL(continueClicked()), this, SLOT(continueClicked()) ); connect( fileList, SIGNAL(stoppedConversion()), this, SLOT(stoppedConversion()) ); convert = new Convert( config, tagEngine, cdManager, fileList, logger ); // connect( this, SIGNAL(setPriority(int)), // convert, SLOT(priorityChanged(int)) // ); // add a horizontal box layout for the add combobutton to the grid QHBoxLayout *addBox = new QHBoxLayout( -1, "addBox" ); gridLayout->addLayout( addBox, 2, 0 ); // create the combobutton for adding files to the file list cAdd = new ComboButton( widget, "cAdd" ); QFont font = cAdd->font(); //font.setWeight( QFont::DemiBold ); font.setPointSize( font.pointSize() + 1 ); cAdd->setFont( font ); cAdd->insertItem( iconLoader->loadIcon("sound",KIcon::Toolbar), i18n("Add files ...") ); cAdd->insertItem( iconLoader->loadIcon("folder",KIcon::Toolbar), i18n("Add folder ...") ); cAdd->insertItem( iconLoader->loadIcon("cdaudio_unmount",KIcon::Toolbar), i18n("Add CD tracks ...") ); cAdd->insertItem( iconLoader->loadIcon("browser",KIcon::Toolbar), i18n("Add URL ...") ); addBox->addWidget( cAdd ); connect( cAdd, SIGNAL(clicked(int)), this, SLOT(addClicked(int)) ); addBox->addSpacing( 18 ); pStart = new KPushButton( iconLoader->loadIcon("run",KIcon::Small), i18n("Start"), widget, "pStart" ); pStart->setFixedHeight( pStart->size().height() ); pStart->setEnabled( false ); addBox->addWidget( pStart ); connect( pStart, SIGNAL(clicked()), fileList, SLOT(startConversion()) ); pStop = new KPushButton( iconLoader->loadIcon("stop",KIcon::Small), i18n("Stop"), widget, "pStop" ); pStop->setFixedHeight( pStop->size().height() ); pStop->hide(); pStop->setPopup( stopActionMenu->popupMenu() ); addBox->addWidget( pStop ); addBox->addSpacing( 8 ); progressIndicator = new ProgressIndicator( systemTray, widget, "progressIndicator" ); addBox->addWidget( progressIndicator ); connect( fileList, SIGNAL(increaseTime(float)), progressIndicator, SLOT(increaseTime(float)) ); connect( fileList, SIGNAL(decreaseTime(float)), progressIndicator, SLOT(decreaseTime(float)) ); /*connect( fileList, SIGNAL(setTime(float)), progressIndicator, SLOT(setTime(float)) );*/ connect( fileList, SIGNAL(finished(float)), progressIndicator, SLOT(finished(float)) ); connect( convert, SIGNAL(countTime(float)), progressIndicator, SLOT(countTime(float)) ); connect( convert, SIGNAL(uncountTime(float)), progressIndicator, SLOT(uncountTime(float)) ); connect( convert, SIGNAL(update(float)), progressIndicator, SLOT(update(float)) ); connect( progressIndicator, SIGNAL(setTitle(const QString&)), this, SLOT(setTitle(const QString&)) ); cAdd->increaseHeight( /*progressIndicator->height() - cAdd->height()*/ 10 ); // FIXME detect the height automaticly cAdd->adjustSize(); // delete the icon loader object delete iconLoader; fileList->load( true ); // restore file list after a crash } soundKonverter::~soundKonverter() { // TODO clean tmp dir (stop all running processes) delete replayGainScanner; delete cuesheetEditor; delete logViewer; } void soundKonverter::increaseInstances() { // a new instance should be created, so this isn't the initial startup no longer instances++; } bool soundKonverter::queryClose() { config->removeProfile( i18n("Last used") ); config->addProfile( i18n("Last used"), options->getCurrentOptions() ); config->write( false ); convert->cleanUp(); logger->cleanUp(); QFile::remove( locateLocal("data","soundkonverter/filelist.autosave.xml") ); return true; } void soundKonverter::setNotify( const QString& cmd ) { fileList->setNotify( cmd ); } /*void soundKonverter::moveEvent( QMoveEvent* e ) { // emit windowMoved( pos().x(), pos().y() + height() ); }*/ void soundKonverter::openArgFiles( const QStringList &files ) { if( ( instances <= 1 || config->data.general.askForNewOptions ) && ( profile == "" || format == "" || directory == "" ) ) { OptionsRequester* dialog = new OptionsRequester( config, files, this ); connect( dialog, SIGNAL(setCurrentOptions(const ConversionOptions&)), options, SLOT(setCurrentOptions(const ConversionOptions&)) ); connect( dialog, SIGNAL(addFiles(QStringList)), fileList, SLOT(addFiles(QStringList)) ); Q_CHECK_PTR( dialog ); if( profile != "" ) { dialog->setProfile( profile ); profile = ""; } if( format != "" ) { dialog->setFormat( format ); format = ""; } if( directory != "" ) { dialog->setOutputDirectory( directory ); directory = ""; } dialog->exec(); disconnect( dialog, SIGNAL(setCurrentOptions(const ConversionOptions&)), 0, 0 ); disconnect( dialog, SIGNAL(addFiles(QStringList)), 0, 0 ); delete dialog; } else { ConversionOptions conversionOptions = options->getCurrentOptions(); if( profile != "" ) { options->setProfile( profile ); profile = ""; } if( format != "" ) { options->setFormat( format ); format = ""; } if( directory != "" ) { options->setOutputDirectory( directory ); directory = ""; } fileList->addFiles( files ); options->setCurrentOptions( conversionOptions ); } if( !visible ) fileList->startConversion(); // NOTE should be save! } void soundKonverter::openArgReplayGainFiles( const QStringList &files ) { showReplayGainScanner(); if( replayGainScanner ) replayGainScanner->addFiles( files ); } // void soundKonverter::openArgRepairFiles( const QStringList &files ) // {} void soundKonverter::startedConversion() { pStart->hide(); if( fileList->queueEnabled() ) { startAction->setEnabled( false ); startAction->setText( i18n("&Start conversion") ); stopActionMenu->remove( startAction ); stopActionMenu->remove( stopAction ); stopActionMenu->remove( continueAction ); stopActionMenu->remove( killAction ); stopActionMenu->insert( stopAction ); stopActionMenu->insert( continueAction ); stopActionMenu->insert( killAction ); } else { startAction->setEnabled( true ); startAction->setText( i18n("&Start queue") ); stopActionMenu->remove( startAction ); stopActionMenu->remove( stopAction ); stopActionMenu->remove( continueAction ); stopActionMenu->remove( killAction ); stopActionMenu->insert( killAction ); stopActionMenu->insert( startAction ); } pStop->show(); stopActionMenu->setEnabled( true ); stopAction->setEnabled( true ); continueAction->setEnabled( false ); killAction->setEnabled( true ); } void soundKonverter::stopClicked() { stopAction->setEnabled( false ); continueAction->setEnabled( true ); } void soundKonverter::continueClicked() { stopAction->setEnabled( true ); continueAction->setEnabled( false ); } void soundKonverter::stoppedConversion() { pStart->show(); startAction->setEnabled( true ); startAction->setText( i18n("&Start conversion") ); pStop->hide(); stopActionMenu->setEnabled( false ); if( autoclose ) kapp->quit(); // NOTE close app on conversion stop (may irritate the user when stopping the conversion) } // void soundKonverter::priorityChanged() // { // int priority = 0; // // //if( veryHighPriorityAction->isChecked() ) priority=-19; // //else if( highPriorityAction->isChecked() ) priority=-10; // if( lowPriorityAction->isChecked() ) priority = 10; // else if( veryLowPriorityAction->isChecked() ) priority = 20; // // emit setPriority( priority ); // } void soundKonverter::addClicked( int index ) { fileList->save( true ); if( index == 0 ) { showFileDialog(); } else if( index == 1 ) { showDirDialog(); } else if( index == 2 ) { showCdDialog( true ); } else { showUrlDialog(); } fileList->save( true ); } void soundKonverter::showFileDialog() { QStringList urls = KFileDialog::getOpenURLs( ":file_open", config->fileFilter(), this, i18n("Choose files to convert") ).toStringList(); if( !urls.empty() ) { /* for( QStringList::Iterator it = urls.begin(); it != urls.end(); ++it ) { *it = KURL::decode_string( *it ); }*/ fileList->addFiles( urls ); } } void soundKonverter::showDirDialog() { // QString directory = KFileDialog::getExistingDirectory( ":file_open", this, i18n("Choose a directory") ); // if( !directory.isEmpty() ) // { // fileList->addDir( directory ); // } DirDialog *dialog = new DirDialog( config, DirDialog::Convert, this, "DirDialog" ); Q_CHECK_PTR( dialog ); if( dialog->exec() ) { fileList->addDir( dialog->directory, dialog->selectedFileTypes, dialog->recursive ); } delete dialog; } void soundKonverter::showCdDialog( bool intern ) { ConversionOptions conversionOptions = options->getCurrentOptions(); if( ( instances <= 1 || config->data.general.askForNewOptions ) && ( profile == "" || format == "" || directory == "" ) && !intern ) { OptionsRequester* dialog = new OptionsRequester( config, "", this ); connect( dialog, SIGNAL(setCurrentOptions(const ConversionOptions&)), options, SLOT(setCurrentOptions(const ConversionOptions&)) ); // connect( dialog, SIGNAL(addFiles(QStringList)), // fileList, SLOT(addFiles(QStringList)) // ); Q_CHECK_PTR( dialog ); if( profile != "" ) { dialog->setProfile( profile ); profile = ""; } if( format != "" ) { dialog->setFormat( format ); format = ""; } if( directory != "" ) { dialog->setOutputDirectory( directory ); directory = ""; } dialog->exec(); disconnect( dialog, SIGNAL(setCurrentOptions(const ConversionOptions&)), 0, 0 ); // disconnect( dialog, SIGNAL(addFiles(QStringList)), 0, 0 ); delete dialog; } else { if( profile != "" ) { options->setProfile( profile ); profile = ""; } if( format != "" ) { options->setFormat( format ); format = ""; } if( directory != "" ) { options->setOutputDirectory( directory ); directory = ""; } } // support for media:/ and system:/ urls if( !device.isEmpty() ) { device.replace( "system:/media", "/dev" ); device.replace( "media:", "/dev" ); device.replace( "devices:", "/dev" ); // NOTE obsolete, since soundkonverter 0.3 won't run on KDE < 3.5 } if( device.left(5) != "/dev/" || device == "auto" ) { device = ""; } kapp->eventLoop()->exitLoop(); // create a new CDOpener object for letting the user add some tracks from a CD CDOpener *dialog = new CDOpener( config, cdManager, tagEngine, device, this, "CDOpener" ); device = ""; Q_CHECK_PTR( dialog ); if( !dialog->noCD ) { connect( dialog, SIGNAL(addTracks(const QString&,QValueList)), fileList, SLOT(addTracks(const QString&,QValueList)) ); connect( dialog, SIGNAL(addDisc(const QString&)), fileList, SLOT(addDisc(const QString&)) ); /*connect( dialog, SIGNAL(openCuesheetEditor(const QString&)), this, SLOT(openCuesheetEditor(const QString&)) );*/ dialog->exec(); disconnect( dialog, SIGNAL(addTracks(const QString&,QValueList)), 0, 0 ); disconnect( dialog, SIGNAL(addDisc(const QString&)), 0, 0 ); //disconnect( dialog, SIGNAL(openCuesheetEditor(const QString&)), 0, 0 ); } delete dialog; kapp->eventLoop()->enterLoop(); options->setCurrentOptions( conversionOptions ); } void soundKonverter::showUrlDialog() { bool ok; QString url = KInputDialog::getText( i18n("Open URL"), i18n("Enter a URL:"), "", &ok ); if( ok ) { // if it isn't a local file and no protocol is given, we assume, it's http if( url.left(1) != "/" && !url.contains(":/") ) url.prepend( "http://" ); fileList->addFiles( url ); } } void soundKonverter::showReplayGainScanner() { if( replayGainScanner == 0 ) { replayGainScanner = new ReplayGainScanner( tagEngine, config, logger, 0, "replayGainScanner", false ); if( replayGainScanner == 0 ) { // TODO error message return; } // connect( this, SIGNAL(addFilesToReplayGainScanner(QStringList)), // replayGainScanner, SLOT(addFiles(QStringList)) // ); } replayGainScanner->show(); replayGainScanner->raise(); } void soundKonverter::showRepairTool() {} void soundKonverter::showCuesheetEditor() { if( cuesheetEditor == 0 ) { cuesheetEditor = new CuesheetEditor( 0, "cuesheetEditor", false ); if( cuesheetEditor == 0 ) { // TODO error message return; } } cuesheetEditor->show(); cuesheetEditor->raise(); } /*void soundKonverter::openCuesheetEditor( const QString& content ) { if( cuesheetEditor == 0 ) { cuesheetEditor = new CuesheetEditor( 0, "cuesheetEditor", false ); if( cuesheetEditor == 0 ) { // TODO error message return; } } cuesheetEditor->setContent( content ); cuesheetEditor->show(); }*/ void soundKonverter::showLogViewer() { if( logViewer == 0 ) { logViewer = new LogViewer( logger, 0, "logViewer", false ); if( logViewer == 0 ) { // TODO error message return; } // connect( convert, SIGNAL(finishedProcess(int,int)), // logViewer, SLOT(processCompleted(int,int)) // ); } logViewer->show(); logViewer->raise(); } void soundKonverter::showConfigDialog() { ConfigDialog *dialog = new ConfigDialog( config, this, "ConfigDialog", ConfigDialog::Page(configStartPage) ); Q_CHECK_PTR( dialog ); //dialog->setGeometry( frameGeometry() ); dialog->resize( size() ); dialog->exec(); delete dialog; configStartPage = ConfigDialog::GeneralPage; } void soundKonverter::showConfigPluginsPage() { configStartPage = ConfigDialog::PluginsPage; showConfigDialog(); } void soundKonverter::showConfigEnvironmentPage() { configStartPage = ConfigDialog::EnvironmentPage; showConfigDialog(); } // void soundKonverter::showAboutPlugins() // { // AboutPlugins *dialog = new AboutPlugins( config, this, "AboutPlugins" ); // // Q_CHECK_PTR( dialog ); // // dialog->exec(); // // delete dialog; // } void soundKonverter::showToolbar() { if( showToolBarAction->isChecked() ) { toolBar()->show(); config->data.general.showToolBar = true; } else { toolBar()->hide(); config->data.general.showToolBar = false; } } void soundKonverter::editToolbar() { saveMainWindowSettings( kapp->config(), "MainWindow" ); KEditToolbar dlg( actionCollection() ); connect( &dlg, SIGNAL(newToolbarConfig()), this, SLOT(newToolbarConfig()) ); dlg.exec(); } void soundKonverter::newToolbarConfig() { createGUI(); applyMainWindowSettings( kapp->config(), "MainWindow" ); } void soundKonverter::fileCountChanged( int count ) { if( count > 0 ) { startAction->setEnabled( true ); pStart->setEnabled( true ); } else { startAction->setEnabled( false ); pStart->setEnabled( false ); } } void soundKonverter::setTitle( const QString& title ) { setCaption( title ); } #include "soundkonverter.moc"