/****************************************************************************
**
** Copyright (C) 2002-2006 Frank Hemer <frank@hemer.org>,
**                         Tilo Riemer <riemer@crossvc.com>,
**                         Jose Hernandez <joseh@tesco.net>,
**                         Tom Mishima <tmishima@mail.at-m.or.jp>
**
**
**----------------------------------------------------------------------------
**
**----------------------------------------------------------------------------
**
** CrossVC is available under two different licenses:
**
** If CrossVC is linked against the GPLed version of Qt 
** CrossVC is released under the terms of GPL also.
**
** If CrossVC is linked against a nonGPLed version of Qt 
** CrossVC is released under the terms of the 
** CrossVC License for non-Unix platforms (CLNU)
**
**
** CrossVC License for non-Unix platforms (CLNU):
**
** Redistribution and use in binary form, without modification, 
** are permitted provided that the following conditions are met:
**
** 1. Redistributions in binary form must reproduce the above copyright
**    notice, this list of conditions and the following disclaimer in the
**    documentation and/or other materials provided with the distribution.
** 2. It is not permitted to distribute the binary package under a name
**    different than CrossVC.
** 3. The name of the authors may not be used to endorse or promote
**    products derived from this software without specific prior written
**    permission.
** 4. The source code is the creative property of the authors.
**    Extensions and development under the terms of the Gnu Public License
**    are limited to the Unix platform. Any distribution or compilation of 
**    the source code against libraries licensed other than gpl requires 
**    the written permission of the authors.
**
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR 
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
** ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 
** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 
** GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
** NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**
**
**
** CrossVC License for Unix platforms:
**
** 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, version 2 of the License.
** 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 version 2 for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software Foundation,
** Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
**
*****************************************************************************/

#include "config.h"

//----------------------------------------------------------------------------

#include <qapplication.h>
#include <qcheckbox.h>
#include <qcombobox.h>
#include <qfiledialog.h>
#include <qlineedit.h>
#include <qlistbox.h>
#include <qmessagebox.h>
#include <qmultilineedit.h>
#include <qpushbutton.h>
#include <qradiobutton.h>
#include <qspinbox.h>
#include <qtoolbutton.h>
#include <qdatetimeedit.h>
#include <qcolordialog.h>
#include <qtabwidget.h>
#include <qfont.h>
#include <qfontdialog.h>
#include <qwhatsthis.h>

//----------------------------------------------------------------------------

#include "globals.h"
#include "settingsdialogimpl.h"
#include "pixmapcache.h"

#include "cvsconfig.h"

#include "SyntaxHighlighter.h"

#include "TextCodec.h"
#include "TextDecoder.h"
#include "TextEncoder.h"
#include "SshKeyDialogImpl.h"

//----------------------------------------------------------------------------

/**
 * Constructs a SettingsDialogImpl which is a child of 'parent', with the name
 * 'name' and widget flags set to 'f'.  The dialog will by default be modeless,
 * unless you set 'modal' to TRUE to construct a modal dialog.
 */

SettingsDialogImpl::SettingsDialogImpl(const QIconSet &whatsThisIconSet, 
      QWidget* parent,  const char* name, bool, WFlags fl)
   : SettingsDialog(parent, name, true, fl),
     m_onTheFlyScanningModeChanged(false),
     m_agentSetupChanged(false),
     m_dialogUp(false)
{
   m_pWhatsThis->setIconSet(whatsThisIconSet);
  
   // tricky and sophisticated? piece of code
   //int margin = m_pWhatsThis->height() - m_pWhatsThis->childrenRect().height();
   //m_pWhatsThis->setMaximumWidth(QIconSet::iconSize(QIconSet::Small).width() + margin);

   // simple solution --> the whatsthis icon should be not wider than high
#ifdef Q_WS_MAC
   m_pWhatsThis->setMaximumWidth(m_pWhatsThis->height() * 2);
#else
   m_pWhatsThis->setMaximumWidth(m_pWhatsThis->height());
#endif
  
   // Set value on GUI to current compresion level
   m_CompressionLevel->setValue(CvsOptions::g_compression);

   // External remote browser
   m_remoteBrowser->setText(ExtApps::g_remoteBrowser.path);
   m_remoteBrowserOptions->setText(ExtApps::g_remoteBrowser.options);

   // External local browser
   m_localBrowser->setText(ExtApps::g_localBrowser.path);
   m_localBrowserOptions->setText(ExtApps::g_localBrowser.options);

   // set the update timer value
   WBUpdateSpinBox->setValue(CHECKSTATUSINTERVALL / 1000);

   // set update check level
   CheckStatusSpinBox->setValue(Polling::checkStatusLevel);

   //set module update timer value
   AutoUpdateSpinBox->setValue(AUTOUPDATEINTERVALL);

   // set ssh agent
   m_sshKeyFiles = ExtApps::g_sshKeyFiles;
   m_SshAgent->setText(ExtApps::g_sshAgent.path);
   m_SshAgentOptions->setText(ExtApps::g_sshAgent.options);

   // set remote shell
   m_RemoteShell->setText(ExtApps::g_cvsRsh.path);

   // set local shell
   m_LocalShell->setText(ExtApps::g_localShell.path);
   m_LocalShellOptions->setText(ExtApps::g_localShell.options);

   // set External diff program
   m_ExternalDiffUse->setChecked(bUSEEXTERNALDIFFFORSIDEBYSIDE);
   m_ExternalDiffEdit->setText(ExtApps::g_diffProg.path);
   m_ExternalDiffEditOptions->setText(ExtApps::g_diffProg.options);

   //fill in the default template text
   m_pTemplate->setText(readDefaultTemplateFile());
   m_pHistorySize->setValue(HistorySize::g_commitinfo);
  
   //set history sizes
   m_pHistorySizeWorkdirs->setValue(HistorySize::g_profiles);
   m_pHistorySizeProfiles->setValue(HistorySize::g_workdirs);
  
   // set on the fly scanning mode
   m_onTheFlyScanning->setChecked(ONTHEFLYSCANNING);

   // set default r/rw permission for files on checkout/update
   m_RO_Permission->setChecked(!bRWPermission);
   m_RW_Permission->setChecked(bRWPermission);

   //virtual dirs
   m_VirtualDirCheckBox->setChecked(CvsOptions::g_bShowVirtualInFiletab);

   //diff-precision
   m_DiffPrecisionSpinBox->setValue(CvsOptions::g_precision);

   //prune empty dirs?
   m_pPruneDirs->setChecked(CvsOptions::g_bPruneDirs);

   //Bring over new dirs?
   m_pBringOverNewDirs->setChecked(CvsOptions::g_bBringOverNewDirs);

   //set default diff mode
   m_KeywordSuppression->setChecked(bKeywordSuppression);
   m_IgnoreWhiteSpace->setChecked(bDiffIgnoreWhiteSpace);

   //run cvs in quiet mode?
   m_pQuietCvs->setChecked(CvsOptions::g_bQuietCvs);
 
   //patch mode
   m_pUnifiedDiffOutput->setChecked(CvsOptions::g_bUnifiedDiffOutput);

   //set icon dir
   m_iconDir->setText(iconDir);

   //set CVSVERSION, CVSPASS and CVSPASSPATH
   m_CvsPath->setText(CVSPATH);
   m_CvsPassPath->setText(CVSPASSPATH);

   //set properties for syntax highlighting
   m_pUseSyntaxHighlighting->setChecked(HighlightProperties::g_bUseSyntaxHighlighting);

   m_pBoldQuestionMark->setChecked(HighlightProperties::g_updateQuestionMark.style & HighlightProperties::FS_BOLD);
   m_pItalicQuestionMark->setChecked(HighlightProperties::g_updateQuestionMark.style & HighlightProperties::FS_ITALIC);
   m_pBoldModified->setChecked(HighlightProperties::g_updateModified.style & HighlightProperties::FS_BOLD);
   m_pItalicModified->setChecked(HighlightProperties::g_updateModified.style & HighlightProperties::FS_ITALIC);
   m_pBoldNeedsUpdate->setChecked(HighlightProperties::g_updateNeedsUpdate.style & HighlightProperties::FS_BOLD);
   m_pItalicNeedsUpdate->setChecked(HighlightProperties::g_updateNeedsUpdate.style & HighlightProperties::FS_ITALIC);
   m_pBoldMerging->setChecked(HighlightProperties::g_updateMerging.style & HighlightProperties::FS_BOLD);
   m_pItalicMerging->setChecked(HighlightProperties::g_updateMerging.style & HighlightProperties::FS_ITALIC);
   m_pBoldConflict->setChecked(HighlightProperties::g_updateConflict.style & HighlightProperties::FS_BOLD);
   m_pItalicConflict->setChecked(HighlightProperties::g_updateConflict.style & HighlightProperties::FS_ITALIC);
   m_pBoldAdded->setChecked(HighlightProperties::g_updateAdded.style & HighlightProperties::FS_BOLD);
   m_pItalicAdded->setChecked(HighlightProperties::g_updateAdded.style & HighlightProperties::FS_ITALIC);
   m_pBoldRemoved->setChecked(HighlightProperties::g_updateRemoved.style & HighlightProperties::FS_BOLD);
   m_pItalicRemoved->setChecked(HighlightProperties::g_updateRemoved.style & HighlightProperties::FS_ITALIC);
   m_pBoldRemovedByOther->setChecked(HighlightProperties::g_updateRemovedByOther.style & HighlightProperties::FS_BOLD);
   m_pItalicRemovedByOther->setChecked(HighlightProperties::g_updateRemovedByOther.style & HighlightProperties::FS_ITALIC);
   m_pBoldDiffOld->setChecked(HighlightProperties::g_diffOld.style & HighlightProperties::FS_BOLD);
   m_pItalicDiffOld->setChecked(HighlightProperties::g_diffOld.style & HighlightProperties::FS_ITALIC);
   m_pBoldDiffNew->setChecked(HighlightProperties::g_diffNew.style & HighlightProperties::FS_BOLD);
   m_pItalicDiffNew->setChecked(HighlightProperties::g_diffNew.style & HighlightProperties::FS_ITALIC);

   m_colorFileA = SELECTION_COLOR_OF_LOGDLG[0];
   m_colorFileB = SELECTION_COLOR_OF_LOGDLG[1];

   m_pColorLogFileA->setColor(m_colorFileA);
   m_pColorLogFileB->setColor(m_colorFileB);

   m_questionMark = HighlightProperties::g_updateQuestionMark.color;
   m_modified     = HighlightProperties::g_updateModified.color;
   m_needsUpdate  = HighlightProperties::g_updateNeedsUpdate.color;
   m_merging      = HighlightProperties::g_updateMerging.color;
   m_conflict     = HighlightProperties::g_updateConflict.color;
   m_added        = HighlightProperties::g_updateAdded.color;
   m_removed      = HighlightProperties::g_updateRemoved.color;
   m_removedByOther = HighlightProperties::g_updateRemovedByOther.color;
   m_diffOld      = HighlightProperties::g_diffOld.color;
   m_diffNew      = HighlightProperties::g_diffNew.color;

   m_pColorQuestionMark->setColor(m_questionMark);
   m_pColorModified->setColor(m_modified);
   m_pColorNeedsUpdate->setColor(m_needsUpdate);
   m_pColorMerging->setColor(m_merging);
   m_pColorConflict->setColor(m_conflict);
   m_pColorAdded->setColor(m_added);
   m_pColorRemoved->setColor(m_removed);
   m_pColorRemovedByOther->setColor(m_removedByOther);
   m_pColorDiffOld->setColor(m_diffOld);
   m_pColorDiffNew->setColor(m_diffNew);
    

   //Language environment (codecs, lang)
   fillLangEnv();

   //fonts
   if (Font::g_general.isEmpty()) {
      m_pGeneralDefault->setChecked(true);
      m_pFontGeneral->setText(Font::g_default);
   } else {
      m_pGeneralDefault->setChecked(false);
      m_pFontGeneral->setText(Font::g_general);
   }
   m_pFontGeneral->setEnabled(!m_pGeneralDefault->isChecked());
   m_pChooseGeneral->setEnabled(!m_pGeneralDefault->isChecked());
   if (Font::g_message.isEmpty()) {
      m_pMessageGeneral->setChecked(true);
      m_pFontMessage->setText(m_pFontGeneral->text());  //we use the font of application
   } else {
      m_pMessageGeneral->setChecked(false);
      m_pFontMessage->setText(Font::g_message);
      QFont f;
      f.fromString(Font::g_message);
      m_pFontMessage->setFont(f);
   }
   m_pFontMessage->setEnabled(!m_pMessageGeneral->isChecked());
   m_pChooseMessage->setEnabled(!m_pMessageGeneral->isChecked());
   if (!Font::g_diff.isEmpty()) {// NOT empty
      QFont f;
      if (!f.fromString(Font::g_diff)) Font::g_diff = QString::null;
      else {
	 m_pDiffGeneral->setChecked(false);
	 m_pFontDiff->setText(Font::g_diff);
	 QFont f;
	 f.fromString(Font::g_diff);
	 m_pFontDiff->setFont(f);
      }
   }
   if (Font::g_diff.isEmpty()) {// empty
      m_pDiffGeneral->setChecked(true);
      m_pFontDiff->setText(m_pFontGeneral->text());  //we use the font of application
   }
   m_pFontDiff->setEnabled(!m_pDiffGeneral->isChecked());
   m_pChooseDiff->setEnabled(!m_pDiffGeneral->isChecked());

   m_pNonStdDlgs->setChecked(!LookAndFeel::g_stdDlg);
   m_p0AsParent->setChecked(LookAndFeel::g_b0AsParent);
  
   QStringList list;
   list.append(tr("DEFAULT"));
   list.append(tr("DMY"));
   list.append(tr("MDY"));
   list.append(tr("YMD"));
   list.append(tr("YDM"));
   DateTimeOrderBox->insertStringList(list);
   DateTimeOrderBox->setCurrentItem(LookAndFeel::g_dateTimeOrder+1);
   m_DateTimeFormat->setText(LookAndFeel::g_dateTimeFormat);

   if (CVSVERSION == "cvs") {
      m_CvsRadioButton->setChecked(true);
      m_CvsntRadioButton->setChecked(false);
   } else {
      m_CvsRadioButton->setChecked(false);
      m_CvsntRadioButton->setChecked(true);
   }

   m_pUseDirWatch->setChecked(DirWatch::b_useDirWatch);
   if (!hasDirWatch() || (DirWatch::b_useDirWatch && (!DirWatch::b_isActive)) ) {//don't show if allready disabled because of a DirWatch crash
      m_pUseDirWatch->setEnabled(false);
   }

   //set proxylist
   m_proxyListBox->insertStringList(proxyList);
   connect(m_proxyListBox,SIGNAL(selectionChanged(QListBoxItem*)),this,SLOT(selectionChanged(QListBoxItem*)));
   connect(m_proxyListBox,SIGNAL(clicked(QListBoxItem*)),this,SLOT(selectionChanged(QListBoxItem*)));

   //set cvs history cmd period
   if (CvsOptions::g_historyPeriod != -1) {
      m_historyPeriod->setChecked(true);
      m_historyDays->setValue(CvsOptions::g_historyPeriod);
   }

   //set log level
   int logLevelIndex;
   switch (Debug::g_logLevel) 
      {
	 case Debug::LL_LIKE_A_FISH:             logLevelIndex = 0; break;
	 case Debug::LL_THE_OLD_MAN_AND_THE_SEA: logLevelIndex = 1; break;
	 case Debug::LL_INFO:                    logLevelIndex = 2; break;
	 case Debug::LL_DEBUG:                   logLevelIndex = 3; break;
	 case Debug::LL_GOSSIP_MONGER:           logLevelIndex = 4; break;
	 default:                                logLevelIndex = 0; break;
      }
   m_pLogLevel->setCurrentItem(logLevelIndex);

   m_pUseAutoUpdate->setChecked(AUTOUPDATE);

   m_dialogUp = true;
}

//----------------------------------------------------------------------------

/** 
 * Destroys the object and frees any allocated resources
 */
SettingsDialogImpl::~SettingsDialogImpl()
{
   // no need to delete child widgets, Qt does it all for us
}

//----------------------------------------------------------------------------

// protected slot
void SettingsDialogImpl::accept()
{
   apply();
   QDialog::accept();
}

//----------------------------------------------------------------------------

// protected slot
void SettingsDialogImpl::apply()
{
   // Set value on GUI to current compresion level
   CvsOptions::g_compression = m_CompressionLevel->value();

   // External browser
   ExtApps::g_remoteBrowser.path    = m_remoteBrowser->text();
   ExtApps::g_remoteBrowser.options = m_remoteBrowserOptions->text();
   ExtApps::g_localBrowser.path     = m_localBrowser->text();
   ExtApps::g_localBrowser.options  = m_localBrowserOptions->text();

   // timer interval
   int sec = WBUpdateSpinBox->value();
   CHECKSTATUSINTERVALL = sec * 1000;

   //set module update timer value
   AUTOUPDATEINTERVALL = AutoUpdateSpinBox->value();

   // set update check level
   Polling::checkStatusLevel = CheckStatusSpinBox->value();

   // ssh agent
   if (ExtApps::g_sshKeyFiles != m_sshKeyFiles) {
      m_agentSetupChanged = true;
      ExtApps::g_sshKeyFiles = m_sshKeyFiles;
   }
   if (ExtApps::g_sshAgent.path != m_SshAgent->text()) {
      m_agentSetupChanged = true;
      ExtApps::g_sshAgent.path = m_SshAgent->text();
   }
   if (ExtApps::g_sshAgent.options != m_SshAgentOptions->text()) {
      m_agentSetupChanged = true;
      ExtApps::g_sshAgent.options = m_SshAgentOptions->text();
   }

   // Remote shell
   ExtApps::g_cvsRsh.path = m_RemoteShell->text();

   // local shell
   ExtApps::g_localShell.path    = m_LocalShell->text();
   ExtApps::g_localShell.options = m_LocalShellOptions->text();

   // External diff program
   bUSEEXTERNALDIFFFORSIDEBYSIDE = m_ExternalDiffUse->isChecked();
   ExtApps::g_diffProg.path    = m_ExternalDiffEdit->text();
   ExtApps::g_diffProg.options = m_ExternalDiffEditOptions->text();

   //store template text in tmpDir/Template/rcsinfo
   writeDefaultTemplateFile(m_pTemplate->text());
   HistorySize::g_commitinfo = m_pHistorySize->value();

   //history sizes
   HistorySize::g_workdirs     = m_pHistorySizeWorkdirs->value();
   HistorySize::g_profiles     = m_pHistorySizeProfiles->value();

   // set on the fly scanning mode
   if (ONTHEFLYSCANNING != m_onTheFlyScanning->isChecked()) {
      m_onTheFlyScanningModeChanged = true;
   }
   ONTHEFLYSCANNING = m_onTheFlyScanning->isChecked();

   // set default r/rw permission for files on checkout/update
   bRWPermission = m_RW_Permission->isChecked();

   //virtual dirs
   CvsOptions::g_bShowVirtualInFiletab = m_VirtualDirCheckBox->isChecked();

   //diff-precision
   CvsOptions::g_precision = m_DiffPrecisionSpinBox->value();

   //Prune empty dirs?
   CvsOptions::g_bPruneDirs = m_pPruneDirs->isChecked();

   //Bring over new dirs?
   CvsOptions::g_bBringOverNewDirs = m_pBringOverNewDirs->isChecked();

   // set default diff mode
   bKeywordSuppression =  m_KeywordSuppression->isChecked();
   bDiffIgnoreWhiteSpace = m_IgnoreWhiteSpace->isChecked();

   //run cvs in quiet mode?
   CvsOptions::g_bQuietCvs = m_pQuietCvs->isChecked();

   //patch mode
   CvsOptions::g_bUnifiedDiffOutput = m_pUnifiedDiffOutput->isChecked();

   // set dir to load additional icons from
   if (m_iconDir->text() != iconDir) {
      iconDir = m_iconDir->text();
      if (!iconDir.isEmpty()) {
	 loadPixmapsFromDisk(iconDir);

	 QMessageBox::information(this, tr("CrossVC - Information"), 
	       tr("CrossVC can't update all icons before next restart."), 0);
      }
   }

   //set CVSVERSION, CVSPASS and CVSPASSPATH
   if (m_CvsntRadioButton->isChecked()) {
      CVSVERSION = "cvsnt";
   } else {
      CVSVERSION = "cvs";
   }


   //set properties for syntax highlighting
   HighlightProperties::g_bUseSyntaxHighlighting = m_pUseSyntaxHighlighting->isChecked();  

   HighlightProperties::g_updateQuestionMark.style = HighlightProperties::FS_NORMAL;
   if (m_pBoldQuestionMark->isChecked()) HighlightProperties::g_updateQuestionMark.style = (HighlightProperties::FontStyle)(HighlightProperties::g_updateQuestionMark.style | HighlightProperties::FS_BOLD);
   if (m_pItalicQuestionMark->isChecked()) HighlightProperties::g_updateQuestionMark.style = (HighlightProperties::FontStyle)(HighlightProperties::g_updateQuestionMark.style | HighlightProperties::FS_ITALIC);

   HighlightProperties::g_updateModified.style = HighlightProperties::FS_NORMAL;
   if (m_pBoldModified->isChecked()) HighlightProperties::g_updateModified.style = (HighlightProperties::FontStyle)(HighlightProperties::g_updateModified.style | HighlightProperties::FS_BOLD);
   if (m_pItalicModified->isChecked()) HighlightProperties::g_updateModified.style = (HighlightProperties::FontStyle)(HighlightProperties::g_updateModified.style | HighlightProperties::FS_ITALIC);

   HighlightProperties::g_updateNeedsUpdate.style = HighlightProperties::FS_NORMAL;
   if (m_pBoldNeedsUpdate->isChecked()) HighlightProperties::g_updateNeedsUpdate.style = (HighlightProperties::FontStyle)(HighlightProperties::g_updateNeedsUpdate.style | HighlightProperties::FS_BOLD);
   if (m_pItalicNeedsUpdate->isChecked()) HighlightProperties::g_updateNeedsUpdate.style = (HighlightProperties::FontStyle)(HighlightProperties::g_updateNeedsUpdate.style | HighlightProperties::FS_ITALIC);

   HighlightProperties::g_updateMerging.style = HighlightProperties::FS_NORMAL;
   if (m_pBoldMerging->isChecked()) HighlightProperties::g_updateMerging.style = (HighlightProperties::FontStyle)(HighlightProperties::g_updateMerging.style | HighlightProperties::FS_BOLD);
   if (m_pItalicMerging->isChecked()) HighlightProperties::g_updateMerging.style = (HighlightProperties::FontStyle)(HighlightProperties::g_updateMerging.style | HighlightProperties::FS_ITALIC);

   HighlightProperties::g_updateConflict.style = HighlightProperties::FS_NORMAL;
   if (m_pBoldConflict->isChecked()) HighlightProperties::g_updateConflict.style = (HighlightProperties::FontStyle)(HighlightProperties::g_updateConflict.style | HighlightProperties::FS_BOLD);
   if (m_pItalicConflict->isChecked()) HighlightProperties::g_updateConflict.style = (HighlightProperties::FontStyle)(HighlightProperties::g_updateConflict.style | HighlightProperties::FS_ITALIC);

   HighlightProperties::g_updateAdded.style = HighlightProperties::FS_NORMAL;
   if (m_pBoldAdded->isChecked()) HighlightProperties::g_updateAdded.style = (HighlightProperties::FontStyle)(HighlightProperties::g_updateAdded.style | HighlightProperties::FS_BOLD);
   if (m_pItalicAdded->isChecked()) HighlightProperties::g_updateAdded.style = (HighlightProperties::FontStyle)(HighlightProperties::g_updateAdded.style | HighlightProperties::FS_ITALIC);

   HighlightProperties::g_updateRemoved.style = HighlightProperties::FS_NORMAL;
   if (m_pBoldRemoved->isChecked()) HighlightProperties::g_updateRemoved.style = (HighlightProperties::FontStyle)(HighlightProperties::g_updateRemoved.style | HighlightProperties::FS_BOLD);
   if (m_pItalicRemoved->isChecked()) HighlightProperties::g_updateRemoved.style = (HighlightProperties::FontStyle)(HighlightProperties::g_updateRemoved.style | HighlightProperties::FS_ITALIC);

   HighlightProperties::g_updateRemovedByOther.style = HighlightProperties::FS_NORMAL;
   if (m_pBoldRemovedByOther->isChecked()) HighlightProperties::g_updateRemovedByOther.style = (HighlightProperties::FontStyle)(HighlightProperties::g_updateRemovedByOther.style | HighlightProperties::FS_BOLD);
   if (m_pItalicRemovedByOther->isChecked()) HighlightProperties::g_updateRemovedByOther.style = (HighlightProperties::FontStyle)(HighlightProperties::g_updateRemovedByOther.style | HighlightProperties::FS_ITALIC);

   HighlightProperties::g_diffOld.style = HighlightProperties::FS_NORMAL;
   if (m_pBoldDiffOld->isChecked()) HighlightProperties::g_diffOld.style = (HighlightProperties::FontStyle)(HighlightProperties::g_diffOld.style | HighlightProperties::FS_BOLD);
   if (m_pItalicDiffOld->isChecked()) HighlightProperties::g_diffOld.style = (HighlightProperties::FontStyle)(HighlightProperties::g_diffOld.style | HighlightProperties::FS_ITALIC);

   HighlightProperties::g_diffNew.style = HighlightProperties::FS_NORMAL;
   if (m_pBoldDiffNew->isChecked()) HighlightProperties::g_diffNew.style = (HighlightProperties::FontStyle)(HighlightProperties::g_diffNew.style | HighlightProperties::FS_BOLD);
   if (m_pItalicDiffNew->isChecked()) HighlightProperties::g_diffNew.style = (HighlightProperties::FontStyle)(HighlightProperties::g_diffNew.style | HighlightProperties::FS_ITALIC);

   SELECTION_COLOR_OF_LOGDLG[0] = m_colorFileA;
   SELECTION_COLOR_OF_LOGDLG[1] = m_colorFileB;

   HighlightProperties::g_updateQuestionMark.color = m_questionMark;
   HighlightProperties::g_updateModified.color = m_modified;
   HighlightProperties::g_updateNeedsUpdate.color = m_needsUpdate;
   HighlightProperties::g_updateMerging.color = m_merging;
   HighlightProperties::g_updateConflict.color = m_conflict;
   HighlightProperties::g_updateAdded.color = m_added;
   HighlightProperties::g_updateRemoved.color = m_removed;
   HighlightProperties::g_updateRemovedByOther.color = m_removedByOther;
   HighlightProperties::g_diffOld.color = m_diffOld;
   HighlightProperties::g_diffNew.color = m_diffNew;


   //Language environment (codecs, lang)
   applyLangEnv();

  
   //fonts
   if (m_pGeneralDefault->isChecked()) {//use default
      Font::g_general = QString::null;
   } else {
      Font::g_general = m_pFontGeneral->text();
   }
   if (m_pMessageGeneral->isChecked()) {//use default
      Font::g_message = QString::null;
   } else {
      Font::g_message = m_pFontMessage->text();
   }
   if (m_pDiffGeneral->isChecked()) {//use default
      Font::g_diff = QString::null;
   } else {
      Font::g_diff = m_pFontDiff->text();
   }
   //apply changed fonts immediately  
   emit setFonts();

   LookAndFeel::g_stdDlg = !m_pNonStdDlgs->isChecked();
   if (LookAndFeel::g_b0AsParent != m_p0AsParent->isChecked()) {
      LookAndFeel::g_b0AsParent = m_p0AsParent->isChecked();
   }
   if (LookAndFeel::g_bTopLevel != m_p0AsParent->isChecked()) {
      LookAndFeel::g_bTopLevel = m_p0AsParent->isChecked();
      if (LookAndFeel::g_bTopLevel) {//Adapt this setup in lincvs.cpp constructor too
	 LookAndFeel::g_nonModalF &= ~Qt::WStyle_Dialog;
      } else {
	 LookAndFeel::g_nonModalF |= Qt::WStyle_Dialog;
      }
      emit createCommitDlg();
   }
   if ( (DateTimeOrderBox->currentItem() == 0) && (LookAndFeel::g_dateTimeOrder != QDateEdit().order()) ) {
      LookAndFeel::g_dateTimeOrder = QDateEdit().order();
   } else if (LookAndFeel::g_dateTimeOrder != static_cast<QDateEdit::Order>(DateTimeOrderBox->currentItem()-1)) {
      LookAndFeel::g_dateTimeOrder = static_cast<QDateEdit::Order>(DateTimeOrderBox->currentItem()-1);
   }
   bool refresh = FALSE;
   if ( (m_DateTimeFormat->text().isEmpty()) && (LookAndFeel::g_dateTimeFormat != "yyyy/MM/dd hh:mm:ss") ) {
      refresh = TRUE;
      LookAndFeel::g_dateTimeFormat = "yyyy/MM/dd hh:mm:ss";
   } else if ( LookAndFeel::g_dateTimeFormat != m_DateTimeFormat->text() ) {
      refresh = TRUE;
      LookAndFeel::g_dateTimeFormat = m_DateTimeFormat->text();
   }
   if (refresh) emit refreshEntries();

   if (m_pUseDirWatch->isEnabled()) {

      if (m_pUseDirWatch->isChecked() && !DirWatch::b_useDirWatch) {
	 QMessageBox::information(this, tr("CrossVC - Information"), 
	       tr("You need to restart CrossVC to activate dir monitoring."), 0);
      }
      DirWatch::b_useDirWatch = m_pUseDirWatch->isChecked();
   }

   CVSPATH = m_CvsPath->text();
   CVSPASSPATH = m_CvsPassPath->text();

   //set proxylist
   proxyList.clear();
   QListBoxItem* item;
   item = m_proxyListBox->firstItem();
   while (item) {
      proxyList.append(item->text());
      item = item->next();
   }

   //set history period
   if (m_historyPeriod->isChecked()) {
      CvsOptions::g_historyPeriod = m_historyDays->value();
   } else {
      CvsOptions::g_historyPeriod = -1;
   }

   //set log level
   switch (m_pLogLevel->currentItem()) 
      {
	 case  0: Debug::g_logLevel = Debug::LL_LIKE_A_FISH;             break;
	 case  1: Debug::g_logLevel = Debug::LL_THE_OLD_MAN_AND_THE_SEA; break;
	 case  2: Debug::g_logLevel = Debug::LL_INFO;                    break;
	 case  3: Debug::g_logLevel = Debug::LL_DEBUG;                   break;
	 case  4: Debug::g_logLevel = Debug::LL_GOSSIP_MONGER;           break;
	 default: Debug::g_logLevel = Debug::LL_LIKE_A_FISH;             break;
      }

   if (m_pUseAutoUpdate->isChecked() != AUTOUPDATE) {
      AUTOUPDATE = m_pUseAutoUpdate->isChecked();
      emit autoUpdateStateChanged();
   }
   qApp->processEvents();
}

//----------------------------------------------------------------------------

// protected slot
void SettingsDialogImpl::setIconDir()
{
   /* Using the Qt standard file dialog preserves the look and feel
    * of the application across platforms.
    */
   QString fn = QFileDialog::getExistingDirectory (iconDir, this, 0,
	 tr("Choose icon directory"),
	 true);

   if ( !fn.isEmpty() ) {
      m_iconDir->setText(fn);
   }
}

//----------------------------------------------------------------------------

void SettingsDialogImpl::loadTemplateFromFile()
{
   QString fn = QFileDialog::getOpenFileName(QString::null, 
	 QString::null, this, 0,
	 tr("Choose a text file as template"));

   if ( !fn.isEmpty() ) {
      m_pTemplate->setText(readTextFile(fn));
   }
}

//----------------------------------------------------------------------------

void SettingsDialogImpl::cvsVersionChecked(int i)
{
   if (i==0) {
      m_CvsPassPath->setEnabled(false);
      m_PathBrowseButton->setEnabled(false);
   } else {
      m_CvsPassPath->setEnabled(true);
      m_PathBrowseButton->setEnabled(true);
   }
}

//----------------------------------------------------------------------------

void SettingsDialogImpl::browseCvsPassFile()
{
   /* Using the Qt standard file dialog preserves the look and feel
    * of the application across platforms.
    */
   QString fn = QFileDialog::getOpenFileName (CVSPASSPATH, NULL, this, 0,
	 tr("Choose .cvspass path"),
	 NULL, true);

   if ( !fn.isEmpty() ) {
      m_CvsPassPath->setText(fn);
   }
}

//----------------------------------------------------------------------------

void SettingsDialogImpl::browseCvsPath()
{
   /* Using the Qt standard file dialog preserves the look and feel
    * of the application across platforms.
    */
   QString fn = QFileDialog::getOpenFileName (m_CvsPath->text(), NULL, this, 0,
	 tr("Choose cvs path"),
	 NULL, true);

   if ( !fn.isEmpty() ) {
      m_CvsPath->setText(fn);
   }
}

//----------------------------------------------------------------------------

void SettingsDialogImpl::selectionChanged(QListBoxItem* item) {
   if (!item) return;
   m_proxyEdit->setText(item->text());
   m_proxyEdit->selectAll();
}

//----------------------------------------------------------------------------

void SettingsDialogImpl::addProxy() {
   QString proxy = m_proxyEdit->text();
   if (proxy.isEmpty()) return;
   m_proxyEdit->clear();
   if (m_proxyListBox->findItem(proxy) == NULL) {
      m_proxyListBox->insertItem(proxy,0);
   }
}

//----------------------------------------------------------------------------

void SettingsDialogImpl::removeProxy() {
   m_proxyListBox->removeItem(m_proxyListBox->currentItem());
   m_proxyEdit->clear();
}

//----------------------------------------------------------------------------

void SettingsDialogImpl::modifyProxy() {
   QString tmp = m_proxyEdit->text();
   if (tmp.isEmpty()) return;
   int pos = m_proxyListBox->currentItem();
   if (pos >=0) {
      m_proxyListBox->changeItem(tmp,pos);
      m_proxyEdit->clear();
   }

}

//----------------------------------------------------------------------------

bool SettingsDialogImpl::isOnTheFlyScanningModeChanged() {
   return m_onTheFlyScanningModeChanged;
}

//----------------------------------------------------------------------------

bool SettingsDialogImpl::isAgentSetupChanged() {
   return m_agentSetupChanged;
}

//----------------------------------------------------------------------------

void SettingsDialogImpl::maintainKeyClicked() {
   SshKeyDialogImpl * dlg = new SshKeyDialogImpl(m_sshKeyFiles,
	 *(m_pWhatsThis->iconSet()),
	 tr("Maintain ssh keys"),
	 this,
	 "",
	 true,
	 LookAndFeel::g_modalF);
   dlg->exec();
   delete dlg;
}

//----------------------------------------------------------------------------

void SettingsDialogImpl::browseSshAgentCmd()
{
   /* Using the Qt standard file dialog preserves the look and feel
    * of the application across platforms.
    */
   QString fn = QFileDialog::getOpenFileName (m_SshAgent->text(), NULL, this, 0,
	 tr("Choose ssh agent"),
	 NULL, true);

   if ( !fn.isEmpty() ) {
      m_SshAgent->setText(fn);
   }
}

//----------------------------------------------------------------------------

void SettingsDialogImpl::browseLocalBrowserCmd()
{
   /* Using the Qt standard file dialog preserves the look and feel
    * of the application across platforms.
    */
   QString fn = QFileDialog::getOpenFileName (m_localBrowser->text(), NULL, this, 0,
	 tr("Choose local browser"),
	 NULL, true);

   if ( !fn.isEmpty() ) {
      m_localBrowser->setText(fn);
   }
}

//----------------------------------------------------------------------------

void SettingsDialogImpl::browseLocalShellCmd()
{
   /* Using the Qt standard file dialog preserves the look and feel
    * of the application across platforms.
    */
   QString fn = QFileDialog::getOpenFileName (m_LocalShell->text(), NULL, this, 0,
	 tr("Choose local shell"),
	 NULL, true);

   if ( !fn.isEmpty() ) {
      m_LocalShell->setText(fn);
   }
}

//----------------------------------------------------------------------------

void SettingsDialogImpl::browseRemoteBrowserCmd()
{
   /* Using the Qt standard file dialog preserves the look and feel
    * of the application across platforms.
    */
   QString fn = QFileDialog::getOpenFileName (m_remoteBrowser->text(), NULL, this, 0,
	 tr("Choose remote browser"),
	 NULL, true);

   if ( !fn.isEmpty() ) {
      m_remoteBrowser->setText(fn);
   }
}

//----------------------------------------------------------------------------

void SettingsDialogImpl::browseRemoteShellCmd()
{
   /* Using the Qt standard file dialog preserves the look and feel
    * of the application across platforms.
    */
   QString fn = QFileDialog::getOpenFileName (m_RemoteShell->text(), NULL, this, 0,
	 tr("Choose remote shell"),
	 NULL, true);

   if ( !fn.isEmpty() ) {
      m_RemoteShell->setText(fn);
   }
}

//----------------------------------------------------------------------------

void SettingsDialogImpl::browseExternalDiffCmd()
{
   /* Using the Qt standard file dialog preserves the look and feel
    * of the application across platforms.
    */
   QString fn = QFileDialog::getOpenFileName (m_ExternalDiffEdit->text(), NULL, this, 0,
	 tr("Choose diff program"),
	 NULL, true);

   if ( !fn.isEmpty() ) {
      m_ExternalDiffEdit->setText(fn);
   }
}

//----------------------------------------------------------------------------

QColor SettingsDialogImpl::showColorDlg(QColor curColor, CColorButton* pBtn)
{
   QColor c = QColorDialog::getColor(curColor);
   if (c.isValid()) {
      curColor = c;
      pBtn->setColor(curColor);
   }

   return curColor;
}

//----------------------------------------------------------------------------

void SettingsDialogImpl::showColorDlgFileA()
{
   m_colorFileA = showColorDlg(m_colorFileA, m_pColorLogFileA);
}

//----------------------------------------------------------------------------

void SettingsDialogImpl::showColorDlgFileB()
{
   m_colorFileB = showColorDlg(m_colorFileB, m_pColorLogFileB);
}

//----------------------------------------------------------------------------

void SettingsDialogImpl::showColorDlgQuestionMark()
{
   m_questionMark = showColorDlg(m_questionMark, m_pColorQuestionMark);
}

//----------------------------------------------------------------------------

void SettingsDialogImpl::showColorDlgModified()
{
   m_modified = showColorDlg(m_modified, m_pColorModified);
}

//----------------------------------------------------------------------------

void SettingsDialogImpl::showColorDlgNeedsUpdate()
{
   m_needsUpdate = showColorDlg(m_needsUpdate, m_pColorNeedsUpdate);
}

//----------------------------------------------------------------------------

void SettingsDialogImpl::showColorDlgMerging()
{
   m_merging = showColorDlg(m_merging, m_pColorMerging);
}

//----------------------------------------------------------------------------

void SettingsDialogImpl::showColorDlgConflict()
{
   m_conflict = showColorDlg(m_conflict, m_pColorConflict);
}

//----------------------------------------------------------------------------

void SettingsDialogImpl::showColorDlgAdded()
{
   m_added = showColorDlg(m_added, m_pColorAdded);
}

//----------------------------------------------------------------------------

void SettingsDialogImpl::showColorDlgRemoved()
{
   m_removed = showColorDlg(m_removed, m_pColorRemoved);
}

//----------------------------------------------------------------------------

void SettingsDialogImpl::showColorDlgRemovedByOther()
{
   m_removedByOther = showColorDlg(m_removedByOther, m_pColorRemovedByOther);
}

//----------------------------------------------------------------------------

void SettingsDialogImpl::showColorDlgDiffOld()
{
   m_diffOld = showColorDlg(m_diffOld, m_pColorDiffOld);
}

//----------------------------------------------------------------------------

void SettingsDialogImpl::showColorDlgDiffNew()
{
   m_diffNew = showColorDlg(m_diffNew, m_pColorDiffNew);
}

//----------------------------------------------------------------------------

void SettingsDialogImpl::chooseFontGeneral()
{
   bool ok;
   QFont oldFont, newFont;
   oldFont.fromString(m_pFontGeneral->text());

   newFont = QFontDialog::getFont(&ok, oldFont, this);

   if (ok) {
      m_pFontGeneral->setText(newFont.toString());
      m_pFontGeneral->setFont(newFont);

      if (m_pMessageGeneral->isChecked()) {
	 m_pFontMessage->setText(m_pFontGeneral->text());  //we use the font of application
	 m_pFontMessage->setFont(newFont);
      }
      if (m_pDiffGeneral->isChecked()) {
	 m_pFontDiff->setText(m_pFontGeneral->text());  //we use the font of application
	 m_pFontDiff->setFont(newFont);
      }
   }
}

//----------------------------------------------------------------------------

void SettingsDialogImpl::chooseFontMessage()
{
   bool ok;
   QFont oldFont, newFont;
   oldFont.fromString(m_pFontMessage->text());

   newFont = QFontDialog::getFont(&ok, oldFont, this);

   if (ok) {
      m_pFontMessage->setText(newFont.toString());
      m_pFontMessage->setFont(newFont);
   }
}

//----------------------------------------------------------------------------

void SettingsDialogImpl::chooseFontDiff()
{
   bool ok;
   QFont oldFont, newFont;
   oldFont.fromString(m_pFontDiff->text());

   newFont = QFontDialog::getFont(&ok, oldFont, this);

   if (ok) {
      m_pFontDiff->setText(newFont.toString());
      m_pFontDiff->setFont(newFont);
   }
}

//----------------------------------------------------------------------------

void SettingsDialogImpl::fontUseDefaultToggled(bool bToggled)
{
   if (bToggled) {
      QFont newFont;
      newFont.fromString(Font::g_default);
      m_pFontGeneral->setText(Font::g_default);
      m_pFontGeneral->setFont(newFont);
      
      if (m_pMessageGeneral->isChecked()) {
         m_pFontMessage->setText(m_pFontGeneral->text());  //we use the font of application
         m_pFontMessage->setFont(newFont);
      }
      if (m_pDiffGeneral->isChecked()) {
         m_pFontDiff->setText(m_pFontGeneral->text());  //we use the font of application
         m_pFontDiff->setFont(newFont);
      }
   }
}

//----------------------------------------------------------------------------

void SettingsDialogImpl::fontMessageUseGeneralToggled(bool bToggled)
{
   if (bToggled) {
      QFont newFont;
      newFont.fromString(m_pFontGeneral->text());
      m_pFontMessage->setText(m_pFontGeneral->text());
      m_pFontMessage->setFont(newFont);
   }
}

//----------------------------------------------------------------------------

void SettingsDialogImpl::fontDiffUseGeneralToggled(bool bToggled)
{
   if (bToggled) {
      QFont newFont;
      newFont.fromString(m_pFontGeneral->text());
      m_pFontDiff->setText(m_pFontGeneral->text());
      m_pFontDiff->setFont(newFont);
   }
}

//----------------------------------------------------------------------------

void SettingsDialogImpl::enterWhatsThisMode()
{
   QWhatsThis::enterWhatsThisMode();
}

//----------------------------------------------------------------------------

void SettingsDialogImpl::fillLangEnv()
{
   const QPtrVector<TextCodec::SCodec>* pCodecs = I18n::g_pTextDecoder->supportedCodecs();

   unsigned int i;
   for (i = 0; i < pCodecs->size(); i++) {
      QString text = pCodecs->at(i)->name;
      if (!(pCodecs->at(i)->comment.isEmpty())) text += " (" + pCodecs->at(i)->comment + ")";
      
      m_pCodecForEncoding->insertItem(text);
      m_pCodecForDecoding->insertItem(text);

      if (pCodecs->at(i)->name == I18n::g_nameOfEncoder) m_pCodecForEncoding->setCurrentItem(i);
      if (pCodecs->at(i)->name == I18n::g_nameOfDecoder) m_pCodecForDecoding->setCurrentItem(i);
   }
}

//----------------------------------------------------------------------------

void SettingsDialogImpl::applyLangEnv()
{
   QString newCoder;
   QString errMsg = tr("CrossVC could not create the desired codec %1 for %2");
   errMsg += "\n";
   errMsg += "CrossVC uses the old codec.";

   QString tmp = m_pCodecForEncoding->currentText();
   int pos = tmp.find(" (");
   if (pos > -1) newCoder = tmp.left(pos);
   else newCoder = tmp;
   try {
      I18n::g_pTextEncoder->setEncoder(newCoder);
      I18n::g_nameOfEncoder = newCoder;
   } catch (XI18n) {
      QMessageBox::critical(this, tr("CrossVC - Error"), 
	    errMsg.arg(newCoder).arg("encoding"), 0);

      const QPtrVector<TextCodec::SCodec>* pCodecs = I18n::g_pTextEncoder->supportedCodecs();
      unsigned int i;
      for (i = 0; i < pCodecs->size(); i++) {
         if (pCodecs->at(i)->name == I18n::g_nameOfEncoder) m_pCodecForEncoding->setCurrentItem(i);
      }
   }
   
   tmp = m_pCodecForDecoding->currentText();
   pos = tmp.find(" (");
   if (pos > -1) newCoder = tmp.left(pos);
   else newCoder = tmp;
   try {
      I18n::g_pTextDecoder->setGeneralDecoder(newCoder);
      I18n::g_nameOfDecoder = newCoder;
   } catch (XI18n) {
      QMessageBox::critical(this, tr("CrossVC - Error"), 
	    errMsg.arg(newCoder).arg("decoding"), 0);

      const QPtrVector<TextCodec::SCodec>* pCodecs = I18n::g_pTextDecoder->supportedCodecs();
      unsigned int i;
      for (i = 0; i < pCodecs->size(); i++) {
         if (pCodecs->at(i)->name == I18n::g_nameOfDecoder) m_pCodecForDecoding->setCurrentItem(i);
      }
   }
}

//----------------------------------------------------------------------------

