/****************************************************************************
**
** Copyright (C) 2002-2006 Tilo Riemer <riemer@crossvc.com>,
**                         Frank Hemer <frank@hemer.at>,
**                         Jose Hernandez <joseh@tesco.net> and
**                         Joerg Preiss <auba@auba.de>
**
**
**----------------------------------------------------------------------------
**
**----------------------------------------------------------------------------
**
** 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 <qregexp.h>
#include <qdesktopwidget.h>
#include <qapplication.h>

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

#include "globals.h"
#include "cvsconfig.h"

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

const char CvsConfig::Version[]                 = "/crossvc/Version";
const char CvsConfig::Debug[]                   = "/crossvc/Debug";
const char CvsConfig::LogLevel[]                = "/crossvc/LogLevel";
const char CvsConfig::VeryFirstStart[]          = "/crossvc/VeryFirstStart";
const char CvsConfig::CheckStatusIntervall[]    = "/crossvc/Timer/checkStatusIntervall";
const char CvsConfig::CheckStatusLevel[]        = "/crossvc/Timer/checkStatusLevel";
const char CvsConfig::ProgressIntervall[]       = "/crossvc/Timer/progressIntervall";

const char CvsConfig::AutoUpdate[]              = "/crossvc/AutoUpdate/Enabled";
const char CvsConfig::AutoUpdateIntervall[]     = "/crossvc/AutoUpdate/Intervall";

const char CvsConfig::cvsPassFile[]             = "/crossvc/CvsPassFilePath";
const char CvsConfig::cvsPath[]                 = "/crossvc/CvsPath";
const char CvsConfig::cvsVersion[]              = "/crossvc/CvsVersion";
const char CvsConfig::useDirWatch[]             = "/crossvc/useDirWatch";

const char CvsConfig::SshKeyList[]              = "/crossvc/SshKeyList";
const char CvsConfig::SshAgent[]                = "/crossvc/SshAgent";
const char CvsConfig::RemoteBrowser[]           = "/crossvc/remoteBrowser";
const char CvsConfig::LocalBrowser[]            = "/crossvc/localBrowser";
const char CvsConfig::CVSRsh[]                  = "/crossvc/cvsRsh";
const char CvsConfig::LocalShell[]              = "/crossvc/localShell";
const char CvsConfig::DirPopupMenu[]            = "/crossvc/dirPopupMenu";
const char CvsConfig::FilePopupMenu[]           = "/crossvc/filePopupMenu";
const char CvsConfig::KeyboarsShortcuts[]       = "/crossvc/keyboardShortcuts";
const char CvsConfig::OpenFileList[]            = "/crossvc/openFileList";
const char CvsConfig::ViewFileList[]            = "/crossvc/viewFileList";
const char CvsConfig::ScanOnTheFly[]            = "/crossvc/scanOnTheFly";
const char CvsConfig::ScanNonCvs[]              = "/crossvc/scanNonCvs";
const char CvsConfig::CvsIgnoreFiles[]          = "/crossvc/cvsIgnoreFiles";
const char CvsConfig::BinaryFileSpecList[]      = "/crossvc/binaryFileSpec";
const char CvsConfig::UseExternalDiff[]         = "/crossvc/useExternalDiffForSideBySide";
const char CvsConfig::ExtDiffProgram[]          = "/crossvc/externalDiffProgram";
const char CvsConfig::HistSizeComments[]        = "/crossvc/historySizeComments";
const char CvsConfig::HistSizeWorkdirs[]        = "/crossvc/historySizeWorkdirs";
const char CvsConfig::HistSizeProfiles[]        = "/crossvc/historySizeProfiles";

const char CvsConfig::GeomX[]                   = "/crossvc/Geometry/geomX";
const char CvsConfig::GeomY[]                   = "/crossvc/Geometry/geomY";
const char CvsConfig::GeomWidth[]               = "/crossvc/Geometry/geomWidth";
const char CvsConfig::GeomHeight[]              = "/crossvc/Geometry/geomHeight";
const char CvsConfig::SplitterPosH[]            = "/crossvc/Geometry/splitterPosH";
const char CvsConfig::SplitterPosV[]            = "/crossvc/Geometry/splitterPosV";
const char CvsConfig::WorkbenchColumnWidth[]    = "/crossvc/Geometry/workbenchColumnWidth";
const char CvsConfig::ToolbarPos[]              = "/crossvc/Geometry/ToolbarPosition";
const char CvsConfig::FileHeaderPos[]           = "/crossvc/Geometry/FileHeaderPosition";

const char CvsConfig::IconDir[]                 = "/crossvc/Looknfeel/iconDir";
const char CvsConfig::ColorRevA[]               = "/crossvc/Looknfeel/colorRevisionA";
const char CvsConfig::ColorRevB[]               = "/crossvc/Looknfeel/colorRevisionB";
const char CvsConfig::UseStandardDialogs[]      = "/crossvc/Looknfeel/useStdDialogs";
const char CvsConfig::DateTimeOrder[]           = "/crossvc/Looknfeel/DateTimeOrder";
const char CvsConfig::DateTimeFormat[]          = "/crossvc/Looknfeel/DateTimeFormat";
const char CvsConfig::Use0AsParent[]            = "/crossvc/Looknfeel/use0AsParent";
const char CvsConfig::TopLevelWidget[]          = "/crossvc/Looknfeel/topLevelWidget";

const char CvsConfig::Compression[]             = "/crossvc/CvsGlobal/compression";
const char CvsConfig::RwPermission[]            = "/crossvc/CvsGlobal/RwPermission";
const char CvsConfig::VirtualInFiletab[]        = "/crossvc/CvsGlobal/virtualInFileTab";
const char CvsConfig::DiffPrecision[]           = "/crossvc/CvsGlobal/diffPrecision";
const char CvsConfig::UnifiedDiffOutput[]       = "/crossvc/CvsGlobal/unifiedDiffOutput";

const char CvsConfig::PruneDirs[]               = "/crossvc/CvsSubcommands/pruneDirs";
const char CvsConfig::BringOverNewDirs[]        = "/crossvc/CvsSubcommands/bringOverNewDirs";
const char CvsConfig::KeywordSuppression[]      = "/crossvc/CvsSubcommands/keywordSuppression";
const char CvsConfig::IgnoreWhiteSpace[]        = "/crossvc/CvsSubcommands/diffIgnoreWhiteSpace";
const char CvsConfig::HistoryPeriod[]           = "/crossvc/CvsSubcommands/historyPeriod";
const char CvsConfig::Quiet[]                   = "/crossvc/CvsSubcommands/quiet";

const char CvsConfig::UserList[]                = "/crossvc/CvsServer/users";
const char CvsConfig::ServerList[]              = "/crossvc/CvsServer/servers";
const char CvsConfig::RepositoryList[]          = "/crossvc/CvsServer/repositories";
const char CvsConfig::ProfileList[]             = "/crossvc/CvsServer/profiles";
const char CvsConfig::XProfileList[]            = "/crossvc/CvsServer/xprofiles";
const char CvsConfig::ModuleList[]              = "/crossvc/CvsServer/modules";
const char CvsConfig::WorkdirList[]             = "/crossvc/CvsServer/workDirs";
const char CvsConfig::CheckoutAsList[]          = "/crossvc/CvsServer/checkoutAs";
const char CvsConfig::ProxyList[]               = "/crossvc/CvsServer/proxys";

const char CvsConfig::Projects[]                = "/crossvc/Projects";

const char CvsConfig::UseSyntaxHighlight[]      = "/crossvc/SyntaxHighlight/UseSyntaxHighlight";
const char CvsConfig::SynHighQuestionMarkStyle[]= "/crossvc/SyntaxHighlight/SynHighQuestionMarkStyle";
const char CvsConfig::SynHighQuestionMarkRgb[]  = "/crossvc/SyntaxHighlight/SynHighQuestionMarkRgb";
const char CvsConfig::SynHighModifiedStyle[]    = "/crossvc/SyntaxHighlight/SynHighModifiedStyle";
const char CvsConfig::SynHighModifiedRgb[]      = "/crossvc/SyntaxHighlight/SynHighModifiedRgb";
const char CvsConfig::SynHighNeedsUpdateStyle[] = "/crossvc/SyntaxHighlight/SynHighNeedsUpdateStyle";
const char CvsConfig::SynHighNeedsUpdateRgb[]   = "/crossvc/SyntaxHighlight/SynHighNeedsUpdateRgb";
const char CvsConfig::SynHighMergingStyle[]     = "/crossvc/SyntaxHighlight/SynHighMergingStyle";
const char CvsConfig::SynHighMergingRgb[]       = "/crossvc/SyntaxHighlight/SynHighMergingRgb";
const char CvsConfig::SynHighConflictStyle[]    = "/crossvc/SyntaxHighlight/SynHighConflictStyle";
const char CvsConfig::SynHighConflictRgb[]      = "/crossvc/SyntaxHighlight/SynHighConflictRgb";
const char CvsConfig::SynHighAddedStyle[]       = "/crossvc/SyntaxHighlight/SynHighAddedStyle";
const char CvsConfig::SynHighAddedRgb[]         = "/crossvc/SyntaxHighlight/SynHighAddedRgb";
const char CvsConfig::SynHighRemovedStyle[]     = "/crossvc/SyntaxHighlight/SynHighRemovedStyle";
const char CvsConfig::SynHighRemovedRgb[]       = "/crossvc/SyntaxHighlight/SynHighRemovedRgb";
const char CvsConfig::SynHighRemovedByOtherStyle[]= "/crossvc/SyntaxHighlight/SynHighRemovedByOtherStyle";
const char CvsConfig::SynHighRemovedByOtherRgb[]  = "/crossvc/SyntaxHighlight/SynHighRemovedByOtherRgb";
const char CvsConfig::SynHighDiffOldStyle[]     = "/crossvc/SyntaxHighlight/SynHighDiffOldStyle";
const char CvsConfig::SynHighDiffOldRgb[]       = "/crossvc/SyntaxHighlight/SynHighDiffOldRgb";
const char CvsConfig::SynHighDiffNewStyle[]     = "/crossvc/SyntaxHighlight/SynHighDiffNewStyle";
const char CvsConfig::SynHighDiffNewRgb[]       = "/crossvc/SyntaxHighlight/SynHighDiffNewRgb";
const char CvsConfig::SynHighScmErrStyle[]      = "/crossvc/SyntaxHighlight/SynHighScmErrStyle";
const char CvsConfig::SynHighScmErrRgb[]        = "/crossvc/SyntaxHighlight/SynHighScmErrRgb";

const char CvsConfig::FontGeneral[]             = "/crossvc/Font/General";
const char CvsConfig::FontMessage[]             = "/crossvc/Font/Message";
const char CvsConfig::FontDiff[]                = "/crossvc/Font/Diff";

const char CvsConfig::TextEncoder[]             = "/crossvc/I18n/TextEncoder";
const char CvsConfig::TextDecoder[]             = "/crossvc/I18n/TextDecoder";

#ifdef Q_WS_MAC
const char CvsConfig::defCvsPath[]              = "ocvs";
const char CvsConfig::defCvsVersion[]           = "cvs";
const char CvsConfig::defSshAgent[]             = "start-ssh-agent.sh\n%n";
const char CvsConfig::defRemoteBrowser[]        = "open";
const char CvsConfig::defLocalBrowser[]         = "open";
const char CvsConfig::defOpenFileList[]         = "*\nopen\n%n\n-";
const char CvsConfig::defViewFileList[]         = "*\nopen\n%n\n-";
const char CvsConfig::defLocalShell[]           = "/Applications/Utilities/Terminal";
#else
#ifdef Q_WS_X11
const char CvsConfig::defCvsPath[]              = "cvs";
const char CvsConfig::defCvsVersion[]           = "cvs";
const char CvsConfig::defSshAgent[]             = "start-ssh-agent.sh\n%n";
const char CvsConfig::defRemoteBrowser[]        = "mozilla";
const char CvsConfig::defLocalBrowser[]         = "mozilla";
const char CvsConfig::defOpenFileList[]         = "*\nxterm\n-e vi %1\n-";
const char CvsConfig::defViewFileList[]         = "*\nxterm\n-e more %1\n-";
const char CvsConfig::defLocalShell[]           = "xterm";
#else
#ifdef Q_WS_QWS
const char CvsConfig::defCvsPath[]              = "cvs";
const char CvsConfig::defCvsVersion[]           = "cvs";
const char CvsConfig::defSshAgent[]             = "";
const char CvsConfig::defRemoteBrowser[]        = "";
const char CvsConfig::defLocalBrowser[]         = "";
const char CvsConfig::defOpenFileList[]         = "";
const char CvsConfig::defViewFileList[]         = "";
const char CvsConfig::defLocalShell[]           = "";
#endif
#endif
#endif
const char CvsConfig::defCvsRsh[]               = "ssh";
const char CvsConfig::defCvsIgnoreFiles[]       = "RCS SCCS CVS CVS.adm RCSLOG cvslog.* tags TAGS .make.state .nse.depinfo *~ #* .#* ,* _$* *$ *.old *.bak *.BAK *.orig *.rej .del-* *.a *.olb *.o *.obj *.so *.exe *.Z *.elc *.ln core";

#ifdef Q_WS_MAC
const char CvsConfig::defKeyboarsShortcuts[]    = "4,12582980:7,8388677:8,4194373:10,4194392:11,4194376:12,12582984:15,8388684:16,4194384:18,8388689:25,4194386:29,4194388:30,8388692:33,4194389:34,8388693:46,12582991:47,4194370:48,4194387:54,4194371:55,8388694:59,4194372:83,4194385:";
#else
const char CvsConfig::defKeyboarsShortcuts[]    = "4,12582980:7,8388677:8,4194373:10,4194392:11,4194376:12,12582984:15,8388684:16,4194384:18,8388689:25,4194386:29,4194388:30,8388692:33,4194389:34,8388693:46,12582991:47,4194370:48,4194387:54,4194371:55,8388694:59,4194372:62,4194385:";
#endif

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

/*!	Initialize the cvs configuration with the default values.
\brief c'tor
*/
#ifndef Q_WS_WIN
CvsConfig::CvsConfig()
{
   m_pSettings = new QSettings();
   #ifdef Q_WS_X11
   if (!Misc::g_rcPath.isEmpty()) m_pSettings->insertSearchPath(QSettings::Unix, Misc::g_rcPath);
   #endif
   #ifdef Q_WS_MAC
   m_pSettings->setPath("crossvc.com", "CrossVC", QSettings::User);
   #endif
   readCfg();
}
#endif
//----------------------------------------------------------------------------

/*!	Free all resources.
\brief d'tor
*/
CvsConfig::~CvsConfig()
{
   writeCfg();
   delete m_pSettings;
}

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

void CvsConfig::readCfg()
{
   /*! Section external apps */
   readExtApps();
   
   /*! Section GENERAL */
   DIRPOPUPMENU  = dirPopupMenu(); 
   FILEPOPUPMENU = filePopupMenu();
   KEYBOARDSHORTCUTS = getKeyboardShortcuts();
   Mapping::openFileAppList = extractMapping(getOpenFileList());
   Mapping::viewFileAppList = extractMapping(getViewFileList());
   
   Misc::g_bVeryFirstStart = getVeryFirstStart(Misc::g_bVeryFirstStart);

   if (bOVERRIDEONTHEFLYSCANNING) {//startup option
      ONTHEFLYSCANNING = true;
   } else {
      ONTHEFLYSCANNING = getOnTheFlyScanning();
   }
   bSCANNONCVS = getScanNonCvs();
   CVSIGNOREFILES = cvsIgnoreFiles();
   BINARYFILESPECLIST = getBinaryFileSpecList();
   
   bUSEEXTERNALDIFFFORSIDEBYSIDE = useExtDiff(); 
   
   Debug::g_bDebug         = debug();
   Debug::g_logLevel       = logLevel();
   DirWatch::b_useDirWatch = getUseDirWatch();
   CVSVERSION              = getCvsVersion();
   CVSPATH                 = getCvsPath();
   CVSPASSPATH             = getCvsPassPath();
   
   /*! Section TIMER */
   CHECKSTATUSINTERVALL = checkStatusIntervall();
   Polling::checkStatusLevel = getCheckStatusLevel();
   PROGRESSINTERVALL    = progressIntervall();
   
   /*! Section AutoUpdate */
   AUTOUPDATE = getAutoUpdate();
   AUTOUPDATEINTERVALL = getAutoUpdateIntervall();
   
   HistorySize::g_workdirs   = historySizeWorkdirs();
   HistorySize::g_profiles   = historySizeProfiles();
   HistorySize::g_commitinfo = historySizeComments();
   
   iconDir = iconDirectory();
   
   int rgbColor = colorRev(false);   //Revision A
   SELECTION_COLOR_OF_LOGDLG[0] = QColor(rgbColor);
   rgbColor = colorRev(true);        //Revision B
   SELECTION_COLOR_OF_LOGDLG[1] = QColor(rgbColor);
   
   /*! Section LookAndFeel */
   LookAndFeel::g_stdDlg = getStdDlg();
   LookAndFeel::g_dateTimeOrder = static_cast<QDateEdit::Order>(getDateTimeOrder());
   LookAndFeel::g_dateTimeFormat = getDateTimeFormat();
   LookAndFeel::g_b0AsParent = get0AsParent();
   LookAndFeel::g_bTopLevel = getTopLevelW();
   
   /*! SECTION GEOMETRY */
   QRect geom        = geometry();
   GEOM_X            = geom.x();
   GEOM_Y            = geom.y();
   GEOM_WIDTH        = geom.width();
   GEOM_HEIGHT       = geom.height();
   
   //take the size of the desktop (including all screens if virtual desktop)
   //and make sure the app window is within its boundaries
   QRect desk = QApplication::desktop()->screen ()->rect ();
   if (GEOM_WIDTH > desk.width())   GEOM_WIDTH  = desk.width();
   if (GEOM_HEIGHT > desk.height()) GEOM_HEIGHT = desk.height();
   
   int geomRight = GEOM_X + GEOM_WIDTH;
   if (geomRight > desk.width()) GEOM_X -= (geomRight - desk.width());
   if (GEOM_X < 0) GEOM_X = 0;
   int geomBottom = GEOM_Y + GEOM_HEIGHT;
   if (geomBottom > desk.height()) GEOM_Y -= (geomBottom - desk.height());
   if (GEOM_Y < 0) GEOM_Y = 0;

   SPLITTER_POS_H    = splitterPosH();
   SPLITTER_POS_V    = splitterPosV();
   WORKBENCH_COLUMN_WIDTH           = workbenchColumnWidth();
   TOOLBARPOS                          = getToolbarPos();
   SizeProperties::g_fileHeader = getFileHeaderPos();
   
   /*! SECTION SyntaxHighlight */
   HighlightProperties::g_bUseSyntaxHighlighting   = getUseSyntaxHighlighting();
   HighlightProperties::g_updateQuestionMark.style = getQuestionMarkStyle();
   HighlightProperties::g_updateQuestionMark.color = getQuestionMarkColor();
   HighlightProperties::g_updateModified.style     = getModifiedStyle();
   HighlightProperties::g_updateModified.color     = getModifiedColor();
   HighlightProperties::g_updateNeedsUpdate.style  = getNeedsUpdateStyle();
   HighlightProperties::g_updateNeedsUpdate.color  = getNeedsUpdateColor();
   HighlightProperties::g_updateMerging.style      = getMergingStyle();
   HighlightProperties::g_updateMerging.color      = getMergingColor();
   HighlightProperties::g_updateConflict.style     = getConflictStyle();
   HighlightProperties::g_updateConflict.color     = getConflictColor();
   HighlightProperties::g_updateAdded.style        = getAddedStyle();
   HighlightProperties::g_updateAdded.color        = getAddedColor();
   HighlightProperties::g_updateRemoved.style      = getRemovedStyle();
   HighlightProperties::g_updateRemoved.color      = getRemovedColor();
   HighlightProperties::g_updateRemovedByOther.style = getRemovedByOtherStyle();
   HighlightProperties::g_updateRemovedByOther.color = getRemovedByOtherColor();
   HighlightProperties::g_diffOld.style            = getDiffOldStyle();
   HighlightProperties::g_diffOld.color            = getDiffOldColor();
   HighlightProperties::g_diffNew.style            = getDiffNewStyle();
   HighlightProperties::g_diffNew.color            = getDiffNewColor();
   HighlightProperties::g_scmErr.style             = getScmErrStyle();
   HighlightProperties::g_scmErr.color             = getScmErrColor();
   
   /*! SECTION Font */
   Font::g_general = getFontGeneral();
   Font::g_message = getFontMessage();
   Font::g_diff    = getFontDiff();
   
   /*! SECTION I18n */
   I18n::g_nameOfEncoder = getTextEncoder();
   I18n::g_nameOfDecoder = getTextDecoder();
   
   /*! SECTION CvsGlobal */
   CvsOptions::g_compression = compression();
   bRWPermission = rwPermission();
   CvsOptions::g_bShowVirtualInFiletab = getShowVirtualInFiletab();
   CvsOptions::g_precision = getDiffPrecision();
   CvsOptions::g_bUnifiedDiffOutput = getUnifiedDiffOutput();
   
   /*! SECTION CvsSubcommands */
   CvsOptions::g_bPruneDirs = pruneDirs();
   CvsOptions::g_bBringOverNewDirs = bringOverNewDirs();
   bKeywordSuppression = keywordSuppression();
   bDiffIgnoreWhiteSpace = getIgnoreWhiteSpace();
   CvsOptions::g_historyPeriod = getHistoryPeriod();
   CvsOptions::g_bQuietCvs = getQuiet();
   
   /*! SECTION CvsServer */
   cvsUsers           = userList();
   cvsServers         = serverList();
   cvsRepositories    = repositoryList();
   MODULEHISTORYLIST  = moduleList();
   WORKDIRHISTORYLIST = workdirList();  //list of locale dirs of working copy
   CHECKOUTASLIST     = getCheckoutAsList();
   proxyList          = getProxyList();
   
   //read profile list, generate *namelist and *contentlist...
   readProfiles(xprofileList());
   
   simplifyStringList(&cvsServers);
   simplifyStringList(&cvsRepositories);
   simplifyStringList(&cvsUsers);
   simplifyStringList(&MODULEHISTORYLIST);
   simplifyStringList(&WORKDIRHISTORYLIST);
   
   //project settings
   if (!bStartedInDir) {//startup option
      readProjectSettings( Projects);
   }
   
   QString lastVersion = m_pSettings->readEntry(Version, "");
   if (lastVersion < getVersion()) {
      updateVersionOnRead(lastVersion,getVersion());
   } else {
      m_needUpdate = FALSE;
   }
}

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

void CvsConfig::writeCfg()
{
   if (m_needUpdate) {
      QString currentVersion = m_pSettings->readEntry(Version, "");
      currentVersion = updateVersionOnWrite(currentVersion,getVersion());
      m_pSettings->writeEntry(Version, currentVersion);
      m_needUpdate = FALSE;
   }
   
   bool res;
   
   /*! Section GENERAL */
   writeExtApps();
   
   setDirPopupMenu(DIRPOPUPMENU); 
   setFilePopupMenu(FILEPOPUPMENU);
   setKeyboardShortcuts(KEYBOARDSHORTCUTS);
   setOpenFileList(joinMapping(Mapping::openFileAppList));
   setViewFileList(joinMapping(Mapping::viewFileAppList));
   
   setVeryFirstStart(Misc::g_bVeryFirstStart);
   
   if (!bOVERRIDEONTHEFLYSCANNING) {//startup option
      setOnTheFlyScanning(ONTHEFLYSCANNING);
   }
   setScanNonCvs(bSCANNONCVS);
   setCvsIgnoreFiles(CVSIGNOREFILES);
   setBinaryFileSpecList(BINARYFILESPECLIST);
   
   setUseExtDiff(bUSEEXTERNALDIFFFORSIDEBYSIDE); 
   
   setDebug(Debug::g_bDebug);
   setLogLevel(Debug::g_logLevel);
   setCvsVersion(CVSVERSION);
   setUseDirWatch(DirWatch::b_useDirWatch);
   setCvsPath(CVSPATH);
   setCvsPassPath(CVSPASSPATH);
   
   setHistorySizeWorkdirs(HistorySize::g_workdirs);
   setHistorySizeProfiles(HistorySize::g_profiles);
   setHistorySizeComments(HistorySize::g_commitinfo);
   
   /*! Section TIMER */
   res = setCheckStatusIntervall(CHECKSTATUSINTERVALL);
   setCheckStatusLevel(Polling::checkStatusLevel);
   res = setProgressIntervall(PROGRESSINTERVALL);
   
   /*! Section AutoUpdate */
   setAutoUpdate(AUTOUPDATE);
   setAutoUpdateIntervall(AUTOUPDATEINTERVALL);
   
   setIconDirectory(iconDir);
   
   setColorRev(false, SELECTION_COLOR_OF_LOGDLG[0].rgb());
   setColorRev(true , SELECTION_COLOR_OF_LOGDLG[1].rgb());
   
   /*! Section LookAndFeel */
   setStdDlg(LookAndFeel::g_stdDlg);
   setDateTimeOrder(LookAndFeel::g_dateTimeOrder);
   setDateTimeFormat(LookAndFeel::g_dateTimeFormat);
   set0AsParent(LookAndFeel::g_b0AsParent);
   setTopLevelW(LookAndFeel::g_bTopLevel);
   
   /*! Geometry */
   QRect geom(GEOM_X, GEOM_Y, GEOM_WIDTH, GEOM_HEIGHT);
   setGeometry(geom);
   
   setSplitterPosH(SPLITTER_POS_H);
   setSplitterPosV(SPLITTER_POS_V);
   setWorkbenchColumnWidth(WORKBENCH_COLUMN_WIDTH);
   setToolbarPos(TOOLBARPOS);
   setFileHeaderPos(SizeProperties::g_fileHeader);
   
   /*! SECTION SyntaxHighlight */
   setUseSyntaxHighlighting(HighlightProperties::g_bUseSyntaxHighlighting);
   setQuestionMarkStyle(HighlightProperties::g_updateQuestionMark.style);
   setQuestionMarkColor(HighlightProperties::g_updateQuestionMark.color);
   setModifiedStyle(HighlightProperties::g_updateModified.style);
   setModifiedColor(HighlightProperties::g_updateModified.color);
   setNeedsUpdateStyle(HighlightProperties::g_updateNeedsUpdate.style);
   setNeedsUpdateColor(HighlightProperties::g_updateNeedsUpdate.color);
   setMergingStyle(HighlightProperties::g_updateMerging.style);
   setMergingColor(HighlightProperties::g_updateMerging.color);
   setConflictStyle(HighlightProperties::g_updateConflict.style);
   setConflictColor(HighlightProperties::g_updateConflict.color);
   setAddedStyle(HighlightProperties::g_updateAdded.style);
   setAddedColor(HighlightProperties::g_updateAdded.color);
   setRemovedStyle(HighlightProperties::g_updateRemoved.style);
   setRemovedColor(HighlightProperties::g_updateRemoved.color);
   setRemovedByOtherStyle(HighlightProperties::g_updateRemovedByOther.style);
   setRemovedByOtherColor(HighlightProperties::g_updateRemovedByOther.color);
   setDiffOldStyle(HighlightProperties::g_diffOld.style);
   setDiffOldColor(HighlightProperties::g_diffOld.color);
   setDiffNewStyle(HighlightProperties::g_diffNew.style);
   setDiffNewColor(HighlightProperties::g_diffNew.color);
   setScmErrStyle(HighlightProperties::g_scmErr.style);
   setScmErrColor(HighlightProperties::g_scmErr.color);
   
   /*! SECTION Font */
   setFontGeneral(Font::g_general);
   setFontMessage(Font::g_message);
   setFontDiff(Font::g_diff); 
   
   /*! SECTION I18n */
   setTextEncoder(I18n::g_nameOfEncoder);
   setTextDecoder(I18n::g_nameOfDecoder);
   
   /*! SECTION CvsGlobal */
   setCompression(CvsOptions::g_compression);
   setRwPermission(bRWPermission);
   setShowVirtualInFiletab(CvsOptions::g_bShowVirtualInFiletab);
   setDiffPrecision(CvsOptions::g_precision);
   setUnifiedDiffOutput(CvsOptions::g_bUnifiedDiffOutput);
   
   /*! SECTION CvsSubcommands */
   setPruneDirs(CvsOptions::g_bPruneDirs);    
   setBringOverNewDirs(CvsOptions::g_bBringOverNewDirs);    
   setKeywordSuppression(bKeywordSuppression);
   setIgnoreWhiteSpace(bDiffIgnoreWhiteSpace);
   setHistoryPeriod(CvsOptions::g_historyPeriod);
   setQuiet(CvsOptions::g_bQuietCvs);
   
   /*! SECTION CvsServer */
   simplifyStringList(&cvsUsers);
   cutList(&cvsUsers, HistorySize::g_profiles);
   setUserList(cvsUsers);
   
   simplifyStringList(&cvsServers);
   cutList(&cvsServers, HistorySize::g_profiles);
   setServerList(cvsServers);
   
   simplifyStringList(&cvsRepositories);
   cutList(&cvsRepositories, HistorySize::g_profiles);
   setRepositoryList(cvsRepositories);
   
   setModuleList(MODULEHISTORYLIST);
   setWorkdirList(WORKDIRHISTORYLIST);
   setCheckoutAsList(CHECKOUTASLIST);
   setProxyList(proxyList);
   
   //save profile content
   QStringList tmpList;
   QValueList<CLincvsProfile>::const_iterator itPro;
   for (itPro = cvsProfileContentList.begin(); itPro != cvsProfileContentList.end(); itPro++) {
      QString line, strSshClientPreset;
      line.setNum((*itPro).method());
      strSshClientPreset.setNum((*itPro).sshClientPreset());
      line = (*itPro).name().stripWhiteSpace() + "," + line;
      line += "," + (*itPro).user().stripWhiteSpace();
      line += "," + (*itPro).server();
      line += "," + (*itPro).repository();
      line += "," + strSshClientPreset;
      
      tmpList.append(line);
   }
   
   setxProfileList(tmpList);
   
   //Project settings
   if (!bStartedInDir) {//startup option
      writeProjectSettings( Projects);
   }
}

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

void CvsConfig::readProjectSettings( QString projectPath) {
   
   unsigned int i = 0;
   QStringList projectList = m_pSettings->subkeyList( projectPath);
   
   if (projectList.isEmpty()) {//fallback to old project settings model, will be removed in near future
      
      QStringList projectNameList     = m_pSettings->readListEntry("/crossvc/Workbench/projectList");
      QStringList projectDisabledList = m_pSettings->readListEntry("/crossvc/Workbench/projectDisabledList");
      
      for( i = 0; i < projectNameList.count(); i++) {
         
         QString projectName = projectNameList[i].mid(projectNameList[i].findRev("/")+1);
         projectSettings->set( projectName,WORKDIR,projectNameList[i]);
         
         QStringList::iterator it;
         QStringList disabled;
         for ( it = projectDisabledList.begin(); it != projectDisabledList.end(); ++it ) {
            if ((*it).startsWith(projectNameList[i]) &&
               ( ((*it).length() == projectNameList[i].length()) ||
            ((*it).at(projectNameList[i].length())=='/'))) {
               
               disabled.append(*it);
               
            }
         }
         projectSettings->set( projectName,DISABLED,disabled);
      }
      return;
   }
   
   projectSettings->readFromSettings( m_pSettings, projectPath);
}

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

void CvsConfig::writeProjectSettings( QString projectPath) {
   
   unsigned int i = 0;
   QStringList oldSettings = m_pSettings->subkeyList( projectPath);
   
   QStringList projectList;
   projectSettings->getProjects( projectList);
   
   for( i = 0; i < projectList.count(); i++) {
      
      QStringList::iterator it = oldSettings.find(projectList[i]);
      if (it != oldSettings.end()) {
         oldSettings.remove(it);
      }
      
   }
   for( i = 0; i < oldSettings.count(); i++) {
      QString key = QString(projectPath)+"/"+oldSettings[i];
      removeProjectSettings( key);
   }
   projectSettings->writeToSettings(m_pSettings,projectPath);
   
   //remove old project settings model list
   m_pSettings->removeEntry("/crossvc/Workbench/projectList");
   m_pSettings->removeEntry("/crossvc/Workbench/projectDisabledList");
   
   //     projectSettings->test();
}

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

void CvsConfig::removeProjectSettings( QString key) {
   
   QStringList projectSubKeys = m_pSettings->entryList( key);//delete all subkeys
   
   unsigned int i = 0;
   for( i = 0; i < projectSubKeys.count(); i++) {
      const QString subKey = key+"/"+projectSubKeys[i];
      m_pSettings->removeEntry(subKey);
   }
}

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

/* Called on reading the settings. If m_needUpdate is set to true here,
* updateVersionOnWrite() will be called on writing the settings.
* For the versionString to be updated, m_needUpdate needs to be
* set to true here.
*/
void CvsConfig::updateVersionOnRead( const QString& oldVersion, const QString& newVersion) {

   qDebug(QObject::tr("Detected old CrossVC resource file")
	 +",\n"
	 + QObject::tr("updating from CrossVC version: ")
	 +QString(oldVersion.isEmpty() ? QObject::tr("unknown") : oldVersion)
	 +"\n"
	 +QObject::tr("to new version: ")+newVersion);

   m_needUpdate = FALSE;
   bool updated = FALSE;
   
   if (oldVersion <= QString("1.3.1")) {
      qDebug(QObject::tr("Update in progress"));
      
      readProfiles(profileList());  // read old profiles list
      simplifyStringList(&cvsServers);
      simplifyStringList(&cvsRepositories);
      simplifyStringList(&cvsUsers);
      
      m_needUpdate = TRUE;
      updated = TRUE;
   }
   if (oldVersion < QString("1.4.0")) {//change to new values on release here
      m_needUpdate = TRUE;
   }
   
   /* as long as the settings format has not changed, the next lines might be adapted
   * to the new values. Otherwise, the update requires a separat section as see above
   */
   //    if (oldVersion < QString("1.4.1")) {//change to new values on release here
      //       m_needUpdate = TRUE;
   //    }
   
   if (!updated) qDebug(QObject::tr("No update required"));
   
}

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

/* Called on writing the settings only if m_needUpdate has been
* set to true in updateVersionOnRead().
* The versionString will be updated to the return value
* (i.e. updatedVersion).
*/
QString CvsConfig::updateVersionOnWrite( const QString& oldVersion, const QString& newVersion) {
   
   QString updatedVersion = oldVersion;
   
   if (oldVersion <= QString("1.2.1")) {//clear toplevel-disabled-list if subprojects exist
      
      unsigned int i;
      QStringList disabledList;
      QStringList topLevelProjectNameList;
      QStringList subProjectNameList;
      
      projectSettings->getTopLevelProjects(topLevelProjectNameList);
      for (i=0; i<topLevelProjectNameList.count(); ++i) {
         if (projectSettings->getSubProjects(topLevelProjectNameList[i],subProjectNameList) && !subProjectNameList.isEmpty()) {
            projectSettings->set(topLevelProjectNameList[i],DISABLED,disabledList);
         }
      }
      
      updatedVersion = "1.3.0";
   }
   if (oldVersion < QString("1.4.0")) {//change to new values on release here
      updatedVersion = "1.4.0";
   }
   
   /* as long as the settings format has not changed, the next lines might be changed
   * to the new values. Otherwise, the update requires a separat section as see above
   */
   //if (oldVersion < QString("1.3.2")) {//change to new values on release here
      //   updatedVersion = "1.3.2";
   //}
   
   bool updated = (oldVersion != updatedVersion);
   if (updated) qDebug(QObject::tr("Update to:")+" "+newVersion+" "+QObject::tr("succeeded")
      +",\n"
   +QObject::tr("version is set to:")
   +" "+updatedVersion);
   else qDebug(QObject::tr("No update required"));
   
   return updatedVersion;
}

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

void CvsConfig::readExtApps()
{
   QString tmpExtApp;
   int pos;
   
   ExtApps::g_sshKeyFiles = getSshKeyList();
   
   tmpExtApp = sshAgent(); pos = tmpExtApp.find("\n");
   if (pos >= 0) {
      ExtApps::g_sshAgent.path = tmpExtApp.left(pos).stripWhiteSpace();
      ExtApps::g_sshAgent.options = tmpExtApp.right(tmpExtApp.length() - pos).stripWhiteSpace();
   } else {
      ExtApps::g_sshAgent.path = tmpExtApp.stripWhiteSpace();
      ExtApps::g_sshAgent.options = QString::null;
   }
   
   tmpExtApp = localShell(); pos = tmpExtApp.find("\n");
   if (pos >= 0) {
      ExtApps::g_localShell.path = tmpExtApp.left(pos).stripWhiteSpace();
      ExtApps::g_localShell.options = tmpExtApp.right(tmpExtApp.length() - pos).stripWhiteSpace();
   } else {
      ExtApps::g_localShell.path = tmpExtApp.stripWhiteSpace();
      ExtApps::g_localShell.options = QString::null;
   }
   tmpExtApp = localBrowser(); pos = tmpExtApp.find("\n");
   if (pos >= 0) {
      ExtApps::g_localBrowser.path = tmpExtApp.left(pos).stripWhiteSpace();
      ExtApps::g_localBrowser.options = tmpExtApp.right(tmpExtApp.length() - pos).stripWhiteSpace();
   } else {
      ExtApps::g_localBrowser.path = tmpExtApp.stripWhiteSpace();
      ExtApps::g_localBrowser.options = QString::null;
   }
   
   tmpExtApp = remoteBrowser(); pos = tmpExtApp.find("\n");
   if (pos >= 0) {
      ExtApps::g_remoteBrowser.path = tmpExtApp.left(pos).stripWhiteSpace();
      ExtApps::g_remoteBrowser.options = tmpExtApp.right(tmpExtApp.length() - pos).stripWhiteSpace();
   } else {
      ExtApps::g_remoteBrowser.path = tmpExtApp.stripWhiteSpace();
      ExtApps::g_remoteBrowser.options = QString::null;
   }
   
   tmpExtApp = CvsRsh(); pos = tmpExtApp.find("\n");
   if (pos >= 0) {
      ExtApps::g_cvsRsh.path = tmpExtApp.left(pos).stripWhiteSpace();
      ExtApps::g_cvsRsh.options = tmpExtApp.right(tmpExtApp.length() - pos).stripWhiteSpace();
   } else {
      ExtApps::g_cvsRsh.path = tmpExtApp.stripWhiteSpace();
      ExtApps::g_cvsRsh.options = QString::null;
   }
   //at the moment we don't use options for cvsRsh
   ExtApps::g_cvsRsh.options = QString::null;
   
   tmpExtApp = extDiffProgram(); pos = tmpExtApp.find("\n");
   if (pos >= 0) {
      ExtApps::g_diffProg.path = tmpExtApp.left(pos).stripWhiteSpace();
      ExtApps::g_diffProg.options = tmpExtApp.right(tmpExtApp.length() - pos).stripWhiteSpace();
   } else {
      ExtApps::g_diffProg.path = tmpExtApp.stripWhiteSpace();
      ExtApps::g_diffProg.options = QString::null;
   }
}

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

void CvsConfig::writeExtApps()
{
   setSshKeyList(ExtApps::g_sshKeyFiles);
   setSshAgent(ExtApps::g_sshAgent.path + "\n" + ExtApps::g_sshAgent.options);
   setLocalShell(ExtApps::g_localShell.path + "\n" + ExtApps::g_localShell.options);
   setLocalBrowser(ExtApps::g_localBrowser.path + "\n" + ExtApps::g_localBrowser.options);
   setRemoteBrowser(ExtApps::g_remoteBrowser.path + "\n" + ExtApps::g_remoteBrowser.options);
   setCvsRsh(ExtApps::g_cvsRsh.path + "\n" + ExtApps::g_cvsRsh.options);
   setExtDiffProgram(ExtApps::g_diffProg.path + "\n" + ExtApps::g_diffProg.options);
}

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

Mapping::FileAppList CvsConfig::extractMapping(const QStringList & src) {
   Mapping::FileAppList dst;
   QStringList::ConstIterator it;
   for (it = src.begin(); it != src.end(); ++it) {
      Mapping::FileAppItem item;
      int pos1 = (*it).find('\n');
      int pos2 = (*it).find('\n',pos1+1);
      int pos3 = (*it).find('\n',pos2+1);
      item.wildcard = (*it).mid(0,pos1);
      item.app = (*it).mid(pos1+1,pos2-pos1-1);
      item.params = (*it).mid(pos2+1,pos3-pos2-1);
      if ((*it).at( pos3+1) == '+') item.isRegExp = TRUE;
      else item.isRegExp = FALSE;
      dst.append(item);
   }
   return dst;
}

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

QStringList CvsConfig::joinMapping(const Mapping::FileAppList & src) {
   QStringList l;
   Mapping::FileAppList::ConstIterator it;
   for ( it = src.begin(); it != src.end(); ++it ) {
      l.append((*it).wildcard+'\n'+(*it).app+'\n'+(*it).params+'\n'+((*it).isRegExp ? "+" : "-"));
   }
   return l;
}

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

void CvsConfig::readProfiles(QStringList tmpList)
{
   cvsProfileContentList.clear();
   
   /*! insert items from qstringlist into a qlist */
   QStringList::Iterator it;
   for ( it = tmpList.begin(); it != tmpList.end(); ++it ) {
      QString line = (*it);
      line.prepend (',');
      line.append  (',');
      // qDebug(line);
      
      unsigned int i, idx, oldidx;
      idx = oldidx = 0;
      i = 0;
      const unsigned int nbItems = 6;
      QString lItem[nbItems + 1];  // one more for the overlast empty item
      
      /*! separate items */
      do {
         oldidx = idx+1;
         idx = line.find (',', oldidx); // WARNING: -1 --> 2^[32|64]
         lItem[i++] = line.mid(oldidx, idx-oldidx);
      } while ((idx < line.length()) && (i < nbItems)); // terminate also if more items than expected
      
      /*! add item to qlist */
      int sshClientPreset = NOSSH;
      if (!lItem[5].isEmpty()) {
         sshClientPreset = lItem[5].stripWhiteSpace().toInt();
         if (sshClientPreset < NOSSH) sshClientPreset = NOSSH;
         else if (sshClientPreset > USESSHAGENTVARS) sshClientPreset = USESSHAGENTVARS;
      }
      cvsProfileContentList.append(CLincvsProfile(lItem[0].stripWhiteSpace(),
      lItem[1].stripWhiteSpace().toInt(),
      lItem[2].stripWhiteSpace(),
      lItem[3].stripWhiteSpace(),
      lItem[4].stripWhiteSpace(),
      sshClientPreset));
   }
   
   cvsProfileNameList.clear(); 
   
   QValueList<CLincvsProfile>::const_iterator itPro;
   for (itPro = cvsProfileContentList.begin(); itPro != cvsProfileContentList.end(); itPro++) {
      cvsProfileNameList.append((*itPro).name().stripWhiteSpace());
      cvsUsers.append((*itPro).user().stripWhiteSpace());
      cvsServers.append((*itPro).server().stripWhiteSpace());
      cvsRepositories.append((*itPro).repository().stripWhiteSpace());
   }
}

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

