/***************************************************************************
                          ProgressDialog.cpp  -  description
                             -------------------
    begin                : Die Mai 15 15:34:19 CEST 2001
    copyright            : (C) 2001 by Dominik Seichter
    email                : domseichter@web.de
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 ***************************************************************************/

// TQt Includes
#include <tqlayout.h>
#include <tqprogressbar.h>
#include <tqtimer.h>
#include <tqtooltip.h>

// TDE includes
#include <tdeapplication.h>
#include <kiconloader.h>
#include <tdelistview.h>
#include <tdelocale.h>
#include <tdepopupmenu.h>
#include <kpushbutton.h>
#include <krun.h>

#include <tqfile.h>

// Own includes
#include "ProgressDialog.h"
#include "krenameimpl.h"
#include "undodialog.h"
#include "fileoperation.h"

#define MNU_ERROR_ID 33999
#define MNU_DONE_ID 33998

// update user interface every 1/2 second
#define TIMER_INTERVAL 500

ProgressDialog::ProgressDialog( TQWidget* parent, const char* name, WFlags fl )
    : TQWidget( parent, name, fl )
{
    renamedFiles = NULL;

    resize( 400, 380 );
    setCaption( i18n("Progress") );
    setIcon( BarIcon( "krename" ) );

    ProgressDialogLayout = new TQVBoxLayout( this, 11, 6 );
    Layout1 = new TQHBoxLayout( 0, 0, 6 );
    TQHBoxLayout* Layout2 = new TQHBoxLayout( 0, 6, 6 );

    bar = new TQProgressBar( this );
    bar->setProgress( 0 );

    buttonCancel = new KPushButton( i18n("&Cancel"), this );

    display = new TDEListView( this );
    display->addColumn( i18n("Messages") );
    display->addColumn( "sort" );
    display->setColumnWidthMode( 0, TQListView::Maximum );
    display->setColumnWidthMode( 1, TQListView::Manual );
    display->setColumnWidth( 1, 0 );
    display->setSorting( -1 );
    display->setUpdatesEnabled( false );
    
    TQSpacerItem* spacer = new TQSpacerItem( 20, 20, TQSizePolicy::Minimum, TQSizePolicy::Minimum );

    buttonUndo = new KPushButton( this );
    buttonUndo->setText( i18n("&Undo") );
    buttonUndo->setEnabled( false );
    
    mnuButton = new TDEPopupMenu( this );
    mnuButton->insertItem( i18n("Restart KRename..."), this, TQ_SLOT( restart() ));
    mnuButton->insertSeparator();
    mnuButton->insertItem( i18n("Rename Processed Files &Again..."), this, TQ_SLOT( again() ), 0, MNU_DONE_ID );
    mnuButton->insertItem( i18n("Rename Unprocessed Files &Again..."), this, TQ_SLOT( unAgain() ), 0, MNU_ERROR_ID );
    mnuButton->insertItem( i18n("Rename All Files &Again..."), this, TQ_SLOT( allAgain() ));
    buttonRestart = new KPushButton( this );
    buttonRestart->setText( i18n( "&Rename More..." ) );
    buttonRestart->setPopup( mnuButton );
    buttonRestart->setEnabled( false );
    
    buttonOpenDest = new KPushButton( this );
    buttonOpenDest->setText( i18n("&Open Destination...") );

    buttonClose = new KPushButton( this );
    buttonClose->setText( i18n( "&Close" ) );
    buttonClose->setEnabled( false );

    Layout1->addItem( spacer );
    Layout1->addWidget( buttonUndo );
    Layout1->addWidget( buttonRestart );
    Layout1->addWidget( buttonOpenDest );
    Layout1->addWidget( buttonClose );
    Layout1->addItem( spacer );

    Layout2->addWidget( bar );
    Layout2->addWidget( buttonCancel );
    Layout2->setStretchFactor( bar, 2 );

    ProgressDialogLayout->addLayout( Layout2 );
    ProgressDialogLayout->addWidget( display );
    ProgressDialogLayout->addLayout( Layout1 );

    connect( buttonClose, TQ_SIGNAL(clicked()), this, TQ_SLOT(quitAll()));
    connect( buttonOpenDest, TQ_SIGNAL(clicked()), this, TQ_SLOT(openDest()));
    connect( buttonCancel, TQ_SIGNAL( clicked()), this, TQ_SLOT(canceled() ));
    connect( buttonUndo, TQ_SIGNAL( clicked() ), this, TQ_SLOT( undo() ) );
    
    m_count = 0;
    m_canceled = false;
    m_timer = new TQTimer( this, "m_timer" );
    connect( m_timer, TQ_SIGNAL( timeout() ), this, TQ_SLOT( slotTimer() ) );
    
    hide();
}

ProgressDialog::~ProgressDialog()
{
    delete m_timer;

    if( renamedFiles )
        delete [] renamedFiles;
}

void ProgressDialog::print( TQString text, TQString pixmap )
{
    if( !m_timer->isActive() )
    {
        TDEApplication::setOverrideCursor( TQt::waitCursor );
        m_timer->start( TIMER_INTERVAL );
    }
    
    // set an icon if we have none yet
    if( pixmap.isNull() )
        pixmap = "ok";
        
    TDEListViewItem* item = new TDEListViewItem( display, text, count() );
    item->setPixmap( 0, SmallIcon(pixmap) );
    display->insertItem( item );
}

void ProgressDialog::error( TQString text )
{
    if( !m_timer->isActive() )
    {
        TDEApplication::setOverrideCursor( TQt::waitCursor );
        m_timer->start( TIMER_INTERVAL );
    }

    //TODO: simplify this (breaks i18n)
    TDEListViewItem* item = new TDEListViewItem( display, i18n("Error: %1").arg( TQString() ) + simplify( text ), count() );
    item->setPixmap( 0, SmallIcon("cancel") );
    display->insertItem( item );
}

void ProgressDialog::warning( TQString text )
{
    if( !m_timer->isActive() )
    {
        TDEApplication::setOverrideCursor( TQt::waitCursor );
        m_timer->start( TIMER_INTERVAL );
    }

    TDEListViewItem* item = new TDEListViewItem( display, i18n("Warning: %1").arg( TQString() ) + simplify( text ), count() );
    item->setPixmap( 0, SmallIcon("idea") );
    display->insertItem( item );
}

void ProgressDialog::quitAll()
{
    TDEApplication::exit(0);
}

void ProgressDialog::done( int errors, int successfull, bool allowundo )
{
    m_timer->stop();
    TDEApplication::restoreOverrideCursor();

    display->setUpdatesEnabled( true );
    display->setSorting( 1, true );
    display->sort();
    display->setSorting( -1 );
    display->triggerUpdate();
    display->ensureItemVisible( display->lastItem() );

    bar->setProgress( bar->totalSteps() );
    mnuButton->setItemEnabled( MNU_ERROR_ID, errors );
    mnuButton->setItemEnabled( MNU_DONE_ID, successfull );
    
    buttonClose->setEnabled( true );
    buttonRestart->setEnabled( true );
    if( allowundo )
        buttonUndo->setEnabled( true );
    buttonCancel->setEnabled( false );

    kapp->processEvents( 0 );
}

void ProgressDialog::show()
{
    TQWidget::show();

    int w = kapp->desktop()->width();
    int h = kapp->desktop()->height();
    move( (w-width())/2,(h-height())/2 );
}

void ProgressDialog::restart()
{
    TQWidget* krename = KRenameImpl::launch( TQRect( 0, 0, 0, 0 ), KURL::List() );
    krename->show();
    close();
}

void ProgressDialog::again()
{
    KURL::List list;
    for( unsigned int i = 0; i < m_size; i++ )
        if( !renamedFiles[i].error )
            list.append( renamedFiles[i].dst );

    TQWidget* krename = KRenameImpl::launch( TQRect( 0, 0, 0, 0 ), list );
    krename->show();
    close();
}

void ProgressDialog::unAgain()
{
    KURL::List list;
    for( unsigned int i = 0; i < m_size; i++ )
        if( renamedFiles[i].error )
            list.append( renamedFiles[i].src );
    
    TQWidget* krename = KRenameImpl::launch( TQRect( 0, 0, 0, 0 ), list );
    krename->show();
    close();
}

void ProgressDialog::allAgain()
{
    KURL::List list;
    for( unsigned int i = 0; i < m_size; i++ )
        list.append( renamedFiles[i].error ? renamedFiles[i].src : renamedFiles[i].dst );
    
    TQWidget* krename = KRenameImpl::launch( TQRect( 0, 0, 0, 0 ), list );
    krename->show();
    close();
}

void ProgressDialog::openDest()
{
    new KRun( m_dest );
}

TQString ProgressDialog::count()
{
    TQString s;
    return s.sprintf( "%0*i", 7, ++m_count );
}

void ProgressDialog::setProgressTotalSteps( int t )
{
    bar->setTotalSteps( t );
}

void ProgressDialog::setProgress( int p )
{
    m_timer->start( TIMER_INTERVAL );
       
    bar->setProgress( p );
}

void ProgressDialog::canceled()
{
    warning( i18n("User pressed cancel!") );
    warning( i18n("Aborting...") );
    m_canceled = true;
}

const TQString ProgressDialog::simplify( const TQString & text )
{
    // make error messages fit in one line!
    TQString t( text );
    t.remove( '\n' );

    return t;
}

void ProgressDialog::undo()
{
    KURL::List list;
    FileOperation fop;
    
    m_timer->start( TIMER_INTERVAL );
    TDEApplication::setOverrideCursor( TQt::waitCursor );
    for( unsigned int i = 0; i < m_size; i++ )
    {
        setProgress( i );
        list.append( renamedFiles[i].src );
        if( !renamedFiles[i].error )
        {
            if( renamedFiles[i].dir ) { 
                /** handle renamed directories and their contents
                  */
                TQString ddir = renamedFiles[i].dst.path();
                TQString sdir = renamedFiles[i].src.path();
                for( unsigned int c = i+1; c < m_size; c++ ) {
                    TQString dpath = renamedFiles[c].dst.path();
                    TQString spath = renamedFiles[c].src.path();

                    if( spath.startsWith( ddir ) )
                    {
                        spath = sdir + spath.right( spath.length() - ddir.length() );
                        renamedFiles[c].src.setPath( spath );
                    }
                    
                    
                    if( dpath.startsWith( ddir ) )
                    {
                        dpath = sdir + dpath.right( dpath.length() - ddir.length() );
                        renamedFiles[c].dst.setPath( dpath );
                    }
                }
            }
            
            if(!fop.start( renamedFiles[i].dst, renamedFiles[i].src, MOVE, false ))
                error( i18n("Undo: ") + fop.error() );
        }
    }
    
    print( i18n("Undoing the renaming operation has been completed."), "undo" );
    m_timer->stop();
    TDEApplication::restoreOverrideCursor();
        
    TQWidget* krename = KRenameImpl::launch( TQRect( 0, 0, 0, 0 ), list );
    krename->show();
    close();
}

void ProgressDialog::slotTimer()
{
    kapp->processEvents( 0 );
}

#include "ProgressDialog.moc"
