/***************************************************************************
 *   Copyright (C) 2007-2011 by Vegeta                                     *
 *                                                                         *
 *   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.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#include "QtGain.h"
#include "Preferences.h"
#include "renamefiles.h"

#include <QFileDialog>
#include <QMessageBox>
#include <QSettings>
#include <QDragEnterEvent>
#include <QUrl>
#include <QAction>
#include <QTimer>
#include <QDirIterator>
#include <QProcess>
#include <QTextEdit>


const QString VERSION = "QtGain 0.9.5";

QtGain::QtGain(QWidget *parent, Qt::WFlags flags) : QMainWindow(parent, flags){
    ui.setupUi(this);

    startupInitiations();
    loadSettings();

    setWindowTitle(VERSION);
    show();

    // Check for command line arguments
    isGainOnlyCommandlineModus = false;
    QStringList arguments = qApp->arguments();
    if (arguments.size() > 1){
        QList<QUrl> fileList;
        isGainOnlyCommandlineModus = arguments.contains("-GainOnly");

        for (int i=1; i<arguments.size(); i++){
            fileList << arguments[i];
        }
        processRawFileList(fileList);
    } else if (isShowBrowserAtStatup()) openDirectoryDialog();
}

QtGain::~QtGain(){
}

// *********************************************************************************************
// Generate Contextmenu, Timer etc.
// *********************************************************************************************
void QtGain::startupInitiations(){
    actionAbout = new QAction(QIcon(":/Icons/lsongs.png"), tr("About..."), this);
    connect(actionAbout, SIGNAL(triggered()), this, SLOT(showAboutDialog()));

    actionCancelOperation = new QAction(QIcon(":/Icons/Stop.png"), tr("&Stop..."), this);
    actionCancelOperation->setShortcut(tr("Ctrl+S"));
    connect(actionCancelOperation, SIGNAL(triggered()), this, SLOT(cancelOperation()));

    actionShowSettings = new QAction(QIcon(":/Icons/Preferences.png"), tr("&Configure"), this);
    actionShowSettings->setShortcut(tr("Ctrl+C"));
    connect(actionShowSettings, SIGNAL(triggered()), this, SLOT(showPreferencesDialog()));

    QAction *Separator = new QAction(this);
    Separator->setSeparator(true);

    QAction *actionDonate= new QAction(QIcon(":/Icons/Donate.png"), tr("Donate"), this);
    connect(actionDonate, SIGNAL(triggered()), this, SLOT(Donate()));

    actionQuit = new QAction(QIcon(":/Icons/Exit.png"), tr("E&xit"), this);
    actionQuit->setShortcut(tr("Ctrl+X"));
    connect(actionQuit, SIGNAL(triggered()), this, SLOT(Quit()));

    this->addAction(actionAbout);
    this->addAction(actionCancelOperation);
    this->addAction(actionShowSettings);
    this->addAction(Separator);
    this->addAction(actionDonate);
    this->addAction(actionQuit);

    actionCancelOperation->setEnabled(false);
    ui.centralWidget->setContextMenuPolicy(Qt::ActionsContextMenu);

    // Timer
    Timer = new QTimer(this);
    connect(Timer, SIGNAL(timeout()), this, SLOT(updateGUI()));

    // Processes
    TrackGainProcess = new QProcess(this);
    TrackGainProcess->setReadChannelMode(QProcess::MergedChannels);
    connect(TrackGainProcess, SIGNAL(finished(int)), this, SLOT(processFiles_TrackGain()));

    AlbumGainProcess = new QProcess(this);
    AlbumGainProcess->setReadChannelMode(QProcess::MergedChannels);
    connect(AlbumGainProcess, SIGNAL(readyRead()),   this, SLOT(processOutput_AlbumGain()));
    connect(AlbumGainProcess, SIGNAL(finished(int)), this, SLOT(processAlbumGain_Coverdownload()));

    FlacAlbumGainProcess = new QProcess(this);
    connect(FlacAlbumGainProcess, SIGNAL(finished(int)), this, SLOT(setGUI_To()));

    RenameFiles = new renameFiles(this);
    connect(RenameFiles, SIGNAL(signal_addToErrorlog(QString)), SLOT(addToErrorlog(QString)));
    connect(RenameFiles, SIGNAL(signal_allJobsFinished()),      SLOT(setGUI_To()));
    connect(RenameFiles, SIGNAL(signal_updateDownloadInfos(QString,QString,QString,int,int,int,int,int,int,bool)), this, SLOT(updateGUIInfos(QString,QString,QString,int,int,int,int,int,int,bool)));
}


// *********************************************************************************************
// Start gaining AlbumGain
// *********************************************************************************************
void QtGain::processFiles_AlbumGain(){

    // MP3
    QStringList Parameter;

    if (allFiles[0].endsWith(".mp3", Qt::CaseInsensitive)){
        ui.FileFormatIcon->setPixmap(QPixmap(":/Icons/mp3.png"));
        Parameter << "-a" << "-k" << "-c" << "-p";

        for (int i=allFiles.size() - 1; i>=0; i--){
            if (allFiles[i].endsWith(".mp3", Qt::CaseInsensitive)) Parameter << allFiles[i];
            else allFiles.removeAt(i);
        }
        AlbumGainProcess->start(MP3GainBinaryPath(), Parameter);
    }

    // MP4 / m4a
    else if (allFiles[0].contains(QRegExp("\\.(mp4|m4a)$", Qt::CaseInsensitive))){
        ui.FileFormatIcon->setPixmap(QPixmap(":/Icons/m4a.png"));

        Parameter << "-a" << "-k" << "-c" << "-p";
        for (int i=allFiles.size() - 1; i>=0; i--){
            if (allFiles[i].contains(QRegExp("\\.(mp4|m4a)$", Qt::CaseInsensitive))) Parameter << allFiles[i];
            else allFiles.removeAt(i);
        }
        AlbumGainProcess->start(MP4GainBinaryPath(), Parameter);
    }


    // Ogg-Vorbis
    else if (allFiles[0].endsWith(".ogg", Qt::CaseInsensitive)){
        ui.FileFormatIcon->setPixmap(QPixmap(":/Icons/ogg.png"));

        Parameter << "-a";
        for (int i=allFiles.size() - 1; i>=0; i--){
            if (allFiles[i].endsWith(".ogg", Qt::CaseInsensitive)) Parameter << allFiles[i];
            else allFiles.removeAt(i);
        }

        AlbumGainProcess->start(VorbisGainBinaryPath(), Parameter);
    }

    // FLAC
    else if (allFiles[0].endsWith(".flac", Qt::CaseInsensitive)){

        ui.FileFormatIcon->setPixmap(QPixmap(":/Icons/flac.png"));
        Parameter << "--add-replay-gain" << "--preserve-modtime";
        for (int i=allFiles.size() - 1; i>=0; i--){
            if (allFiles[i].endsWith(".flac", Qt::CaseInsensitive)) Parameter << allFiles[i];
            else allFiles.removeAt(i);
        }

        // MetaFlac generates no output so we can't say something about the progress till it ends
        ui.Statustext->setText("Executing Metaflac, please wait");
        ui.progressBar->setMaximum(0);
        FlacAlbumGainProcess->start(FlacGainBinaryPath(), Parameter);
        return;
    }

    // Update GUI
    processOutput_AlbumGain();
}


// *********************************************************************************************
// AlbumGain-Output Analysis
// *********************************************************************************************
void QtGain::processOutput_AlbumGain(){

    QString Output = AlbumGainProcess->readAllStandardOutput();
    if (!m_lastAlbumGainOutput.isEmpty() && Output.contains(m_lastAlbumGainOutput)) return;

    // Check for early finish (MP3 and MP4)
    if (Output.contains(QRegExp("No changes to .* are necessary"))) {
        setGUI_To(RESET_ALL, "No need to update files");
        return;
    }


    // Check Vorbisgain-Output
    if (finishedFiles() < allFiles.size()){
        if (Output.contains(QRegExp("100%.*\\.(ogg|mp4|m4a)", Qt::CaseInsensitive)) || // VorbisGain and AACGain
                Output.contains(QRegExp(QString("\\[%1/%2\\] 9\\d+% of \\d+ bytes analyzed").arg(finishedFiles() + 1).arg(allFiles.size())))// MP3Gain

                ) addFinishedFiles();

        // Once again check finishedFiles() < allFiles.size()
        QString Info;
        if (finishedFiles() < allFiles.size()) {
            QFileInfo file(allFiles[finishedFiles()]);
            Info = file.path().mid(file.path().lastIndexOf("/") + 1).left(30);
        }

        updateGUIInfos(ui.Statustext->text(),
                       Info,
                       FilenameWithoutPath(finishedFiles()).left(30),
                       qMax(0, allFiles.size() - finishedFiles()),
                       Errors(),
                       skippedFiles(),
                       qMax(0, finishedFiles() - skippedFiles() - Errors()),
                       finishedFiles(),
                       allFiles.size(),
                       false);
    }
    m_lastAlbumGainOutput = Output;
}


// *********************************************************************************************
// AlbumGain finished and start cover download if enabled
// AlbumGain starts only one process so we don't need to do further checks
// *********************************************************************************************
void QtGain::processAlbumGain_Coverdownload(){
    // Gaining is finished, now we starting id3v2 and
    // 1. renaming files with the tags of the mp3 files
    // 2. downloading cover arts
    // 3. renaming folders
    // 4. disabling drag & drop
    if (isGainOnlyCommandlineModus){
        setGUI_To();
        if (isAutoExit()) Quit();
        return;
    }

    if ((!isAutorenameFiles() && !isAutorenameFolder() && !isDownloadCovers()) || !isid3v2Found()){
        setGUI_To(IDLE);
        resetVariables();
        if (isAutoExit()) Quit();
        return;
    }

    setIsDragDropAllowed(false);
    RenameFiles->startRenaming(allFiles, isAutorenameFiles(), isAutorenameFolder(), isDownloadCovers(), TemplateFolderRename(), TemplateFileRename(), searchEngine());
}

// *********************************************************************************************
// Start TrackGain
// *********************************************************************************************
void QtGain::processFiles_TrackGain(){

    // Cancel gaining
    if (isOperationCanceled()){
        setGUI_To(RESET_ALL);
        resetVariables();
        return;
    }

    // Check output of replay gain tools
    processOutput();

    if (finishedFiles() < allFiles.size()){

        QStringList Parameter;
        QFileInfo file(allFiles[finishedFiles()]);
        ui.Foldername->setText(file.path().mid(file.path().lastIndexOf("/") + 1).left(30));
        ui.Filename->setText(FilenameWithoutPath(finishedFiles()).left(30));

        // MP3
        if (allFiles[finishedFiles()].endsWith(".mp3", Qt::CaseInsensitive)){
            ui.FileFormatIcon->setPixmap(QPixmap(":/Icons/mp3.png"));

            Parameter << "-d" << QString("%1.0").arg(Volume() - 89) << "-r" << "-c" << allFiles[finishedFiles()];
            TrackGainProcess->start(MP3GainBinaryPath(), Parameter);
        }

        // MP4 / m4a
        else if (allFiles[finishedFiles()].contains(QRegExp("\\.(mp4|m4a)$", Qt::CaseInsensitive))){
            ui.FileFormatIcon->setPixmap(QPixmap(":/Icons/m4a.png"));

            Parameter << "-d" << QString("%1.0").arg(Volume() - 89) << "-r" << "-c" << allFiles[finishedFiles()];
            TrackGainProcess->start(MP4GainBinaryPath(), Parameter);
        }

        // Ogg-Vorbis
        else if (allFiles[finishedFiles()].endsWith(".ogg", Qt::CaseInsensitive)){
            ui.FileFormatIcon->setPixmap(QPixmap(":/Icons/ogg.png"));
            Parameter << "-f" << allFiles[finishedFiles()]; // vorbisgain allways gains to 89dB in track mode
            TrackGainProcess->start(VorbisGainBinaryPath(), Parameter);
        }

        // FLAC
        else if (allFiles[finishedFiles()].endsWith(".flac", Qt::CaseInsensitive)){
            ui.FileFormatIcon->setPixmap(QPixmap(":/Icons/flac.png"));
            Parameter << "--add-replay-gain" << allFiles[finishedFiles()];
            TrackGainProcess->start(FlacGainBinaryPath(), Parameter);
        }
    }

    // Update GUI
    updateGUIInfos(ui.Statustext->text(),
                   ui.Foldername->text(),
                   ui.Filename->text(),
                   allFiles.size() - finishedFiles(),
                   Errors(),
                   skippedFiles(),
                   qMax(0, finishedFiles() - skippedFiles() - Errors()),
                   finishedFiles(),
                   allFiles.size(),
                   false);

    if (allFiles.size() == finishedFiles()) {
        if ((!isAutorenameFiles() && !isAutorenameFolder() && !isDownloadCovers()) || !isid3v2Found()){
            setGUI_To(IDLE);
            resetVariables();
            if (isAutoExit()) Quit();
            return;
        }

        // Gaining is finished, now we starting id3v2 and
        // 1. renaming files with the tags of the mp3 files
        // 2. downloading cover arts
        // 3. renaming folders
        // 4. disabling drag & drop
        if (isGainOnlyCommandlineModus){
            setGUI_To();
            if (isAutoExit()) Quit();
            return;
        }

        setIsDragDropAllowed(false);
        RenameFiles->startRenaming(allFiles, isAutorenameFiles(), isAutorenameFolder(), isDownloadCovers(), TemplateFolderRename(), TemplateFileRename(), searchEngine());
    }
    else {
        setCurrentFileName(allFiles[finishedFiles()]);
        addFinishedFiles();
    }
}


// *********************************************************************************************
// Check the output of Replay gain tools
// *********************************************************************************************
void QtGain::processOutput(){

    QString Output(TrackGainProcess->readAll());

    // No media file
    if (Output.contains("not a layer III file")                            ||
            Output.contains("File does not contain Vorbis data")           ||
            Output.contains("The file does not appear to be a FLAC file.") ||
            Output.contains("Can't find any valid MP3 frames in file")
            ){
        addErrors();
        addToErrorlog(tr("<font color='red'>Not a valid media file</font> :: %1<br>").arg(currentFileName()));
    }

    // Cannot access file
    else if (Output.contains("for reading")){
        addErrors();
        addToErrorlog(tr("<font color='red'>Cannot read file</font> :: %1<br>").arg(currentFileName()));
    }

    // Cannot write
    else if (Output.contains("Permission denied") || Output.contains("for modifying")){
        addErrors();
        addToErrorlog(tr("<font color='red'>Cannot write file</font> :: %1<br>").arg(currentFileName()));
    }

    // File already gained (only MP3 and Ogg-Vorbis)
    else if (Output.contains("are necessary") || Output.contains("Tags present;")){

        // File was fully analyzed but no need to update the file only tags:
        // we count this as Gained (mp3gain)
        if (!Output.contains("but tag needs update:")){
            addSkippedFiles();
            if (isLogSkippedFiles()) addToErrorlog(tr("<font color='green'>File already gained -> skipped</font> :: %1<br>").arg(currentFileName()));
        }
    }
}


// *********************************************************************************************
// Search for all files, including subdirs
// *********************************************************************************************
void QtGain::findFiles(const QString &dirName){
    if (!Timer->isActive()) setGUI_To(BUSY, tr("Scanning directories..."));
    setOperationCanceled(false);

    QDirIterator it(dirName, QDirIterator::Subdirectories);
    QString temp;
    while (it.hasNext()) {
        qApp->processEvents(QEventLoop::AllEvents);

        // Cancel scanning
        if (isOperationCanceled()){
            setGUI_To(RESET_ALL);
            resetVariables();
            return;
        }

        ui.sumFilesUnprocessed->display(allFiles.size() - finishedFiles());
        temp = it.next();
        if (
                ((temp.endsWith(".mp3",  Qt::CaseInsensitive) && isMP3GainFound())    ||
                 (temp.endsWith(".ogg",  Qt::CaseInsensitive) && isVorbisGainFound()) ||
                 (temp.endsWith(".flac", Qt::CaseInsensitive) && isFlacGainFound())   ||
                 (temp.contains(QRegExp("\\.(mp4|m4a)$", Qt::CaseInsensitive)) && isMP4GainFound())
                 ) && !allFiles.contains(temp)) allFiles << temp;
    }

    ui.sumFilesUnprocessed->display(allFiles.size() - finishedFiles());
}


void QtGain::dragEnterEvent(QDragEnterEvent *event){
    // Drag & Drop is only allowed during gaining or idle state
    if (!isDragDropAllowed()) event->ignore();
    else if (event->mimeData()->hasFormat("text/uri-list")) event->acceptProposedAction();
}


// *********************************************************************************************
// Add files/directories via drag & drop
// *********************************************************************************************
void QtGain::dropEvent(QDropEvent *event){
    QList<QUrl> urls = event->mimeData()->urls();
    if (urls.isEmpty()) return;

    processRawFileList(urls);
}


void QtGain::processRawFileList(QList<QUrl> &urls){
    QFileInfo Tempfile;
    QString temp;

    for (int i=0; i<urls.count(); i++){
        qApp->processEvents(QEventLoop::AllEvents);

        Tempfile = urls[i].toLocalFile();
        temp = Tempfile.absoluteFilePath();

        if (
                ((temp.endsWith(".mp3",  Qt::CaseInsensitive) && isMP3GainFound())    ||
                 (temp.endsWith(".ogg",  Qt::CaseInsensitive) && isVorbisGainFound()) ||
                 (temp.endsWith(".flac", Qt::CaseInsensitive) && isFlacGainFound())   ||
                 (temp.contains(QRegExp("\\.(mp4|m4a)$", Qt::CaseInsensitive)) && isMP4GainFound())
                 ) && !Tempfile.isDir() && !allFiles.contains(temp)) allFiles << temp;
        else if (Tempfile.isDir()) findFiles(Tempfile.absoluteFilePath());

        // Cancel
        if (isOperationCanceled()){
            setGUI_To(RESET_ALL);
            resetVariables();
            return;
        }
    }
    processFoundFiles();
}


// *********************************************************************************************
// Show file dialog at startup
// *********************************************************************************************
void QtGain::openDirectoryDialog(){
    QString directory = QFileDialog::getExistingDirectory(this, tr("Please choose a directory"),
                                                          QDir::homePath() + "/Desktop", QFileDialog::DontResolveSymlinks | QFileDialog::ShowDirsOnly);
    if (directory.isEmpty()) return;

    findFiles(directory);
    processFoundFiles();
}

// *********************************************************************************************
// Used by openDirectoryDialog and processRawFileList
// *********************************************************************************************
void QtGain::processFoundFiles(){
    if (allFiles.size() > 0){

        // Skip Replay Gain when not selected
        if (!isReplayGain()){
            processAlbumGain_Coverdownload();
            return;
        }

        setGUI_To(BUSY);
        isTrackGain() ? processFiles_TrackGain() : processFiles_AlbumGain();
    } else {
        setGUI_To(IDLE, tr("No media files found..."));
        resetVariables();
    }
}



// *********************************************************************************************
// Show settings dialog
// *********************************************************************************************
void QtGain::showPreferencesDialog(){
    Preferences Preferences(this);

    Preferences.MP3GainPfad->setText(MP3GainBinaryPath());
    Preferences.MP4GainPfad->setText(MP4GainBinaryPath());
    Preferences.VorbisGainPfad->setText(VorbisGainBinaryPath());
    Preferences.FlacGainPfad->setText(FlacGainBinaryPath());
    Preferences.id3v2Path->setText(id3v2BinaryPath());
    Preferences.setIcons();

    Preferences.TemplateFolderRename->setText(TemplateFolderRename());
    Preferences.TemplateFileRename->setText(TemplateFileRename());
    Preferences.Pegel->setValue(Volume());
    Preferences.isAlbumGain->setChecked(!isTrackGain());
    Preferences.isStartBrowserAtStartup->setChecked(isShowBrowserAtStatup());
    Preferences.isLogSkippedFiles->setChecked(isLogSkippedFiles());
    Preferences.isAutoExit->setChecked(isAutoExit());

    Preferences.isReplayGain->setChecked(isReplayGain());
    Preferences.isAutorenameFiles->setChecked(isAutorenameFiles());
    Preferences.isAutorenameFolder->setChecked(isAutorenameFolder());
    Preferences.isDownloadCovers->setChecked(isDownloadCovers());
    Preferences.searchEngine->setCurrentIndex(searchEngine());
    Preferences.exec();


    if (Preferences.result() == QDialog::Accepted){
        // Save new settings
        setMP3GainBinaryPath(Preferences.MP3GainPfad->text());
        setMP4GainBinaryPath(Preferences.MP4GainPfad->text());
        setVorbisGainBinaryPath(Preferences.VorbisGainPfad->text());
        setFlacGainBinaryPath(Preferences.FlacGainPfad->text());
        setVolume(Preferences.Pegel->value());
        setTrackGain(Preferences.isTrackGain->isChecked());
        setShowBrowserAtStatup(Preferences.isStartBrowserAtStartup->isChecked());
        setIsLogSkippedFiles(Preferences.isLogSkippedFiles->isChecked());
        setIsAutoExit(Preferences.isAutoExit->isChecked());

        setid3v2BinaryPath(Preferences.id3v2Path->text());
        setTemplateFolderRename(Preferences.TemplateFolderRename->text());
        setTemplateFileRename(Preferences.TemplateFileRename->text());

        setIsReplayGain(Preferences.isReplayGain->isChecked());
        setIsAutorenameFolder(Preferences.isAutorenameFolder->isChecked());
        setisAutorenameFiles(Preferences.isAutorenameFiles->isChecked());
        setIsDownloadCovers(Preferences.isDownloadCovers->isChecked());
        setSearchEngine(Preferences.searchEngine->currentIndex());
        if (!isReplayGain() && !isAutorenameFiles() && !isAutorenameFolder() && !isDownloadCovers()) setIsReplayGain(true);

        // Check if Replay gain tools are available
        setIsMP3GainFound   (QFile::exists(MP3GainBinaryPath()));
        setIsMP4GainFound   (QFile::exists(MP4GainBinaryPath()));
        setIsVorbisGainFound(QFile::exists(VorbisGainBinaryPath()));
        setIsFlacGainFound  (QFile::exists(FlacGainBinaryPath()));
        setid3v2Found       (QFile::exists(id3v2BinaryPath()));
    }
}


// *********************************************************************************************
// Load settings
// *********************************************************************************************
void QtGain::loadSettings(){
    QSettings settings("Vegeta", "QtGain");
    move(settings.value("pos", QPoint(200, 200)).toPoint());
    setMP3GainBinaryPath   (settings.value("MP3Gain",    "/usr/bin/mp3gain").toString());
    setMP4GainBinaryPath   (settings.value("aacgain",    "/usr/bin/aacgain").toString());
    setVorbisGainBinaryPath(settings.value("VorbisGain", "/usr/bin/vorbisgain").toString());
    setFlacGainBinaryPath  (settings.value("FlacGain",   "/usr/bin/metaflac").toString());
    setVolume(settings.value("Volume", 89).toInt());

    setTrackGain(settings.value("TrackGain",                    true).toBool());
    setShowBrowserAtStatup(settings.value("ShowBrowser",        false).toBool());
    setStatistic(settings.value("filesProcessed", 0).toInt(), settings.value("filesGained", 0).toInt(), settings.value("installDate", QDate::currentDate()).toDate());
    setIsLogSkippedFiles(settings.value("isLogSkippedFiles",   false).toBool());
    setIsAutoExit(settings.value("isAutoExit",                 false).toBool());

    setIsReplayGain(settings.value("isReplayGain",              true).toBool());
    setIsAutorenameFolder(settings.value("isAutorenameFolder", false).toBool());
    setisAutorenameFiles(settings.value("isAutorenameFiles",   false).toBool());
    setIsDownloadCovers(settings.value("isDownloadCovers",     false).toBool());
    setSearchEngine(settings.value("SearchEngine", 0).toInt());

    setTemplateFolderRename(settings.value("TemplateFolderRename", tr("%Artist - %Album")).toString());
    setTemplateFileRename(settings.value("TemplateFileRename", tr("%Artist - %Song")).toString());

    // Fallback falls Replay-Gain-Tools über die geladenen Infos nicht gefunden werden können
    if (!QFile::exists(MP3GainBinaryPath()))    setMP3GainBinaryPath("/usr/bin/mp3gain");
    if (!QFile::exists(MP4GainBinaryPath()))    setMP4GainBinaryPath("/usr/bin/aacgain");
    if (!QFile::exists(VorbisGainBinaryPath())) setVorbisGainBinaryPath("/usr/bin/vorbisgain");
    if (!QFile::exists(FlacGainBinaryPath()))   setFlacGainBinaryPath("/usr/bin/metaflac");
    if (!QFile::exists(id3v2BinaryPath()))      setid3v2BinaryPath("/usr/bin/id3v2");

    // Check if Replay gain tools are available
    setIsMP3GainFound   (QFile::exists(MP3GainBinaryPath()));
    setIsMP4GainFound   (QFile::exists(MP4GainBinaryPath()));
    setIsVorbisGainFound(QFile::exists(VorbisGainBinaryPath()));
    setIsFlacGainFound  (QFile::exists(FlacGainBinaryPath()));
    setid3v2Found       (QFile::exists(id3v2BinaryPath()));

    if (!isMP3GainFound() && !isMP4GainFound() && !isVorbisGainFound() && !isFlacGainFound()) ui.Statustext->setText(tr("<font color=red>No replay gain tools found!</font>"));
}


// *********************************************************************************************
// Save settings
// *********************************************************************************************
void QtGain::saveSettings(){
    QSettings settings("Vegeta", "QtGain");
    settings.setValue("pos",                  pos());
    settings.setValue("MP3Gain",              MP3GainBinaryPath());
    settings.setValue("aacgain",              MP4GainBinaryPath());
    settings.setValue("VorbisGain",           VorbisGainBinaryPath());
    settings.setValue("FlacGain",             FlacGainBinaryPath());
    settings.setValue("Volume",               Volume());
    settings.setValue("TrackGain",            isTrackGain());
    settings.setValue("ShowBrowser",          isShowBrowserAtStatup());
    settings.setValue("isLogSkippedFiles",    isLogSkippedFiles());
    settings.setValue("isAutoExit",           isAutoExit());
    settings.setValue("isReplayGain",         isReplayGain());
    settings.setValue("isAutorenameFolder",   isAutorenameFolder());
    settings.setValue("isAutorenameFiles",    isAutorenameFiles());
    settings.setValue("isDownloadCovers",     isDownloadCovers());
    settings.setValue("SearchEngine",         searchEngine());
    settings.setValue("TemplateFolderRename", TemplateFolderRename());
    settings.setValue("TemplateFileRename",   TemplateFileRename());


    int filesProcessed, filesGained;
    QDate installDate;
    Statistic(filesProcessed, filesGained, installDate);
    settings.setValue("filesProcessed",    filesProcessed);
    settings.setValue("filesGained",       filesGained);
    settings.setValue("installDate",       installDate);
}


// *********************************************************************************************
// Close the application and save settings
// *********************************************************************************************
void QtGain::Quit() {
    saveSettings();
    QApplication::quit();
}

void QtGain::closeEvent(QCloseEvent *event){
    Q_UNUSED(event);
    Quit();
}


// *********************************************************************************************
// About dialog
// *********************************************************************************************
void QtGain::showAboutDialog() {
    int filesProcessed, filesGained;
    QDate installDate;
    Statistic(filesProcessed, filesGained, installDate);

    QMessageBox::information(this, tr("About"),
                             tr("<h2>%1</h2>"
                                "Replay Gain frontend for MP3Gain, VorbisGain, AACGain and Metaflac.<br>"
                                "Uses id3v2 to rename files/folders of MP3 files.<br>"
                                "Cover Arts Downloader via Amazon or Google Picture Search.<br><br>"
                                "(c) 2007-2011, Vegeta<br>"
                                "<a href='http://qt-apps.org/content/show.php/QtGain?content=56842'>Project page</a><br><br>"
                                "QtGain 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.<br>"
                                "<h4>Thanks to the following translator(s):</h4>"
                                "%5"
                                "<h4>Statistic:</h4>QtGain has %2 files processed (%3 files were replay gained) since %4.").arg(VERSION).arg(filesProcessed).arg(filesGained).arg(installDate.toString("dd.MM.yyyy"))
                             .arg("Pavel Fric (Czech)<br>")
                             );
}


// *********************************************************************************************
// Updates the time that has left since start gaining
// *********************************************************************************************
void QtGain::updateGUI() {
    ui.Time->setText(TimeUpdateString());
}


// *********************************************************************************************
// Cancel all operations
// *********************************************************************************************
void QtGain::cancelOperation() {
    setOperationCanceled(true);
    RenameFiles->cancelAllOperations();

    TrackGainProcess->close();
    AlbumGainProcess->close();
    FlacAlbumGainProcess->close();

    setGUI_To(RESET_ALL);
}


// *********************************************************************************************
// Show Error-Log
// *********************************************************************************************
void QtGain::showErrors() {
    if (ErrorLog().isEmpty()) return;

    QDialog window(this);
    QTextEdit Text;
    Text.setReadOnly(true);
    Text.setText(ErrorLog());
    window.setWindowTitle(tr("Errorlog"));
    window.setMinimumSize(850, 500);
    QPushButton showMessageButton(tr("Close"));
    showMessageButton.setDefault(true);

    QGridLayout messageLayout;
    messageLayout.addWidget(&Text,0,0);
    messageLayout.addWidget(&showMessageButton);
    window.setLayout(&messageLayout);

    connect(&showMessageButton, SIGNAL(clicked()), &window, SLOT(close()));
    window.exec();
}


// *********************************************************************************************
// Change state of GUI
// *********************************************************************************************
void QtGain::setGUI_To(int const &Status, QString Message){
    if (Status == IDLE || Status == RESET_ALL){
        actionCancelOperation->setEnabled(false);
        Timer->stop();

        if (Message.isEmpty()) isOperationCanceled() ? ui.Statustext->setText(tr("Operation aborted...")) : isReplayGain() ? ui.Statustext->setText(isTrackGain() ? tr("TrackGain finished!") : tr("AlbumGain finished!")) : ui.Statustext->setText(tr("Operation finished!"));
        else ui.Statustext->setText(Message);
        ui.Foldername->clear();
        ui.Filename->clear();
        ui.FileFormatIcon->setPixmap(QPixmap(":/Icons/audio.png"));

        // Context menu
        actionAbout->setEnabled(true);
        actionShowSettings->setEnabled(true);
        actionQuit->setEnabled(true);

        showErrors();
        resetVariables();
        resetErrorlog();

        if (Status == RESET_ALL){
            ui.progressBar->setMaximum(100);
            ui.progressBar->reset();
            updateGUIInfos(ui.Statustext->text(), "", "", 0, 0, 0, 0, 0, 100, false);

            ui.Time->setText("00:00:00");
            ui.FolderIcon->setPixmap(QPixmap(":/Icons/folder.png"));
            FlacAlbumGainProcess->close();
            TrackGainProcess->close();
            AlbumGainProcess->close();
        }

        if (!isOperationCanceled() && isAutoExit()) {
            Quit();
            return;
        }


    } else if (Status == BUSY) {
        actionCancelOperation->setEnabled(true);
        setStartTime();
        Timer->start(1000);

        updateGUIInfos(Message.isEmpty() ? (isTrackGain() ? tr("TrackGain in process...") : tr("AlbumGain in process...")) : Message, "", "", 0, 0, 0, 0, 0, 100, false);

        actionAbout->setEnabled(false);
        actionShowSettings->setEnabled(false);
        actionQuit->setEnabled(false);

        ui.Time->setText("00:00:00");
    }
}


// *********************************************************************************************
// Update GUI-Infos via Slot/Signal
// *********************************************************************************************
void QtGain::updateGUIInfos(QString Statustext,
                            QString Foldertext,
                            QString Filetext,
                            int ToDo,
                            int Error,
                            int Skipped,
                            int Gained,
                            int progressBarValue,
                            int progressBarMax,
                            bool setDownloadIcon){

    ui.Statustext->setText(Statustext);
    ui.Foldername->setText(Foldertext);
    ui.Filename->setText(Filetext);
    ui.sumFilesUnprocessed->display(ToDo);
    ui.sumErrors->setNum(Error);
    ui.sumFilesSkipped->setNum(Skipped);
    ui.sumFilesGained->setNum(Gained);
    ui.progressBar->setValue((progressBarValue * 100) / progressBarMax);


    if (setDownloadIcon){
        ui.FolderIcon->setPixmap(QPixmap(":/Icons/Download.png"));
        ui.FileFormatIcon->clear();
        ui.Filename->clear();
        ui.sumFilesGained->setEnabled(false);
        ui.labelText_Gained->setEnabled(false);
    } else {
        ui.sumFilesGained->setEnabled(true);
        ui.labelText_Gained->setEnabled(true);
    }
}


// *********************************************************************************************
// Donate message, please do not change
// *********************************************************************************************
void QtGain::Donate(){

    QMessageBox::information(this, tr("QtGain"),
                             tr("<h2>Donate</h2>"
                                "Thank you for your interest in donating money to the QtGain project to support further development."
                                "<hr><center>You can donate via PayPal"
                                "<h4>%1</h4>"
                                "or"
                                "<h4>%2</h4>"
                                "by clicking on the above links.</center><hr>"
                                "Thank you for your support!"
                                )
                             .arg("<a href='https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=URQFHPDHQW336'>5 Euro</a>")
                             .arg("<a href='https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=T62B9KWHB7UWU'>10 Euro</a>")
                             );
}
