/** 
 * Copyright (C) 2000-2002 the KGhostView authors. See file AUTHORS.
 * 	
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include <stdlib.h>

#include <kaction.h>
#include <kapplication.h>
#include <kfiledialog.h>
#include <kiconloader.h>
#include <klibloader.h>
#include <klocale.h>
#include <kmessagebox.h>
#include <kstandarddirs.h>
#include <kstatusbar.h>
#include <kstdaction.h>
#include <ktempfile.h>

#include "kgv_miniwidget.h"
#include "kgv_view.h"
#include "kgvpageview.h"

#undef Always  // avoid X11/Qt namespace clash
#include "kgvshell.moc"

//TODO -- disable GUI when no file
//TODO -- don't stay open when no file, go directly to KFileDialog

KGVShell::KGVShell() : 
    _tmpFile( 0 )
{
    m_gvpart = new KGVPart( this, "kgvpart", this, "kgvpart" );

    /*---- File -----------------------------------------------------------*/
    openact = 
	    KStdAction::open( this, SLOT( slotFileOpen() ), 
			      actionCollection() );
    recent = 
	    KStdAction::openRecent( this, SLOT( openURL( const KURL& ) ), 
				    actionCollection() );
	    KStdAction::print( m_gvpart->miniWidget(), SLOT( print() ), 
			       actionCollection() );
    (void)
	    KStdAction::quit( this, SLOT( slotQuit() ), actionCollection() );

    /*---- View -----------------------------------------------------------*/
	    KStdAction::redisplay( m_gvpart->miniWidget(), SLOT( redisplay() ),
				   actionCollection());
	    new KAction( i18n( "&Fit to Page Width" ), 0, this,
			 SLOT( slotFitToPage() ), actionCollection(),
			 "fit_to_page");
  
    /*---- Settings -------------------------------------------------------*/
    showtoolbar = 
	    KStdAction::showToolbar( this, SLOT(slotShowToolBar() ),
				     actionCollection());
    showstatusbar = 
	    KStdAction::showStatusbar( this, SLOT(slotShowStatusBar() ),
				       actionCollection());

    // Just save them automatically is destructor. (TODO: of kgv_view!)
    //KStdAction::saveOptions ( this, SLOT (slotWriteSettings()),			    actionCollection());


    setXMLFile( "kghostviewui.rc" );

    // We could, at the user's option, make this connection and kghostview
    // will always resize to fit the width of the page.  But, for now,
    // let's not.
    // connect ( m_gvpart->widget(), SIGNAL (sizeHintChanged()),	    this, SLOT (slotResize ()) );

    setCentralWidget( m_gvpart->widget() );
    createGUI( m_gvpart );

    if (!initialGeometrySet())
        resize(640,400);

    (void) statusBar(); // Create statusBar
    readSettings();
    stateChanged( "initState" );

    // Make sure the view has the keyboard focus.
    m_gvpart->widget()->setFocus();
}

KGVShell::~KGVShell()
{
    writeSettings();
    
    if( _tmpFile )
    {
	_tmpFile->setAutoDelete( true );
	delete _tmpFile;
	_tmpFile = 0;
    }
    
    // delete m_gvpart;
}

void
KGVShell::slotQuit()
{
    kapp->closeAllWindows();
}

void
KGVShell::readProperties( KConfig *config )
{
    KURL url = config->readEntry( "URL" );
    if ( url.isValid() ) {
        openURL( url );
        m_gvpart->miniWidget()->goToPage( config->readNumEntry( "Current Page", 0 ));
        // m_gvpart->miniWidget()->setMagstep( config->readNumEntry( "Magnification", 1 ));
    }
}

void 
KGVShell::saveProperties( KConfig* config )
{
    config->writeEntry( "URL", m_gvpart->url().prettyURL() );
    config->writeEntry( "Current Page", m_gvpart->miniWidget()->currentPage() );
    config->writeEntry( "Magnification", m_gvpart->miniWidget()->magnification() );
}

void
KGVShell::readSettings()
{
    applyMainWindowSettings(KGlobal::config(), "MainWindow");

    showstatusbar->setChecked(!statusBar()->isHidden());
    showtoolbar->setChecked(!toolBar()->isHidden());
    
    recent->loadEntries( KGlobal::config() );
}

void
KGVShell::writeSettings()
{
    saveMainWindowSettings(KGlobal::config(), "MainWindow");

    recent->saveEntries( KGlobal::config() );

    KGlobal::config()->sync();
}

void
KGVShell::openURL( const KURL & url )
{
    if( m_gvpart->openURL( url ) ) {
	recent->addURL (url);
	stateChanged( "documentState" );
    }
}

void
KGVShell::openStdin()
{    
    if( _tmpFile ) 
    {
	_tmpFile->setAutoDelete( true );
	delete _tmpFile;
    }
 
    _tmpFile = new KTempFile;
    _tmpFile->setAutoDelete( true );
    
    if( _tmpFile->status() != 0 ) {
	KMessageBox::error( this,
		i18n( "Could not create temporary file: %1" )
		.arg( strerror( _tmpFile->status() ) ) );
	return;
    }

    QByteArray buf( BUFSIZ );
    int read = 0, wrtn = 0;
    while( ( read = fread( buf.data(), sizeof(char), buf.size(), stdin ) )
	    > 0 ) {
	wrtn = _tmpFile->file()->writeBlock( buf.data(), read );
	if( read != wrtn )
	    break;
	kapp->processEvents();
    }

    if( read != 0 ) {
	KMessageBox::error( this,
		i18n( "Could not open standard input stream: %1" )
		.arg( strerror( errno ) ) );
	return;
    }

    _tmpFile->close();

    if( m_gvpart->openURL( _tmpFile->name() ) )
    {
	setCaption( "stdin" );
	stateChanged( "documentState" );
    }
}

void KGVShell::slotFileOpen()
{
    KURL url = KFileDialog::getOpenURL( cwd, i18n(
		    "*.ps *.ps.gz *.eps *.eps.gz *.pdf|All document files\n"
		    "*.ps *.ps.gz|Postscript files\n"
		    "*.eps *.eps.gz|Encapsulated Postscript files\n"
		    "*.pdf|Portable Document Format files" ) );

    if( !url.isEmpty() )
	openURL( url );
}

void KGVShell::slotFitToPage()
{
    if( m_gvpart->pageView()->page() )
	resize( m_gvpart->pageView()->page()->width() +
		( width() - centralWidget()->width() ) +
		( m_gvpart->widget()->width() -
		  m_gvpart->pageView()->viewport()->width() )
		, height() );
}

void KGVShell::slotResize()
{
    resize( m_gvpart->pageView()->sizeHint().width(), height() );
}

void KGVShell::slotShowStatusBar()
{
    if( showstatusbar->isChecked() )
	statusBar()->show();
    else
	statusBar()->hide();
}

void KGVShell::slotShowToolBar()
{
    KToolBar* bar = toolBar( "mainToolBar" );

    if( bar ) {
	if( showtoolbar->isChecked() )
	    bar->show();
	else
	    bar->hide();
    }
}

