/***************************************************************************
                          krenameimpl.cpp  -  description
                             -------------------
    begin                : Die Mai 20 2003
    copyright            : (C) 2003 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.                                   *
 *                                                                         *
 ***************************************************************************/

#include "krenameimpl.h"

// Own includes
#include "ProgressDialog.h"
#include "confdialog.h"
#include "fileoperation.h"
#include "kmylistview.h"
#include "kmyhistorycombo.h"
#include "pluginloader.h"
#include "replacedialog.h"
#include "undodialog.h"
#include "helpdialog.h"
#include "coorddialog.h"
#include "numberdialog.h"
#include "firststartdlg.h"
#include "wizard.h"
#include "tabs.h"
#include "dsdirselectdialog.h"
#include "krenamedcop.h"
#include "profiledlg.h"

// TDE includes
#include <dcopclient.h>
#include <tdeaboutapplication.h>
#include <tdeapplication.h>
#include <tdeaction.h>
#include <tdecmdlineargs.h>
#include <kdirselectdialog.h>
#include <tdefiledialog.h>
#include <tdefileitem.h>
#include <khelpmenu.h>
#include <kiconloader.h>
#include <tdemessagebox.h>
#include <tdemenubar.h>
#include <tdepopupmenu.h>
#include <kurlrequester.h>
#include <tdetempfile.h> 
#include <tdelocale.h>
#include <tdeio/netaccess.h>

// TQt includes
#include <tqbuttongroup.h>
#include <tqcursor.h>
#include <tqgrid.h>
#include <tqlabel.h>
#include <tqlayout.h>
#include <tqradiobutton.h>
#include <tqrect.h>
#include <tqregexp.h>
#include <tqtabwidget.h>
#include <tqtimer.h>
#include <tqtooltip.h>
#include <tqvgroupbox.h>
#include <tqvbox.h>
#include <tqvbuttongroup.h>
#include <tqwidget.h>
#include <tqwidgetstack.h> 

#define ID_WIZARD 2905
#define ID_TAB 2904

TQCString pageTitle[] = {
    I18N_NOOP( "F&iles" ),
    I18N_NOOP( "Des&tination" ),
    I18N_NOOP( "P&lugins" ),
    I18N_NOOP( "File&name" )
};

KPushButton* createButton( KGuiItem item, TQWidget* parent )
{
    return new KPushButton( item.iconSet(), item.text(), parent );
}

KRenameImpl::KRenameImpl( TQWidget* p, KMenuBar* m, TQPushButton* finish )
    : DCOPObject( "KRename" ), TQObject( (TQObject*)p ),
      parent( p ), menuBar( m ), finishButton( finish )
{
    m_hasCommandlineProfile = false;

    // Load Plugins
    plugin = PluginLoader::instance();
    helpDialogData = new HelpDialogData();
    // Maybe parent instead of 0 but might crash when switching from wizard to tab mode
    helpDialog = new HelpDialog( helpDialogData, NULL, NULL, false );

    m_switching = false;
    
    kapp->dcopClient()->registerAs( kapp->name() );

}

KRenameImpl::~KRenameImpl()
{
    delete helpDialog;
}

int KRenameImpl::numRealTimePreview = -1;

void KRenameImpl::setup( bool wizardmode )
{
    parent->setCaption( "KRename" ); // "KRename by Dominik Seichter
    setupActions();
    setupPages();
    updateCount();

    connect( buttonAdd, TQ_SIGNAL( clicked() ), this, TQ_SLOT( addFile() ));
    connect( buttonRemoveAll, TQ_SIGNAL( clicked()), this, TQ_SLOT( clearList() ));
    connect( buttonRemove, TQ_SIGNAL( clicked()), this, TQ_SLOT( removeFile() ));
    connect( buttonHelp, TQ_SIGNAL( clicked()), this, TQ_SLOT( showTokenHelp() ));
    connect( finishButton, TQ_SIGNAL( clicked()), this, TQ_SLOT( start() ));

    connect( checkExtension, TQ_SIGNAL( clicked()), this, TQ_SLOT( enableControls() ));
    connect( optionRename, TQ_SIGNAL( clicked()), this, TQ_SLOT( enableControls() ));
    connect( optionMove, TQ_SIGNAL( clicked()), this, TQ_SLOT( enableControls() ));
    connect( optionCopy, TQ_SIGNAL( clicked()), this, TQ_SLOT( enableControls() ));
    connect( optionLink, TQ_SIGNAL( clicked()), this, TQ_SLOT( enableControls() ));
    connect( checkUndoScript, TQ_SIGNAL( clicked()), this, TQ_SLOT( enableControls() ));

    connect( fileList, TQ_SIGNAL( updateCount()), this, TQ_SLOT( updateCount() ));
    connect( fileList, TQ_SIGNAL( updatePreview()), this, TQ_SLOT( updatePreview() ));
    connect( fileList, TQ_SIGNAL( deletePressed()), this, TQ_SLOT( removeFile() ));
    connect( fileList, TQ_SIGNAL( addFiles()), this, TQ_SLOT( addFile() ));
    connect( buttonUp, TQ_SIGNAL( clicked()), fileList, TQ_SLOT( moveUp() ));
    connect( buttonDown, TQ_SIGNAL( clicked()), fileList, TQ_SLOT( moveDown() ));
    connect( buttonUp, TQ_SIGNAL( clicked()), this, TQ_SLOT( updatePreview() ));
    connect( buttonDown, TQ_SIGNAL( clicked()), this, TQ_SLOT( updatePreview() ));
    connect( buttonUp2, TQ_SIGNAL( clicked()), this, TQ_SLOT( moveUp() ));
    connect( buttonDown2, TQ_SIGNAL( clicked()), this, TQ_SLOT( moveDown() ));
    connect( buttonReplace, TQ_SIGNAL( clicked()), this, TQ_SLOT( replace() ));
    connect( buttonEasyReplace, TQ_SIGNAL( clicked()), this, TQ_SLOT( replace() ));
    connect( buttonCoord, TQ_SIGNAL( clicked()), this, TQ_SLOT( getCoordinates() ));
    connect( comboSort, TQ_SIGNAL( activated(int)), fileList, TQ_SLOT( setSorting(int) ));
    
    connect( filename, TQ_SIGNAL( delayedTextChanged() ), this, TQ_SLOT( updatePreview() ));
    connect( extemplate, TQ_SIGNAL( delayedTextChanged() ), this, TQ_SLOT( updatePreview() ));
    connect( checkExtension, TQ_SIGNAL( clicked()), this, TQ_SLOT( updatePreview() ));
    connect( comboExtension, TQ_SIGNAL( activated(int) ), this, TQ_SLOT( updatePreview() ));
    connect( checkPreview, TQ_SIGNAL( clicked()), this, TQ_SLOT( toggleImagePreview() ));
    connect( preview, TQ_SIGNAL( itemChanged() ), this, TQ_SLOT( updatePreview() ));
    connect( preview, TQ_SIGNAL( removeItem(int) ), this, TQ_SLOT( removeFile(int) ));
    connect( preview, TQ_SIGNAL( addFile() ), this, TQ_SLOT( addFile() ));
    connect( undorequester, TQ_SIGNAL( urlSelected(const TQString &)), this, TQ_SLOT( changeUndoScriptName() ));
    connect( kapp, TQ_SIGNAL( aboutToQuit() ), this, TQ_SLOT( saveConfig() ) );
    connect( buttonMove, TQ_SIGNAL( clicked()), fileList, TQ_SLOT( moveMode() ));
    connect( checkName, TQ_SIGNAL( clicked()), this, TQ_SLOT( toggleName() ));
    connect( buttonNumber, TQ_SIGNAL( clicked()), this, TQ_SLOT( changeNumbers() ));

    // Load Configuration
    loadConfig();
    page_1->setEnabled( true );
    TDEApplication::restoreOverrideCursor();
        
    filename->setText( "$" );   // no i18n() ! ;)
    extemplate->setText( "$" );

    // do it now so that it can be overwritten by commandline args
    setWizardMode( wizardmode );

    parseCommandline();
    enableControls();
}

const TQString KRenameImpl::title( int index ) const
{
    return i18n( pageTitle[index] );
}

void KRenameImpl::parseCommandline()
{
    TDECmdLineArgs *args = TDECmdLineArgs::parsedArgs();

    QCStringList optlist = args->getOptionList ( "r" );
    for (QCStringList::ConstIterator it=optlist.begin(); it!=optlist.end(); ++it)
    {

        KURL url;
        url.setPath( *it );
        fileList->addDir( url, "*", false, true, false );
    }

    //fileList->setUpdatesEnabled( false );
    //fileList->viewport()->setUpdatesEnabled( false );
    for( int i = 0; i < args->count(); i++)
        fileList->addFile( args->url( i ) );
    //fileList->viewport()->setUpdatesEnabled( true );
    //fileList->setUpdatesEnabled( true );

    // load the profile first, so that we do not overwrite other
    // commandline settings
    TQCString templ = args->getOption( "profile" );
    if( !templ.isEmpty() )
    {
        m_hasCommandlineProfile = true;
        ProfileManager::loadProfile( TQString( templ ), this );
    }

    if( !args->isSet( "previewitems" ) )
        numRealTimePreview = -1;
    else
        numRealTimePreview = TQString( args->getOption( "previewitems" ) ).toInt();

    templ = args->getOption( "template" );
    if( !templ.isEmpty() )
        filename->setText( templ );

    templ = args->getOption( "extension" );
    if( !templ.isEmpty() ) 
    {
        extemplate->setText( templ );
        checkExtension->setChecked( false );
    }

    templ = args->getOption( "copy" );
    if( !templ.isEmpty() ) 
    {
        urlrequester->setURL( templ );
        optionCopy->setChecked( true );
    }

    templ = args->getOption( "move" );
    if( !templ.isEmpty() ) 
    {
        urlrequester->setURL( templ );
        optionMove->setChecked( true );
    }
        
    QCStringList uselist = args->getOptionList ( "use-plugin" );
    if( !uselist.isEmpty() ) 
    {
        for(unsigned int i = 0; i < uselist.count(); i++ )
            uselist[i] = uselist[i].lower();
    
        TQPtrListIterator<PluginLoader::PluginLibrary> it( plugin->libs );
        while ( it.current() ) 
        {
            if( uselist.contains( (*it)->plugin->getName().lower().utf8() ) )
                (*it)->check->setChecked( true );
                
            ++it;
        }

        pluginHelpChanged();
    }
    
    bool startnow = args->isSet( "start" );
    
    // Free some memory
    args->clear();      

    enableControls();
    updateCount();
    updatePreview();
    
    if( fileList->count() )
    {
        // we got already filenames over the commandline, so show directly the last
        // page of the wizard
        emit showPage( m_wizard ? 3 : 4 );
    }

    if( startnow ) 
    {
        // As file adding runs in a another trhread,
        // there might be adding in progress but not yet
        // all files in the list.
        // so let's wait for file adding to finish first
        // before starting.
        while( fileList->runningAddListeners() > 0 )
            kapp->processEvents();

        if( fileList->count() ) 
            // start renaming
            TQTimer::singleShot( 200, this, TQ_SLOT( start() ) );
    }
}

void KRenameImpl::setupActions()
{
    TDEActionCollection* actionCollection = new TDEActionCollection( this );

    TDEPopupMenu* mnuExtra = new TDEPopupMenu( parent );
    TDEPopupMenu* mnuSettings = new TDEPopupMenu( parent );
    KHelpMenu* mnuHelp = new KHelpMenu( parent );

    menuBar->insertItem( i18n("E&xtras"), mnuExtra );
    mnuExtra->insertItem( i18n("&Profiles..."), this, TQ_SLOT( manageProfiles() ) );
    mnuExtra->insertSeparator();
    mnuExtra->insertItem( SmallIcon("edit-undo"), i18n("&Undo Old Renaming Action..."), this, TQ_SLOT( undo() ) );
    menuBar->insertItem( i18n("&Settings"), mnuSettings );
    menuBar->insertSeparator();
    menuBar->insertItem( i18n("&Help"), mnuHelp->menu() );

    TDEAction* prefAct = KStdAction::preferences( this, TQ_SLOT(preferences()), actionCollection );
    loadPlugins = new TDEAction( i18n("&Load TDE file plugins"), 0, this, TQ_SLOT( loadFilePlugins() ), actionCollection );
    TDEAction* reloadAct = new TDEAction( i18n("&Reload Plugin Data"), 0, this, TQ_SLOT( reloadFilePluginData() ), actionCollection );
    
    prefAct->plug( mnuSettings );
    mnuSettings->insertSeparator();
    loadPlugins->plug( mnuSettings );
    reloadAct->plug( mnuSettings );
    
    connect( mnuHelp, TQ_SIGNAL(showAboutApplication()), this, TQ_SLOT(about()));
}

void KRenameImpl::setupPages()
{
    setupPage1();
    setupPage2();
    setupPage3();
    setupPage4();

    // Disable dirname ;)
    enableControls();
}

void KRenameImpl::setupPage1()
{
    page_1 = new TQWidget( parent );

    pageLayout = new TQHBoxLayout( page_1, 11, 6 );
    Layout3 = new TQVBoxLayout( 0, 0, 6 );
    Layout4 = new TQHBoxLayout( 0, 0, 6 );
    Layout5 = new TQVBoxLayout( 0, 0, 6 );

    TQSpacerItem* spacer = new TQSpacerItem( 20, 20, TQSizePolicy::Minimum, TQSizePolicy::Expanding );
    TQSpacerItem* spacer2 = new TQSpacerItem( 20, 20, TQSizePolicy::Expanding, TQSizePolicy::Minimum );

    fileList = new KMyListBox( page_1 );

    buttonAdd = new KPushButton( page_1 );
    buttonAdd->setText( i18n( "&Add..." ) );

    buttonRemove = new KPushButton( page_1 );
    buttonRemove->setText( i18n( "Re&move" ) );

    buttonRemoveAll = new KPushButton( page_1 );
    buttonRemoveAll->setText( i18n( "R&emove All" ) );

    comboSort = new KComboBox( false, page_1 );
    comboSort->insertItem( i18n("Sort: Unsorted") );
    comboSort->insertItem( i18n("Sort: Ascending") );
    comboSort->insertItem( i18n("Sort: Descending") );
    comboSort->insertItem( i18n("Sort: Random") );
    comboSort->insertItem( i18n("Sort: Numeric") );
    
    checkPreview = new TQCheckBox( page_1 );
    checkPreview->setText( i18n("&Preview") );

    labelCount = new TQLabel( page_1 );

    buttonUp = new KPushButton( page_1 );
    buttonUp->setPixmap( BarIcon( "1uparrow" ) );

    buttonDown = new KPushButton( page_1 );
    buttonDown->setPixmap( BarIcon( "1downarrow" ) );

    checkName = new TQCheckBox( page_1 );
    checkName->setText( i18n("&Display name") );

    buttonMove = new KPushButton( page_1 );
    buttonMove->setPixmap( BarIcon( "move" ) );

    Layout5->addWidget( buttonUp );
    Layout5->addWidget( buttonMove );
    Layout5->addWidget( buttonDown );

    Layout4->addLayout( Layout5 );
    Layout4->addItem( spacer2 );
    
    Layout3->addWidget( buttonAdd );
    Layout3->addWidget( buttonRemove );
    Layout3->addWidget( buttonRemoveAll );
    Layout3->addWidget( comboSort );
    Layout3->addWidget( checkPreview );
    Layout3->addWidget( checkName );
    Layout3->addWidget( labelCount );
    Layout3->addItem( spacer );
    Layout3->addLayout( Layout4 );
    Layout3->addItem( spacer );
    
    pageLayout->addWidget( fileList );
    pageLayout->setStretchFactor( fileList, 2 );
    pageLayout->addLayout( Layout3 );

    emit pageDone( page_1, i18n( pageTitle[0] ) );

    TQToolTip::add( buttonAdd, i18n( "Add one or more files or directories" ) );
    TQToolTip::add( buttonRemove, i18n( "Remove selected files" ) );
    TQToolTip::add( buttonRemoveAll, i18n( "Remove all files" ) );
    TQToolTip::add( checkPreview, i18n( "Enable/disable preview of pictures." ) );
    TQToolTip::add( labelCount, i18n( "Displays the number of files in the list." ) );
    TQToolTip::add( buttonUp, i18n( "Move selected items up" ));
    TQToolTip::add( buttonDown, i18n( "Move selected items down" ));
    TQToolTip::add( checkName, i18n( "Enable/disable display of file name." ) );
    TQToolTip::add( buttonMove, i18n( "Move selected items (select the new location with the mouse)" ));
}

void KRenameImpl::setupPage2()
{
    page_2 = new TQWidget( parent );

    pageLayout_2 = new TQVBoxLayout( page_2, 6, 6 );

    TQSpacerItem* spacer_3 = new TQSpacerItem( 20, 20, TQSizePolicy::Minimum, TQSizePolicy::Expanding );

    groupOptions = new TQButtonGroup( page_2 );
    groupOptions->setTitle( i18n( "O&ptions" ) );
    groupOptions->setColumnLayout(0, TQt::Vertical );
    groupOptions->layout()->setSpacing( 6 );
    groupOptions->layout()->setMargin( 11 );
    groupOptionsLayout = new TQVBoxLayout( groupOptions->layout() );
    groupOptionsLayout->setAlignment( TQt::AlignTop );

    optionRename = new TQRadioButton( groupOptions );
    optionRename->setText( i18n( "&Rename input files" ) );
    optionRename->setChecked( true );

    optionCopy = new TQRadioButton( groupOptions );
    optionCopy->setText( i18n( "Cop&y files to destination directory" ) );

    optionMove = new TQRadioButton( groupOptions );
    optionMove->setText( i18n( "&Move files to destination directory" ) );

    optionLink = new TQRadioButton( groupOptions );
    optionLink->setText( i18n("Create symbolic &links in destination directory") );
    
    dirname = new KMyHistoryCombo( false, groupOptions, "Path" );
    urlrequester = new KURLRequester( dirname, groupOptions );
    urlrequester->setMode( KFile::Directory | KFile::ExistingOnly );
    
    checkOverwrite = new TQCheckBox( groupOptions );
    checkOverwrite->setText( i18n( "&Overwrite existing files" ) );

    groupOptionsLayout->addWidget( optionRename );
    groupOptionsLayout->addWidget( optionCopy );
    groupOptionsLayout->addWidget( optionMove );
    groupOptionsLayout->addWidget( optionLink );
    groupOptionsLayout->addWidget( urlrequester );
    groupOptionsLayout->addItem( spacer_3 );
    groupOptionsLayout->addWidget( checkOverwrite );

    groupUndo = new TQVGroupBox( page_2 );
    groupUndo->setTitle( i18n("&Undo Renaming") );

    checkUndoScript = new TQCheckBox( i18n("&Create an undo script"), groupUndo );

    undorequester = new KURLRequester( groupUndo );
    undorequester->setEnabled( false );
    undorequester->setMode( KFile::File | KFile::LocalOnly  );
    undorequester->setFilter( i18n("*.krename|KRename undo scripts (*.krename)\n"
                                   "*|All Files (*)") );
    undorequester->fileDialog()->setOperationMode( KFileDialog::Saving );

    pageLayout_2->addWidget( groupOptions );
    pageLayout_2->addWidget( groupUndo );
    pageLayout_2->addItem( spacer_3 );

    emit pageDone( page_2, i18n( pageTitle[1] ) );

    TQToolTip::add( optionRename, i18n( "Input files will be renamed." ) );
    TQToolTip::add( optionCopy, i18n( "Copies all files to the destination directory and renames them." ) );
    TQToolTip::add( optionMove, i18n( "Moves all files to the destination directory and renames them." ) );
}

void KRenameImpl::setupPage3()
{
    page_3 = new KJanusWidget( parent, "janus", KJanusWidget::TreeList );
    page_3->setShowIconsInTreeList( true );
    page_3->setTreeListAutoResize( true );

    setupTab1();
    
    emit pageDone( page_3, i18n( pageTitle[2] ) );
}

void KRenameImpl::setupPage4()
{
    page_4 = new TQWidget( parent );
    pageLayout_4 = new TQVBoxLayout( page_4, 11, 6 );

    fileTab = new TQWidgetStack( page_4 );
    setupFileTab1();
    setupFileTab2();
    
    Layout22 = new TQHBoxLayout( 0, 0, 6 );
    Layout23 = new TQVBoxLayout( 0, 0, 6 );
    
    preview = new KMyListView( &changes, fileList, page_4 );
    preview->setSorting( -1 );
    preview->addColumn( i18n( "Origin" ) );
    preview->addColumn( i18n( "Renamed" ) );

    buttonUp2 = new KPushButton( page_4 );
    buttonUp2->setPixmap( BarIcon( "1uparrow" ) );

    buttonDown2 = new KPushButton( page_4 );
    buttonDown2->setPixmap( BarIcon( "1downarrow" ) );

    TQSpacerItem* spacer = new TQSpacerItem( 20, 20, TQSizePolicy::Expanding, TQSizePolicy::Expanding );

    Layout23->addItem( spacer );
    Layout23->addWidget( buttonUp2 );
    Layout23->addWidget( buttonDown2 );
    Layout23->addItem( spacer );

    Layout22->addWidget( preview );
    Layout22->addLayout( Layout23 );
    Layout22->setStretchFactor( preview, 2 );

    pageLayout_4->addWidget( fileTab );
    pageLayout_4->addLayout( Layout22 );

    emit pageDone( page_4, i18n( pageTitle[3] ) );

    TQToolTip::add( filename, i18n( "Add a template.<br>Example: <i>picture###</i>" ) );
    TQToolTip::add( extemplate, i18n( "Add a template for the file extension.<br>It behaves like the filename template.") );
    TQToolTip::add( checkExtension, i18n("Checking this checkbox is the same as setting the extension template to $"));
    TQToolTip::add( buttonUp2, i18n( "Move selected items up" ));
    TQToolTip::add( buttonDown2, i18n( "Move selected items down" ));
    TQToolTip::add( preview, i18n( "Double click on an item to modify it." ));
    TQToolTip::add( buttonHelp, i18n("Help Dialog with all tokens supported by KRename."));
    TQToolTip::add( buttonReplace, i18n("<qt>Find and replace characters or part string of the source filename in the destination filename.</qt>") );
    TQToolTip::add( buttonEasyReplace, i18n("<qt>Find and replace characters or part string of the source filename in the destination filename.</qt>") );
    TQToolTip::add( comboExtension, i18n("<qt>You can use \".gz\" and \".tar.gz\" as file extension of the file backup.tar.gz depending on this setting.</qt>") );
}

void KRenameImpl::setupFileTab1()
{
    TQWidget* tab = new TQWidget( fileTab );

    labelTemplate = new TQLabel( tab );
    labelTemplate->setText( i18n( "&Template:" ) );

    filename = new KMyHistoryCombo( true, tab, "Template" );
    labelTemplate->setBuddy( filename );

    TQLabel* labelDot = new TQLabel( tab );
    labelDot->setText("<b>.</b>");

    extemplate = new KMyHistoryCombo( true, tab, "ExTemplate" );
    extemplate->setEnabled( FALSE );

    buttonHelp = new KPushButton( i18n("&Functions..."), tab );
    buttonHelp->setIconSet( SmallIcon("help") );

    checkExtension = new TQCheckBox( tab );
    checkExtension->setText( i18n( "&Use extension of the input file" ) );
    checkExtension->setChecked( TRUE );

    comboExtension = new KComboBox( false, tab );

    buttonReplace = new KPushButton( i18n("Find &and Replace..."), tab );
    buttonReplace->setIconSet( SmallIconSet("edit-find") );

    buttonNumber = new KPushButton( i18n("&Numbering..."), tab );
    buttonCoord = new KPushButton( i18n("&Insert Part of Filename..."), tab );

    helpDialog->setLineEdit( filename->lineEdit() );
    
    TQStringList help;
    help.append("$;;" + i18n("old filename") );
    help.append("%;;" + i18n("old filename converted to lower case") );
    help.append("&;;" + i18n("old filename converted to upper case") );
    help.append("*;;" + i18n("first letter of every word upper case") );
    help.append("[&1][%2-];;" + i18n("first letter of filename upper case") );
    help.append("#;;" + i18n("number (try also ##, ###, ... for leading zeros)") );
    help.append("#{0;1};;" + i18n("counter with custom start value 0 and custom stepping 1") );
    help.append("/;;" + i18n("create a subdirectory") );
    help.append("\\;;" + i18n("strip whitespaces leading and trailing") );
    help.append("[$x-y];;" + i18n("character x to y of old filename") );
    help.append("[$x;y];;" + i18n("y characters of old filename starting at x") );
    help.append("[$dirname];;" + i18n("insert name of directory") );
    help.append("[$dirname.];;" + i18n("insert name of parent directory") );
    help.append("[#length-0];;" + i18n("insert the length of the input filename") );
    helpDialogData->add( i18n("Built-in Functions:" ), &help, SmallIcon("krename"), true );

    help.clear();
    help.append( "\\$;;" + i18n("Insert '$'") );
    help.append( "\\%;;" + i18n("Insert '%'") );
    help.append( "\\&;;" + i18n("Insert '&'") );
    help.append( "\\*;;" + i18n("Insert '*'") );
    help.append( "\\/;;" + i18n("Insert '/'") );
    help.append( "\\\\;;" + i18n("Insert '\\\\'") );
    help.append( "\\[;;" + i18n("Insert '['") );
    help.append( "\\];;" + i18n("Insert ']'") );
    help.append( "\\#;;" + i18n("Insert '#'") );
    helpDialogData->add( i18n("Special Characters:" ), &help, SmallIcon("krename") );

    /*
        //TODO: FIX this tooltip
    TQToolTip::add( buttonHelp,
    i18n(
        "<b>$</b> old filename<br><b>%</b> old filename"
        " converted to lower case<br><b>&</b> old filename converted to upper case<br>"
        "<b>*</b> first letter of every word uppercase<br>"
        "<b>#</b> Adds a number to the filename (add more #'s for leading zeros)<br>"
        "<b>/</b> creates a subdirectory<br>"
        "<b>[$x-y]</b> Characters x to y of the old filename<br>"
        "<b>[%x-y]</b> Characters x to y converted to lower case"
    ) );
    */

    TQSpacerItem* spacer_9 = new TQSpacerItem( 200, 20, TQSizePolicy::Maximum, TQSizePolicy::Maximum );

    TQVBoxLayout* layout = new TQVBoxLayout( tab );
    TQHBoxLayout* Layout1 = new TQHBoxLayout( 0, 6, 6 );
    TQHBoxLayout* Layout2 = new TQHBoxLayout( 0, 6, 6 );
    TQHBoxLayout* ExtensionLayout = new TQHBoxLayout( 0, 6, 6 );
    
    Layout1->addWidget( labelTemplate );
    Layout1->addWidget( filename );
    Layout1->setStretchFactor( filename, 4 );
    Layout1->addWidget( labelDot );
    Layout1->addWidget( extemplate );
    Layout1->addWidget( buttonHelp );

    Layout2->addWidget( buttonReplace );    
    Layout2->addWidget( buttonNumber );
    Layout2->addWidget( buttonCoord );
    Layout2->addItem( spacer_9 );
    
    ExtensionLayout->addWidget( checkExtension );
    ExtensionLayout->addItem( spacer_9 );
    ExtensionLayout->addWidget( new TQLabel( i18n("File extension starts at:"), tab ) );
    ExtensionLayout->addWidget( comboExtension );
    
    layout->addLayout( Layout1 );
    layout->addLayout( ExtensionLayout );
    layout->addLayout( Layout2 );
    layout->addItem( spacer_9 );
    
    fileTab->addWidget( tab, ID_TAB );
}

void KRenameImpl::setupFileTab2()
{
    TQWidget* tab = new TQWidget( page_4 );

    TQHBoxLayout* layout = new TQHBoxLayout( tab, 6, 6 );
    
    TQVGroupBox* vgroup1 = new TQVGroupBox( i18n("&Filename"), tab );
    TQGrid* grid = new TQGrid( 4, vgroup1 );
        
    TQLabel* l = new TQLabel( i18n("&Prefix:"), grid );
    comboKRenamePrefix = new KComboBox( false, grid );
    comboPrefix = new KMyHistoryCombo( true, grid, "comboPrefix" );   
    buttonEasy1 = new KPushButton( grid );
    l->setBuddy( comboPrefix );
    
    l = new TQLabel( i18n("&Suffix:"), grid );
    comboKRenameSuffix = new KComboBox( false, grid, "comboSuffix"  );
    comboSuffix = new KMyHistoryCombo( true, grid );
    buttonEasy2 = new KPushButton( grid );
    l->setBuddy( comboSuffix );

    TQStringList comboItems;
    comboItems.append( i18n("Convert to lower case ") );
    comboItems.append( i18n("Convert to upper case") );
    comboItems.append( i18n("Capitalize") ); 
    
    l = new TQLabel( i18n("&Name:"), grid );
    comboKRenameFilename = new KComboBox( false, grid );
    comboKRenameFilename->insertItem( i18n("Use original name") );
    comboKRenameFilename->insertStringList( comboItems );
    comboKRenameFilename->insertItem( i18n("Custom name") );
    l->setBuddy( comboKRenameFilename );
    
    comboCustom = new KMyHistoryCombo( true, grid, "comboCustom" );
    buttonEasy3 = new KPushButton( grid );
             
    l = new TQLabel( i18n("&Extension:"), grid );
    comboKRenameExtension = new KComboBox( false, grid );
    comboKRenameExtension->insertItem( i18n("Use original extension") );
    comboKRenameExtension->insertStringList( comboItems );
    comboKRenameExtension->insertItem( i18n("Custom extension") );
    l->setBuddy( comboKRenameExtension );
    
    comboCustomExtension = new KMyHistoryCombo( true, grid, "comboCustomExtension" );
    buttonEasy4 = new KPushButton( grid );
    
    TQVBox* rightBox = new TQVBox( tab );
    TQVGroupBox* group = new TQVGroupBox( i18n("&Number" ), rightBox );
    
    spinStart = new KIntNumInput( group );
    spinStart->setLabel( i18n( "Start &index:" ), AlignLeft | AlignVCenter );

    spinNull = new KIntNumInput( spinStart, 1, group );        
    spinNull->setLabel( i18n("&Number of digits:"), AlignLeft | AlignVCenter );
    spinNull->setRange( 1, 100, 1, false );
    
    buttonEasyReplace = new KPushButton( i18n("&Find and Replace..."), rightBox );
    buttonEasyReplace->setIconSet( SmallIconSet("edit-find") );
    
    layout->addWidget( vgroup1 );
    layout->addWidget( rightBox );
    
    comboKRenamePrefix->insertItem( "" );
    comboKRenamePrefix->insertItem( i18n("Number") );
    comboKRenamePrefix->insertItem( i18n("Date") );
    
    comboKRenameSuffix->insertItem( "" );
    comboKRenameSuffix->insertItem( i18n("Number") );
    comboKRenameSuffix->insertItem( i18n("Date") );
    
    enableControls();
        
    connect( comboPrefix, TQ_SIGNAL( textChanged( const TQString &)), this, TQ_SLOT( changed()));
    connect( comboSuffix, TQ_SIGNAL( textChanged( const TQString &)), this, TQ_SLOT( changed()));
    connect( comboKRenameFilename, TQ_SIGNAL( activated(int)), this, TQ_SLOT( changed()));
    connect( comboCustom, TQ_SIGNAL( textChanged( const TQString & ) ), this, TQ_SLOT( changed() ));
    connect( comboKRenamePrefix, TQ_SIGNAL(activated(int)), this, TQ_SLOT(changed()));
    connect( comboKRenameExtension, TQ_SIGNAL( activated(int)), this, TQ_SLOT( changed()));
    connect( comboCustomExtension, TQ_SIGNAL( textChanged( const TQString & ) ), this, TQ_SLOT( changed() ));
    connect( comboKRenameSuffix, TQ_SIGNAL(activated(int)), this, TQ_SLOT(changed()));
    connect( spinNull, TQ_SIGNAL( valueChanged(int) ), this, TQ_SLOT( changed() ));
    connect( spinStart, TQ_SIGNAL( valueChanged(int) ), this, TQ_SLOT( changed() ));   
        
    buttonEasy1->setIconSet( SmallIcon("help") );
    buttonEasy2->setIconSet( SmallIcon("help") );
    buttonEasy3->setIconSet( SmallIcon("help") );
    buttonEasy4->setIconSet( SmallIcon("help") );
    
    buttonEasy1->setSizePolicy( TQSizePolicy::Maximum, TQSizePolicy::Maximum );
    buttonEasy2->setSizePolicy( TQSizePolicy::Maximum, TQSizePolicy::Maximum );
    buttonEasy3->setSizePolicy( TQSizePolicy::Maximum, TQSizePolicy::Maximum );
    buttonEasy4->setSizePolicy( TQSizePolicy::Maximum, TQSizePolicy::Maximum );
    
    const TQString easy_text( i18n("<qt>Insert a special KRename command which inserts file information into the filename.</qt>") );
    
    connect( buttonEasy1, TQ_SIGNAL( clicked() ), this, TQ_SLOT( slotEasy1() ) );
    connect( buttonEasy2, TQ_SIGNAL( clicked() ), this, TQ_SLOT( slotEasy2() ) );
    connect( buttonEasy3, TQ_SIGNAL( clicked() ), this, TQ_SLOT( slotEasy3() ) );
    connect( buttonEasy4, TQ_SIGNAL( clicked() ), this, TQ_SLOT( slotEasy4() ) );
    
    TQToolTip::add( buttonEasy1, easy_text );
    TQToolTip::add( buttonEasy2, easy_text );
    TQToolTip::add( buttonEasy3, easy_text );
    TQToolTip::add( buttonEasy4, easy_text );
    
    fileTab->addWidget( tab, ID_WIZARD );
}

TQString KRenameImpl::easyOptions( KComboBox* combo, KMyHistoryCombo* custom )
{
    TQString t = TQString();
    if( combo->currentItem() == 0 )
        t = "$";
    else if( combo->currentItem() == 1 )
        t = "%";
    else if( combo->currentItem() == 2 )
        t = "&";
    else if( combo->currentItem() == 3 )
        t = "*";
    else if( combo->currentItem() == 4 )
        t = custom->text();
    
    return t;
}

void KRenameImpl::changed()
{
    TQString t = easyOptions( comboKRenameFilename, comboCustom );
    t = comboPrefix->text() + t + comboSuffix->text();

    for( int i=0; i<spinNull->value();i++)
    {
        if( comboKRenamePrefix->currentItem() == 1 )
            t.prepend("#");
        if( comboKRenameSuffix->currentItem() == 1 )
            t.append("#");
    }

    if( comboKRenamePrefix->currentItem() == 2 )        
        t.prepend( "[date]" );
    
    if( comboKRenameSuffix->currentItem() == 2 )
        t.append( "[date]" );

    TQString e = easyOptions( comboKRenameExtension, comboCustomExtension );
    
    bool update = false;
    update = ( counterStart() != spinStart->value() && t == fileNameTemplate() );
    setCounterStart( spinStart->value() );
    
    filename->setText( t );
    extemplate->setText( e );
    checkExtension->setChecked( (comboKRenameExtension->currentItem() == 0) );
    
    if( update )
        updatePre();
        
    enableControls();
}

void KRenameImpl::parseWizardMode()
{
    /** This function is not very accrurate and 
      * guesses most cases.
      * But it works pretty well and is IMHO enough for this
      * simple dialog.
      */
    TQString t = filename->text();
    
    spinNull->setValue( t.contains( "#" ) );
    
    if( t.startsWith( "[date]") ) 
    {
        t = t.right( t.length() - 6 );
        comboKRenamePrefix->setCurrentItem( 2 );
    }
    else if( t.startsWith( "#") )
    {
        while( t.startsWith( "#" ) )
            t = t.right( t.length() - 1 );
        comboKRenamePrefix->setCurrentItem( 1 );
    }
    
    if( t.endsWith( "[date]" ) )
    {
        t = t.left( t.length() - 6 );
        comboKRenameSuffix->setCurrentItem( 2 );
    }
    else if( t.endsWith( "#") )
    {
        while( t.endsWith( "#" ) )
            t = t.left( t.length() - 1 );
        
        comboKRenameSuffix->setCurrentItem( 1 );
    }
    
    int pos = -1;
    if( (pos = t.find( "$" )) > -1 )
        comboKRenameFilename->setCurrentItem( 0 );
    else if( (pos = t.find( "%" )) > -1 )
        comboKRenameFilename->setCurrentItem( 1 );
    else if( (pos = t.find( "&" )) > -1 )
        comboKRenameFilename->setCurrentItem( 2 );
    else if( (pos = t.find( "*" )) > -1 ) 
        comboKRenameFilename->setCurrentItem( 3 );
    else
    {
        comboKRenameFilename->setCurrentItem( 4 );
        comboCustom->setText( t );
    }
        
    if( pos > 0 )
    {
        comboPrefix->setText( t.left( pos ) );
        comboSuffix->setText( t.mid( pos + 1, t.length() - pos - 1) );
    }
    
    spinStart->setValue( m_index );
}

void KRenameImpl::setupTab1()
{
    /*
     * Draw plugin user interfaces
     */

    TQFrame* parent;
    TQVBoxLayout* Layout;
    TQVBoxLayout* gLayout;
    TQGroupBox* g;
    TQWidget* page;

    /* strangely I do not have to delete this stuff
     * after plugins have been reloaded.
     * could cause a memory leak though
     */
    while( ( page = page_3->pageWidget( 0 ) ) )
        page_3->removePage( page );

    TQPtrListIterator<PluginLoader::PluginLibrary> it( plugin->libs ); // iterator for dict
    while ( it.current() ) {
        if( !(*it)->plugin->alwaysUsed() )
        {
            parent = page_3->addPage( (*it)->plugin->getName(), TQString(), (*it)->plugin->getIcon() );
        
            Layout = new TQVBoxLayout( parent, 11, 6, "Layout");
            g = new TQGroupBox( parent );
            gLayout = new TQVBoxLayout( g, 11, 6, "gLayout" );

            (*it)->check = new TQCheckBox( i18n("&Use this plugin"), parent );
            connect( (*it)->check, TQ_SIGNAL( clicked() ), this, TQ_SLOT( pluginHelpChanged() ) );
            connect( (*it)->plugin, TQ_SIGNAL( previewChanged( Plugin* ) ), this, TQ_SLOT( updatePluginPreview( Plugin* ) ) );
            Layout->addWidget( (*it)->check );
            (*it)->plugin->drawInterface( g, gLayout );

            Layout->addWidget( g );
            
        } else
            (*it)->plugin->addHelp( helpDialogData );
            
        ++it;
    }

    page_3->showPage( 1 );
}

void KRenameImpl::addFile()
{
    bool auto_up = false;
    
    DSDirSelectDialog* dsd = new DSDirSelectDialog( parent );
    if( dsd->exec() == TQDialog::Accepted ) {
        KURL::List slist = dsd->selectedURLs();
        KURL::List::Iterator it = slist.begin();

        for ( ; it != slist.end(); ++it )
        {
            if( !fileList->isFile( *it, false ) )
            {
                if( dsd->onlyDirs() )
                    fileList->addDirName( *it, dsd->currentFilter(), dsd->hidden(), dsd->recursively() );
                else
                    fileList->addDir( *it, dsd->currentFilter(), dsd->hidden(), dsd->recursively(), dsd->dirs() );
            }
            else
            {
                fileList->addFile( *it, true );
                auto_up = true;
            }
        }
        
        if( auto_up )
        {
            updatePreview();
            updateCount();
        }
    }
}

void KRenameImpl::clearList()
{
    fileList->clear();
    changes.clear();
    updateCount();
    updatePreview();
}

void KRenameImpl::removeFile()
{
    unsigned int i = 0;
    do {
        if(fileList->isSelected( i ))
            removeFile( i );
        else
            i++;
    } while( i < fileList->count() );

    updateCount();
    updatePreview();
}

void KRenameImpl::removeFile( int index )
{
    KURL url = fileList->url( index );
    fileList->removeItem( index );
    // we have this to display the add files url label when count() == 0
    fileList->positionLabel();
    // remove this file from changes, too
    for( unsigned int i = 0; i < changes.count(); i++ )
        if( changes[i].url == url )
            changes.remove( changes.at( i ) );

    updateCount();
    updatePreview();
}

void KRenameImpl::help()
{
    kapp->invokeHelp();
}

void KRenameImpl::start()
{
    if(!checkErrors())
        return;

    // Let the plugins check for erorrs
    TQPtrListIterator<PluginLoader::PluginLibrary> it( plugin->libs );
    while ( it.current() ) {
        if( (*it)->usePlugin && !(*it)->plugin->checkError() )
            return;
        ++it;
    }

    ProgressDialog* p = new ProgressDialog( 0, "p" );
    p->print(i18n("Starting conversion of %1 files.").arg(fileList->count()));

    // Save History
    dirname->saveSettings();
    filename->saveSettings();
    extemplate->saveSettings();

    TDEConfig * config = kapp->config();
    config->setGroup("FileExtension");
    config->writeEntry("FileExtensionCombo", comboExtension->currentItem() );

    // save the configuration
    saveConfig();

    b = new BatchRenamer();
    if( setupBatchRenamer( b, false ) )
    {
        p->show();
        parent->hide();
        b->processFiles( p, this );
    }

    // Memory leak!!! :  ??
    //delete parent;
}

void KRenameImpl::enableControls()
{
    comboCustom->setEnabled( comboKRenameFilename->currentItem() == 4 );
    comboCustomExtension->setEnabled( comboKRenameExtension->currentItem() == 4 );
    buttonEasy3->setEnabled( comboKRenameFilename->currentItem() == 4 );
    buttonEasy4->setEnabled( comboKRenameExtension->currentItem() == 4 );
    urlrequester->setEnabled( !optionRename->isChecked() );
    checkUndoScript->setEnabled( !optionCopy->isChecked() && !optionLink->isChecked() );
    undorequester->setEnabled( checkUndoScript->isChecked() && checkUndoScript->isEnabled() );
    extemplate->setEnabled( !checkExtension->isChecked() );
    loadPlugins->setEnabled( !plugin->filePluginsLoaded() );
}

bool KRenameImpl::checkErrors()
{
    if( filename->text().isEmpty() ) {
        KMessageBox::sorry( parent, i18n("Specify a template to use for renaming files.") );
        return false;
    }
    if( dirname->text().isEmpty() && !optionRename->isChecked()) {
        KMessageBox::sorry( parent, i18n("Please give a destination directory !") );
        emit showPage( 2 );
        return false;
    }
    if( checkUndoScript->isChecked() && !optionCopy->isChecked() && undorequester->url().isEmpty() ) {
        KMessageBox::sorry( parent, i18n("Please give the name of the undo script!") );
        showPage( 2 );
        return false;
    }

    return true;
}

void KRenameImpl::updateCount()
{
    labelCount->setText(i18n("Files: <b>%1</b>").arg(fileList->count()));

    buttonCoord->setEnabled( (bool)fileList->count() );
    buttonReplace->setEnabled( (bool)fileList->count() );
    buttonEasyReplace->setEnabled( (bool)fileList->count() );
    emit enableFinish( (bool)fileList->count() );
    buttonRemove->setEnabled( (bool)fileList->count() );
    buttonRemoveAll->setEnabled( (bool)fileList->count() );
    buttonMove->setEnabled( (bool)fileList->count() );
    buttonUp->setEnabled( (bool)fileList->count() );
    buttonUp2->setEnabled( (bool)fileList->count() );
    buttonDown->setEnabled( (bool)fileList->count() );
    buttonDown2->setEnabled( (bool)fileList->count() );

    updateDots();
}

void KRenameImpl::fillStructures( BatchRenamer* b, bool preview )
{
    TQValueList<data> f;
    unsigned int max = (preview && KRenameImpl::numRealTimePreview > -1 ? KRenameImpl::numRealTimePreview : fileList->count());

    for( unsigned int i = 0; i < max; i++) {
        KURL url = fileList->url( i );
        TQFileInfo fi( url.path() );
        
        data fdata;
        fdata.dir = fileList->dir( i );
        if( !fdata.dir ) {
            splitFilename( &fi, &fdata.src.name, &fdata.src.extension );
        } else {
            fdata.src.name = BatchRenamer::findDirName( "dirname", url.path() );
            fdata.src.extension = "";
        }

        fdata.src.url = url;

        /* Let's do some error checking for files
         * called: file_xy.
         */
        if( url.path().right(1) == "." )
            // File ends with a dot
            fdata.src.name.append( "." );

        fdata.src.directory = fi.dirPath( true );
        if( fdata.src.directory.right(1) != "/" )
            fdata.src.directory.append("/");

        f.append( fdata );
    }

    /*
     * Tell plugins that they should fill their structure, too.
     * Check also which plugins should be used !
     */
    TQPtrListIterator<PluginLoader::PluginLibrary> it( plugin->libs );
    for( int z = 0; it.current(); ++it, z++ ) {
        if( (*it)->plugin->alwaysUsed() || ((*it)->check && (*it)->check->isChecked()) )
            (*it)->plugin->fillStructure();
    }

    b->setFiles( f );
}

void KRenameImpl::updatePre()
{
    updatePreview();
    updateCount();
    toggleImagePreview();
}

void KRenameImpl::addFileOrDir( const TQString & name )
{
    fileList->addFile( name, false );
}

void KRenameImpl::addFileOrDir( const KURL & name )
{
    fileList->addFile( name, true );
}

bool KRenameImpl::setupBatchRenamer( BatchRenamer* b, bool preview )
{
    b->setText( filename->text() );
    b->setExText( ( checkExtension->isChecked() ? TQString("$") : extemplate->text() ) );
    b->setIndex( m_index );
    b->setResetCounter( m_reset );
    b->setStep( m_step );
    b->setSkipList( skip );
    b->setReplaceList( rep );
    b->setChanges( changes );
    
    if( !preview ) {
        TQString url = urlrequester->url();
        if( url.right(1) != "/" )
            url.append( "/" );

        if (!TDEIO::NetAccess::exists(KURL(url), true, parent))
        {
            int m = KMessageBox::warningContinueCancel( parent, i18n("The directory %1 does not exist. "
            "KRename will create it for you.").arg( url ) );
            if( m == KMessageBox::Cancel )
                return false;

            int i = 0;
            TQString d = "/";
            TQString ds = TQString::null;
            for (ds = url.section("/", i, i, TQString::SectionSkipEmpty);
                 !ds.isEmpty();
                 i++, d.append("/"), ds = url.section("/", i, i, TQString::SectionSkipEmpty))
            {
                d += ds;
                if (!TDEIO::NetAccess::exists(d, false, parent) &&
                    !TDEIO::NetAccess::mkdir(d, parent, -1))
                {
                    tqDebug( "Can't create %s", d.latin1() );
                    break;
                }
            }
        }

        b->setDirname( url );
        b->setOverwrite( checkOverwrite->isChecked() );
        b->setUndo( checkUndoScript->isChecked() && !optionCopy->isChecked() );
        if( checkUndoScript->isChecked() && !optionCopy->isChecked() )
            b->setUndoScript( undorequester->url() );

        b->setMode( currentRenameMode() );
    }

    fillStructures( b, preview );
    return true;
}

int KRenameImpl::currentRenameMode()
{
    if( optionCopy->isChecked() )
        return COPY;
    else if( optionMove->isChecked() )
        return MOVE;
    else if( optionRename->isChecked() )
        return RENAME;
    else if( optionLink->isChecked() )
        return LINK;
    // prevent a compiler warning
    return RENAME;
}

void KRenameImpl::updatePluginPreview( Plugin* p ) 
{
    TQPtrListIterator<PluginLoader::PluginLibrary> it( plugin->libs ); // iterator for dict
    while ( it.current() ) {
        if( (*it)->plugin == p && (*it)->usePlugin ) {
            updatePreview();
            return;
        }

        ++it;
    }
}

void KRenameImpl::updatePreview()
{
    // is there a number in the filename or extension
    if( filename->text().contains( "#" ) || extemplate->text().contains( "#" ) )
        buttonNumber->setEnabled( true );
    else
        buttonNumber->setEnabled( false );

    if( filename->isEmpty() && extemplate->isEmpty() && !checkExtension->isChecked() )
        return;

    int h = preview->horizontalScrollBar()->value();
    int v = preview->verticalScrollBar()->value();
    
    preview->clear();

    if( fileList->count() <= 0 )
        return;

    BatchRenamer b;
    if( setupBatchRenamer( &b, true ) )
    {
        TDEApplication::setOverrideCursor( TQt::WaitCursor );
        b.createPreview( preview );
        TDEApplication::restoreOverrideCursor();
    }
    preview->horizontalScrollBar()->setValue( h );
    preview->verticalScrollBar()->setValue( v );
}

void KRenameImpl::loadConfig()
{
    TDEConfig* config = kapp->config();

    config->setGroup("HistSize");
    m_hist = config->readNumEntry("HistoryItems", 10 );
    updateHist();

    config->setGroup("GUISettings");
    // Image Preview
    checkPreview->setChecked(config->readBoolEntry("ImagePreview", false ));
    fileList->setPreview( checkPreview->isChecked() );
    m_index = config->readNumEntry("StartIndex", 1);
    m_step = 1;
    m_reset = false;
    m_loadplugins = config->readBoolEntry("LoadFilePlugins", true );
    m_autosize = config->readBoolEntry("ColumnAutosize", false );
    checkName->setChecked(config->readBoolEntry("Name", false ));
    fileList->setPreviewSize( config->readNumEntry("PreviewSize", 80) );
    fileList->setName( checkName->isChecked() );
    fileList->setSorting( config->readNumEntry("FileListSorting", KMyListBox::UNSORTED ) );
    comboSort->setCurrentItem( fileList->sorting() );
    
    CoordDialog::m_inversion = config->readBoolEntry("Inverse", false);
    m_wizard = config->readBoolEntry( "GUIWizardMode", true );

    int width = config->readNumEntry( "Width", parent->width() );
    int height = config->readNumEntry( "Height", parent->height() );
    if( config->readBoolEntry("Maximized", false ) ) {
        parent->showMaximized();
    } else {
        parent->resize( width, height );
    }
    
    refreshColumnMode();
    if( !m_autosize ) {
        preview->setColumnWidth( 0, 
            config->readNumEntry("Column0", (width/2) - 40 ) );
        preview->setColumnWidth( 1, 
            config->readNumEntry("Column1", (width/2) - 40 ) );
                
        if( preview->columnWidth( 0 ) > (width/2) )
        {
            preview->setColumnWidth( 0, (width/2) - 40 );
            preview->setColumnWidth( 1, (width/2) - 40 );
        }
    }

    if( !checkPreview->isChecked() ) {
        checkName->setChecked( true );
        checkName->setEnabled( false );
    }

    //parent->show();
    page_1->setEnabled( false );
    TDEApplication::setOverrideCursor( TQt::WaitCursor );
    plugin->loadPlugins( m_loadplugins );
    setupTab1();
    config->setGroup("GUISettings");

    // File Extension
    config->setGroup("FileExtension");
    // default LAST DOT
    comboExtension->setCurrentItem( config->readNumEntry("FileExtensionCombo", 1 ) );
}

void KRenameImpl::saveConfig()
{
    TDEConfig* config = kapp->config();

    config->setGroup("HistSize");
    config->writeEntry("HistoryItems", m_hist );

    config->setGroup("GUISettings");
    config->writeEntry("firststart", false );
    config->writeEntry("ImagePreview", checkPreview->isChecked() );
    config->writeEntry("StartIndex", m_index );
    config->writeEntry("Maximized", parent->isMaximized() );
    config->writeEntry("Width", parent->width() );
    config->writeEntry("Height", parent->height() );
    config->writeEntry("XPos", parent->x() );
    config->writeEntry("YPos", parent->y() );
    config->writeEntry("LoadFilePlugins", m_loadplugins );
    config->writeEntry("ColumnAutosize", m_autosize );
    config->writeEntry("Name", checkName->isChecked() );
    config->writeEntry("PreviewSize", fileList->getPreviewSize() );
    config->writeEntry("Inverse", CoordDialog::m_inversion );
    config->writeEntry("Column0", preview->columnWidth( 0 ) );
    config->writeEntry("Column1", preview->columnWidth( 1 ) );
    config->writeEntry("GUIWizardMode", m_wizard );
    config->writeEntry("FileListSorting", fileList->sorting() );

    config->sync();
}

void KRenameImpl::replace()
{
    ReplaceDialog* r = new ReplaceDialog( rep, parent );
    if( r->exec() == TQDialog::Accepted )
    {
        rep = r->getList();
        updatePreview();
    }
}

void KRenameImpl::toggleImagePreview()
{
    TDEApplication::setOverrideCursor( TQt::waitCursor );
    fileList->setPreview( checkPreview->isChecked() );
    checkName->setEnabled( checkPreview->isChecked() );
    if( !checkPreview->isChecked() )
        checkName->setChecked( true );
    fileList->setName( checkName->isChecked() );
    TDEApplication::restoreOverrideCursor();
}

void KRenameImpl::toggleName()
{
    TDEApplication::setOverrideCursor( TQt::waitCursor );
    fileList->setName( checkName->isChecked() );
    TDEApplication::restoreOverrideCursor();
}

void KRenameImpl::preferences()
{
    ConfDialog* cd = new ConfDialog( parent, "cd" );
    cd->setLoadPlugins( m_loadplugins );
    cd->setThumbSize( fileList->getPreviewSize() );
    cd->setAutosize( m_autosize );
    cd->setHistoryItems( m_hist );
    cd->setUseWizard( m_wizard );

    if( cd->exec() == TQDialog::Accepted ) {
        bool oldwiz = m_wizard;
    
        m_loadplugins = cd->loadplugins();
        m_autosize = cd->autosize();
        m_hist = cd->historyItems();
        m_wizard = cd->useWizard();

        refreshColumnMode();

//        fileList->setHiddenDirs( cd->hiddendir() );

        if( fileList->getPreviewSize() != cd->thumbSize() ) {
            fileList->setPreviewSize( cd->thumbSize() );
            fileList->setPreview( checkPreview->isChecked() );
        }

        updatePreview();
        updateHist();

        if( oldwiz != m_wizard )
            changeGUIMode();
    }
}

void KRenameImpl::changeGUIMode()
{
    /* GUI Mode was changed by the user */
    saveConfig();

    int x = parent->x();
    int y = parent->y();
    int w = parent->width();
    int h = parent->height();

    TQWidget* oldparent = parent;
    TQWidget* krename = KRenameImpl::launch( TQRect( x, y, w, h ), TQStringList(), this, false );
    
    m_switching = true;
    oldparent->removeChild( this );
    oldparent->hide();
    krename->insertChild( this );
    krename->show();

    oldparent->close();
    m_switching = false;            
}

void KRenameImpl::moveUp()
{
    TQListViewItem* item = preview->selectedItem();
    if(item) {
        int i = preview->itemIndex( item );
        fileList->moveUp( i );
        updatePreview();
        if( (i-1) > 0 ) {
            preview->setCurrentItem( preview->itemAtIndex( i-1 ) );
            preview->ensureItemVisible( preview->itemAtIndex( i-1 ) );
        }
    }
}

void KRenameImpl::moveDown()
{
    TQListViewItem* item = preview->selectedItem();
    if(item) {
        int i = preview->itemIndex( item );
        fileList->moveDown( i );
        updatePreview();
        preview->setCurrentItem( preview->itemAtIndex( i+1 ) );
        preview->ensureItemVisible( preview->itemAtIndex( i+1 ) );
    }
}

void KRenameImpl::undo()
{
    UndoDialog* u = new UndoDialog( parent );
    u->exec();
    delete u;
}

void KRenameImpl::changeUndoScriptName()
{
    const char* EXTENSION = ".krename";
    TQString script = undorequester->url();
    if( script.right( 8 ) != EXTENSION ) {
        script += EXTENSION;
        undorequester->setURL( script );
    }
}

void KRenameImpl::pluginHelpChanged()
{
    TQPtrListIterator<PluginLoader::PluginLibrary> it( plugin->libs ); // iterator for dict
    while ( it.current() ) {
        if( !(*it)->plugin->alwaysUsed() ) {
            (*it)->plugin->removeHelp( helpDialogData );

            if( (*it)->check )
            {
                (*it)->usePlugin = (*it)->check->isChecked();
                if( (*it)->check->isChecked() )
                    (*it)->plugin->addHelp( helpDialogData );
            }
        } 
        else
        {
            (*it)->plugin->removeHelp( helpDialogData );
            (*it)->plugin->addHelp( helpDialogData );
        }
        
        ++it;
    }
}

void KRenameImpl::showTokenHelp()
{
    helpDialog->show();
}

void KRenameImpl::getCoordinates()
{
    TQString name;
    TQListViewItem* item = preview->selectedItem();
    if( item )
        name = item->text( 0 );
    else {
        item = preview->itemAtIndex( 0 );
        if( item )
            name = item->text( 0 );
    }

    TQFileInfo fi( name );
    TQString extension;
    splitFilename( &fi, &name, &extension );
    CoordDialog* cd = new CoordDialog( name, parent );
    if( cd->exec() == TQDialog::Accepted ) {
        TQString t = filename->text();

        if( filename->text() == "$" )
            filename->setText( cd->coords() );
        else {
            t.insert( filename->cursorPosition(), cd->coords() );
            filename->setText( t );
        }
    }

    delete cd;
}

void KRenameImpl::splitFilename( TQFileInfo* fi, TQString* base, TQString* extension )
{
    // first dot
    if( comboExtension->currentItem() == 0 ) {
        *base = fi->baseName();
        *extension = fi->extension( true );
    // last dot
    } else if( comboExtension->currentItem() == 1 ) {
        *extension = fi->extension( false );
        if( !extension->isEmpty() )
            *base = fi->fileName().left( fi->fileName().length() - extension->length() - 1 );
        else
            *base = fi->baseName();
    } else {
    // custom value
        int dot = comboExtension->currentText().toInt();

        TQString file = FileOperation::getName( fi->filePath() );
        int p = 0;

        if( !file.contains( "." ) || !dot || dot > file.contains( "." ) ) {
            *base = file;
            *extension = "";
            return;
        }

        for( int i = 0; i < dot; i++ )
            p = file.find( ".", p + 1 );

        *base = file.left( p );
        *extension = file.right( file.length() - p - 1 );
    }
}

void KRenameImpl::refreshColumnMode()
{
    if( !m_autosize ) {
        preview->setColumnWidthMode( 0, TQListView::Manual );
        preview->setColumnWidthMode( 1, TQListView::Manual );
    } else {
        preview->setColumnWidthMode( 0, TQListView::Maximum );
        preview->setColumnWidthMode( 1, TQListView::Maximum );
    }
}

void KRenameImpl::updateHist()
{
    dirname->setMaxCount( m_hist );
    filename->setMaxCount( m_hist );
    extemplate->setMaxCount( m_hist );
}

void KRenameImpl::changeNumbers()
{
    NumberDialog* nd = new NumberDialog( skip, parent );
    nd->spinIndex->setValue( m_index );
    nd->spinStep->setValue( m_step );
    nd->checkResetCounter->setChecked( m_reset );

    if( nd->exec() ) {
        m_index = nd->spinIndex->value();
        m_step = nd->spinStep->value();
        skip = nd->getList();
        m_reset = nd->checkResetCounter->isChecked();

        updatePreview();
    }
}


void KRenameImpl::about()
{
    TDEAboutApplication * d = new TDEAboutApplication( kapp->aboutData(), parent );
    d->show();
}

void KRenameImpl::setWizardMode( bool mode )
{
    fileTab->raiseWidget( mode ? ID_WIZARD : ID_TAB );
    // Maybe we should create a WidgetStack here, too
    if( mode )
    {
        optionLink->hide();
        if( optionLink->isChecked() )
        {
            optionLink->setChecked( false );
            optionRename->setChecked( true );
            enableControls();
        }
    }
    else
        optionLink->show();
    
    if( mode )
        parseWizardMode();
}

void KRenameImpl::changeParent( TQWidget* p, KMenuBar* m, TQPushButton* finish, TQRect r )
{
    parent = p;
    menuBar = m;
    finishButton = finish;

    connect( finishButton, TQ_SIGNAL( clicked()), this, TQ_SLOT( start() ));

    if( !r.isNull() ) {
        parent->resize( r.size() );
        parent->move( r.x(), r.y() );
    }
        
    setupActions();

    page_1->reparent( parent, TQPoint( 0, 0 ) );
    page_2->reparent( parent, TQPoint( 0, 0 ) );
    page_3->reparent( parent, TQPoint( 0, 0 ) );
    page_4->reparent( parent, TQPoint( 0, 0 ) );

    emit pageDone( page_1, i18n( pageTitle[0] ) );
    emit pageDone( page_2, i18n( pageTitle[1] ) );
    emit pageDone( page_3, i18n( pageTitle[2] ) );
    emit pageDone( page_4, i18n( pageTitle[3] ) );
}

TQWidget* KRenameImpl::launch( TQRect rect, const KURL::List & list, KRenameImpl* impl, bool loadprofile )
{
    TDEConfig* config = kapp->config();
    config->setGroup("GUISettings");
    bool firststart = config->readBoolEntry( "firststart", true );
    bool wizardmode = config->readBoolEntry( "GUIWizardMode", false );

    if( firststart ) {
        /* start the GUI Mode selction dialog */
        FirstStartDlg* fsd = new FirstStartDlg();
        fsd->exec();
        wizardmode = fsd->useWizard();

        config->setGroup("GUISettings");
        config->writeEntry( "firststart", false );
        config->writeEntry( "GUIWizardMode", wizardmode );
        config->sync();
    }

    TQWidget* w = NULL;
    KRenameImpl* k = NULL;

    if( wizardmode ) {
        wizard* krename = new wizard( impl, rect );
        k = krename->getKRename();
        w = (TQWidget*)krename;
    } else {
        tabs* krename = new tabs( impl, rect );
        k = krename->getKRename();
        w = (TQWidget*)krename;
    }

    kapp->setMainWidget( w );

    for( unsigned int i = 0; i < list.count(); i++ )
        k->addFileOrDir( list[i] );

    k->updatePre();

    // it is time to load a default profile now (if the user has specified one)
    if( loadprofile && !k->hasCommandlineProfile() && ProfileManager::hasDefaultProfile() )
	ProfileManager::loadDefaultProfile( k );
    else if ( !k->hasCommandlineProfile() )
        w->show();

    return w;
}

void KRenameImpl::updateDots()
{
    int index = comboExtension->currentItem();
    comboExtension->clear();

    comboExtension->insertItem( i18n("First Dot") );
    comboExtension->insertItem( i18n("Last Dot") );

    unsigned int max = 0;
    for( unsigned int i = 0; i < fileList->count(); i++ ) {
        TQString name = fileList->url( i ).fileName();
        int c = name.contains( "." );
        max = ( c > (int)max ? c : (int)max);
    }

    for( unsigned int i = 2; i <= max; i++ )
        comboExtension->insertItem( TQString::number( i ) );

    comboExtension->setCurrentItem( index );
}

/** DCOP functions implementation
  */

void KRenameImpl::setFileNameTemplate( const TQString & t )
{
    filename->setText( t );
}

const TQString KRenameImpl::fileNameTemplate() const
{
    return filename->text();
}

void KRenameImpl::setExtensionTemplate( const TQString & t )
{
    extemplate->setText( t );
}

const TQString KRenameImpl::extensionTemplate() const
{
    return extemplate->text();
}

void KRenameImpl::setUseExtension( bool b )
{
    checkExtension->setChecked( b );
    enableControls();
}

bool KRenameImpl::useExtension() const
{
    return checkExtension->isChecked();
}

TQStringList KRenameImpl::tokens() const
{
    return helpDialogData->tokens();
}

TQString KRenameImpl::parseString( const TQString & token, const TQString & string )
{
    BatchRenamer b;
    b.setIndex( 0 );
    b.setStep( 0 );
   
    return b.processString( token, string, 0 );
}

void KRenameImpl::addDir( const TQString & name, const TQString & filter, bool recursive, bool hidden, bool dirnames )
{
    fileList->addDir( name, filter, hidden, recursive, dirnames );    
}

void KRenameImpl::setCounterStart( int index )
{
    m_index = index;
}

void KRenameImpl::loadFilePlugins()
{
    TDEApplication::setOverrideCursor( TQt::WaitCursor );        
    plugin->loadPlugins( true );
    TDEApplication::restoreOverrideCursor();
    pluginHelpChanged();
    
    enableControls();
}

void KRenameImpl::reloadFilePluginData()
{
    plugin->clearCache();
    updatePreview();
}

void KRenameImpl::manageProfiles()
{
    ProfileDlg dlg( this, parent, "dlg" );
    dlg.exec();
}

void KRenameImpl::getHelpDialogString( TQLineEdit* edit )
{
    HelpDialog hdlg( helpDialogData, parent, "hdlg", true );
    hdlg.setLineEdit( edit );
    hdlg.updateHeadline();
    hdlg.updateItems();
    hdlg.exec();
}

void KRenameImpl::slotEasy1()
{
    getHelpDialogString( comboPrefix->lineEdit() );
}

void KRenameImpl::slotEasy2()
{
    getHelpDialogString( comboSuffix->lineEdit() );
}

void KRenameImpl::slotEasy3()
{
    getHelpDialogString( comboCustom->lineEdit() );
}

void KRenameImpl::slotEasy4()
{
    getHelpDialogString( comboCustomExtension->lineEdit() );
}

#include "krenameimpl.moc"
