/****************************************************************************
**
** Copyright (C) 2000-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.
**
*****************************************************************************/

#include "config.h"

#include <qapplication.h>
#include <qdir.h>
#include <qfileinfo.h>
#include <qpixmap.h>
#include <qevent.h>
#include <qmessagebox.h>
#include <qstring.h>
#include <qbuttongroup.h>
#include <qpushbutton.h>
#include <qlayout.h>
#include <qdatetime.h> 
#include <qlineedit.h>
#include <qhbox.h>
#include <qlabel.h>

#include "globals.h"
#include "getCvsMod.h"
#include "pixmapcache.h"

/*****************************************************************************
 *  Definitions, Macros
 *****************************************************************************/

/*****************************************************************************
 *  typedefs
 *****************************************************************************/

/*****************************************************************************
 *  file global Variables
 *****************************************************************************/
QLineEdit    *selLine;
static QString RcsExt = ",v";    // extention for RCS files

/*****************************************************************************
 *  Prototypes
 *****************************************************************************/

//
// non class related functions
//

/*---------------------------------------------------------------------------*/
/*!
\fn			QString rmRcsExt( QString filename )
\brief		Filters out the rcs extension ",v".

\param		filename		

\return		filename
<BR><HR>*/
/*---------------------------------------------------------------------------*/

QString rmRcsExt( QString filename )
{
  int rcsIdx = filename.findRev ( RcsExt );
  if (rcsIdx > 0 )
  {
    filename=filename.remove(rcsIdx, RcsExt.length() );
  }
  return filename;
}


/*********************************************************************/
/*!
\fn			CvsRootDir::CvsRootDir( CvsRootDir * parent, const QString& filename )
\brief		Constructor.

\param		parent		
\param		filename		

<BR><HR>*/
/*********************************************************************/

CvsRootDir::CvsRootDir( CvsRootDir * parent, const QString& filename )
    : QListViewItem( parent ), f(filename)
{
  pDir = parent;
  readable = QDir( fullName() ).isReadable();

  if ( !readable )
    setPixmap (0, findEmbeddedPixmap ("FolderClosedLocked16x16"));
  else
    setPixmap (0, findEmbeddedPixmap ("FolderClosed16x16"));
}




/*********************************************************************/
/*!
\fn			CvsRootDir::CvsRootDir( QListView * parent, const QString& filename )
\brief		Constructor.

\param		parent		
\param		filename		

<BR><HR>*/
/*********************************************************************/

CvsRootDir::CvsRootDir( QListView * parent, const QString& filename )
    : QListViewItem( parent ), f(filename)
{
  pDir = 0;
  readable = QDir( fullName() ).isReadable();
}




/*********************************************************************/
/*!
\fn			void CvsRootDir::setOpen( bool o )
\brief		Read CVS repository and put into QListView. CVSROOT dir is not
          shown because its for CVS internal use only. Also the 'Attic'
          dirs are hidden because CVS will not checkout any files from 
          there. The extension of the RCS files '*,v' is removed for
          easier reading.

\param		o		

<BR><HR>*/
/*********************************************************************/

void CvsRootDir::setOpen( bool o )
{
  if ( o )
    setPixmap (0, findEmbeddedPixmap ("FolderOpened16x16"));
  else
  {
    setPixmap (0, findEmbeddedPixmap ("FolderClosed16x16"));
  }

  if ( o && !childCount() ) {
    QString s( fullName() );
    const QString nFilter =  QString::null;
    // const int sort = QDir::Name | QDir::IgnoreCase | QDir::DirsFirst;
      
    QDir thisDir( s, nFilter, QDir::DirsFirst );
    if ( !thisDir.isReadable() ) {
      setPixmap (0, findEmbeddedPixmap ("FolderClosedLocked16x16"));
          
      readable = FALSE;
      setExpandable( FALSE );
      return;
    }

    const QFileInfoList * files = thisDir.entryInfoList();
    if ( files ) {
      QFileInfoListIterator it( *files );
      QFileInfo * f;
            
      while( (f=it.current()) != 0 ) {
        ++it;
        if ( f->fileName() == "." || f->fileName() == ".." )
          ; // nothing

        /*! check if dir and name not CVSROOT, that's for system not for user  */
        /*! CVS will not checkout any files from Attic */
        else if ( f->isDir() ) {
          if ( (f->fileName() != cvsRootDir() ) &&
               (f->fileName() != "Attic" ) ){
            (void)new CvsRootDir( this, f->fileName() );
          }
        }
                
        else  {
          QString sizeStr;
          QListViewItem *item = new QListViewItem( this, f->fileName(),  
                                                   (sizeStr=sizeStr.number(f->size())),
                                                   (f->lastModified ()).toString(LookAndFeel::g_dateTimeFormat));
          QString fname= item->text(0);

          if (f->isFile() && f->isReadable()) {
            item->setPixmap (0, findEmbeddedPixmap ("FileASCII16x16"));//("FileText16x16"));
          }
          else {
            item->setText(1, "Unreadable File");
            item->setPixmap (0, findEmbeddedPixmap ("FileLocked16x16"));
          }
          item->setText(0, rmRcsExt(fname) );
        }
      }
    }
  }

  QListViewItem::setOpen( o );
}



/*********************************************************************/
/*!
\fn			void CvsRootDir::setup()
\brief		Reimplementation for virtual function
          void QListViewItem::setup () [virtual]. Is called from QListView 
          object.

\param		CvsRootDir::setup		

<BR><HR>*/
/*********************************************************************/

void CvsRootDir::setup()
{
  setExpandable( TRUE );
  QListViewItem::setup();
}




/*********************************************************************/
/*!
\fn			QString CvsRootDir::fullName()
\brief		Gets dir path or filename.

\param		CvsRootDir::fullName		

\return		

<BR><HR>*/
/*********************************************************************/

QString CvsRootDir::fullName()
{
  QString s;
  if ( pDir ) {
    s = pDir->fullName();   // full pathname
    s.append( f.name() );   // current dir name
    s.append( "/" );
  } 
  else {
    s = f.name();           // file name
  }
  return s;
}




/*********************************************************************/
/*!
\fn			QString CvsRootDir::text( int column )
\brief		Checks if directory is readable.

\param		column		
\return		Qstring

<BR><HR>*/
/*********************************************************************/

QString CvsRootDir::text( int column ) const
{
  if ( column == 0 )
    return f.name();
  else if ( readable )
    return "";
  else
    return "Unreadable Directory";
}





/*****************************************************************************
 *
 * Class CvsRootDirView
 *
 *****************************************************************************/



/*********************************************************************/
/*!
\fn			CvsRootDirView::CvsRootDirView( QWidget *parent, const char *name )
\brief		Constructor.

\param		*parent		
\param		*name		

\return		

<BR><HR>*/
/*********************************************************************/

CvsRootDirView::CvsRootDirView( QWidget *parent, const char *name )
    : QListView( parent, name )
{

  connect( this, SIGNAL( doubleClicked( QListViewItem * ) ),
           this, SLOT( slotFolderSelected( QListViewItem * ) ) );

  connect( this, SIGNAL( selectionChanged( QListViewItem * ) ),
           this, SLOT( itemHighLighted( QListViewItem * ) ) );

  connect( this, SIGNAL( returnPressed( QListViewItem * ) ),
           this, SLOT( slotFolderSelected( QListViewItem * ) ) );
}





/*********************************************************************/
/*!
\fn			bool CvsRootDirView::ckreadable( const QString& path )
\brief		Checks if item is readable. Handles dirs and files differently.

\param		QString& path		full name of a selected path or file.
\param		bool addExt		If TRUE (=default) add rcs extension to filename
  only. Extension is deleted in QListView for easier reading.

\return		readable : TRUE otherwise FALSE
  
<BR><HR>*/
/*********************************************************************/

bool CvsRootDirView::ckReadable( QString& path, bool addExt )
{
  if (QDir(path).exists()) {
    if (!(QDir(path).isReadable())) {
      QMessageBox::warning( this, "CrossVC - Directory Error",
                            QString("Unable to read\n  ")+path+"\nCheck permissions" );
      return FALSE;
    }
  }

  else  {
    /*! should be a filename then, and must prior append the rcs extension */
    if (addExt) path.append(RcsExt);
    if (!(QFileInfo(path).isReadable())) {
      QString caption = "CrossVC - ";
      caption +=  tr("File Error");
      QString msg = tr("Unable to read");
      msg += "\n%1\n";
      msg += "Check permissions";
      QMessageBox::warning( this, caption, msg.arg(path));
      return FALSE;
    }
  }
  return TRUE;
}




/*********************************************************************/
/*!
\fn			void CvsRootDirView::slotFolderSelected( QListViewItem *i )
\brief		Get the Pathname of a highlighted item and check if it is 
  readable. Emit signal folderSelected( dirName ) and close window.

\param		*i		Currently selected item.

<BR><HR>*/
/*********************************************************************/

void CvsRootDirView::slotFolderSelected( QListViewItem *i )
{
  dirName = fullPath( i);

  if ( ckReadable (dirName)) {
    selLine->setText (rmRcsExt(dirName));
    emit folderSelected( dirName );
  }
}




/*********************************************************************/
/*!
\fn			void CvsRootDirView::itemHighLighted ( QListViewItem *i )
\brief		Get the Pathname of a highlighted item and check if it is readable.

\param		*i		Currently selected item.

<BR><HR>*/
/*********************************************************************/

void CvsRootDirView::itemHighLighted ( QListViewItem *i )
{
  dirName = fullPath( i );
  ckReadable (dirName);
  selLine->setText (rmRcsExt(dirName));
}





/*********************************************************************/
/*!
\fn			void CvsRootDirView::openFolder()
\brief		Get contents of new folder.

\param		CvsRootDirView::openFolder		

<BR><HR>*/
/*********************************************************************/

void CvsRootDirView::openFolder()
{
  if ( dropItem && !dropItem->isOpen() ) {
    dropItem->setOpen( TRUE );
    dropItem->repaint();
  }
}




/*********************************************************************/
/*!
\fn			QString CvsRootDirView::fullPath(QListViewItem* item)
\brief		Get the full Path name corresponding to a QListViewItem.

\param		item		

\return		

<BR><HR>*/
/*********************************************************************/

QString CvsRootDirView::fullPath(QListViewItem* item)
{
  QString fullpath = item->text(0);
  while ( (item=item->parent()) ) {
    if ( item->parent() )
      fullpath = item->text(0) + "/" + fullpath;
    else
      fullpath = item->text(0) + fullpath;
  }
  return fullpath;
}




/*********************************************************************/
/*!
\fn			getCvsModule::getCvsModule( const QString& pathName, QWidget *parent, const char* name )
\brief		Constructor for a modal QDialog to create a main window and
          open the CVSROOT directory.


\param		pathName		should be CVSROOT (environment variable)
\param		*parent		
\param		name		

\return		

<BR><HR>*/
/*********************************************************************/

getCvsModule::getCvsModule( const QString& pathName,
                            QWidget *parent, const char* name )
    :QDialog( parent , name, TRUE, 0 )

{
  cvsRootPath=pathName;
/*! Create Widgets which allow layouting */
  QGroupBox *top = new QGroupBox ( this );

  QVBox *box0 = new QVBox ( top );
  QVBox *box1 = new QVBox ( top );

  QHBox *hbox1 = new QHBox (box1);
  
  new QLabel (tr("selected : "), hbox1);
  selLine = new QLineEdit(hbox1);

  QGroupBox *grp = new QButtonGroup( 1, QGroupBox::Vertical, box1 );

/*! insert some dummies to get the pushButtons to the right edge, instead of a grid */
  QWidget *dummy = new QWidget (grp);
  dummy = new QWidget (grp);
  dummy = new QWidget (grp);

/*! insert two pushbuttons at right  */
  QPushButton *pbOk = new QPushButton(tr("&OK"), grp );
  connect( pbOk, SIGNAL( clicked( ) ), SLOT( okButton() ) );

  QPushButton *pbCancel = new QPushButton(tr("&Cancel"), grp );
  connect( pbCancel, SIGNAL( clicked( ) ), SLOT( cancelButton() ) );


/*! insert dir view in 1st box */
  dirWin= new CvsRootDirView( box0 );
  connect (dirWin, SIGNAL (folderSelected( const QString & )), SLOT (okButton()));

  dirWin->addColumn(tr("Name"));
  dirWin->addColumn(tr("Size"));
  dirWin->addColumn(tr("Last Modified"));
  dirWin->setTreeStepSize( 20 );

  CvsRootDir *root = new CvsRootDir( dirWin, cvsRootPath );
  root->setOpen( TRUE );

/*!  a top grid  */
  QGridLayout *wdgGrid = new QGridLayout( this, 1, 1 );
  wdgGrid->addWidget( top, 0, 0 );

  QGridLayout *topgrid = new QGridLayout( top, 2, 1);
 
  topgrid->addWidget( box0, 0, 0 );
  topgrid->addWidget( box1, 1, 0 );
}




/*********************************************************************/
/*!
\fn			void getCvsModule::okButton()
\brief		When OK button is pressed checks if dir /file is readable and 
  removes the CVSROOT dir from the pathname to get a rel pathname
  to CVSROOT dir.

\param		getCvsModule::okButton		

<BR><HR>*/
/*********************************************************************/

void getCvsModule::okButton()
{
  QString pathFound = selLine->text();

  bool readable = dirWin->ckReadable( pathFound, TRUE );
  
  if (readable) {
    uint len=cvsRootPath.length();
    if (!pathFound.isNull())
    {
      /*! remove CVSROOT dir to get rel. path */
      pathFound.remove(0, len);
    }

    emit cvsModuleSelected( rmRcsExt(pathFound) );
    getCvsModule::close();
  }
  else {
    return;
  }
}



/*********************************************************************/
/*!
\fn			void getCvsModule::cancelButton()
\brief		Cancel Button pressed. An empty path is returned.

\param		getCvsModule::cancelButton		

<BR><HR>*/
/*********************************************************************/

void getCvsModule::cancelButton()
{
  emit cvsModuleSelected( "" );
  getCvsModule::close();  
}


/*--- END OF FILE ----------------------------------------------------------*/

