/*****************************************************************************
  This file is part of KBabel

  Copyright (C) 1999-2000 by Matthias Kiefer
                            <matthias.kiefer@gmx.de>
		2001-2003 by Stanislav Visnovsky <visnovsky@kde.org>

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  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., 675 Mass Ave, Cambridge, MA 02139, USA.

**************************************************************************** */

#include "catalogmanager.h"
#include "catalog.h"
#include "catalogmanagerapp.h"
#include "kbabeldictbox.h"
#include "resources.h"
#include "prefwidgets.h"
#include "msgfmt.h"

#include <qlabel.h>
#include <qpainter.h>

#include <dcopclient.h>
#include <kapplication.h>
#include <kaction.h>
#include <kcmenumngr.h>
#include <kconfig.h>
#include <kcursor.h>
#include <kdialogbase.h>
#include <kedittoolbar.h>
#include <kglobal.h>
#include <kglobalsettings.h>
#include <kiconloader.h>
#include <kmessagebox.h>
#include <kkeydialog.h>
#include <klocale.h>
#include <kpopupmenu.h>
#include <kprogress.h>
#include <kstdaccel.h>
#include <kstdaction.h>
#include <kstandarddirs.h>
#include <kstatusbar.h>
#include <ktoolbar.h>
#include <kwin.h>

#include <qfileinfo.h>
#include <qdir.h>
#include <qtimer.h>
#include <qbitmap.h>
#include <qwhatsthis.h>
#include <qheader.h>
#include <qdragobject.h>
#include <qlayout.h>
#include <qhbox.h>

WId CatalogManagerApp::_preferredWindow = 0;

QStringList CatalogManager::_foundFilesList;
QStringList CatalogManager::_toBeSearched;

CatalogManager::CatalogManager(QString configFile )
                 :KMainWindow(0,0)
{
   if( configFile.isEmpty() ) _configFile = "kbabelrc";
   else _configFile = configFile;

   init();
   restoreSettings(_configFile);
   setSettings(_settings);
}

CatalogManager::CatalogManager(CatManSettings settings)
                 :KMainWindow(0,0)
{
   _configFile = "kbabelrc";

   init();
   _settings = settings;
   setSettings(settings);
}

CatalogManager::~CatalogManager()
{
   saveView();
   saveSettings(_configFile);
   delete config;
}

void CatalogManager::init()
{
    _foundToBeSent = 0;
    _totalFound = 0;
    _foundFilesList.clear();
    _toBeSearched.clear();
    _timerFind = new QTimer( this );
    connect(_timerFind, SIGNAL( timeout() ), this, SLOT(findNextFile()) );
    _searchStopped = false;

   _prefWidget=0;
   _prefDialog=0;
   _findDialog=0;
   _replaceDialog=0;

   QWidget *view = new QWidget(this);
   QVBoxLayout* layout= new QVBoxLayout(view);
   layout->setMargin(0);
   layout->setSpacing(KDialog::spacingHint());

   _catalogManager=new CatalogManagerView(view,"catalog manager");
   layout->addWidget(_catalogManager);
   layout->setStretchFactor(_catalogManager,1);

   connect(_catalogManager,SIGNAL(settingsChanged(CatManSettings))
            ,this,SIGNAL(settingsChanged(CatManSettings)));
   connect(_catalogManager,SIGNAL(openFile(QString,QString))
           ,this,SLOT(openFile(QString,QString)));
   connect(_catalogManager,SIGNAL(openFileInNewWindow(QString,QString))
           ,this,SLOT(openFileInNewWindow(QString,QString)));
   connect(_catalogManager,SIGNAL(openTemplate(QString,QString,QString))
           ,this,SLOT(openTemplate(QString,QString,QString)));
   connect(_catalogManager,SIGNAL(openTemplateInNewWindow(QString,QString,QString))
           ,this,SLOT(openTemplateInNewWindow(QString,QString,QString)));
   connect(_catalogManager,SIGNAL(selectedChanged(bool,bool,bool))
	   ,this,SLOT(selectedChanged(bool,bool,bool)));

   KWin::setIcons(winId(),BarIcon("catalogmanager",32)
           ,SmallIcon("catalogmanager"));

   QHBoxLayout* hBoxL = new QHBoxLayout(layout);
   _progressLabel = new QLabel(view);
   hBoxL->addWidget(_progressLabel);
   _progressBar=new KProgress(view);
   hBoxL->addWidget(_progressBar);
   hBoxL->setStretchFactor(_progressBar,1);

   _progressLabel->hide();
   _progressBar->hide();

   connect(_catalogManager,SIGNAL(prepareProgressBar(QString,int))
           , this, SLOT(prepareProgressBar(QString,int)));
   connect(_catalogManager,SIGNAL(clearProgressBar())
           , this, SLOT(clearProgressBar()));
   connect(_catalogManager,SIGNAL(progress(int))
           , _progressBar, SLOT(setProgress(int)));
   connect(_catalogManager, SIGNAL(signalBuildTree(bool))
	   , this, SLOT(enableMenuForFiles(bool)));
   connect(this, SIGNAL(searchStopped())
	   , _catalogManager, SLOT(stopSearch()));
   connect(_catalogManager, SIGNAL(prepareFindProgressBar(int))
	   , this, SLOT(prepareStatusProgressBar(int)));

   setCentralWidget(view);
   resize( 600,300);

   setupActions();
   setupStatusBar();

   QPopupMenu* popup;
   popup = (QPopupMenu*)(factory()->container("rmb_file", this));
   if(popup)
   {
       _catalogManager->setRMBMenuFile(popup);
   }
   popup = (QPopupMenu*)(factory()->container("rmb_dir", this));
   if(popup)
   {
       _catalogManager->setRMBMenuDir(popup);
   }

   connect(_catalogManager, SIGNAL(signalSearchedFile(int))
           , _statusProgressBar, SLOT(advance(int)));

   restoreView();
}

void CatalogManager::setupActions()
{
    KGlobal::iconLoader()->addAppDir("kbabel");

    KAction *action;

    // the file menu
    action = new KAction( i18n("&Open"), CTRL+Key_O, _catalogManager,
                          SLOT(slotOpenFile()),actionCollection(), "open");
    action->setEnabled(false);
    action = new KAction(i18n("&Open Template"),Key_Space,_catalogManager,
                         SLOT(slotOpenTemplate()),actionCollection(), "open_template");
    action->setEnabled(false);
    action = new KAction(i18n("Open in &New Window"),CTRL+SHIFT+Key_O,_catalogManager,
                         SLOT(slotOpenFileInNewWindow()),actionCollection(), "open_new_window");
    action->setEnabled(false);

    action = KStdAction::quit(kapp, SLOT (closeAllWindows()), actionCollection());

    // the edit menu
    action = new KAction( i18n("Fi&nd in Files..."), CTRL+Key_F, this,
                          SLOT(find()), actionCollection(), "find_in_files");
    action->setEnabled(false);
    action = new KAction( i18n("Re&place in Files..."), CTRL+Key_R, this,
                          SLOT(replace()), actionCollection(), "replace_in_files");
    action->setEnabled(false);
    action = new KAction( i18n("&Stop Searching"), "stop", Key_Escape, this,
                          SLOT(stopSearching()), actionCollection(), "stop_search");
    action->setEnabled(false);
    action = new KAction( i18n("&Toggle Marking"), CTRL+Key_M, _catalogManager,
                          SLOT(toggleMark()), actionCollection(), "toggle_marking");
    action->setEnabled(false);
    action = new KAction( i18n("Remove Marking"), 0, _catalogManager,
                          SLOT(slotClearMarksInDir()), actionCollection(), "remove_marking");
    action->setEnabled(false);
    action = new KAction( i18n("Toggle All Markings"), 0, _catalogManager,
                          SLOT(toggleAllMarks()), actionCollection(), "toggle_all_marking");
    action->setEnabled(false);
    action = new KAction( i18n("Remove All Markings"), 0, _catalogManager,
                          SLOT(clearAllMarks()), actionCollection(), "remove_all_marking");
    action->setEnabled(false);
    action = new KAction( i18n("&Load Markings..."), 0, _catalogManager,
                          SLOT(loadMarks()), actionCollection(), "load_marking");
    action->setEnabled(false);
    action = new KAction( i18n("&Save Markings..."), 0, _catalogManager,
                          SLOT(saveMarks()), actionCollection(), "save_marking");
    action->setEnabled(false);
    action = new KAction( i18n("&Reload"), "reload", KStdAccel::reload(), _catalogManager,
                          SLOT(updateCurrent()), actionCollection(), "reload");
    action->setEnabled(false);

    // go menu
    action = new KAction(i18n("Nex&t Untranslated"), "nextuntranslated", ALT+Key_Next,
                         _catalogManager, SLOT(gotoNextUntranslated()),actionCollection(), "go_next_untrans");
    action->setEnabled(false);
    action = new KAction(i18n("Prev&ious Untranslated"), "prevuntranslated", ALT+Key_Prior,
                         _catalogManager, SLOT(gotoPreviousUntranslated()),actionCollection(), "go_prev_untrans");
    action->setEnabled(false);
    action = new KAction(i18n("Ne&xt Fuzzy"), "nextfuzzy", CTRL+Key_Next,
                         _catalogManager, SLOT(gotoNextFuzzy()),actionCollection(), "go_next_fuzzy");
    action->setEnabled(false);
    action = new KAction(i18n("Pre&vious Fuzzy"), "prevfuzzy", CTRL+Key_Prior,
                         _catalogManager, SLOT(gotoPreviousFuzzy()),actionCollection(), "go_prev_fuzzy");
    action->setEnabled(false);
    action = new KAction(i18n("N&ext Fuzzy or Untranslated"), "nextfuzzyuntrans", CTRL+SHIFT+Key_Next,
                         _catalogManager, SLOT(gotoNextFuzzyOrUntranslated()),actionCollection(), "go_next_fuzzyUntr");
    action->setEnabled(false);
    action = new KAction(i18n("P&revious Fuzzy or Untranslated"), "prevfuzzyuntrans", CTRL+SHIFT+Key_Prior,
                         _catalogManager, SLOT(gotoPreviousFuzzyOrUntranslated()),actionCollection(), "go_prev_fuzzyUntr");
    action->setEnabled(false);

    action = new KAction(i18n("Next Err&or"), "nexterror", ALT+SHIFT+Key_Next,
                         _catalogManager, SLOT(gotoNextError()),actionCollection(), "go_next_error");
    action->setEnabled(false);
    action = new KAction(i18n("Previo&us Error"), "preverror", ALT+SHIFT+Key_Prior,
                         _catalogManager, SLOT(gotoPreviousError()),actionCollection(), "go_prev_error");
    action->setEnabled(false);
    action = new KAction(i18n("Next Te&mplate Only"), "nexttemplate", CTRL+Key_Down,
                         _catalogManager, SLOT(gotoNextTemplate()),actionCollection(), "go_next_template");
    action->setEnabled(false);
    action = new KAction(i18n("Previous Temp&late Only"), "prevtemplate", CTRL+Key_Up,
                         _catalogManager, SLOT(gotoPreviousTemplate()),actionCollection(), "go_prev_template");
    action->setEnabled(false);
    action = new KAction(i18n("Next Tran&slation Exists"), "nextpo", ALT+Key_Down,
                         _catalogManager, SLOT(gotoNextPo()),actionCollection(), "go_next_po");
    action->setEnabled(false);
    action = new KAction(i18n("Previous Transl&ation Exists"), "prevpo", ALT+Key_Up,
                         _catalogManager, SLOT(gotoPreviousPo()),actionCollection(), "go_prev_po");
    action->setEnabled(false);

    action = new KAction(i18n("Previous Marke&d"), "prevmarked", SHIFT+Key_Up,
                         _catalogManager, SLOT(gotoPreviousMarked()),actionCollection(), "go_prev_marked");
    action->setEnabled(false);
    action = new KAction(i18n("Next &Marked"), "nextmarked", SHIFT+Key_Down,
                         _catalogManager, SLOT(gotoNextMarked()),actionCollection(), "go_next_marked");
    action->setEnabled(false);

    // tools menu
    action = new KAction( i18n("&Statistics"), "statistics",  CTRL+Key_S,
                          _catalogManager, SLOT(statistics()), actionCollection(), "statistics");
    action->setEnabled(false);
    action = new KAction( i18n("S&tatistics in Marked"), "statistics",  CTRL+ALT+Key_S,
                          _catalogManager, SLOT(markedStatistics()), actionCollection(), "statistics_marked");
    action->setEnabled(false);
    action = new KAction( i18n("Check S&yntax"), "syntax", CTRL+Key_Y,
                          _catalogManager, SLOT(checkSyntax()), actionCollection(), "syntax");
    action->setEnabled(false);
    action = new KAction( i18n("S&pell Check"), "spellcheck",  CTRL+Key_I,
                          this, SLOT(spellcheck()), actionCollection(), "spellcheck");
    action->setEnabled(false);
    action = new KAction( i18n("Spell Check in &Marked"), "spellcheck", CTRL+ALT+Key_I,
                          this, SLOT(markedSpellcheck()), actionCollection(), "spellcheck_marked");
    action->setEnabled(false);
    action = new KAction( i18n("&Rough Translation"),  CTRL+Key_T,
                          _catalogManager, SLOT(roughTranslation()), actionCollection(), "rough_translation");
    action->setEnabled(false);
    action = new KAction( i18n("Rough Translation in M&arked"), CTRL+ALT+Key_T,
                          _catalogManager, SLOT(markedRoughTranslation()), actionCollection(), "rough_translation_marked");
    action->setEnabled(false);
    action = new KAction( i18n("Mai&l"), "mail_send", CTRL+Key_A,
                          _catalogManager, SLOT(mailFiles()), actionCollection(), "mail_file");
    action->setEnabled(false);
    action = new KAction( i18n("Mail Mar&ked"), "mail_send", CTRL+ALT+Key_A,
                          _catalogManager, SLOT(mailMarkedFiles()), actionCollection(),	"mail_file_marked");
    action->setEnabled(false);

    // settings menu
    KStdAction::preferences(this, SLOT( optionsPreferences()), actionCollection());
    KStdAction::keyBindings(this, SLOT( optionsKeys() ), actionCollection());
    KStdAction::configureToolbars(this,SLOT(optionsEditToolbars()), actionCollection() );
    KToggleAction * toggle = KStdAction::showStatusbar( this,SLOT( dummySlot() ), actionCollection() );
    connect( toggle, SIGNAL( toggled(bool) ), this, SLOT( optionsShowStatusbar(bool) ) );
    
    setStandardToolBarMenuEnabled ( true );

    // commands menus
    KActionMenu* actionMenu=new KActionMenu(i18n("Commands"), 0,
                                            actionCollection(), "dir_commands");
    _catalogManager->setDirCommandsMenu( actionMenu->popupMenu());

    actionMenu=new KActionMenu(i18n("Commands"), 0,
                               actionCollection(), "file_commands");
    _catalogManager->setFileCommandsMenu( actionMenu->popupMenu());

    action = new KAction(i18n("&Delete"),Key_Delete,_catalogManager,SLOT(slotDeleteFile()),actionCollection(), "delete");
    action->setEnabled(false);

     createGUI();
}

void CatalogManager::setupStatusBar()
{
    _foundLabel = new QLabel( "          ", statusBar());
    statusBar()->addWidget(_foundLabel,0);

    QHBox* progressBox = new QHBox(statusBar(), "progressBox" );
    progressBox->setSpacing(2);
    _statusProgressLabel = new QLabel( "", progressBox );
    _statusProgressBar = new KProgress( progressBox, "progressBar");
    _statusProgressBar->hide();

    statusBar()->addWidget(progressBox,1);
    statusBar()->setMinimumHeight(_statusProgressBar->sizeHint().height());

    QWhatsThis::add(statusBar(),
	i18n("<qt><p><b>Statusbar</b></p>\n"
         "<p>The statusbar displays information about progress of"
         " the current find or replace operation. The first number in <b>Found:</b>"
         " displays the number of files with an occurrence of the searched text not"
         " yet shown in the KBabel window. The second shows the total number of files"
         " containing the searched text found so far.</p></qt>"));
}

void CatalogManager::enableMenuForFiles(bool enable)
{
    stateChanged( "treeBuilt", enable ? StateNoReverse: StateReverse );
}

void CatalogManager::selectedChanged(bool hasPo, bool hasPot, bool hasMarks)
{
    stateChanged("onPo", hasPo ? StateNoReverse: StateReverse );
    stateChanged("onPot", hasPot ? StateNoReverse: StateReverse );
    
    stateChanged("onMarked", hasMarks ? StateNoReverse: StateReverse );
    stateChanged("onPoMarked", (hasMarks && hasPo) ? StateNoReverse: StateReverse );
}

CatManSettings CatalogManager::settings() const
{
    return _catalogManager->settings();
}

void CatalogManager::setSettings(CatManSettings newSettings)
{
    _catalogManager->setSettings(newSettings);

   _openNewWindow=newSettings.openWindow;
}

void CatalogManager::saveSettings( QString configFile )
{
    _settings = _catalogManager->settings(); // restore settings from the view

    config = new KConfig(configFile);

    KConfigGroupSaver cs(config,"CatalogManager");

    config->writeEntry("PoBaseDir",_settings.poBaseDir);
    config->writeEntry("PotBaseDir",_settings.potBaseDir);
    config->writeEntry("OpenWindow",_settings.openWindow);

    config->writeEntry("KillCmdOnExit",_settings.killCmdOnExit);
    config->writeEntry("IndexWords", _settings.indexWords);

    config->writeEntry("DirCommands",_settings.dirCommands);
    config->writeEntry("DirCommandNames",_settings.dirCommandNames);
    config->writeEntry("FileCommands",_settings.fileCommands);
    config->writeEntry("FileCommandNames",_settings.fileCommandNames);

    _catalogManager->saveView(config);

    config->sync();
}

void CatalogManager::restoreSettings( QString configFile )
{
    config = new KConfig(configFile);

    KConfigGroupSaver cs(config,"CatalogManager");

    _settings.poBaseDir=config->readEntry("PoBaseDir"
               ,Defaults::CatalogManager::poBaseDir());
    _settings.potBaseDir=config->readEntry("PotBaseDir"
	       ,Defaults::CatalogManager::potBaseDir());
    _settings.openWindow=config->readBoolEntry("OpenWindow"
               ,Defaults::CatalogManager::openWindow);

    _settings.killCmdOnExit=config->readBoolEntry("KillCmdOnExit"
               ,Defaults::CatalogManager::killCmdOnExit);
    _settings.indexWords=config->readBoolEntry("IndexWords"
               ,Defaults::CatalogManager::indexWords);


    if(config->hasKey("DirCommands"))
    {
          _settings.dirCommands = config->readListEntry("DirCommands");
          _settings.dirCommandNames =
              config->readListEntry("DirCommandNames");
    }
    else
    {
          _settings.dirCommands = Defaults::CatalogManager::dirCommands();
          _settings.dirCommandNames =
              Defaults::CatalogManager::dirCommandNames();
    }
    if(config->hasKey("FileCommands"))
    {
          _settings.fileCommands = config->readListEntry("FileCommands");
          _settings.fileCommandNames =
              config->readListEntry("FileCommandNames");
    }
    else
    {
          _settings.fileCommands=Defaults::CatalogManager::fileCommands();
          _settings.fileCommandNames =
              Defaults::CatalogManager::fileCommandNames();
    }

    if(!config->hasGroup("PathInfo"))
    {
           config->setGroup("PathInfo");
           config->writeEntry("MessageRoot",_settings.poBaseDir);
           config->writeEntry("TemplateRoot",_settings.potBaseDir);
    }

    _catalogManager->restoreView(config);
}

void CatalogManager::setPreferredWindow(WId window)
{
    _preferredWindow = window;
    kdDebug(KBABEL_CATMAN) << "setPrefereedWindow set to :" << _preferredWindow << endl;
}

void CatalogManager::updateFile(QString fileWithPath)
{
    _catalogManager->updateFile(fileWithPath,true); //force update
}

void CatalogManager::updateAfterSave(QString fileWithPath, PoInfo &info)
{
    _catalogManager->updateAfterSave(fileWithPath, info);
}

CatalogManagerView *CatalogManager::view()
{
    return _catalogManager;
}

void CatalogManager::openFile(QString filename, QString package)
{
    DCOPClient * client = kapp->dcopClient();

    if( startKBabel() )
    {

        QByteArray data;
        QCString url = filename.local8Bit();
        QDataStream arg(data, IO_WriteOnly);
        arg << url;
        arg << package.utf8();
        arg << CatalogManagerApp::_preferredWindow;
        arg << ( _openNewWindow ? 1 : 0 );

        kdDebug(KBABEL_CATMAN) << "Open file with project " << _configFile << endl;

        QCString callfunc="openURL(QCString, QCString, WId,int)";
        if(_configFile != "kbabelrc" )
        {
            arg << _configFile.utf8();
            callfunc="openURL(QCString, QCString, WId,int,QCString)";
        }

        kdDebug(KBABEL_CATMAN) << callfunc << endl;

        if( !client->send("kbabel","KBabelIFace", callfunc, data) )
            KMessageBox::error(this, i18n("Can't send a message to KBabel.\n"
                                          "Please check your installation of KDE."));
    }
}

void CatalogManager::openFileInNewWindow(QString filename, QString package)
{
    DCOPClient * client = kapp->dcopClient();

    if( startKBabel() )
    {

        QByteArray data;
        QCString url = filename.local8Bit();
        QDataStream arg(data, IO_WriteOnly);
        arg << url;
        arg << package.utf8();
        arg << CatalogManagerApp::_preferredWindow;
        arg << ((int)1);

        QCString callfunc="openURL(QCString, QCString, WId,int)";
        if(_configFile != "kbabelrc" )
        {
            arg << _configFile.utf8();
            callfunc="openURL(QCString, QCString, WId,int,QCString)";
        }

        if( !client->send("kbabel","KBabelIFace", callfunc, data) )
            KMessageBox::error(this, i18n("Can't send a message to KBabel.\n"
                                          "Please check your installation of KDE."));
    }
}

void CatalogManager::openTemplate(QString openFilename,QString saveFilename,QString package)
{
    DCOPClient * client = kapp->dcopClient();

    if( startKBabel() ) {
        QByteArray data;
        QCString url = openFilename.local8Bit();
        QDataStream arg(data, IO_WriteOnly);
        arg << url;
        url = saveFilename.utf8();
        arg << url;
        arg << package.utf8();
        arg << (_openNewWindow ? 1 : 0 );

        QCString callfunc="openTemplate(QCString,QCString,QCString,int)";
        if(_configFile != "kbabelrc" )
        {
            arg << _configFile.utf8();
            callfunc="openTemplate(QCString,QCString,QCString,int,QCString)";
        }

        if( !client->send("kbabel","KBabelIFace", callfunc, data) )
            KMessageBox::error(this, i18n("Can't send a message to KBabel.\n"
                                          "Please check your installation of KDE."));
    }
}

void CatalogManager::openTemplateInNewWindow(QString openFilename,QString saveFilename,QString package)
{
    DCOPClient * client = kapp->dcopClient();

    if( startKBabel() ) {
        QByteArray data;
        QCString url = openFilename.local8Bit();
        QDataStream arg(data, IO_WriteOnly);
        arg << url;
        url = saveFilename.utf8();
        arg << url;
        arg << package.utf8();
        arg << ((int)1);

        QCString callfunc="openTemplate(QCString,QCString,QCString,int)";
        if(_configFile != "kbabelrc" )
        {
            arg << _configFile.utf8();
            callfunc="openTemplate(QCString,QCString,QCString,int,QCString)";
        }

        if( !client->send("kbabel","KBabelIFace", callfunc, data) )
            KMessageBox::error(this, i18n("Can't send a message to KBabel.\n"
                                          "Please check your installation of KDE."));
    }
}

void CatalogManager::spellcheck()
{
    DCOPClient * client = kapp->dcopClient();

    QStringList fileList = _catalogManager->current();

    if( startKBabel() ) {
        QByteArray data;
        QDataStream arg(data, IO_WriteOnly);
        arg << fileList;
        if( !client->send("kbabel","KBabelIFace", "spellcheck(QStringList)", data) )
            KMessageBox::error(this, i18n("Can't send a message to KBabel.\n"
                                          "Please check your installation of KDE."));
    }
}

void CatalogManager::markedSpellcheck()
{
    DCOPClient * client = kapp->dcopClient();

    QStringList fileList = _catalogManager->marked();

    if( startKBabel() ) {
        QByteArray data;
        QDataStream arg(data, IO_WriteOnly);
        arg << fileList;
        if( !client->send("kbabel","KBabelIFace", "spellcheck(QStringList)", data) )
            KMessageBox::error(this, i18n("Can't send a message to KBabel.\n"
                                          "Please check your installation of KDE."));
    }
}

bool CatalogManager::startKBabel()
{
    QCString service;
    QString result;

    DCOPClient * client = kapp->dcopClient();

    // find out, if there is a running kbabel
    QCStringList apps = client->registeredApplications();
    for( QCStringList::Iterator it = apps.begin() ; it != apps.end() ; it++ )
    {
        QString clientID = *it;
        if( clientID=="kbabel" )
        {
            service = *it;
            break;
        }
    }

    // if there is no running kbabel, start one
    if( service.isEmpty() )
    {
        QString app = "kbabel";
        QString url = "";
        if( kapp->startServiceByDesktopName(app,url, &result, &service))
        {
            KMessageBox::error( this, i18n("Unable to use KLauncher to start KBabel.\n"
                                           "You should check the installation of KDE.\n"
                                           "Please start KBabel manually."));
            return false;
        } else sleep(1);
    }

    return true;
}


void CatalogManager::prepareProgressBar(QString msg, int max)
{
   _progressBar->setTotalSteps(max);
   _progressBar->setProgress(0);
   _progressLabel->setText(msg);

   _progressBar->show();
   _progressLabel->show();
}

void CatalogManager::clearProgressBar()
{
   _progressBar->setProgress(0);

   _progressBar->hide();
   _progressLabel->hide();
}

void CatalogManager::prepareStatusProgressBar(QString msg, int max)
{
   _totalFound = 0;
   _foundToBeSent = 0;
   _statusProgressBar->setRange(0,max);
   _statusProgressLabel->setText(msg);
   _foundLabel->setText( i18n("Found: 0/0") );

   _statusProgressBar->show();
   _statusProgressLabel->show();
}

void CatalogManager::prepareStatusProgressBar(int max)
{
   _statusProgressBar->setRange(0,max);
}

void CatalogManager::clearStatusProgressBar()
{
   _statusProgressBar->setValue(0);

   _statusProgressBar->hide();
   _statusProgressLabel->hide();
   _foundLabel->setText("          ");
}

void CatalogManager::setNumberOfFound(int toBeSent, int total)
{
    _foundLabel->setText(i18n("Found: %1/%2").arg(toBeSent).arg(total));
}

void CatalogManager::decreaseNumberOfFound()
{
    if( _foundToBeSent > 0 ) {
        _foundToBeSent--;
        setNumberOfFound( _foundToBeSent, _totalFound );
    }
}

void CatalogManager::slotHelp()
{
   kapp->invokeHelp("CATALOGMANAGER","kbabel");
}

void CatalogManager::find()
{
    if( !_findDialog ) _findDialog = new FindDialog(false,this);

    if( _findDialog->exec("") == QDialog::Accepted )
    {
        _timerFind->stop();
        _searchStopped = false;
        _catalogManager->stop(false); // surely we are not in process of quitting, since there is no window and user cannot invoke Find
        prepareStatusProgressBar(i18n("Searching"),1); // just show the progress bar

        // enable stop action to stop searching
        KAction *action = (KAction*)actionCollection()->action("stop_search");
        action->setEnabled(true);

        _findOptions = _findDialog->findOpts();

        // get from options the information for ignoring text parts
        config = new KConfig( "kbabelrc");
        config->setGroup( "Misc" );
        Defaults::Misc defaultMisc;
        _findOptions.contextInfo = config->readEntry( "contextInfo", defaultMisc.contextInfo().pattern() );
        _findOptions.accelMarker = (config->readEntry( "accelMarker", QString(defaultMisc.accelMarker()) ))[0];

        _foundFilesList.clear();
        kdDebug(KBABEL_CATMAN) << "Calling catalogmanagerview::find" << endl;
        QString url = _catalogManager->find(_findOptions, _toBeSearched );

        if( _catalogManager->isStopped() ) return;
        if( !url.isEmpty() )
        {
            if( startKBabel() )
            {
                DCOPClient *client = kapp->dcopClient();
                QByteArray data;
                QDataStream arg(data, IO_WriteOnly);
                arg << client->appId();
                arg << url.utf8();
                arg << _findOptions.findStr;
                arg << (_findOptions.caseSensitive ? 1 : 0);
                arg << (_findOptions.wholeWords ? 1 : 0);
                arg << (_findOptions.isRegExp ? 1 : 0);
                arg << (_findOptions.inMsgid ? 1 : 0);
                arg << (_findOptions.inMsgstr ? 1 : 0);
                arg << (_findOptions.inComment ? 1 : 0);
                arg << (_findOptions.ignoreAccelMarker ? 1 : 0);
                arg << (_findOptions.ignoreContextInfo ? 1 : 0);
                arg << (_findOptions.askForNextFile ? 1 : 0);
                arg << (_findOptions.askForSave ? 1 : 0);
                if( !client->send("kbabel","KBabelIFace",
                                  "findInFile(QCString,QCString,QString,int,int,int,int,int,int,int,int,int,int)", data)
                    ) {
                    KMessageBox::error( this, i18n("DCOP communication with KBabel failed."), i18n("DCOP communication error"));
                    stopSearching();
                    return;
                }

                if( !_toBeSearched.isEmpty() )
                {
                    _totalFound = 1;
                    _foundToBeSent = 0;
                    setNumberOfFound( 0, 1 );	// one found, but already sent
                    _timerFind->start(100,true);
                } else stopSearching();
            }
            else
            {
                KMessageBox::error( this, i18n("KBabel cannot be started."), i18n("Cannot Start KBabel"));
                stopSearching();
            }

        }
        else
        {
            if( !_searchStopped) KMessageBox::information(this, i18n("Search string not found!"));
            stopSearching();
        }
    }
}

void CatalogManager::replace()
{
    if( !_replaceDialog ) _replaceDialog = new FindDialog(true,this);


    if( _replaceDialog->exec("") == QDialog::Accepted )
    {
        _timerFind->stop();
        _searchStopped = false;
        _catalogManager->stop(false); // surely we are not in process of quitting, since there is no window and user cannot invoke Find
        prepareStatusProgressBar(i18n("Searching"),1); // just show the progress bar

        // enable stop action to stop searching
        KAction *action = (KAction*)actionCollection()->action("stop_search");
        action->setEnabled(true);

        ReplaceOptions options = _replaceDialog->replaceOpts();

        _findOptions = options;

        // get from options the information for ignoring text parts
        config = new KConfig( "kbabelrc");
        config->setGroup( "Misc" );
        Defaults::Misc defaultMisc;
        options.contextInfo = config->readEntry( "contextInfo", defaultMisc.contextInfo().pattern() );
        options.accelMarker = (config->readEntry( "accelMarker", QString(defaultMisc.accelMarker()) ))[0];

        _foundFilesList.clear();
        QString url = _catalogManager->find(options, _toBeSearched );

        if( _catalogManager->isStopped() ) return;
        if( !url.isEmpty() )
        {
            if( startKBabel() )
            {
                DCOPClient *client = kapp->dcopClient();
                QByteArray data;
                QDataStream arg(data, IO_WriteOnly);
                arg << client->appId();
                arg << url.utf8();
                arg << options.findStr;
                arg << options.replaceStr;
                arg << (options.caseSensitive ? 1 : 0);
                arg << (options.wholeWords ? 1 : 0);
                arg << (options.isRegExp ? 1 : 0);
                arg << (options.inMsgid ? 1 : 0);
                arg << (options.inMsgstr ? 1 : 0);
                arg << (options.inComment ? 1 : 0);
                arg << (options.ignoreAccelMarker ? 1 : 0);
                arg << (options.ignoreContextInfo ? 1 : 0);
                arg << (options.ask ? 1 : 0);
                arg << (options.askForNextFile ? 1 : 0);
                arg << (options.askForSave ? 1 : 0);
                if( !client->send("kbabel","KBabelIFace",
                                  "replaceInFile(QCString,QCString,QString,QString,int,int,int,int,int,int,int,int,int,int,int)", data)
                    ) {
                    KMessageBox::error( this, i18n("DCOP communication with KBabel failed."), i18n("DCOP Communication Error"));
                    stopSearching();
                    return;
                }

                if( !_toBeSearched.isEmpty() )
                {
                    _totalFound = 1;
                    setNumberOfFound( 0, 1 );
                    _timerFind->start(100,true);
                } else stopSearching();
            }
            else
            {
                KMessageBox::error( this, i18n("KBabel cannot be started."), i18n("Cannot Start KBabel"));
                stopSearching(); // update window
            }

        }
        else
        {
            if( !_searchStopped ) KMessageBox::information(this, i18n("Search string not found!"));
            stopSearching(); // update window
        }
    }
}

void CatalogManager::findNextFile()
{
    _timerFind->stop(); // stop the timer for lookup time
    if(_toBeSearched.empty() )
    {
        stopSearching();
        return;
    }
    QString file = _toBeSearched.first();
    _toBeSearched.pop_front();
    if( Catalog::findInFile( file, _findOptions ) )
    {
        _foundFilesList.append(file);
        _totalFound++;
        _foundToBeSent++;
        setNumberOfFound(_foundToBeSent,_totalFound);
    }
    _statusProgressBar->advance(1);
    if( !_toBeSearched.empty() )
        _timerFind->start(100,true); // if there is more files to be searched, start the timer again
    else
        stopSearching();
}

void CatalogManager::stopSearching()
{
    _searchStopped = true;
    emit searchStopped();
    // clear the list of files to be searched
    _toBeSearched.clear();

    // fake that we are over (fake, because findNextFile can still be running for the last file
    clearStatusProgressBar(); // clear the status bar, we are finished
    // disable stop action as well
    KAction *action = (KAction*)actionCollection()->action("stop_search");
    action->setEnabled(false);
}

void CatalogManager::optionsPreferences()
{
   if(!_prefDialog)
   {
      _prefDialog = new KDialogBase(this,0,true,i18n("Catalog Manager Preferences")
                     ,KDialogBase::Ok|KDialogBase::Cancel|KDialogBase::Help);
      _prefDialog->setHelp("preferences_catalogmanager");

      _prefWidget=new CatManPreferences(_prefDialog);

      _prefDialog->setMainWidget(_prefWidget);
   }

   _prefWidget->setSettings(_catalogManager->settings());
   if(_prefDialog->exec())
   {
      CatManSettings settings;
      _prefWidget->mergeSettings(settings);
      setSettings(settings);
      emit settingsChanged(settings);
   }
}

void CatalogManager::optionsKeys()
{
    KKeyDialog::configureKeys(actionCollection(), xmlFile());
}


void CatalogManager::optionsEditToolbars()
{
    KEditToolbar dlg(actionCollection());

    if( dlg.exec() == true ) createGUI();
}

void CatalogManager::optionsShowStatusbar(bool on)
{
    if( on )
        statusBar()->show();
    else
        statusBar()->hide();
}

bool CatalogManager::queryClose()
{
    _catalogManager->stop();
    saveView();
    saveSettings(_configFile);
    return true;
}

void CatalogManager::saveView()
{
    saveMainWindowSettings( KGlobal::config(), "View");
}


void CatalogManager::restoreView()
{
    applyMainWindowSettings( KGlobal::config(), "View");

    KToggleAction * toggle = (KToggleAction*)actionCollection()->
	action(KStdAction::stdName(KStdAction::ShowStatusbar));
    toggle->setChecked(!statusBar()->isHidden() );
}

#include "catalogmanager.moc"
