/****************************************************************************
**
** Copyright (C) 1999-2006 Frank Hemer <frank@hemer.org>,
**                         Tilo Riemer <riemer@crossvc.com>,
**                         Wim Delvaux <wim.delvaux@chello.be>,
**                         Jose Hernandez <joseh@tesco.net>,
**                         Helmut Koll <HelmutKoll@web.de>,
**                         Tom Mishima <tmishima@mail.at-m.or.jp>,
**                         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.
**
*****************************************************************************/

#ifndef DIRECTORY_H_20010626
#define DIRECTORY_H_20010626

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

#include "config.h"


#include <qlistview.h>
#include <qfileinfo.h>
#include <qdict.h>
#include <qtextedit.h>

#include "DirBase.h"
#include "colortab.h"
#include "qstringlist.h"
#include "CEntries.h"

class GuardedDir;

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

class CmdThread;
class Directory;
class NonCvsListView;
class CvsIgnoreListView;
class CvsListView;
class CCvsOutput;

class EntryState
{

 public:
   EntryState(const QString& fileName, EntryStates state, Directory * Dir ) {
      m_fileName = fileName;
      m_state = ES_unknown;
      myDirectory = Dir;
      setState( state );
   }

   void setState( EntryStates s );
   Directory * getDirectory() { return myDirectory; }
   
   QString fileName() {return m_fileName;}
   EntryStates state() {return m_state;}
   
 protected:
   QString m_fileName;
   Directory * myDirectory;
   EntryStates m_state;
};


class CCvsCommand;


class Directory : public DirBase
{
 public:
 
   virtual ~Directory();

   static void initialize( const QObject *,
	 QListView *,
	 ColorTabWidget *,
	 QPopupMenu *,
	 CvsListView *,
	 NonCvsListView *,
	 CvsIgnoreListView *);

   static Directory * createInstance(const QString&);
   static Directory * createChildInstance( QListViewItem *,
	 const QString&,
	 bool=false);

   //inherited methods
   virtual int rtti() const;
   virtual int compare ( QListViewItem *, int, bool) const;
   virtual void setOpen( bool);
   Directory * parent() const;
   Directory * firstChild();
   Directory * nextSibling();
   Directory * dyncast_dir(QListViewItem *);
   void afterCall(int,CvsBuffer*,bool);

   void activateItem(bool=false,int=Controled|NonControled|Ignored);

   // open/close dirs
   void setOpen(bool,QString &);
   void setAllOpen( );
   void expandAllDir();
   void collapsAllDir();
   void analyzeAll();
   void saveViewPort();
    
   // readonly methods
   QString fullName() {return m_fullName;}
   QString shortName();
   QString relativeName();
   QListView * topView() {return s_topView;}
   DirBase * topDir();
   DirBase * topControlledDir();
   QString rootDir() {return m_rootDir;}
   bool isControlled() {return m_isControlledDir;}//fixme move to CvsDirectory
   bool isAnalyzed() {return m_isAnalyzedDir;}
   bool isDisabled() {return m_disabled;}
   bool isVirtual() {return m_virtual;}
   QString getLastError() {return m_lastErrorMsg;}
   bool hasDisabled();
   QStringList getSelectedFiles();
   QString getFirstSelectedFile();
   QListViewItem * firstControlledFile() {return ((QListView*)m_pFileListView)->firstChild();}
   QListViewItem * firstNonFile() {return ((QListView*)m_pNonFileListView)->firstChild();}
   QListViewItem * firstIgnoredFile() {return ((QListView*)m_pIgnoreFileListView)->firstChild();}
   
   //repository
   QString repository() {return m_repository;}
   QString userName() {return m_userName;}
   QString host() {return m_host;}
   int port() {return m_port;}
   QString connectMethod() {return m_connectMethod;}
   QString getDirTag() {return m_dirTag;}
   QString getRoot() {return m_root;}
   
   // rw methods
   DirBase * addDir(QString newDir,bool addVirtual=false);
   DirBase * reloadChild(QString); //remove and reinsert Dir with all its subdirs without rereading the whole project
   void removeChild(DirBase *);
   
   QStringList* getSubProjectList() {return &m_subProjectList;}
   QStringList* getDisabledList() {return &m_disabledList;}
   void updateDisabledList(QStringList&);
   void updateSubProjectList(QStringList&);
   void recGetOpenDirsStringList(QStringList&);
   void setAutoUpdate(bool);
   void setCallTime(QDateTime &);
   
   // Methods for state tracking
   void setFilesToUpToDate(QStringList& updateFileList);   
   void setAllToUpToDate();
   bool setEntryState(QString&, EntryStates);
   EntryStates getEntryState(QString);
   
   bool execute(CCvsCommand &);
   bool unexecute(CCvsCommand &);
   
   bool recCopyControlledFiles(QString,int=Create);
   bool copyFile(QString,QString,int,bool deleteSource=FALSE);
   bool recRemoveNonControlledFiles(QString &);
   bool removeNonControlled(QString&);
   
   // virtual methods
   virtual int getType() {return Plain;}
   virtual bool loginOk(CCvsOutput*,bool = false) {return false;}
   virtual void removeLogin(CCvsOutput*) {}
   virtual bool isModified() {return false;}
   virtual bool isControlledTree() {return m_hasControlledSubDir;}
   virtual bool checkDirForControl() {return false;}
   virtual void recCheckForModifications(bool);
   virtual bool postCallCheck(int=Controled|NonControled|Ignored);
   virtual void validateControlledFilesStatus(bool=false, bool=false, bool=false);
   virtual void checkAndShowStatus(FileListViewItem * =0, bool=false, int=Controled|NonControled|Ignored, bool=false);
   virtual void checkAndUpdateFileCache(QString&);
   virtual void removeTmpEntries(QString name=QString::null);
   virtual void recRemoveTmpEntries(bool);
   virtual bool recCopyTree(QString,QString,bool=FALSE);
   virtual bool parseCallResult(CvsBuffer*, int, QStringList * =0) {return false;}
   virtual bool backupFiles(QStringList);
   virtual bool restoreFiles(QStringList);
   virtual QStringList getControledSubdirs() {return QStringList();}
   virtual DirBase * searchDirOfPath(QString path, bool findVirtual = false);
   virtual DirBase * searchLastValidDirOfPath(QString path);
   
   
   //functions telling about cvs file state
   virtual bool isControlled(QString) {return false;}
   virtual bool isBinary(QString) {return false;}
   virtual void getNameAndRevOfFirstSelectedFile(QString *, QString *) {}
   virtual QString getRev(QString *) {return QString::null;}
    

 protected:

   friend class EntryState;

   //static
   static const unsigned int nextPrime( unsigned int i);
   static const int checkType(const QString);

   static const bool VIRTUAL;
   static QObject * s_control;
   static QListView * s_topView;
   static ColorTabWidget * s_pListView;
   static QPopupMenu * s_fileMenu;
   static CvsListView * s_FileListView;
   static NonCvsListView * s_NonFileListView;
   static CvsIgnoreListView * s_IgnoreFileListView;
   int m_tabIdx;

   //inherited methods
   virtual void paintCell( QPainter *p, const QColorGroup &cg,
	 int column, int width, int alignment );
   
   //constructors
   Directory(QStringList);
   Directory( QListViewItem *, bool);
    
   //virtual methods
   virtual bool analyzeDirs();
   virtual Entries * getEntries(bool=false) {return NULL;}
   
   //local methods
   void init(const QString& fileName);

   void setAndAppendEntry(QString&, EntryStates);
   
   // state bubble up
   void setDirState( EntryStates, bool fromChild = false);
   void setDirIcon();
   void checkNonControlledFilesDirState();
   void resetDirState( void );
   
   // keep to accelerate setState()
   EntryStates get_ES_Max();
   void set_ES_Max(EntryStates);
   void calc_ES_Max();
   void calcDirChilds_ES_Max();
   
   int isTreeEmpty( void );
   void recResetDirState( void );
   bool recAnalyzeAll();
   
   void removeChild( QString);
   bool getDisabled(QString filename);
   void removeEntry(QString&);
   void appendEntry(QString&, EntryState*);
   
   bool updateFileCacheAndCheckForIgnores(const QString, QString&, bool, bool&);
   
   QString     m_fullName;
   bool        m_disabled;
   bool        m_readable;
   bool        m_isControlledDir;
   bool        m_hasControlledSubDir;
   bool        m_isAnalyzedDir;
   CvsListView  *m_pFileListView;
   NonCvsListView  *m_pNonFileListView;
   CvsIgnoreListView *m_pIgnoreFileListView;
   bool        m_activatingIsNecessary;
   
   QString     m_root;
   QString     m_connectMethod;
   QString     m_userName;
   QString     m_passwd;
   QString     m_host;
   int         m_port;
   QString     m_rootDir;
   QString     m_repository;
   QString     m_dirTag;
   
   QDict<EntryState> m_entries;
   QDateTime   m_modTimeOfEntries;
   QDateTime   m_modTimeOfEntriesLog;
   
   QDict<bool> m_ignoreFiles;
   QDict<bool> m_nonFiles;
   QDateTime   m_modTimeOfIgnores;
   
   QString m_curRepository;
   
   Directory* m_topDir;//topdir of project
   bool m_isSubProjectRoot;
   QStringList m_subProjectList;
   
   QString m_lastErrorMsg;
   
   bool m_hasDSTBug;
   QDateTime m_lastCallTime;
   
   QDateTime m_lastModTimeOfDir;
   
   bool m_virtual;
   bool m_isAutoUpdate;
   
 private:

   //static vars
   static GuardedDir s_activeDir;

   //virtual methods
   virtual Directory * createChild( const QString&, bool=false);
   virtual const QString getHomeFilesToIgnore(QDateTime&, bool&) {return QString::null;}
   virtual const QString getDirFilesToIgnore(const QString, bool&) {return QString::null;}
   
   //local methods
   void setStatusText( const QString &, int ms=0);
   
   bool recExecute(CCvsCommand &);
   bool recUnexecute(CCvsCommand &);
   
   QStringList m_disabledList;
   
   QSignal * m_pDirectorySuicide;
   QSignal * m_pFileContentsChanged;
   EntryStates m_curState;
   
   // cache state for acceleration
   EntryStates m_curStateMax;
   EntryStates m_curDirStateMax;

   //set/reset ViewPort
   int m_lastHScrollBarValue;
   int m_lastVScrollBarValue;
   QStringList m_selectedList;
};

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

#endif   //DIRECTORY_H_20010626

