//
// pageSize.h
//
// Part of KVIEWSHELL - A framework for multipage text/gfx viewers
//
// (C) 2002-2004 Stefan Kebekus
// Distributed under the GPL

// Add header files alphabetically

#ifndef PAGESIZE_H
#define PAGESIZE_H

#include <math.h>
#include <qobject.h>
#include <qsize.h>

#include "simplePageSize.h"

class QString;
class QStringList;


/** This class represents page sizes. The main difference to the
    simplePageSize class is that this class knows about standard page
    sizes and accepts page sizes in various formats, e.g. as a string
    "DIN A4", or by specifiying the page width and height. The class
    can handle several units (Inch, Millimeters, Centimeters), ensures
    that data is in a meaningful range and provides locale-depending
    defaults.

    @short Class for storing/retrieving a page size.
    @author Stefan Kebekus <kebekus@kde.org>
    @version 1.0 0
*/

class pageSize : public QObject, public simplePageSize
{
Q_OBJECT

public:
  /** Initializs the pageSize with a default which depends on the
      locale. */
  pageSize();

  /** Initializs the pageSize with a simplePageSize. */
  pageSize(simplePageSize);

  /** Returns all possible names of known paper sizes. These can be
      used e.g. by a QComboBox to let the user choose known sizes. The
      returned list is also a list of all possible return values of
      the formatName() method explained below. If you call
      pageSizeNames(void) more than once, it is guaranteed that the
      same list of strings will be returned. */
  QStringList pageSizeNames(void);
  
  /** Set page size by name. Acceptable strings are
      
      (1) a Name from "staticList", defined in pageSize.cpp, such as
          "DIN A4"
      
      (2) a string like "500x300", which describes a page of width
          500mm and height 300mm.
	  
      If the name is not of these types, the input is silently
      ignored, and a default value (which depends on the locale) is
      used. In any case, the values will be trimmed so as not to
      exceed the minima/maxima. This method return 'true', if 'name'
      could be parsed. Otherwise, an error message is printed to
      stderr, and 'false' is returned. */
  bool        setPageSize(QString name);
  
  /** Sets the page size to "width" and "height", given in the
      associated units. If a unit is not recognized, "mm" is siliently
      assumed. If width or height does not contain a number, the
      result is an undefined value. However, it is guaranteed in any
      case, that both width and height are between the minimal and
      maximal possible values. */
  void        setPageSize(QString width, QString widthUnits, QString height, QString heightUnits);

  /** Similar to the function above */
  virtual void setPageSize(double width_in_mm, double height_in_mm);

  /** Copy operator. Will emit the signal 'sizeChanged' if the
      dimensions of *this and src differ by more than two
      millimeters. */
  pageSize &  operator= (const pageSize &src);

  /** Returns the name of the unit (currently one of "cm", "mm" or
      "in") which is most commonly used with the current page
      format. For instance, US Letter and US Legal are best given in
      inches, to avoid very odd numbers. If the page format is
      unknown, returns a guess based on the current locale. */
  QString     preferredUnit(void) const;

  /** Returns a string containing a number which gives the page width
      in the given unit. Here unit must be one of "cm", "mm" or
      "in". If the unit is not recognized, "mm" is siliently
      assumed. */
  QString     widthString(QString unit) const;

  /** Analogue to the widthString() method. */
  QString     heightString(QString unit) const;

  /** Returns a name for the current format, or QString::null, if the
      format does not have a name. If the result is not QString::null,
      it is guaranteed to be one of the strings returned by the
      pageSizeNames(void) method. NOTE: this method does not take care
      of orientation, e.g. it will return "DIN A4" if the page size is
      210x297 or 297x210. */
  QString     formatName(void) const;

  /** If the current paper format is known by name,
      i.e. formatNumber() != -1, this method can be used to get the
      orientation. or=0 means: 'portrait', or=1 is 'landscape'. If
      formatNumber is 0, this method prints an error message to stdErr
      and returns an undefined value. */
  int         getOrientation(void) const;

  /** Returns a number which describes the current format. If the
      number is non-negative, is points to the string with the same
      number outputted by the pageSizeNames(void) method. If it is -1,
      this means that the current format is not known by any
      name. Other values will never be returned. */
  int         formatNumber(void) const {return currentSize;};

  /** This method returns a string like "210x297". The numbers are
      page width and height in millimeters. The setPageSize(QString)
      method will understand this output. */
  QString     serialize(void) const;

public slots:
  /** If the current paper format is known by name,
      i.e. formatNumber() != -1, this method can be used to set the
      orientation. or=0 means: 'portrait', or=1 is 'landscape'. If
      formatNumber is 0, this method prints an error message to stdErr
      and does nothing. */
  void        setOrientation(int orient);

signals:
  /** emitted to indicate that the size changed. Not emitted
      immediately after construction, when the constructor sets the
      default size. */
  void        sizeChanged(simplePageSize t);

private:
  /** Makes sure that pageWidth and pageHeight are in the permissible
      range and not, e.g., negative. */
  void        rectifySizes(void);

  /** Tries to find one of the known sizes which matches pageWidth and
      pageHeigt, with an error margin of 2 millimeters. If found, the
      value of 'currentsize' is set to point to the known size, and
      pageWidth and pageHeight are set to the correct values for that
      size. Otherwise, currentSize is set to -1 to indicate "custom
      size". Note: this method does not take care of orientation,
      e.g. the method will set 'currentsize' to point to "DIN A4" if
      either the page size is 210x297 or 297x210. */
  void        reconstructCurrentSize(void);

  /** Gives a default value for currentSize, which depends on the
      locale. In countries with metric system, this will be "DIN A4",
      in countries with the imperial system, "US Letter". */
  int         defaultPageSize(void);

  /** Permissible range: 0--#Size_of_array staticList, or -1 to
      indicate a "user defined setting". Other values may lead to a
      segfault. */
  int         currentSize;
};

#endif
