#include <qtimer.h>

#include <kiconloader.h>
#include <kstddirs.h>
#include <kapp.h>
#include <kaction.h>
#include <klocale.h>
#include <kfiledialog.h>
#include <kmessagebox.h>
//#include <kcmdlineargs.h>
#include <klibloader.h>
#include <kstdaction.h>

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

#include "kgvshell.moc"

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

KGVShell::KGVShell()
{

  // Try to find libkghostview
  KLibFactory *factory = KLibLoader::self()->factory( "libkghostview" );
  if (factory)
  {
    // Create the part
    m_gvpart = (KGVPart *)factory->create( this, "kgvpart",
               "KParts::ReadOnlyPart" );
  }
  else
    {
      //TODO - KNotify
      KMessageBox::error(this, "No libkghostview found !");
    }





  //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());
  KStdAction::quit ( this, SLOT (slotQuit()),
		     actionCollection());

  //View
  KStdAction::redisplay ( m_gvpart->miniWidget(), SLOT (redisplay()),
		       actionCollection());

  //This could be a KToggleAction in &Settings instead...
  new KAction (i18n("&Fit To Page Width"), 0, this, 
	       SLOT (slotFitToPage()), actionCollection(),
	       "fit_to_page");
  new KAction (i18n("&Information"), 0, m_gvpart->miniWidget(),
	       SLOT (info()),
	       actionCollection(), "info");



  //Pagemarks
  new KAction (i18n("Mark &Current Page"), 0, m_gvpart->miniWidget(),
	       SLOT (markPage()),
	       actionCollection(), "mark_current");
  new KAction (i18n("Mark &All Pages"), 0, m_gvpart->miniWidget()->markList(),
	       SLOT (markAll()),
	       actionCollection(), "mark_all");
  new KAction (i18n("Mark &Even Pages"), 0, m_gvpart->miniWidget()->markList(),
	       SLOT (markEven()),
	       actionCollection(), "mark_even");
  new KAction (i18n("Mark &Odd Pages"), 0, m_gvpart->miniWidget()->markList(),
	       SLOT (markOdd()),
	       actionCollection(), "mark_odd");

  new KAction (i18n("&Toggle Page Marks"), 0, m_gvpart->miniWidget()->markList(),
	       SLOT (toggleMarks()),
	       actionCollection(), "toggle");
  new KAction (i18n("&Remove Page Marks"), 0, m_gvpart->miniWidget()->markList(),
	       SLOT (removeMarks()),
	       actionCollection(), "remove");

  //Settings

  showtoolbar = 
    KStdAction::showToolbar ( this, SLOT(slotShowToolBar()),
			      actionCollection());
  
  showstatusbar = 
    KStdAction::showStatusbar ( this, SLOT(slotShowStatusBar()),
				actionCollection());

  // Just save them automatically is destructor.
  //KStdAction::saveOptions ( this, SLOT (slotWriteSettings()),			    actionCollection());
  
  showmarklist =
    new KToggleAction (i18n("Show &Page List"), 0, this,
		       SLOT (slotShowMarkList()),
		       actionCollection(), "show_page_list");
  connect ( m_gvpart->miniWidget(), 
	    SIGNAL (markListShown (bool)),
	    this, SLOT (slotMarkListShown(bool)) );
  
  watchaction =
    new KToggleAction (i18n("&Watch File"), 0, this, SLOT (slotWatchFile()),
		       actionCollection(), "watch_file");

  new KAction (i18n("Configure &Interpreter"), 0, m_gvpart->miniWidget(),
	       SLOT (configureGhostscript()),
	       actionCollection(), "config_interpreter");


  KTMainWindow::createGUI();

  //We could, at the user's option, make this connection and kghostview
  // will always resize to fit the width of the page.  But, for know,
  // let's not.
  //  connect ( m_gvpart->widget(), SIGNAL (sizeHintChanged()),	    this, SLOT (slotResize ()) );
  // Set the main widget
  setView( m_gvpart->widget() );
  // Integrate its GUI
  createGUI( m_gvpart );
    
  watch = 0L;

  readSettings();
  enableAllActions( false );

  resize (600,300);
}

KGVShell::~KGVShell()
{
  printf ("~KGVShell\n");
  slotWriteSettings();
  delete m_gvpart;
}

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

void
KGVShell::readSettings()
{
  KConfig *config = KGlobal::config();
  
  config->setGroup( "General" );   
  
  watchaction->setChecked (config->readBoolEntry ("WatchFile", false));
  slotWatchFile();

  showtoolbar->setChecked (config->readBoolEntry ("ShowToolBar", true));
  slotShowToolBar();

  showstatusbar->
    setChecked (config->readBoolEntry ("ShowStatusBar", true));
  slotShowStatusBar();

  

  showmarklist->setChecked (m_gvpart->miniWidget()->isMarkListShown());

  recent->loadEntries (config);
}

void
KGVShell::slotWriteSettings()
{
  KConfig *config = KGlobal::config();
  
  config->setGroup( "General" );

  config->writeEntry ("WatchFile", watchaction->isChecked());
  config->writeEntry ("ShowToolBar", showtoolbar->isChecked());
  config->writeEntry ("ShowStatusBar", showstatusbar->isChecked());

  m_gvpart->miniWidget()->writeSettings();

  recent->saveEntries (config);

  config->sync();
}

void
KGVShell::openURL( const KURL & url )
{
  if (m_gvpart->openURL( url ))
    {
      recent->addURL (url);
      slotWatchFile();
      enableAllActions( true );
    }
}

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

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

void
KGVShell::slotFitToPage()
{
  m_gvpart->miniWidget()->shrinkWrap();
  slotResize();
}

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

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

void
KGVShell::slotShowToolBar()
{
  if (showtoolbar->isChecked())
    toolBar()->show();
  else
    toolBar()->hide();
}

 
void
KGVShell::startWatching()
{
  if (!m_gvpart->miniWidget()->isFileOpen())
    return;
 
  if (watch!=0L)
    delete watch;
 
  watch = new QTimer;
 
  connect ( watch, SIGNAL (timeout()),
            m_gvpart->miniWidget(),
	    SLOT (redisplayChanged ()) );
 
  watch->start (500);
}

void
KGVShell::stopWatching()
{
  if (watch!=0L)
    {
      delete watch;
      watch=0L;
    }
}

void
KGVShell::slotWatchFile()
{

  if (watchaction->isChecked())
    startWatching();
  else
    stopWatching();
}

void
KGVShell::slotShowMarkList()
{
  m_gvpart->miniWidget()->showMarkList (showmarklist->isChecked());
}

void
KGVShell::slotMarkListShown(bool yes)
{
  showmarklist->setChecked (yes);  
}

void
KGVShell::keyPressEvent (QKeyEvent *ke)
{

  switch (ke->key())
    {
    case Key_Up:
      m_gvpart->miniWidget()->scrollUp();
      break;
    case Key_Down:
      m_gvpart->miniWidget()->scrollDown();
      break;
    case Key_Left:
      m_gvpart->miniWidget()->scrollLeft();
      break;
    case Key_Right:
      m_gvpart->miniWidget()->scrollRight();
      break;
    default:
      ke->ignore();
    }
}

void
KGVShell::enableAllActions( bool enable )
{
  int count = actionCollection()->count();
  for ( int i = 0; i < count; i++ )
    actionCollection()->action( i )->setEnabled( enable );

  if (!enable)
    openact->setEnabled (true);
}
