#ifndef __KVIEWPART_H
#define __KVIEWPART_H


#include <kparts/part.h>
#include <kparts/browserextension.h>
#include <kparts/factory.h>
#include <kdirwatch.h>
#include <qtimer.h>

class KAccel;
class KAction;
class KSelectAction;
class KTempFile;
class KToggleAction;
class KViewPartExtension;
class ScrollBox;
class MarkList;
class KInstance;
class GotoDialog;
class QSize;
class pageSizeDialog;

#include "kviewpart_iface.h"
#include "kmultipage.h"
#include "pageSize.h"
#include "zoom.h"
#include "zoomlimits.h"

class KViewPartFactory : public KParts::Factory
{
  Q_OBJECT

public:
  KViewPartFactory();
  virtual ~KViewPartFactory();

  virtual KParts::Part *createPartObject( QWidget *parentWidget, const char *widgetName, QObject *parent, const char *name, const char *classname, const QStringList &args );
  
  static KInstance *instance();

private:
  static KInstance *s_instance;
};


class KViewPart : public KViewPart_Iface
{
  Q_OBJECT

public:
  KViewPart(QString partname, QWidget *parentWidget, const char *widgetName, QObject *parent, const char *name);
  virtual ~KViewPart();

  bool isValid() { return multiPage; }

  // Returns a description of the current page size, for use in the
  // statusbar of the kviewshell that embeds this KViewPart.
  QString pageSizeDescription(void);

signals:
  void zoomChanged(const QString &);
  void pageChanged(const QString &);
  void sizeChanged(const QString &);
  void scrollbarStatusChanged(bool);

public slots:
  void slotSetFullPage(bool fullpage);
  virtual bool closeURL();
  virtual QStringList fileFormats();
  void setStatusBarTextFromMultiPage(const QString &);
  /** Calling this slot will cause the kmultipage to reload the file */
  void reload(void);

protected slots:
  void slotShowMarkList();
  void slotMedia (int);

  void prevPage();
  void nextPage();
  void firstPage();
  void lastPage();
  void goToPage();

  void zoomIn();
  void zoomOut();

  void fitToPage();
  void fitSize();
  void fitToHeight();
  void fitToWidth();

  void scrollUp();
  void scrollDown();
  void scrollLeft();
  void scrollRight();

  void scrollUpPage();
  void scrollDownPage();
  void scrollLeftPage();
  void scrollRightPage();

  void readUp();
  void readDown();

  void slotPrint();

  void fileChanged(const QString&);

  // Connected to the QLineEdit in the toolbar.
  void setZoomValue(const QString &);

  void updatePreview(bool previewAvailable=false);

  void slotPreview();


protected:
  KToggleAction *showmarklist, *showPreview, *scrollbarHandling;
  KSelectAction *orientation, *media, *zoom_action;

  virtual bool openFile();

  int page() const { return _currentPage; };
  int pages() const { return _numberOfPages; };
  void setPage(int page);

  bool eventFilter(QObject *obj, QEvent *ev);
  void connectNotify ( const char * );

  void partActivateEvent( KParts::PartActivateEvent *ev );
  void guiActivateEvent( KParts::GUIActivateEvent *ev );

  /** Scrolls the main scrollview by deltaInPixel (positive values
      scroll DOWN). If the user tries to scroll past the beginning or
      the end of a page, then the method either returns without doing
      anything (if the current page is the first or last page, resp,
      or if the method is called within 200ms after the beg. or end of
      the page was reached), or goes the the next/previous page. The
      delay makes it a little easier for the user to scroll with the
      mouse wheel or the keyboard without involuntarily moving to
      another page. */
  void scroll(Q_INT32 deltaInPixel);


private slots:
  void numberOfPages(int nr);
  void pageInfo(int numpages, int currentpage);
  void pageSelected(int nr);
  void contentsMoving(int x, int y);
  void scrollBoxChanged(QPoint np);
  void updateScrollBox();
  void scrollTo(int x, int y);
  void slotGotoDialog(const QString &page);
  void checkActions();

  /** This is the slot where mouseWheel events are processed that come
      from the multipage/scrollview. This method calles scroll, a
      delta-value of 120 (i.e. one notch on a standard wheel mouse)
      scrolls by two 'lines'. */
  void wheelEvent(QWheelEvent *);

  // This slot is connected to userRequestedPaperSize. Whenever the
  // size changes, this slot is called. It checks if the
  // userRequestedPaperSize has an orientation and
  // enables/set/disables the menu entries accordingly. It also sets
  // the media menu entries. Finally, the slot sets the _paperSize, if
  // appropriate, and initiates an update of the GUI, if necessary.
  void slotUserPreferredSizeChanged(float, float);

  // This slot is connected to the useDocumentSpecifiedSize action,
  // and is called when the user checks/unchecks the "use document
  // specified paper size" menu entry
  void slotUseDocumentSpecifiedSize(bool);

  // This slot is connected to _paperSize: whenever the paper size
  // changes, this slot is called and the necessary upates in the GUI
  // are performed
  void setPaperSize(float width_in_mm, float height_in_mm);

  void doRepaintScrollBoxBackground(void);

  // Reacts to page size requests of the multipage
  void slotPageSizeRequests(const pageSize &size);
  
private:
  // This method reads the configuration file. It should only be
  // called when no document is loaded.
  void readSettings();

  void writeSettings();

  // The method openFile of this kviewpart can be called even if
  // m_file points to a compressed file. In that case, the temporary
  // file tmpUnzipped will be created and a decompressed copy of the
  // file stored there.
  KTempFile *tmpUnzipped;

  KDirWatch *watch;
  QString _partname;
  QSize sizeOfPage();
  KAccel *accel;
  KAction *zoomInAct, *zoomOutAct, *backAct, *forwardAct,
    *startAct, *endAct, *endDocAct, *markAct, *gotoAct,
    *fitAct, *fitPageAct, *fitHeightAct, *fitWidthAct,
    *saveAction, *saveAsAction, *printAction, *readUpAct, *readDownAct;
  KToggleAction *watchAct,*useDocumentSpecifiedSize;

  KMultiPage *multiPage;
  ScrollBox *scrollBox;
  MarkList  *markList;
  KViewPartExtension *m_extension;

  int _numberOfPages, _currentPage;
  bool pageChangeIsConnected;

  QWidget *mainWidget;

  // This QTimer is used for idle processing. Whenver the preview
  // needs to be re-painted, this timer is set with an interval of
  // 0sec. This means the the timeout() signal is emitted after all
  // events in the queue have been processed. That way the (lengthy)
  // re-painting takes place only when no user input needs to be
  // processed.
  QTimer previewPaintInitiator;

  pageSize  _paperSize;

  /** Some documents specify the paper size. In that case, the
      kmultipage implementation will call the slotPageSizeRequests()
      method. The method will then set this flag to 'true' and store
      the requested size in 'documentRequestedPaperSize'. */
  bool      documentHasRequestedPaperSize;
  pageSize  documentRequestedPaperSize;

  /** This entry stores the paper size that the user has requested in
      the preferences dialog. If that paper size is actually used or
      not, depends on if the document specifies a paper size of its
      own and if the user has chosen the option "use document
      specified paper size if available" */
  pageSize  userRequestedPaperSize;


  class zoom      _zoomVal; // stores the current zoom value
  pageSizeDialog *_pageSizeDialog;
  GotoDialog     *_gotoDialog;

  /** Stores the mouse position between two mouse events. This is used
      to implement the "grab and drag the scrollview contents"
      feature. */
  QPoint mousePos;

  /** This timer is used to implement a brief delay when the user
      scrolls past the beginning or the end of the page before a the
      program moves to a new page. That way, it is a little easier for
      the user to scroll with the mouse wheel or the keyboard without
      involuntarily moving to another page. The timer is used in the
      scroll() method. */
  QTimer changePageDelayTimer;
};


class KViewPartExtension : public KParts::BrowserExtension
{
  Q_OBJECT
  friend class KViewPart;

public:

  KViewPartExtension(KViewPart *parent);
  virtual ~KViewPartExtension() {}

};


#endif
