<commit_before>/********************************************************************************
  $Header$

  purpose:

  notes:

  to do:

  author(s):
   - Dirk Farin, dirk.farin@gmx.de

  modifications:
    24/Jan/2002 - Dirk Farin - Complete reimplementation based on old Image type.
    02/Jun/1999 - Dirk Farin - first implementation
 ********************************************************************************
    LibVideoGfx - video processing library
    Copyright (C) 2002  Dirk Farin

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library 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
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 ********************************************************************************/

#ifndef LIBVIDEOGFX_GRAPHICS_BASIC_IMAGE_HH
#define LIBVIDEOGFX_GRAPHICS_BASIC_IMAGE_HH

#include <assert.h>

#include <libvideogfx/types.hh>
#include <libvideogfx/graphics/datatypes/bitmap.hh>
#include <algorithm>

namespace videogfx {

  enum Colorspace
  {
    Colorspace_RGB, Colorspace_YUV, Colorspace_Greyscale, Colorspace_HSV,
    Colorspace_Invalid
  };

  enum ChromaFormat
  {
    /** subsampling h:2 v:2 */ Chroma_420,
    /** subsampling h:2 v:1 */ Chroma_422,
    /** No subsampling      */ Chroma_444,
    Chroma_Invalid
  };

  enum BitmapChannel
  {
    Bitmap_Red = 0, Bitmap_Green = 1, Bitmap_Blue = 2,
    Bitmap_Y   = 0, Bitmap_Cb    = 1, Bitmap_Cr   = 2,
                    Bitmap_U     = 1, Bitmap_V    = 2,
    Bitmap_Hue = 0, Bitmap_Saturation = 1, Bitmap_Value = 2,
    Bitmap_Alpha=3
  };

  /** Check if chroma is horizontally subsampled. Usage of the more general #ChromaSubH()# is recommended. */
  inline bool IsSubH(ChromaFormat cf) { return cf != Chroma_444; }
  /** Check if chroma is vertically subsampled. Usage of the more general #ChromaSubV()# is recommended. */
  inline bool IsSubV(ChromaFormat cf) { return cf == Chroma_420; }
  /** Get horizontal subsampling factor. */
  inline int  ChromaSubH(ChromaFormat cf) { return (cf != Chroma_444) ? 2 : 1; }
  /** Get vertical subsampling factor. */
  inline int  ChromaSubV(ChromaFormat cf) { return (cf == Chroma_420) ? 2 : 1; }

  struct ImageParam
  {
    ImageParam() : width(0), height(0), halign(1), valign(1), border(0),
		   colorspace(Colorspace_Invalid), has_alpha(false),
		   chroma(Chroma_444), reduced_chroma_resolution(true),
		   chroma_border(-1), chroma_halign(-1), chroma_valign(-1)
    { }

    int width,height;
    int halign,valign;
    int border;

    Colorspace colorspace;
    bool has_alpha;

    ChromaFormat chroma;
    bool reduced_chroma_resolution;
    int  chroma_border;
    int  chroma_halign;
    int  chroma_valign;

    int  AskChromaWidth()  const
    {
      if (colorspace==Colorspace_YUV)
	return (width +ChromaSubH(chroma)-1)/ChromaSubH(chroma);
      else
	return width;
    }
    int  AskChromaHeight() const
    {
      if (colorspace==Colorspace_YUV)
	return (height+ChromaSubV(chroma)-1)/ChromaSubV(chroma);
      else
	return height;
    }
    void AskChromaSizes(int& w,int &h) const;
    int  AskChromaBorder() const;
    int  AskChromaHAlign() const;
    int  AskChromaVAlign() const;

    int  BitmapWidth (BitmapChannel b) const { if (b==1||b==2) return AskChromaWidth();  else return width; }
    int  BitmapHeight(BitmapChannel b) const { if (b==1||b==2) return AskChromaHeight(); else return height; }
    int  ChromaScaleH(BitmapChannel b,int x) const
    { if ((b==1||b==2) && colorspace==Colorspace_YUV) return x/ChromaSubH(chroma); else return x; }
    int  ChromaScaleV(BitmapChannel b,int y) const
    { if ((b==1||b==2) && colorspace==Colorspace_YUV) return y/ChromaSubV(chroma); else return y; }
  };

  template <class Pel> class Image
  {
  public:
    virtual ~Image() { }

    void Create(const ImageParam&);
    void Release();

    /// Get colorspace independent image parameters.
    ImageParam AskParam() const { return d_param; }
    int  AskWidth()  const { return d_param.width; }
    int  AskHeight() const { return d_param.height; }
    int  AskBorder() const { return d_param.border; }
    void GetSize(int& w,int& h) const { w=d_param.width; h=d_param.height; }

    Bitmap<Pel>&       AskBitmap(BitmapChannel pm_id)       { return d_pm[pm_id]; }
    const Bitmap<Pel>& AskBitmap(BitmapChannel pm_id) const { return d_pm[pm_id]; }

    Pel*const*       AskFrame(BitmapChannel pm_id)       { return d_pm[pm_id].AskFrame(); }
    const Pel*const* AskFrame(BitmapChannel pm_id) const { return d_pm[pm_id].AskFrame(); }

    /** Replace a complete bitmap. Note that the new bitmap either has to be empty or has to
	be exactly the same size as the old one.
	Furthermore you are responsible that all alignments and the border size is sufficient
	for your application. This is not checked!

	If you insert or remove (by replacing a bitmap by an empty one) an alpha bitmap,
	the alphamask-flag in ImageParam will be set accordingly.
    */
    void ReplaceBitmap(BitmapChannel id,const Bitmap<Pel>&);
    /// Set new image parameters.
    void SetParam(const ImageParam& param) { d_param=param; }

    Image<Pel> Clone() const;

    Image<Pel> CreateSubView  (int x0,int y0,int w,int h) const;
    Image<Pel> CreateFieldView(bool top) const;

    bool IsEmpty() const { return d_pm[0].IsEmpty(); }

    Pel*const* AskFrameR()        { return d_pm[Bitmap_Red].AskFrame(); }
    const Pel*const* AskFrameR()  const { return d_pm[Bitmap_Red].AskFrame(); }
    Pel*const* AskFrameG()        { return d_pm[Bitmap_Green].AskFrame(); }
    const Pel*const* AskFrameG()  const { return d_pm[Bitmap_Green].AskFrame(); }
    Pel*const* AskFrameB()        { return d_pm[Bitmap_Blue].AskFrame(); }
    const Pel*const* AskFrameB()  const { return d_pm[Bitmap_Blue].AskFrame(); }
    Pel*const* AskFrameY()        { return d_pm[Bitmap_Y].AskFrame(); }
    const Pel*const* AskFrameY()  const { return d_pm[Bitmap_Y].AskFrame(); }
    Pel*const* AskFrameU()        { return d_pm[Bitmap_U].AskFrame(); }
    const Pel*const* AskFrameU()  const { return d_pm[Bitmap_U].AskFrame(); }
    Pel*const* AskFrameV()        { return d_pm[Bitmap_V].AskFrame(); }
    const Pel*const* AskFrameV()  const { return d_pm[Bitmap_V].AskFrame(); }
    Pel*const* AskFrameCb()       { return d_pm[Bitmap_Cb].AskFrame(); }
    const Pel*const* AskFrameCb() const { return d_pm[Bitmap_Cb].AskFrame(); }
    Pel*const* AskFrameCr()       { return d_pm[Bitmap_Cr].AskFrame(); }
    const Pel*const* AskFrameCr() const { return d_pm[Bitmap_Cr].AskFrame(); }
    Pel*const* AskFrameA()        { return d_pm[Bitmap_Alpha].AskFrame(); }
    const Pel*const* AskFrameA()  const { return d_pm[Bitmap_Alpha].AskFrame(); }

    Bitmap<Pel>& AskBitmapR()        { return d_pm[Bitmap_Red]; }
    const Bitmap<Pel>& AskBitmapR()  const { return d_pm[Bitmap_Red]; }
    Bitmap<Pel>& AskBitmapG()        { return d_pm[Bitmap_Green]; }
    const Bitmap<Pel>& AskBitmapG()  const { return d_pm[Bitmap_Green]; }
    Bitmap<Pel>& AskBitmapB()        { return d_pm[Bitmap_Blue]; }
    const Bitmap<Pel>& AskBitmapB()  const { return d_pm[Bitmap_Blue]; }
    Bitmap<Pel>& AskBitmapY()        { return d_pm[Bitmap_Y]; }
    const Bitmap<Pel>& AskBitmapY()  const { return d_pm[Bitmap_Y]; }
    Bitmap<Pel>& AskBitmapU()        { return d_pm[Bitmap_U]; }
    const Bitmap<Pel>& AskBitmapU()  const { return d_pm[Bitmap_U]; }
    Bitmap<Pel>& AskBitmapV()        { return d_pm[Bitmap_V]; }
    const Bitmap<Pel>& AskBitmapV()  const { return d_pm[Bitmap_V]; }
    Bitmap<Pel>& AskBitmapCb()       { return d_pm[Bitmap_Cb]; }
    const Bitmap<Pel>& AskBitmapCb() const { return d_pm[Bitmap_Cb]; }
    Bitmap<Pel>& AskBitmapCr()       { return d_pm[Bitmap_Cr]; }
    const Bitmap<Pel>& AskBitmapCr() const { return d_pm[Bitmap_Cr]; }
    Bitmap<Pel>& AskBitmapA()        { return d_pm[Bitmap_Alpha]; }
    const Bitmap<Pel>& AskBitmapA()  const { return d_pm[Bitmap_Alpha]; }

    bool IsShared() const
    {
      for (int i=0;i<4;i++)
	if (d_pm[i].IsShared())
	  return true;

      return false;
    }

  private:
    Bitmap<Pel> d_pm[4];
    ImageParam  d_param;
  };

  template <class Pel> void Image<Pel>::Create(const ImageParam& param)
  {
    d_pm[0].Create(param.width, param.height, param.border,param.halign,param.valign);

    switch (param.colorspace)
      {
      case Colorspace_RGB:
      case Colorspace_HSV:
	d_pm[1].Create(param.width, param.height, param.border,param.halign,param.valign);
	d_pm[2].Create(param.width, param.height, param.border,param.halign,param.valign);
	break;

      case Colorspace_YUV:
	if (param.reduced_chroma_resolution)
	  {
	    d_pm[1].Create(param.AskChromaWidth(), param.AskChromaHeight(), param.AskChromaBorder(),
			   param.AskChromaHAlign(),param.AskChromaVAlign());
	    d_pm[2].Create(param.AskChromaWidth(), param.AskChromaHeight(), param.AskChromaBorder(),
			   param.AskChromaHAlign(),param.AskChromaVAlign());
	  }
	else
	  {
	    d_pm[1].Create(param.width, param.height, param.border,param.halign,param.valign);
	    d_pm[2].Create(param.width, param.height, param.border,param.halign,param.valign);
	  }
	break;

      case Colorspace_Greyscale:
	d_pm[1].Release();
	d_pm[2].Release();
	break;

      case Colorspace_Invalid:
	Assert(0);
	break;
      }

    if (param.has_alpha)
      d_pm[Bitmap_Alpha].Create(param.width, param.height, param.border,param.halign,param.valign);
    else
      d_pm[Bitmap_Alpha].Release();

    d_param = param;
  }

  template <class Pel> void Image<Pel>::Release()
  {
    for (int i=0;i<4;i++)
      d_pm[i].Release();

    d_param = ImageParam();
  }

  template <class Pel> Image<Pel> Image<Pel>::Clone() const
  {
    Image<Pel> img;
    for (int i=0;i<4;i++)
      img.d_pm[i] = d_pm[i].Clone();

    img.d_param = d_param;

    return img;
  }

  template <class Pel> Image<Pel> Image<Pel>::CreateSubView(int x0,int y0,int w,int h) const
  {
    Image<Pel> newimg;
    newimg.d_param = d_param;

    newimg.d_param.width  = w;
    newimg.d_param.height = h;
    newimg.d_param.halign = 1;
    newimg.d_param.valign = 1;
    newimg.d_param.border = 0;
    newimg.d_param.chroma_border = -1;
    newimg.d_param.chroma_halign = -1;
    newimg.d_param.chroma_valign = -1;

    if (d_param.colorspace == Colorspace_YUV)
      {
	newimg.d_pm[0] = d_pm[0].CreateSubView(x0,y0,w,h);
	newimg.d_pm[3] = d_pm[3].CreateSubView(x0,y0,w,h);

	int subh = ChromaSubH(d_param.chroma);
	int subv = ChromaSubV(d_param.chroma);

	newimg.d_pm[1] = d_pm[1].CreateSubView(x0/subh,y0/subv,(w+subh-1)/subh,(h+subv-1)/subv);
	newimg.d_pm[2] = d_pm[2].CreateSubView(x0/subh,y0/subv,(w+subh-1)/subh,(h+subv-1)/subv);
      }
    else
      {
	for (int i=0;i<4;i++)
	  newimg.d_pm[i] = d_pm[i].CreateSubView(x0,y0,w,h);
      }

    return newimg;
  }

  template <class Pel> Image<Pel> Image<Pel>::CreateFieldView(bool top) const
  {
    if (!top && d_param.colorspace==Colorspace_YUV && d_param.chroma==Chroma_420 &&
	(d_pm[0].AskHeight()%2)==0 && (d_pm[1].AskHeight()%2)==1)
      {
	AssertDescr(false,"not enough chroma information for bottom field");
      }

    Image<Pel> newimg;
    newimg.d_param = d_param;

    for (int i=0;i<4;i++)
      newimg.d_pm[i] = d_pm[i].CreateFieldView(top);

    newimg.d_param.width  = newimg.d_pm[0].AskWidth();
    newimg.d_param.height = newimg.d_pm[0].AskHeight();
    newimg.d_param.halign = 1;
    newimg.d_param.valign = 1;
    newimg.d_param.border = 0;
    newimg.d_param.chroma_border = -1;
    newimg.d_param.chroma_halign = -1;
    newimg.d_param.chroma_valign = -1;

    return newimg;
  }

}

#endif
<commit_msg>exchanged ImageParam initialization because of name-clash to ncurses library<commit_after>/********************************************************************************
  $Header$

  purpose:

  notes:

  to do:

  author(s):
   - Dirk Farin, dirk.farin@gmx.de

  modifications:
    24/Jan/2002 - Dirk Farin - Complete reimplementation based on old Image type.
    02/Jun/1999 - Dirk Farin - first implementation
 ********************************************************************************
    LibVideoGfx - video processing library
    Copyright (C) 2002  Dirk Farin

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library 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
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 ********************************************************************************/

#ifndef LIBVIDEOGFX_GRAPHICS_BASIC_IMAGE_HH
#define LIBVIDEOGFX_GRAPHICS_BASIC_IMAGE_HH

#include <assert.h>

#include <libvideogfx/types.hh>
#include <libvideogfx/graphics/datatypes/bitmap.hh>
#include <algorithm>

namespace videogfx {

  enum Colorspace
  {
    Colorspace_RGB, Colorspace_YUV, Colorspace_Greyscale, Colorspace_HSV,
    Colorspace_Invalid
  };

  enum ChromaFormat
  {
    /** subsampling h:2 v:2 */ Chroma_420,
    /** subsampling h:2 v:1 */ Chroma_422,
    /** No subsampling      */ Chroma_444,
    Chroma_Invalid
  };

  enum BitmapChannel
  {
    Bitmap_Red = 0, Bitmap_Green = 1, Bitmap_Blue = 2,
    Bitmap_Y   = 0, Bitmap_Cb    = 1, Bitmap_Cr   = 2,
                    Bitmap_U     = 1, Bitmap_V    = 2,
    Bitmap_Hue = 0, Bitmap_Saturation = 1, Bitmap_Value = 2,
    Bitmap_Alpha=3
  };

  /** Check if chroma is horizontally subsampled. Usage of the more general #ChromaSubH()# is recommended. */
  inline bool IsSubH(ChromaFormat cf) { return cf != Chroma_444; }
  /** Check if chroma is vertically subsampled. Usage of the more general #ChromaSubV()# is recommended. */
  inline bool IsSubV(ChromaFormat cf) { return cf == Chroma_420; }
  /** Get horizontal subsampling factor. */
  inline int  ChromaSubH(ChromaFormat cf) { return (cf != Chroma_444) ? 2 : 1; }
  /** Get vertical subsampling factor. */
  inline int  ChromaSubV(ChromaFormat cf) { return (cf == Chroma_420) ? 2 : 1; }

  struct ImageParam
  {
    ImageParam() : width(0), height(0), halign(1), valign(1),
		   colorspace(Colorspace_Invalid), has_alpha(false),
		   chroma(Chroma_444), reduced_chroma_resolution(true),
		   chroma_border(-1), chroma_halign(-1), chroma_valign(-1)
    {
      border=0;
    }

    int width,height;
    int halign,valign;
    int border;

    Colorspace colorspace;
    bool has_alpha;

    ChromaFormat chroma;
    bool reduced_chroma_resolution;
    int  chroma_border;
    int  chroma_halign;
    int  chroma_valign;

    int  AskChromaWidth()  const
    {
      if (colorspace==Colorspace_YUV)
	return (width +ChromaSubH(chroma)-1)/ChromaSubH(chroma);
      else
	return width;
    }
    int  AskChromaHeight() const
    {
      if (colorspace==Colorspace_YUV)
	return (height+ChromaSubV(chroma)-1)/ChromaSubV(chroma);
      else
	return height;
    }
    void AskChromaSizes(int& w,int &h) const;
    int  AskChromaBorder() const;
    int  AskChromaHAlign() const;
    int  AskChromaVAlign() const;

    int  BitmapWidth (BitmapChannel b) const { if (b==1||b==2) return AskChromaWidth();  else return width; }
    int  BitmapHeight(BitmapChannel b) const { if (b==1||b==2) return AskChromaHeight(); else return height; }
    int  ChromaScaleH(BitmapChannel b,int x) const
    { if ((b==1||b==2) && colorspace==Colorspace_YUV) return x/ChromaSubH(chroma); else return x; }
    int  ChromaScaleV(BitmapChannel b,int y) const
    { if ((b==1||b==2) && colorspace==Colorspace_YUV) return y/ChromaSubV(chroma); else return y; }
  };

  template <class Pel> class Image
  {
  public:
    virtual ~Image() { }

    void Create(const ImageParam&);
    void Release();

    /// Get colorspace independent image parameters.
    ImageParam AskParam() const { return d_param; }
    int  AskWidth()  const { return d_param.width; }
    int  AskHeight() const { return d_param.height; }
    int  AskBorder() const { return d_param.border; }
    void GetSize(int& w,int& h) const { w=d_param.width; h=d_param.height; }

    Bitmap<Pel>&       AskBitmap(BitmapChannel pm_id)       { return d_pm[pm_id]; }
    const Bitmap<Pel>& AskBitmap(BitmapChannel pm_id) const { return d_pm[pm_id]; }

    Pel*const*       AskFrame(BitmapChannel pm_id)       { return d_pm[pm_id].AskFrame(); }
    const Pel*const* AskFrame(BitmapChannel pm_id) const { return d_pm[pm_id].AskFrame(); }

    /** Replace a complete bitmap. Note that the new bitmap either has to be empty or has to
	be exactly the same size as the old one.
	Furthermore you are responsible that all alignments and the border size is sufficient
	for your application. This is not checked!

	If you insert or remove (by replacing a bitmap by an empty one) an alpha bitmap,
	the alphamask-flag in ImageParam will be set accordingly.
    */
    void ReplaceBitmap(BitmapChannel id,const Bitmap<Pel>&);
    /// Set new image parameters.
    void SetParam(const ImageParam& param) { d_param=param; }

    Image<Pel> Clone() const;

    Image<Pel> CreateSubView  (int x0,int y0,int w,int h) const;
    Image<Pel> CreateFieldView(bool top) const;

    bool IsEmpty() const { return d_pm[0].IsEmpty(); }

    Pel*const* AskFrameR()        { return d_pm[Bitmap_Red].AskFrame(); }
    const Pel*const* AskFrameR()  const { return d_pm[Bitmap_Red].AskFrame(); }
    Pel*const* AskFrameG()        { return d_pm[Bitmap_Green].AskFrame(); }
    const Pel*const* AskFrameG()  const { return d_pm[Bitmap_Green].AskFrame(); }
    Pel*const* AskFrameB()        { return d_pm[Bitmap_Blue].AskFrame(); }
    const Pel*const* AskFrameB()  const { return d_pm[Bitmap_Blue].AskFrame(); }
    Pel*const* AskFrameY()        { return d_pm[Bitmap_Y].AskFrame(); }
    const Pel*const* AskFrameY()  const { return d_pm[Bitmap_Y].AskFrame(); }
    Pel*const* AskFrameU()        { return d_pm[Bitmap_U].AskFrame(); }
    const Pel*const* AskFrameU()  const { return d_pm[Bitmap_U].AskFrame(); }
    Pel*const* AskFrameV()        { return d_pm[Bitmap_V].AskFrame(); }
    const Pel*const* AskFrameV()  const { return d_pm[Bitmap_V].AskFrame(); }
    Pel*const* AskFrameCb()       { return d_pm[Bitmap_Cb].AskFrame(); }
    const Pel*const* AskFrameCb() const { return d_pm[Bitmap_Cb].AskFrame(); }
    Pel*const* AskFrameCr()       { return d_pm[Bitmap_Cr].AskFrame(); }
    const Pel*const* AskFrameCr() const { return d_pm[Bitmap_Cr].AskFrame(); }
    Pel*const* AskFrameA()        { return d_pm[Bitmap_Alpha].AskFrame(); }
    const Pel*const* AskFrameA()  const { return d_pm[Bitmap_Alpha].AskFrame(); }

    Bitmap<Pel>& AskBitmapR()        { return d_pm[Bitmap_Red]; }
    const Bitmap<Pel>& AskBitmapR()  const { return d_pm[Bitmap_Red]; }
    Bitmap<Pel>& AskBitmapG()        { return d_pm[Bitmap_Green]; }
    const Bitmap<Pel>& AskBitmapG()  const { return d_pm[Bitmap_Green]; }
    Bitmap<Pel>& AskBitmapB()        { return d_pm[Bitmap_Blue]; }
    const Bitmap<Pel>& AskBitmapB()  const { return d_pm[Bitmap_Blue]; }
    Bitmap<Pel>& AskBitmapY()        { return d_pm[Bitmap_Y]; }
    const Bitmap<Pel>& AskBitmapY()  const { return d_pm[Bitmap_Y]; }
    Bitmap<Pel>& AskBitmapU()        { return d_pm[Bitmap_U]; }
    const Bitmap<Pel>& AskBitmapU()  const { return d_pm[Bitmap_U]; }
    Bitmap<Pel>& AskBitmapV()        { return d_pm[Bitmap_V]; }
    const Bitmap<Pel>& AskBitmapV()  const { return d_pm[Bitmap_V]; }
    Bitmap<Pel>& AskBitmapCb()       { return d_pm[Bitmap_Cb]; }
    const Bitmap<Pel>& AskBitmapCb() const { return d_pm[Bitmap_Cb]; }
    Bitmap<Pel>& AskBitmapCr()       { return d_pm[Bitmap_Cr]; }
    const Bitmap<Pel>& AskBitmapCr() const { return d_pm[Bitmap_Cr]; }
    Bitmap<Pel>& AskBitmapA()        { return d_pm[Bitmap_Alpha]; }
    const Bitmap<Pel>& AskBitmapA()  const { return d_pm[Bitmap_Alpha]; }

    bool IsShared() const
    {
      for (int i=0;i<4;i++)
	if (d_pm[i].IsShared())
	  return true;

      return false;
    }

  private:
    Bitmap<Pel> d_pm[4];
    ImageParam  d_param;
  };

  template <class Pel> void Image<Pel>::Create(const ImageParam& param)
  {
    d_pm[0].Create(param.width, param.height, param.border,param.halign,param.valign);

    switch (param.colorspace)
      {
      case Colorspace_RGB:
      case Colorspace_HSV:
	d_pm[1].Create(param.width, param.height, param.border,param.halign,param.valign);
	d_pm[2].Create(param.width, param.height, param.border,param.halign,param.valign);
	break;

      case Colorspace_YUV:
	if (param.reduced_chroma_resolution)
	  {
	    d_pm[1].Create(param.AskChromaWidth(), param.AskChromaHeight(), param.AskChromaBorder(),
			   param.AskChromaHAlign(),param.AskChromaVAlign());
	    d_pm[2].Create(param.AskChromaWidth(), param.AskChromaHeight(), param.AskChromaBorder(),
			   param.AskChromaHAlign(),param.AskChromaVAlign());
	  }
	else
	  {
	    d_pm[1].Create(param.width, param.height, param.border,param.halign,param.valign);
	    d_pm[2].Create(param.width, param.height, param.border,param.halign,param.valign);
	  }
	break;

      case Colorspace_Greyscale:
	d_pm[1].Release();
	d_pm[2].Release();
	break;

      case Colorspace_Invalid:
	Assert(0);
	break;
      }

    if (param.has_alpha)
      d_pm[Bitmap_Alpha].Create(param.width, param.height, param.border,param.halign,param.valign);
    else
      d_pm[Bitmap_Alpha].Release();

    d_param = param;
  }

  template <class Pel> void Image<Pel>::Release()
  {
    for (int i=0;i<4;i++)
      d_pm[i].Release();

    d_param = ImageParam();
  }

  template <class Pel> Image<Pel> Image<Pel>::Clone() const
  {
    Image<Pel> img;
    for (int i=0;i<4;i++)
      img.d_pm[i] = d_pm[i].Clone();

    img.d_param = d_param;

    return img;
  }

  template <class Pel> Image<Pel> Image<Pel>::CreateSubView(int x0,int y0,int w,int h) const
  {
    Image<Pel> newimg;
    newimg.d_param = d_param;

    newimg.d_param.width  = w;
    newimg.d_param.height = h;
    newimg.d_param.halign = 1;
    newimg.d_param.valign = 1;
    newimg.d_param.border = 0;
    newimg.d_param.chroma_border = -1;
    newimg.d_param.chroma_halign = -1;
    newimg.d_param.chroma_valign = -1;

    if (d_param.colorspace == Colorspace_YUV)
      {
	newimg.d_pm[0] = d_pm[0].CreateSubView(x0,y0,w,h);
	newimg.d_pm[3] = d_pm[3].CreateSubView(x0,y0,w,h);

	int subh = ChromaSubH(d_param.chroma);
	int subv = ChromaSubV(d_param.chroma);

	newimg.d_pm[1] = d_pm[1].CreateSubView(x0/subh,y0/subv,(w+subh-1)/subh,(h+subv-1)/subv);
	newimg.d_pm[2] = d_pm[2].CreateSubView(x0/subh,y0/subv,(w+subh-1)/subh,(h+subv-1)/subv);
      }
    else
      {
	for (int i=0;i<4;i++)
	  newimg.d_pm[i] = d_pm[i].CreateSubView(x0,y0,w,h);
      }

    return newimg;
  }

  template <class Pel> Image<Pel> Image<Pel>::CreateFieldView(bool top) const
  {
    if (!top && d_param.colorspace==Colorspace_YUV && d_param.chroma==Chroma_420 &&
	(d_pm[0].AskHeight()%2)==0 && (d_pm[1].AskHeight()%2)==1)
      {
	AssertDescr(false,"not enough chroma information for bottom field");
      }

    Image<Pel> newimg;
    newimg.d_param = d_param;

    for (int i=0;i<4;i++)
      newimg.d_pm[i] = d_pm[i].CreateFieldView(top);

    newimg.d_param.width  = newimg.d_pm[0].AskWidth();
    newimg.d_param.height = newimg.d_pm[0].AskHeight();
    newimg.d_param.halign = 1;
    newimg.d_param.valign = 1;
    newimg.d_param.border = 0;
    newimg.d_param.chroma_border = -1;
    newimg.d_param.chroma_halign = -1;
    newimg.d_param.chroma_valign = -1;

    return newimg;
  }

}

#endif
<|endoftext|>


<commit_before>/**
 * This file is part of TelepathyQt
 *
 * @copyright Copyright (C) 2012 Collabora Ltd. <http://www.collabora.co.uk/>
 * @copyright Copyright (C) 2012 Nokia Corporation
 * @license LGPL 2.1
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include <TelepathyQt/DBusService>

#include "TelepathyQt/_gen/dbus-service.moc.hpp"

#include "TelepathyQt/debug-internal.h"

#include <TelepathyQt/Constants>
#include <TelepathyQt/DBusObject>

#include <QDBusConnection>
#include <QString>

namespace Tp
{

struct TP_QT_NO_EXPORT DBusService::Private
{
    Private(DBusService *parent, const QDBusConnection &dbusConnection)
        : parent(parent),
          dbusObject(new DBusObject(dbusConnection, parent)),
          registered(false)
    {
    }

    DBusService *parent;
    QString busName;
    QString objectPath;
    DBusObject *dbusObject;
    bool registered;
};

/**
 * \class DBusService
 * \ingroup servicesideimpl
 * \headerfile TelepathyQt/dbus-service.h <TelepathyQt/DBusService>
 *
 * \brief Base class for D-Bus services.
 *
 * This class serves as a base for all the classes that are used to implement
 * D-Bus services.
 */

/**
 * Construct a DBusService that uses the given \a dbusConnection.
 *
 * \param dbusConnection The D-Bus connection that will be used by this service.
 */
DBusService::DBusService(const QDBusConnection &dbusConnection)
    : mPriv(new Private(this, dbusConnection))
{
}

/**
 * Class destructor.
 */
DBusService::~DBusService()
{
    delete mPriv;
}

/**
 * Return the D-Bus connection associated with this service.
 *
 * \return the D-Bus connection associated with this service.
 */
QDBusConnection DBusService::dbusConnection() const
{
    return mPriv->dbusObject->dbusConnection();
}

/**
 * Return the D-Bus service name of this service.
 *
 * This is only valid after this service has been registered
 * on the bus using registerObject().
 *
 * \return the D-Bus service name of this service.
 */
QString DBusService::busName() const
{
    return mPriv->busName;
}

/**
 * Return the D-Bus object path of this service.
 *
 * This is only valid after this service has been registered
 * on the bus using registerObject().
 *
 * \return the D-Bus object path of this service.
 */
QString DBusService::objectPath() const
{
    return mPriv->objectPath;
}

/**
 * Return the DBusObject that is used for registering this service on the bus.
 *
 * The DBusObject is the object on which all the interface adaptors
 * for this service are plugged.
 *
 * \return a pointer to the DBusObject that is used for registering
 * this service on the bus.
 */
DBusObject *DBusService::dbusObject() const
{
    return mPriv->dbusObject;
}

/**
 * Return whether this D-Bus service has been registered on the bus or not.
 *
 * \return \c true if the service has been registered, or \c false otherwise.
 */
bool DBusService::isRegistered() const
{
    return mPriv->registered;
}

/**
 * Register this service object on the bus with the given \a busName and \a objectPath.
 *
 * \a error needs to be a valid pointer to a DBusError instance, where any
 * possible D-Bus error will be stored.
 *
 * A service may only be registered once in its lifetime.
 * Use isRegistered() to find out if it has already been registered or not.
 *
 * You normally don't need to use this method directly.
 * Subclasses should provide a simplified version of it.
 *
 * \param busName The D-Bus service name of this object.
 * \param objectPath The D-Bus object path of this object.
 * \param error A pointer to a valid DBusError instance, where any
 * possible D-Bus error will be stored.
 * \return \c true on success or \c false otherwise.
 */
bool DBusService::registerObject(const QString &busName, const QString &objectPath,
        DBusError *error)
{
    if (mPriv->registered) {
        return true;
    }

    if (!mPriv->dbusObject->dbusConnection().registerService(busName)) {
        error->set(TP_QT_ERROR_INVALID_ARGUMENT,
                QString(QLatin1String("Name %s already in use by another process"))
                    .arg(busName));
        warning() << "Unable to register service" << busName <<
            "- name already registered by another process";
        return false;
    }

    if (!mPriv->dbusObject->dbusConnection().registerObject(objectPath, mPriv->dbusObject)) {
        error->set(TP_QT_ERROR_INVALID_ARGUMENT,
                QString(QLatin1String("Object at path %s already registered"))
                    .arg(objectPath));
        warning() << "Unable to register object" << objectPath <<
            "- path already registered";
        return false;
    }

    debug() << "Registered object" << objectPath << "at bus name" << busName;

    mPriv->busName = busName;
    mPriv->objectPath = objectPath;
    mPriv->registered = true;
    return true;
}

/**
 * \fn QVariantMap DBusService::immutableProperties() const
 *
 * Return the immutable properties of this D-Bus service object.
 *
 * Immutable properties cannot change after the object has been registered
 * on the bus with registerObject().
 *
 * \return The immutable properties of this D-Bus service object.
 */

struct AbstractDBusServiceInterface::Private
{
    Private(const QString &interfaceName)
        : interfaceName(interfaceName),
          dbusObject(0),
          registered(false)
    {
    }

    QString interfaceName;
    DBusObject *dbusObject;
    bool registered;
};

/**
 * \class AbstractDBusServiceInterface
 * \ingroup servicesideimpl
 * \headerfile TelepathyQt/dbus-service.h <TelepathyQt/AbstractDBusServiceInterface>
 *
 * \brief Base class for D-Bus service interfaces.
 *
 * This class serves as a base for all the classes that are used to implement
 * interfaces that sit on top of D-Bus services.
 */

/**
 * Construct an AbstractDBusServiceInterface that implements
 * the interface with the given \a interfaceName.
 *
 * \param interfaceName The name of the interface that this class implements.
 */
AbstractDBusServiceInterface::AbstractDBusServiceInterface(const QString &interfaceName)
    : mPriv(new Private(interfaceName))
{
}

/**
 * Class destructor.
 */
AbstractDBusServiceInterface::~AbstractDBusServiceInterface()
{
    delete mPriv;
}

/**
 * Return the name of the interface that this class implements,
 * as given on the constructor.
 *
 * \return The name of the interface that this class implements.
 */
QString AbstractDBusServiceInterface::interfaceName() const
{
    return mPriv->interfaceName;
}

/**
 * Return the DBusObject on which the adaptor of this interface is plugged.
 *
 * This is only accessible after the interface has been registered
 * with registerInterface().
 *
 * \return a pointer to the DBusObject on which the adaptor
 * of this interface is plugged.
 * \sa DBusService::dbusObject()
 */
DBusObject *AbstractDBusServiceInterface::dbusObject() const
{
    return mPriv->dbusObject;
}

/**
 * Return whether this interface has been registered.
 *
 * \return \c true if the service has been registered, or \c false otherwise.
 * \sa registerInterface()
 */
bool AbstractDBusServiceInterface::isRegistered() const
{
    return mPriv->registered;
}

/**
 * Registers this interface by plugging its adaptor
 * on the given \a dbusObject.
 *
 * \param dbusObject The object on which to plug the adaptor.
 * \return \c false if the interface has already been registered,
 * or \a true otherwise.
 * \sa isRegistered()
 */
bool AbstractDBusServiceInterface::registerInterface(DBusObject *dbusObject)
{
    if (mPriv->registered) {
        return true;
    }

    mPriv->dbusObject = dbusObject;
    createAdaptor();
    mPriv->registered = true;
    return true;
}

/**
 * \fn QVariantMap AbstractDBusServiceInterface::immutableProperties() const
 *
 * Return the immutable properties of this interface.
 *
 * Immutable properties cannot change after the interface has been registered
 * on a service on the bus with registerInterface().
 *
 * \return The immutable properties of this interface.
 */

/**
 * \fn void AbstractDBusServiceInterface::createAdaptor()
 *
 * Create the adaptor for this interface.
 *
 * Subclasses should reimplement this appropriately.
 */

}
<commit_msg>DBusService: Fix QString args replacement in registerObject()<commit_after>/**
 * This file is part of TelepathyQt
 *
 * @copyright Copyright (C) 2012 Collabora Ltd. <http://www.collabora.co.uk/>
 * @copyright Copyright (C) 2012 Nokia Corporation
 * @license LGPL 2.1
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include <TelepathyQt/DBusService>

#include "TelepathyQt/_gen/dbus-service.moc.hpp"

#include "TelepathyQt/debug-internal.h"

#include <TelepathyQt/Constants>
#include <TelepathyQt/DBusObject>

#include <QDBusConnection>
#include <QString>

namespace Tp
{

struct TP_QT_NO_EXPORT DBusService::Private
{
    Private(DBusService *parent, const QDBusConnection &dbusConnection)
        : parent(parent),
          dbusObject(new DBusObject(dbusConnection, parent)),
          registered(false)
    {
    }

    DBusService *parent;
    QString busName;
    QString objectPath;
    DBusObject *dbusObject;
    bool registered;
};

/**
 * \class DBusService
 * \ingroup servicesideimpl
 * \headerfile TelepathyQt/dbus-service.h <TelepathyQt/DBusService>
 *
 * \brief Base class for D-Bus services.
 *
 * This class serves as a base for all the classes that are used to implement
 * D-Bus services.
 */

/**
 * Construct a DBusService that uses the given \a dbusConnection.
 *
 * \param dbusConnection The D-Bus connection that will be used by this service.
 */
DBusService::DBusService(const QDBusConnection &dbusConnection)
    : mPriv(new Private(this, dbusConnection))
{
}

/**
 * Class destructor.
 */
DBusService::~DBusService()
{
    delete mPriv;
}

/**
 * Return the D-Bus connection associated with this service.
 *
 * \return the D-Bus connection associated with this service.
 */
QDBusConnection DBusService::dbusConnection() const
{
    return mPriv->dbusObject->dbusConnection();
}

/**
 * Return the D-Bus service name of this service.
 *
 * This is only valid after this service has been registered
 * on the bus using registerObject().
 *
 * \return the D-Bus service name of this service.
 */
QString DBusService::busName() const
{
    return mPriv->busName;
}

/**
 * Return the D-Bus object path of this service.
 *
 * This is only valid after this service has been registered
 * on the bus using registerObject().
 *
 * \return the D-Bus object path of this service.
 */
QString DBusService::objectPath() const
{
    return mPriv->objectPath;
}

/**
 * Return the DBusObject that is used for registering this service on the bus.
 *
 * The DBusObject is the object on which all the interface adaptors
 * for this service are plugged.
 *
 * \return a pointer to the DBusObject that is used for registering
 * this service on the bus.
 */
DBusObject *DBusService::dbusObject() const
{
    return mPriv->dbusObject;
}

/**
 * Return whether this D-Bus service has been registered on the bus or not.
 *
 * \return \c true if the service has been registered, or \c false otherwise.
 */
bool DBusService::isRegistered() const
{
    return mPriv->registered;
}

/**
 * Register this service object on the bus with the given \a busName and \a objectPath.
 *
 * \a error needs to be a valid pointer to a DBusError instance, where any
 * possible D-Bus error will be stored.
 *
 * A service may only be registered once in its lifetime.
 * Use isRegistered() to find out if it has already been registered or not.
 *
 * You normally don't need to use this method directly.
 * Subclasses should provide a simplified version of it.
 *
 * \param busName The D-Bus service name of this object.
 * \param objectPath The D-Bus object path of this object.
 * \param error A pointer to a valid DBusError instance, where any
 * possible D-Bus error will be stored.
 * \return \c true on success or \c false otherwise.
 */
bool DBusService::registerObject(const QString &busName, const QString &objectPath,
        DBusError *error)
{
    if (mPriv->registered) {
        return true;
    }

    if (!mPriv->dbusObject->dbusConnection().registerService(busName)) {
        error->set(TP_QT_ERROR_INVALID_ARGUMENT,
                QString(QLatin1String("Name %1 already in use by another process"))
                    .arg(busName));
        warning() << "Unable to register service" << busName <<
            "- name already registered by another process";
        return false;
    }

    if (!mPriv->dbusObject->dbusConnection().registerObject(objectPath, mPriv->dbusObject)) {
        error->set(TP_QT_ERROR_INVALID_ARGUMENT,
                QString(QLatin1String("Object at path %1 already registered"))
                    .arg(objectPath));
        warning() << "Unable to register object" << objectPath <<
            "- path already registered";
        return false;
    }

    debug() << "Registered object" << objectPath << "at bus name" << busName;

    mPriv->busName = busName;
    mPriv->objectPath = objectPath;
    mPriv->registered = true;
    return true;
}

/**
 * \fn QVariantMap DBusService::immutableProperties() const
 *
 * Return the immutable properties of this D-Bus service object.
 *
 * Immutable properties cannot change after the object has been registered
 * on the bus with registerObject().
 *
 * \return The immutable properties of this D-Bus service object.
 */

struct AbstractDBusServiceInterface::Private
{
    Private(const QString &interfaceName)
        : interfaceName(interfaceName),
          dbusObject(0),
          registered(false)
    {
    }

    QString interfaceName;
    DBusObject *dbusObject;
    bool registered;
};

/**
 * \class AbstractDBusServiceInterface
 * \ingroup servicesideimpl
 * \headerfile TelepathyQt/dbus-service.h <TelepathyQt/AbstractDBusServiceInterface>
 *
 * \brief Base class for D-Bus service interfaces.
 *
 * This class serves as a base for all the classes that are used to implement
 * interfaces that sit on top of D-Bus services.
 */

/**
 * Construct an AbstractDBusServiceInterface that implements
 * the interface with the given \a interfaceName.
 *
 * \param interfaceName The name of the interface that this class implements.
 */
AbstractDBusServiceInterface::AbstractDBusServiceInterface(const QString &interfaceName)
    : mPriv(new Private(interfaceName))
{
}

/**
 * Class destructor.
 */
AbstractDBusServiceInterface::~AbstractDBusServiceInterface()
{
    delete mPriv;
}

/**
 * Return the name of the interface that this class implements,
 * as given on the constructor.
 *
 * \return The name of the interface that this class implements.
 */
QString AbstractDBusServiceInterface::interfaceName() const
{
    return mPriv->interfaceName;
}

/**
 * Return the DBusObject on which the adaptor of this interface is plugged.
 *
 * This is only accessible after the interface has been registered
 * with registerInterface().
 *
 * \return a pointer to the DBusObject on which the adaptor
 * of this interface is plugged.
 * \sa DBusService::dbusObject()
 */
DBusObject *AbstractDBusServiceInterface::dbusObject() const
{
    return mPriv->dbusObject;
}

/**
 * Return whether this interface has been registered.
 *
 * \return \c true if the service has been registered, or \c false otherwise.
 * \sa registerInterface()
 */
bool AbstractDBusServiceInterface::isRegistered() const
{
    return mPriv->registered;
}

/**
 * Registers this interface by plugging its adaptor
 * on the given \a dbusObject.
 *
 * \param dbusObject The object on which to plug the adaptor.
 * \return \c false if the interface has already been registered,
 * or \a true otherwise.
 * \sa isRegistered()
 */
bool AbstractDBusServiceInterface::registerInterface(DBusObject *dbusObject)
{
    if (mPriv->registered) {
        return true;
    }

    mPriv->dbusObject = dbusObject;
    createAdaptor();
    mPriv->registered = true;
    return true;
}

/**
 * \fn QVariantMap AbstractDBusServiceInterface::immutableProperties() const
 *
 * Return the immutable properties of this interface.
 *
 * Immutable properties cannot change after the interface has been registered
 * on a service on the bus with registerInterface().
 *
 * \return The immutable properties of this interface.
 */

/**
 * \fn void AbstractDBusServiceInterface::createAdaptor()
 *
 * Create the adaptor for this interface.
 *
 * Subclasses should reimplement this appropriately.
 */

}
<|endoftext|>


<commit_before>/*
 * This file is part of TelepathyQt4
 *
 * Copyright (C) 2010 Collabora Ltd. <http://www.collabora.co.uk/>
 * Copyright (C) 2010 Nokia Corporation
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include <TelepathyQt4/AccountSet>
#include "TelepathyQt4/account-set-internal.h"

#include "TelepathyQt4/_gen/account-set.moc.hpp"
#include "TelepathyQt4/_gen/account-set-internal.moc.hpp"

#include "TelepathyQt4/debug-internal.h"

#include <TelepathyQt4/Account>
#include <TelepathyQt4/AccountManager>
#include <TelepathyQt4/ConnectionCapabilities>
#include <TelepathyQt4/ConnectionManager>

namespace Tp
{

AccountSet::Private::Private(AccountSet *parent,
        const AccountManagerPtr &accountManager,
        const QList<AccountFilterConstPtr> &filters)
    : parent(parent),
      accountManager(accountManager),
      filters(filters),
      ready(false)
{
    init();
}

AccountSet::Private::Private(AccountSet *parent,
        const AccountManagerPtr &accountManager,
        const QVariantMap &filter)
    : parent(parent),
      accountManager(accountManager),
      ready(false)
{
    AccountPropertyFilterPtr filterObj = AccountPropertyFilter::create();
    for (QVariantMap::const_iterator i = filter.constBegin();
            i != filter.constEnd(); ++i) {
        filterObj->addProperty(i.key(), i.value());
    }
    filters.append(filterObj);
    init();
}

void AccountSet::Private::init()
{
    if (checkFilters()) {
        connectSignals();
        insertAccounts();
        ready = true;
    }
}

bool AccountSet::Private::checkFilters()
{
    foreach (const AccountFilterConstPtr &filter, filters) {
        if (!filter->isValid()) {
            return false;
        }
    }

    return true;
}

void AccountSet::Private::connectSignals()
{
    parent->connect(accountManager.data(),
            SIGNAL(newAccount(Tp::AccountPtr)),
            SLOT(onNewAccount(Tp::AccountPtr)));
}

void AccountSet::Private::insertAccounts()
{
    foreach (const Tp::AccountPtr &account, accountManager->allAccounts()) {
        insertAccount(account);
    }
}

void AccountSet::Private::insertAccount(const Tp::AccountPtr &account)
{
    QString accountPath = account->objectPath();
    Q_ASSERT(!wrappers.contains(accountPath));
    wrapAccount(account);
    filterAccount(account);
}

void AccountSet::Private::removeAccount(const Tp::AccountPtr &account)
{
    QString accountPath = account->objectPath();
    Q_ASSERT(wrappers.contains(accountPath));
    accounts.remove(accountPath);
    AccountWrapper *wrapper = wrappers[accountPath];
    delete wrapper;
    emit parent->accountRemoved(account);
}

void AccountSet::Private::wrapAccount(const AccountPtr &account)
{
    AccountWrapper *wrapper = new AccountWrapper(account, parent);
    parent->connect(wrapper,
            SIGNAL(accountRemoved(Tp::AccountPtr)),
            SLOT(onAccountRemoved(Tp::AccountPtr)));
    parent->connect(wrapper,
            SIGNAL(accountPropertyChanged(Tp::AccountPtr,QString)),
            SLOT(onAccountChanged(Tp::AccountPtr)));
    parent->connect(wrapper,
            SIGNAL(accountCapabilitiesChanged(Tp::AccountPtr,Tp::ConnectionCapabilities*)),
            SLOT(onAccountChanged(Tp::AccountPtr)));
    wrappers.insert(account->objectPath(), wrapper);
}

void AccountSet::Private::filterAccount(const AccountPtr &account)
{
    QString accountPath = account->objectPath();
    Q_ASSERT(wrappers.contains(accountPath));
    AccountWrapper *wrapper = wrappers[accountPath];

    /* account changed, let's check if it matches filter */
    if (accountMatchFilters(wrapper)) {
        if (!accounts.contains(account->objectPath())) {
            accounts.insert(account->objectPath(), account);
            if (ready) {
                emit parent->accountAdded(account);
            }
        }
    } else {
        if (accounts.contains(account->objectPath())) {
            accounts.remove(account->objectPath());
            if (ready) {
                emit parent->accountRemoved(account);
            }
        }
    }
}

bool AccountSet::Private::accountMatchFilters(AccountWrapper *wrapper)
{
    if (filters.isEmpty()) {
        return true;
    }

    AccountPtr account = wrapper->account();
    foreach (const AccountFilterConstPtr &filter, filters) {
        if (!filter->matches(account)) {
            return false;
        }
    }

    return true;
}

AccountSet::Private::AccountWrapper::AccountWrapper(
        const AccountPtr &account, QObject *parent)
    : QObject(parent),
      mAccount(account)
{
    connect(account.data(),
            SIGNAL(removed()),
            SLOT(onAccountRemoved()));
    connect(account.data(),
            SIGNAL(propertyChanged(QString)),
            SLOT(onAccountPropertyChanged(QString)));
    connect(account.data(),
            SIGNAL(capabilitiesChanged(Tp::ConnectionCapabilities*)),
            SLOT(onAccountCapalitiesChanged(Tp::ConnectionCapabilities*)));
}

AccountSet::Private::AccountWrapper::~AccountWrapper()
{
}

ConnectionCapabilities *AccountSet::Private::AccountWrapper::capabilities() const
{
    if (mAccount->haveConnection() &&
        mAccount->connection()->status() == Connection::StatusConnected) {
        return mAccount->connection()->capabilities();
    } else {
        if (mAccount->protocolInfo()) {
            return mAccount->protocolInfo()->capabilities();
        }
    }
    /* either we don't have a connected connection or
     * Account::FeatureProtocolInfo is not ready */
    return 0;
}

void AccountSet::Private::AccountWrapper::onAccountRemoved()
{
    emit accountRemoved(mAccount);
}

void AccountSet::Private::AccountWrapper::onAccountPropertyChanged(
        const QString &propertyName)
{
    emit accountPropertyChanged(mAccount, propertyName);
}

void AccountSet::Private::AccountWrapper::onAccountCapalitiesChanged(
        ConnectionCapabilities *caps)
{
    emit accountCapabilitiesChanged(mAccount, caps);
}

/**
 * \class AccountSet
 * \ingroup clientaccount
 * \headerfile TelepathyQt4/account-set.h <TelepathyQt4/AccountSet>
 *
 * \brief The AccountSet class provides an object representing a set of
 * Telepathy accounts filtered by a given criteria.
 *
 * AccountSet is automatically updated whenever accounts that match the given
 * criteria are added, removed or updated.
 *
 * \section account_set_usage_sec Usage
 *
 * \subsection account_set_create_sec Creating an AccountSet object
 *
 * The easiest way to create AccountSet objects is through AccountManager. One
 * can just use the AccountManager convenience methods such as
 * AccountManager::validAccountsSet() to get a set of account objects
 * representing valid accounts.
 *
 * For example:
 *
 * \code
 *
 * class MyClass : public QObject
 * {
 *     QOBJECT
 *
 * public:
 *     MyClass(QObject *parent = 0);
 *     ~MyClass() { }
 *
 * private Q_SLOTS:
 *     void onAccountManagerReady(Tp::PendingOperation *);
 *     void onValidAccountAdded(const Tp::AccountPtr &);
 *     void onValidAccountRemoved(const Tp::AccountPtr &);
 *
 * private:
 *     AccountManagerPtr am;
 *     AccountSetPtr validAccountsSet;
 * };
 *
 * MyClass::MyClass(QObject *parent)
 *     : QObject(parent)
 *       am(AccountManager::create())
 * {
 *     connect(am->becomeReady(),
 *             SIGNAL(finished(Tp::PendingOperation*)),
 *             SLOT(onAccountManagerReady(Tp::PendingOperation*)));
 * }
 *
 * void MyClass::onAccountManagerReady(Tp::PendingOperation *op)
 * {
 *     if (op->isError()) {
 *         qWarning() << "Account manager cannot become ready:" <<
 *             op->errorName() << "-" << op->errorMessage();
 *         return;
 *     }
 *
 *     validAccountsSet = am->validAccountsSet();
 *     connect(validAccountsSet.data(),
 *             SIGNAL(accountAdded(const Tp::AccountPtr &)),
 *             SLOT(onValidAccountAdded(const Tp::AccountPtr &)));
 *     connect(validAccountsSet.data(),
 *             SIGNAL(accountRemoved(const Tp::AccountPtr &)),
 *             SLOT(onValidAccountRemoved(const Tp::AccountPtr &)));
 *
 *     QList<AccountPtr> accounts = validAccountsSet->accounts();
 *     // do something with accounts
 * }
 *
 * void MyClass::onValidAccountAdded(const Tp::AccountPtr &account)
 * {
 *     // do something with account
 * }
 *
 * void MyClass::onValidAccountRemoved(const Tp::AccountPtr &account)
 * {
 *     // do something with account
 * }
 *
 * \endcode
 *
 * You can also define your own filter using AccountManager::filterAccounts:
 *
 * \code
 *
 * void MyClass::onAccountManagerReady(Tp::PendingOperation *op)
 * {
 *     ...
 *
 *     QList<AccountFilterConstPtr> filters;
 *     AccountPropertyFilterPtr filter = AccountPropertyFilter::create();
 *     filter->addProperty(QLatin1String("protocolName"), QLatin1String("jabber"));
 *     filter->addProperty(QLatin1String("enabled"), true);
 *     filters.append(filter);
 *
 *     AccountSetPtr filteredAccountSet = am->filterAccounts(filter);
 *     // connect to AccountSet::accountAdded/accountRemoved signals
 *     QList<AccountPtr> accounts = filteredAccountSet->accounts();
 *     // do something with accounts
 *
 *     ....
 * }
 *
 * \endcode
 *
 * Note that for AccountSet to property work with AccountCapabilityFilter
 * objects, the feature Account::FeatureCapabilities need to be enabled in all
 * accounts return by the AccountManager passed as param in the constructor.
 * The easiest way to do this is to enable AccountManager feature
 * AccountManager::FeatureFilterByCapabilities.
 *
 * AccountSet can also be instantiated directly, but when doing it,
 * the AccountManager object passed as param in the constructor must be ready
 * for AccountSet properly work.
 */

/**
 * Construct a new AccountSet object.
 *
 * \param accountManager An account manager object used to filter accounts.
 *                       The account manager object must be ready.
 * \param filters The desired filter.
 */
AccountSet::AccountSet(const AccountManagerPtr &accountManager,
        const QList<AccountFilterConstPtr> &filters)
    : QObject(),
      mPriv(new Private(this, accountManager, filters))
{
}

/**
 * Construct a new AccountSet object.
 *
 * The \a filter must contain Account property names and values as map items.
 *
 * \param accountManager An account manager object used to filter accounts.
 *                       The account manager object must be ready.
 * \param filter The desired filter.
 */
AccountSet::AccountSet(const AccountManagerPtr &accountManager,
        const QVariantMap &filter)
    : QObject(),
      mPriv(new Private(this, accountManager, filter))
{
}

/**
 * Class destructor.
 */
AccountSet::~AccountSet()
{
}

/**
 * Return the account manager object used to filter accounts.
 *
 * \return The AccountManager object used to filter accounts.
 */
AccountManagerPtr AccountSet::accountManager() const
{
    return mPriv->accountManager;
}

/**
 * Return whether the filter returned by filter()/filters() is valid.
 *
 * If the filter is invalid accounts() will always return an empty list.
 *
 * This method is deprecated and should not be used in newly written code. Use
 * Filter::isValid() instead.
 *
 * \return \c true if the filter returned by filter()/filters() is valid, otherwise \c
 *         false.
 */
bool AccountSet::isFilterValid() const
{
    foreach (const AccountFilterConstPtr &filter, filters()) {
        if (!filter->isValid()) {
            return false;
        }
    }

    return true;
}

/**
 * Return the filter used to filter accounts.
 *
 * The filter is composed by Account property names and values as map items.
 *
 * This method is deprecated and should not be used in newly written code. Use
 * filters() instead.
 *
 * \return A QVariantMap representing the filter used to filter accounts.
 */
QVariantMap AccountSet::filter() const
{
    QVariantMap result;
    foreach (const AccountFilterConstPtr &filter, mPriv->filters) {
        const AccountPropertyFilterConstPtr filterObj =
            AccountPropertyFilterConstPtr::dynamicCast(filter);
        if (filterObj) {
            result.unite(filterObj->filter());
        }
    }
    return result;
}

/**
 * Return the filters used to filter accounts.
 *
 * \return A list of filter objects used to filter accounts.
 */
QList<AccountFilterConstPtr> AccountSet::filters() const
{
    return mPriv->filters;
}

/**
 * Return a list of account objects that match filters().
 *
 * \return A list of account objects that match filters().
 */
QList<AccountPtr> AccountSet::accounts() const
{
    return mPriv->accounts.values();
}

/**
 * \fn void AccountSet::accountAdded(const Tp::AccountPtr &account);
 *
 * This signal is emitted whenever an account that matches filters() is added to
 * this set.
 *
 * \param account The account that was added to this set.
 */

/**
 * \fn void AccountSet::accountRemoved(const Tp::AccountPtr &account);
 *
 * This signal is emitted whenever an account that matches filters() is removed
 * from this set.
 *
 * \param account The account that was removed from this set.
 */

void AccountSet::onNewAccount(const AccountPtr &account)
{
    mPriv->insertAccount(account);
}

void AccountSet::onAccountRemoved(const AccountPtr &account)
{
    mPriv->removeAccount(account);
}

void AccountSet::onAccountChanged(const AccountPtr &account)
{
    mPriv->filterAccount(account);
}

} // Tp
<commit_msg>AccountSet: Don't leave wrappers around when accounts are removed<commit_after>/*
 * This file is part of TelepathyQt4
 *
 * Copyright (C) 2010 Collabora Ltd. <http://www.collabora.co.uk/>
 * Copyright (C) 2010 Nokia Corporation
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include <TelepathyQt4/AccountSet>
#include "TelepathyQt4/account-set-internal.h"

#include "TelepathyQt4/_gen/account-set.moc.hpp"
#include "TelepathyQt4/_gen/account-set-internal.moc.hpp"

#include "TelepathyQt4/debug-internal.h"

#include <TelepathyQt4/Account>
#include <TelepathyQt4/AccountManager>
#include <TelepathyQt4/ConnectionCapabilities>
#include <TelepathyQt4/ConnectionManager>

namespace Tp
{

AccountSet::Private::Private(AccountSet *parent,
        const AccountManagerPtr &accountManager,
        const QList<AccountFilterConstPtr> &filters)
    : parent(parent),
      accountManager(accountManager),
      filters(filters),
      ready(false)
{
    init();
}

AccountSet::Private::Private(AccountSet *parent,
        const AccountManagerPtr &accountManager,
        const QVariantMap &filter)
    : parent(parent),
      accountManager(accountManager),
      ready(false)
{
    AccountPropertyFilterPtr filterObj = AccountPropertyFilter::create();
    for (QVariantMap::const_iterator i = filter.constBegin();
            i != filter.constEnd(); ++i) {
        filterObj->addProperty(i.key(), i.value());
    }
    filters.append(filterObj);
    init();
}

void AccountSet::Private::init()
{
    if (checkFilters()) {
        connectSignals();
        insertAccounts();
        ready = true;
    }
}

bool AccountSet::Private::checkFilters()
{
    foreach (const AccountFilterConstPtr &filter, filters) {
        if (!filter->isValid()) {
            return false;
        }
    }

    return true;
}

void AccountSet::Private::connectSignals()
{
    parent->connect(accountManager.data(),
            SIGNAL(newAccount(Tp::AccountPtr)),
            SLOT(onNewAccount(Tp::AccountPtr)));
}

void AccountSet::Private::insertAccounts()
{
    foreach (const Tp::AccountPtr &account, accountManager->allAccounts()) {
        insertAccount(account);
    }
}

void AccountSet::Private::insertAccount(const Tp::AccountPtr &account)
{
    QString accountPath = account->objectPath();
    Q_ASSERT(!wrappers.contains(accountPath));
    wrapAccount(account);
    filterAccount(account);
}

void AccountSet::Private::removeAccount(const Tp::AccountPtr &account)
{
    QString accountPath = account->objectPath();
    Q_ASSERT(wrappers.contains(accountPath));
    accounts.remove(accountPath);

    AccountWrapper *wrapper = wrappers.take(accountPath);
    wrapper->deleteLater();

    emit parent->accountRemoved(account);
}

void AccountSet::Private::wrapAccount(const AccountPtr &account)
{
    AccountWrapper *wrapper = new AccountWrapper(account, parent);
    parent->connect(wrapper,
            SIGNAL(accountRemoved(Tp::AccountPtr)),
            SLOT(onAccountRemoved(Tp::AccountPtr)));
    parent->connect(wrapper,
            SIGNAL(accountPropertyChanged(Tp::AccountPtr,QString)),
            SLOT(onAccountChanged(Tp::AccountPtr)));
    parent->connect(wrapper,
            SIGNAL(accountCapabilitiesChanged(Tp::AccountPtr,Tp::ConnectionCapabilities*)),
            SLOT(onAccountChanged(Tp::AccountPtr)));
    wrappers.insert(account->objectPath(), wrapper);
}

void AccountSet::Private::filterAccount(const AccountPtr &account)
{
    QString accountPath = account->objectPath();
    Q_ASSERT(wrappers.contains(accountPath));
    AccountWrapper *wrapper = wrappers[accountPath];

    /* account changed, let's check if it matches filter */
    if (accountMatchFilters(wrapper)) {
        if (!accounts.contains(account->objectPath())) {
            accounts.insert(account->objectPath(), account);
            if (ready) {
                emit parent->accountAdded(account);
            }
        }
    } else {
        if (accounts.contains(account->objectPath())) {
            accounts.remove(account->objectPath());
            if (ready) {
                emit parent->accountRemoved(account);
            }
        }
    }
}

bool AccountSet::Private::accountMatchFilters(AccountWrapper *wrapper)
{
    if (filters.isEmpty()) {
        return true;
    }

    AccountPtr account = wrapper->account();
    foreach (const AccountFilterConstPtr &filter, filters) {
        if (!filter->matches(account)) {
            return false;
        }
    }

    return true;
}

AccountSet::Private::AccountWrapper::AccountWrapper(
        const AccountPtr &account, QObject *parent)
    : QObject(parent),
      mAccount(account)
{
    connect(account.data(),
            SIGNAL(removed()),
            SLOT(onAccountRemoved()));
    connect(account.data(),
            SIGNAL(propertyChanged(QString)),
            SLOT(onAccountPropertyChanged(QString)));
    connect(account.data(),
            SIGNAL(capabilitiesChanged(Tp::ConnectionCapabilities*)),
            SLOT(onAccountCapalitiesChanged(Tp::ConnectionCapabilities*)));
}

AccountSet::Private::AccountWrapper::~AccountWrapper()
{
}

ConnectionCapabilities *AccountSet::Private::AccountWrapper::capabilities() const
{
    if (mAccount->haveConnection() &&
        mAccount->connection()->status() == Connection::StatusConnected) {
        return mAccount->connection()->capabilities();
    } else {
        if (mAccount->protocolInfo()) {
            return mAccount->protocolInfo()->capabilities();
        }
    }
    /* either we don't have a connected connection or
     * Account::FeatureProtocolInfo is not ready */
    return 0;
}

void AccountSet::Private::AccountWrapper::onAccountRemoved()
{
    emit accountRemoved(mAccount);
}

void AccountSet::Private::AccountWrapper::onAccountPropertyChanged(
        const QString &propertyName)
{
    emit accountPropertyChanged(mAccount, propertyName);
}

void AccountSet::Private::AccountWrapper::onAccountCapalitiesChanged(
        ConnectionCapabilities *caps)
{
    emit accountCapabilitiesChanged(mAccount, caps);
}

/**
 * \class AccountSet
 * \ingroup clientaccount
 * \headerfile TelepathyQt4/account-set.h <TelepathyQt4/AccountSet>
 *
 * \brief The AccountSet class provides an object representing a set of
 * Telepathy accounts filtered by a given criteria.
 *
 * AccountSet is automatically updated whenever accounts that match the given
 * criteria are added, removed or updated.
 *
 * \section account_set_usage_sec Usage
 *
 * \subsection account_set_create_sec Creating an AccountSet object
 *
 * The easiest way to create AccountSet objects is through AccountManager. One
 * can just use the AccountManager convenience methods such as
 * AccountManager::validAccountsSet() to get a set of account objects
 * representing valid accounts.
 *
 * For example:
 *
 * \code
 *
 * class MyClass : public QObject
 * {
 *     QOBJECT
 *
 * public:
 *     MyClass(QObject *parent = 0);
 *     ~MyClass() { }
 *
 * private Q_SLOTS:
 *     void onAccountManagerReady(Tp::PendingOperation *);
 *     void onValidAccountAdded(const Tp::AccountPtr &);
 *     void onValidAccountRemoved(const Tp::AccountPtr &);
 *
 * private:
 *     AccountManagerPtr am;
 *     AccountSetPtr validAccountsSet;
 * };
 *
 * MyClass::MyClass(QObject *parent)
 *     : QObject(parent)
 *       am(AccountManager::create())
 * {
 *     connect(am->becomeReady(),
 *             SIGNAL(finished(Tp::PendingOperation*)),
 *             SLOT(onAccountManagerReady(Tp::PendingOperation*)));
 * }
 *
 * void MyClass::onAccountManagerReady(Tp::PendingOperation *op)
 * {
 *     if (op->isError()) {
 *         qWarning() << "Account manager cannot become ready:" <<
 *             op->errorName() << "-" << op->errorMessage();
 *         return;
 *     }
 *
 *     validAccountsSet = am->validAccountsSet();
 *     connect(validAccountsSet.data(),
 *             SIGNAL(accountAdded(const Tp::AccountPtr &)),
 *             SLOT(onValidAccountAdded(const Tp::AccountPtr &)));
 *     connect(validAccountsSet.data(),
 *             SIGNAL(accountRemoved(const Tp::AccountPtr &)),
 *             SLOT(onValidAccountRemoved(const Tp::AccountPtr &)));
 *
 *     QList<AccountPtr> accounts = validAccountsSet->accounts();
 *     // do something with accounts
 * }
 *
 * void MyClass::onValidAccountAdded(const Tp::AccountPtr &account)
 * {
 *     // do something with account
 * }
 *
 * void MyClass::onValidAccountRemoved(const Tp::AccountPtr &account)
 * {
 *     // do something with account
 * }
 *
 * \endcode
 *
 * You can also define your own filter using AccountManager::filterAccounts:
 *
 * \code
 *
 * void MyClass::onAccountManagerReady(Tp::PendingOperation *op)
 * {
 *     ...
 *
 *     QList<AccountFilterConstPtr> filters;
 *     AccountPropertyFilterPtr filter = AccountPropertyFilter::create();
 *     filter->addProperty(QLatin1String("protocolName"), QLatin1String("jabber"));
 *     filter->addProperty(QLatin1String("enabled"), true);
 *     filters.append(filter);
 *
 *     AccountSetPtr filteredAccountSet = am->filterAccounts(filter);
 *     // connect to AccountSet::accountAdded/accountRemoved signals
 *     QList<AccountPtr> accounts = filteredAccountSet->accounts();
 *     // do something with accounts
 *
 *     ....
 * }
 *
 * \endcode
 *
 * Note that for AccountSet to property work with AccountCapabilityFilter
 * objects, the feature Account::FeatureCapabilities need to be enabled in all
 * accounts return by the AccountManager passed as param in the constructor.
 * The easiest way to do this is to enable AccountManager feature
 * AccountManager::FeatureFilterByCapabilities.
 *
 * AccountSet can also be instantiated directly, but when doing it,
 * the AccountManager object passed as param in the constructor must be ready
 * for AccountSet properly work.
 */

/**
 * Construct a new AccountSet object.
 *
 * \param accountManager An account manager object used to filter accounts.
 *                       The account manager object must be ready.
 * \param filters The desired filter.
 */
AccountSet::AccountSet(const AccountManagerPtr &accountManager,
        const QList<AccountFilterConstPtr> &filters)
    : QObject(),
      mPriv(new Private(this, accountManager, filters))
{
}

/**
 * Construct a new AccountSet object.
 *
 * The \a filter must contain Account property names and values as map items.
 *
 * \param accountManager An account manager object used to filter accounts.
 *                       The account manager object must be ready.
 * \param filter The desired filter.
 */
AccountSet::AccountSet(const AccountManagerPtr &accountManager,
        const QVariantMap &filter)
    : QObject(),
      mPriv(new Private(this, accountManager, filter))
{
}

/**
 * Class destructor.
 */
AccountSet::~AccountSet()
{
}

/**
 * Return the account manager object used to filter accounts.
 *
 * \return The AccountManager object used to filter accounts.
 */
AccountManagerPtr AccountSet::accountManager() const
{
    return mPriv->accountManager;
}

/**
 * Return whether the filter returned by filter()/filters() is valid.
 *
 * If the filter is invalid accounts() will always return an empty list.
 *
 * This method is deprecated and should not be used in newly written code. Use
 * Filter::isValid() instead.
 *
 * \return \c true if the filter returned by filter()/filters() is valid, otherwise \c
 *         false.
 */
bool AccountSet::isFilterValid() const
{
    foreach (const AccountFilterConstPtr &filter, filters()) {
        if (!filter->isValid()) {
            return false;
        }
    }

    return true;
}

/**
 * Return the filter used to filter accounts.
 *
 * The filter is composed by Account property names and values as map items.
 *
 * This method is deprecated and should not be used in newly written code. Use
 * filters() instead.
 *
 * \return A QVariantMap representing the filter used to filter accounts.
 */
QVariantMap AccountSet::filter() const
{
    QVariantMap result;
    foreach (const AccountFilterConstPtr &filter, mPriv->filters) {
        const AccountPropertyFilterConstPtr filterObj =
            AccountPropertyFilterConstPtr::dynamicCast(filter);
        if (filterObj) {
            result.unite(filterObj->filter());
        }
    }
    return result;
}

/**
 * Return the filters used to filter accounts.
 *
 * \return A list of filter objects used to filter accounts.
 */
QList<AccountFilterConstPtr> AccountSet::filters() const
{
    return mPriv->filters;
}

/**
 * Return a list of account objects that match filters().
 *
 * \return A list of account objects that match filters().
 */
QList<AccountPtr> AccountSet::accounts() const
{
    return mPriv->accounts.values();
}

/**
 * \fn void AccountSet::accountAdded(const Tp::AccountPtr &account);
 *
 * This signal is emitted whenever an account that matches filters() is added to
 * this set.
 *
 * \param account The account that was added to this set.
 */

/**
 * \fn void AccountSet::accountRemoved(const Tp::AccountPtr &account);
 *
 * This signal is emitted whenever an account that matches filters() is removed
 * from this set.
 *
 * \param account The account that was removed from this set.
 */

void AccountSet::onNewAccount(const AccountPtr &account)
{
    mPriv->insertAccount(account);
}

void AccountSet::onAccountRemoved(const AccountPtr &account)
{
    mPriv->removeAccount(account);
}

void AccountSet::onAccountChanged(const AccountPtr &account)
{
    mPriv->filterAccount(account);
}

} // Tp
<|endoftext|>


<commit_before>/* Copyright (C) 2008-2011 Xavier Pujol
   (C) 2015 Michael Walter.
   (C) 2016 Marc Stevens. (generic improvements, auxiliary solutions, subsolutions)
   (C) 2016 Guillaume Bonnoron. (CVP improvements)

   This file is part of fplll. fplll is free software: you
   can redistribute it and/or modify it under the terms of the GNU Lesser
   General Public License as published by the Free Software Foundation,
   either version 2.1 of the License, or (at your option) any later version.

   fplll 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 Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public License
   along with fplll. If not, see <http://www.gnu.org/licenses/>. */

#include "enumerate_base.h"

FPLLL_BEGIN_NAMESPACE

#ifdef FPLLL_WITH_RECURSIVE_ENUM
template <int kk, int kk_start, bool dualenum, bool findsubsols, bool enable_reset>
inline void EnumerationBase::enumerate_recursive(
    EnumerationBase::opts<kk, kk_start, dualenum, findsubsols, enable_reset>)
{
  enumf alphak  = x[kk] - center[kk];
  enumf newdist = partdist[kk] + alphak * alphak * rdiag[kk];

  if (!(newdist <= partdistbounds[kk]))
    return;
  ++nodes[kk];

  alpha[kk] = alphak;
  if (findsubsols && newdist < subsoldists[kk] && newdist != 0.0)
  {
    subsoldists[kk] = newdist;
    process_subsolution(kk, newdist);
  }

  if (kk == 0)
  {
    if (newdist > 0.0 || !is_svp)
      process_solution(newdist);
  }
  else if (enable_reset &&
           kk < reset_depth)  // in CVP, below the max GS vector, we reset the partial distance
  {
    reset(newdist, kk);
    return;
  }
  else
  {
    partdist[kk - 1] = newdist;
    if (dualenum)
    {
      for (int j = center_partsum_begin[kk]; j > kk - 1; --j)
        center_partsums[kk - 1][j] = center_partsums[kk - 1][j + 1] - alpha[j] * mut[kk - 1][j];
    }
    else
    {
      for (int j = center_partsum_begin[kk]; j > kk - 1; --j)
        center_partsums[kk - 1][j] = center_partsums[kk - 1][j + 1] - x[j] * mut[kk - 1][j];
    }
    if (center_partsum_begin[kk] > center_partsum_begin[kk - 1])
      center_partsum_begin[kk - 1] = center_partsum_begin[kk];
    center_partsum_begin[kk] = kk;
    center[kk - 1]           = center_partsums[kk - 1][kk];
    roundto(x[kk - 1], center[kk - 1]);
    dx[kk - 1] = ddx[kk - 1] = (((int)(center[kk - 1] >= x[kk - 1]) & 1) << 1) - 1;
  }

  while (true)
  {
    FPLLL_TRACE("Level k=" << kk << " dist_k=" << partdist[kk] << " x_k=" << x[kk]
                           << " newdist=" << newdist << " partdistbounds_k=" << partdistbounds[kk]);
    enumerate_recursive(opts<kk - 1, kk_start, dualenum, findsubsols, enable_reset>());

    if (partdist[kk] != 0.0)
    {
      x[kk] += dx[kk];
      ddx[kk] = -ddx[kk];
      dx[kk]  = ddx[kk] - dx[kk];

      enumf alphak2  = x[kk] - center[kk];
      enumf newdist2 = partdist[kk] + alphak2 * alphak2 * rdiag[kk];
      if (!(newdist2 <= partdistbounds[kk]))
        return;
      ++nodes[kk];
      alpha[kk] = alphak2;
      if (kk == 0)
      {
        if (newdist2 > 0.0 || !is_svp)
          process_solution(newdist2);
      }
      else
      {
        partdist[kk - 1] = newdist2;
        if (dualenum)
          center_partsums[kk - 1][kk - 1 + 1] =
              center_partsums[kk - 1][kk - 1 + 1 + 1] - alpha[kk - 1 + 1] * mut[kk - 1][kk - 1 + 1];
        else
          center_partsums[kk - 1][kk - 1 + 1] =
              center_partsums[kk - 1][kk - 1 + 1 + 1] - x[kk - 1 + 1] * mut[kk - 1][kk - 1 + 1];
        if (kk > center_partsum_begin[kk - 1])
          center_partsum_begin[kk - 1] = kk;
        center[kk - 1] = center_partsums[kk - 1][kk - 1 + 1];
        roundto(x[kk - 1], center[kk - 1]);
        dx[kk - 1] = ddx[kk - 1] = (((int)(center[kk - 1] >= x[kk - 1]) & 1) << 1) - 1;
      }
    }
    else
    {
      ++x[kk];

      enumf alphak2  = x[kk] - center[kk];
      enumf newdist2 = partdist[kk] + alphak2 * alphak2 * rdiag[kk];
      if (!(newdist2 <= partdistbounds[kk]))
        return;
      ++nodes[kk];
      alpha[kk] = alphak2;
      if (kk == 0)
      {
        if (newdist2 > 0.0 || !is_svp)
          process_solution(newdist2);
      }
      else
      {
        partdist[kk - 1] = newdist2;
        if (dualenum)
          center_partsums[kk - 1][kk - 1 + 1] =
              center_partsums[kk - 1][kk - 1 + 1 + 1] - alpha[kk - 1 + 1] * mut[kk - 1][kk - 1 + 1];
        else
          center_partsums[kk - 1][kk - 1 + 1] =
              center_partsums[kk - 1][kk - 1 + 1 + 1] - x[kk - 1 + 1] * mut[kk - 1][kk - 1 + 1];
        if (kk > center_partsum_begin[kk - 1])
          center_partsum_begin[kk - 1] = kk;
        center[kk - 1] = center_partsums[kk - 1][kk - 1 + 1];
        roundto(x[kk - 1], center[kk - 1]);
        dx[kk - 1] = ddx[kk - 1] = (((int)(center[kk - 1] >= x[kk - 1]) & 1) << 1) - 1;
      }
    }
  }
}

#define ENUM_TABLE_FILL8(a)                                                                        \
  &EnumerationBase::enumerate_recursive_wrapper<a + 0, dualenum, findsubsols, enable_reset>,       \
      &EnumerationBase::enumerate_recursive_wrapper<a + 1, dualenum, findsubsols, enable_reset>,   \
      &EnumerationBase::enumerate_recursive_wrapper<a + 2, dualenum, findsubsols, enable_reset>,   \
      &EnumerationBase::enumerate_recursive_wrapper<a + 3, dualenum, findsubsols, enable_reset>,   \
      &EnumerationBase::enumerate_recursive_wrapper<a + 4, dualenum, findsubsols, enable_reset>,   \
      &EnumerationBase::enumerate_recursive_wrapper<a + 5, dualenum, findsubsols, enable_reset>,   \
      &EnumerationBase::enumerate_recursive_wrapper<a + 6, dualenum, findsubsols, enable_reset>,   \
      &EnumerationBase::enumerate_recursive_wrapper<a + 7, dualenum, findsubsols, enable_reset>
#define ENUM_TABLE_FILL64(a)                                                                       \
  ENUM_TABLE_FILL8(a)                                                                              \
  , ENUM_TABLE_FILL8(a + 8), ENUM_TABLE_FILL8(a + 16), ENUM_TABLE_FILL8(a + 24),                   \
      ENUM_TABLE_FILL8(a + 32), ENUM_TABLE_FILL8(a + 40), ENUM_TABLE_FILL8(a + 48),                \
      ENUM_TABLE_FILL8(a + 56)
#define ENUM_TABLE_FILL256(a)                                                                      \
  ENUM_TABLE_FILL64(a)                                                                             \
  , ENUM_TABLE_FILL64(a + 64), ENUM_TABLE_FILL64(a + 128), ENUM_TABLE_FILL64(a + 192)

template <bool dualenum, bool findsubsols, bool enable_reset>
inline void EnumerationBase::enumerate_recursive_dispatch(int kk)
{
  typedef void (EnumerationBase::*enum_recur_type)();
  static const enum_recur_type lookup[] = {
      ENUM_TABLE_FILL256(0),    ENUM_TABLE_FILL256(256),  ENUM_TABLE_FILL256(512),
      ENUM_TABLE_FILL256(768),  ENUM_TABLE_FILL256(1024), ENUM_TABLE_FILL256(1280),
      ENUM_TABLE_FILL256(1536), ENUM_TABLE_FILL256(1792),
  };
  (this->*lookup[kk])();
}

#endif

template <bool dualenum, bool findsubsols, bool enable_reset> void EnumerationBase::enumerate_loop()
{
  if (k >= k_end)
    return;

  center_partsum_begin[0] = 0;
  for (int i = 0; i < k_end; ++i)
  {
    center_partsum_begin[i + 1] = k_end - 1;
    center_partsums[i][k_end]   = center_partsum[i];
  }

  partdist[k_end] = 0.0;  // needed to make next_pos_up() work properly

  nodes[k_end] -= k_end - k;
  k = k_end - 1;

#ifdef FPLLL_WITH_RECURSIVE_ENUM
  enumerate_recursive_dispatch<dualenum, findsubsols, enable_reset>(k);
  return;
#endif

  finished = false;
  while (!finished)
  {
    enumf alphak  = x[k] - center[k];
    enumf newdist = partdist[k] + alphak * alphak * rdiag[k];
    FPLLL_TRACE("Level k=" << k << " dist_k=" << partdist[k] << " x_k=" << x[k]
                           << " newdist=" << newdist << " partdistbounds_k=" << partdistbounds[k]);
    if (newdist <= partdistbounds[k])
    {
      ++nodes[k];
      alpha[k] = alphak;
      if (findsubsols && newdist < subsoldists[k] && newdist != 0.0)
      {
        subsoldists[k] = newdist;
        process_subsolution(k, newdist);
      }
      --k;
      if (k < 0)
      {
        if (newdist > 0.0 || !is_svp)
          process_solution(newdist);
        finished = !next_pos_up();
        continue;
      }
      if (enable_reset &&
          k < reset_depth)  // in CVP, below the max GS vector, we reset the partial distance
      {
        reset(newdist, k);
        finished = !next_pos_up();
        continue;
      }
      if (dualenum)
      {
        for (int j = center_partsum_begin[k + 1]; j > k; --j)
          center_partsums[k][j] = center_partsums[k][j + 1] - alpha[j] * mut[k][j];
      }
      else
      {
        for (int j = center_partsum_begin[k + 1]; j > k; --j)
          center_partsums[k][j] = center_partsums[k][j + 1] - x[j] * mut[k][j];
      }
      center_partsum_begin[k]     = max(center_partsum_begin[k], center_partsum_begin[k + 1]);
      center_partsum_begin[k + 1] = k + 1;

      enumf newcenter = center_partsums[k][k + 1];
      center[k]       = newcenter;
      partdist[k]     = newdist;
      roundto(x[k], newcenter);
      dx[k] = ddx[k] = (((int)(newcenter >= x[k]) & 1) << 1) - 1;
    }
    else
    {
      finished = !next_pos_up();
    }
  }
}

template void EnumerationBase::enumerate_loop<false, false, true>();
template void EnumerationBase::enumerate_loop<false, true, true>();
template void EnumerationBase::enumerate_loop<false, false, false>();
template void EnumerationBase::enumerate_loop<false, true, false>();
template void EnumerationBase::enumerate_loop<true, false, false>();
template void EnumerationBase::enumerate_loop<true, true, false>();

FPLLL_END_NAMESPACE
<commit_msg>Adjust per level, rather than on k_end<commit_after>/* Copyright (C) 2008-2011 Xavier Pujol
   (C) 2015 Michael Walter.
   (C) 2016 Marc Stevens. (generic improvements, auxiliary solutions, subsolutions)
   (C) 2016 Guillaume Bonnoron. (CVP improvements)

   This file is part of fplll. fplll is free software: you
   can redistribute it and/or modify it under the terms of the GNU Lesser
   General Public License as published by the Free Software Foundation,
   either version 2.1 of the License, or (at your option) any later version.

   fplll 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 Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public License
   along with fplll. If not, see <http://www.gnu.org/licenses/>. */

#include "enumerate_base.h"

FPLLL_BEGIN_NAMESPACE

#ifdef FPLLL_WITH_RECURSIVE_ENUM
template <int kk, int kk_start, bool dualenum, bool findsubsols, bool enable_reset>
inline void EnumerationBase::enumerate_recursive(
    EnumerationBase::opts<kk, kk_start, dualenum, findsubsols, enable_reset>)
{
  enumf alphak  = x[kk] - center[kk];
  enumf newdist = partdist[kk] + alphak * alphak * rdiag[kk];

  if (!(newdist <= partdistbounds[kk]))
    return;
  ++nodes[kk];

  alpha[kk] = alphak;
  if (findsubsols && newdist < subsoldists[kk] && newdist != 0.0)
  {
    subsoldists[kk] = newdist;
    process_subsolution(kk, newdist);
  }

  if (kk == 0)
  {
    if (newdist > 0.0 || !is_svp)
      process_solution(newdist);
  }
  else if (enable_reset &&
           kk < reset_depth)  // in CVP, below the max GS vector, we reset the partial distance
  {
    reset(newdist, kk);
    return;
  }
  else
  {
    partdist[kk - 1] = newdist;
    if (dualenum)
    {
      for (int j = center_partsum_begin[kk]; j > kk - 1; --j)
        center_partsums[kk - 1][j] = center_partsums[kk - 1][j + 1] - alpha[j] * mut[kk - 1][j];
    }
    else
    {
      for (int j = center_partsum_begin[kk]; j > kk - 1; --j)
        center_partsums[kk - 1][j] = center_partsums[kk - 1][j + 1] - x[j] * mut[kk - 1][j];
    }
    if (center_partsum_begin[kk] > center_partsum_begin[kk - 1])
      center_partsum_begin[kk - 1] = center_partsum_begin[kk];
    center_partsum_begin[kk] = kk;
    center[kk - 1]           = center_partsums[kk - 1][kk];
    roundto(x[kk - 1], center[kk - 1]);
    dx[kk - 1] = ddx[kk - 1] = (((int)(center[kk - 1] >= x[kk - 1]) & 1) << 1) - 1;
  }

  while (true)
  {
    FPLLL_TRACE("Level k=" << kk << " dist_k=" << partdist[kk] << " x_k=" << x[kk]
                           << " newdist=" << newdist << " partdistbounds_k=" << partdistbounds[kk]);
    enumerate_recursive(opts<kk - 1, kk_start, dualenum, findsubsols, enable_reset>());

    if (partdist[kk] != 0.0)
    {
      x[kk] += dx[kk];
      ddx[kk] = -ddx[kk];
      dx[kk]  = ddx[kk] - dx[kk];

      enumf alphak2  = x[kk] - center[kk];
      enumf newdist2 = partdist[kk] + alphak2 * alphak2 * rdiag[kk];
      if (!(newdist2 <= partdistbounds[kk]))
        return;
      ++nodes[kk];
      alpha[kk] = alphak2;
      if (kk == 0)
      {
        if (newdist2 > 0.0 || !is_svp)
          process_solution(newdist2);
      }
      else
      {
        partdist[kk - 1] = newdist2;
        if (dualenum)
          center_partsums[kk - 1][kk - 1 + 1] =
              center_partsums[kk - 1][kk - 1 + 1 + 1] - alpha[kk - 1 + 1] * mut[kk - 1][kk - 1 + 1];
        else
          center_partsums[kk - 1][kk - 1 + 1] =
              center_partsums[kk - 1][kk - 1 + 1 + 1] - x[kk - 1 + 1] * mut[kk - 1][kk - 1 + 1];
        if (kk > center_partsum_begin[kk - 1])
          center_partsum_begin[kk - 1] = kk;
        center[kk - 1] = center_partsums[kk - 1][kk - 1 + 1];
        roundto(x[kk - 1], center[kk - 1]);
        dx[kk - 1] = ddx[kk - 1] = (((int)(center[kk - 1] >= x[kk - 1]) & 1) << 1) - 1;
      }
    }
    else
    {
      ++x[kk];

      enumf alphak2  = x[kk] - center[kk];
      enumf newdist2 = partdist[kk] + alphak2 * alphak2 * rdiag[kk];
      if (!(newdist2 <= partdistbounds[kk]))
        return;
      ++nodes[kk];
      alpha[kk] = alphak2;
      if (kk == 0)
      {
        if (newdist2 > 0.0 || !is_svp)
          process_solution(newdist2);
      }
      else
      {
        partdist[kk - 1] = newdist2;
        if (dualenum)
          center_partsums[kk - 1][kk - 1 + 1] =
              center_partsums[kk - 1][kk - 1 + 1 + 1] - alpha[kk - 1 + 1] * mut[kk - 1][kk - 1 + 1];
        else
          center_partsums[kk - 1][kk - 1 + 1] =
              center_partsums[kk - 1][kk - 1 + 1 + 1] - x[kk - 1 + 1] * mut[kk - 1][kk - 1 + 1];
        if (kk > center_partsum_begin[kk - 1])
          center_partsum_begin[kk - 1] = kk;
        center[kk - 1] = center_partsums[kk - 1][kk - 1 + 1];
        roundto(x[kk - 1], center[kk - 1]);
        dx[kk - 1] = ddx[kk - 1] = (((int)(center[kk - 1] >= x[kk - 1]) & 1) << 1) - 1;
      }
    }
  }
}

#define ENUM_TABLE_FILL8(a)                                                                        \
  &EnumerationBase::enumerate_recursive_wrapper<a + 0, dualenum, findsubsols, enable_reset>,       \
      &EnumerationBase::enumerate_recursive_wrapper<a + 1, dualenum, findsubsols, enable_reset>,   \
      &EnumerationBase::enumerate_recursive_wrapper<a + 2, dualenum, findsubsols, enable_reset>,   \
      &EnumerationBase::enumerate_recursive_wrapper<a + 3, dualenum, findsubsols, enable_reset>,   \
      &EnumerationBase::enumerate_recursive_wrapper<a + 4, dualenum, findsubsols, enable_reset>,   \
      &EnumerationBase::enumerate_recursive_wrapper<a + 5, dualenum, findsubsols, enable_reset>,   \
      &EnumerationBase::enumerate_recursive_wrapper<a + 6, dualenum, findsubsols, enable_reset>,   \
      &EnumerationBase::enumerate_recursive_wrapper<a + 7, dualenum, findsubsols, enable_reset>
#define ENUM_TABLE_FILL64(a)                                                                       \
  ENUM_TABLE_FILL8(a)                                                                              \
  , ENUM_TABLE_FILL8(a + 8), ENUM_TABLE_FILL8(a + 16), ENUM_TABLE_FILL8(a + 24),                   \
      ENUM_TABLE_FILL8(a + 32), ENUM_TABLE_FILL8(a + 40), ENUM_TABLE_FILL8(a + 48),                \
      ENUM_TABLE_FILL8(a + 56)
#define ENUM_TABLE_FILL256(a)                                                                      \
  ENUM_TABLE_FILL64(a)                                                                             \
  , ENUM_TABLE_FILL64(a + 64), ENUM_TABLE_FILL64(a + 128), ENUM_TABLE_FILL64(a + 192)

template <bool dualenum, bool findsubsols, bool enable_reset>
inline void EnumerationBase::enumerate_recursive_dispatch(int kk)
{
  typedef void (EnumerationBase::*enum_recur_type)();
  static const enum_recur_type lookup[] = {
      ENUM_TABLE_FILL256(0),    ENUM_TABLE_FILL256(256),  ENUM_TABLE_FILL256(512),
      ENUM_TABLE_FILL256(768),  ENUM_TABLE_FILL256(1024), ENUM_TABLE_FILL256(1280),
      ENUM_TABLE_FILL256(1536), ENUM_TABLE_FILL256(1792),
  };
  (this->*lookup[kk])();
}

#endif

template <bool dualenum, bool findsubsols, bool enable_reset> void EnumerationBase::enumerate_loop()
{
  if (k >= k_end)
    return;

  center_partsum_begin[0] = 0;
  for (int i = 0; i < k_end; ++i)
  {
    center_partsum_begin[i + 1] = k_end - 1;
    center_partsums[i][k_end]   = center_partsum[i];
  }

  partdist[k_end] = 0.0;  // needed to make next_pos_up() work properly

  /* The next few lines provide compatibility between the various different enumerators in fplll.
   * Because the recursive enumerator needs to start at one level down from the last position, we
   * decrement it. However, this has the tendency of screwing up the node count by a factor of k
   * (which, although asymptotically shouldn't matter, practically it will). In particular, it has
   * the property of meaning we count an extra node per level (in k+1....k_end-1) in the initial
   * descent. You can think of this as fplll just Babai lifting from k_end->k. However, clearly this
   * may screw up the total - so we adjust this. For more info, see
   * https://github.com/fplll/fplll/pull/442.
   *
   * Note: this adjustment does no checks on the nodes array. This will cause wrap arounds if the
   * values are 0. But, adding to these later will reset them, so this should  not matter in
   * practice.
   */

  for (int i = k + 1; i < k_end; i++)
  {
    nodes[i]--;
  }

  k = k_end - 1;

#ifdef FPLLL_WITH_RECURSIVE_ENUM
  enumerate_recursive_dispatch<dualenum, findsubsols, enable_reset>(k);
  return;
#endif

  finished = false;
  while (!finished)
  {
    enumf alphak  = x[k] - center[k];
    enumf newdist = partdist[k] + alphak * alphak * rdiag[k];
    FPLLL_TRACE("Level k=" << k << " dist_k=" << partdist[k] << " x_k=" << x[k]
                           << " newdist=" << newdist << " partdistbounds_k=" << partdistbounds[k]);
    if (newdist <= partdistbounds[k])
    {
      ++nodes[k];
      alpha[k] = alphak;
      if (findsubsols && newdist < subsoldists[k] && newdist != 0.0)
      {
        subsoldists[k] = newdist;
        process_subsolution(k, newdist);
      }
      --k;
      if (k < 0)
      {
        if (newdist > 0.0 || !is_svp)
          process_solution(newdist);
        finished = !next_pos_up();
        continue;
      }
      if (enable_reset &&
          k < reset_depth)  // in CVP, below the max GS vector, we reset the partial distance
      {
        reset(newdist, k);
        finished = !next_pos_up();
        continue;
      }
      if (dualenum)
      {
        for (int j = center_partsum_begin[k + 1]; j > k; --j)
          center_partsums[k][j] = center_partsums[k][j + 1] - alpha[j] * mut[k][j];
      }
      else
      {
        for (int j = center_partsum_begin[k + 1]; j > k; --j)
          center_partsums[k][j] = center_partsums[k][j + 1] - x[j] * mut[k][j];
      }
      center_partsum_begin[k]     = max(center_partsum_begin[k], center_partsum_begin[k + 1]);
      center_partsum_begin[k + 1] = k + 1;

      enumf newcenter = center_partsums[k][k + 1];
      center[k]       = newcenter;
      partdist[k]     = newdist;
      roundto(x[k], newcenter);
      dx[k] = ddx[k] = (((int)(newcenter >= x[k]) & 1) << 1) - 1;
    }
    else
    {
      finished = !next_pos_up();
    }
  }
}

template void EnumerationBase::enumerate_loop<false, false, true>();
template void EnumerationBase::enumerate_loop<false, true, true>();
template void EnumerationBase::enumerate_loop<false, false, false>();
template void EnumerationBase::enumerate_loop<false, true, false>();
template void EnumerationBase::enumerate_loop<true, false, false>();
template void EnumerationBase::enumerate_loop<true, true, false>();

FPLLL_END_NAMESPACE
<|endoftext|>


<commit_before>// Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.

#include "cefsimple/simple_app.h"

#include <string>

#include "cefsimple/simple_handler.h"
#include "include/cef_browser.h"
#include "include/cef_command_line.h"
#include "include/wrapper/cef_helpers.h"
#include <shlwapi.h>
#include <fstream>

HWND SimpleApp::gameWindow = 0;

SimpleApp::SimpleApp() {
}

void GetDesktopResolution(int& horizontal, int& vertical)
{
	RECT desktop;
	const HWND hDesktop = GetDesktopWindow();
	GetWindowRect(hDesktop, &desktop);
	horizontal = desktop.right;
	vertical = desktop.bottom;
}

void SimpleApp::OnContextInitialized() {
  CEF_REQUIRE_UI_THREAD();

  // Information used when creating the native window.
  CefWindowInfo window_info;

#if defined(OS_WIN)
  // On Windows we need to specify certain flags that will be passed to
  // CreateWindowEx().
  window_info.SetAsPopup(NULL, "Custom Menu");
#endif

  int horizontal, vertical;
  GetDesktopResolution(horizontal, vertical);
  window_info.width = horizontal - 100;
  window_info.height = vertical - 100;

  int xPos = (horizontal - window_info.width) / 2;
  int yPos = (vertical - window_info.height) / 2;
  window_info.x = xPos;
  window_info.y = yPos;

  // SimpleHandler implements browser-level callbacks.
  CefRefPtr<SimpleHandler> handler(new SimpleHandler());

  // Specify CEF browser settings here.
  CefBrowserSettings browser_settings;

  wchar_t pathToOurDirectory[260];
  GetModuleFileName(NULL, pathToOurDirectory, 260);
  PathRemoveFileSpec(pathToOurDirectory);

  std::wstring path(pathToOurDirectory);
  path.append(L"\\mods\\menus\\default");

  CefRefPtr<CefCookieManager> manager = CefCookieManager::GetGlobalManager(NULL);
  manager->SetStoragePath(path, true, NULL);

  CefRefPtr<CefCommandLine> command_line = CefCommandLine::GetGlobalCommandLine();

  std::wstring url = L"http://thefeeltrain.github.io/";

  std::wstring urlString = command_line->GetSwitchValue("url").ToWString();
  if (!urlString.empty())
  {
	  url = urlString;
  }

  std::string hwndString = command_line->GetSwitchValue("hwnd").ToString();
  if (!hwndString.empty())
  {
	  gameWindow = (HWND)stoi(hwndString);
	  ShowWindow(gameWindow, SW_HIDE);
  }
  else
  {
	  CefShutdown();
  }

  // Create the first browser window.
  CefBrowserHost::CreateBrowser(window_info, handler.get(), url,
	  browser_settings, NULL);
}<commit_msg>Change URL<commit_after>// Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.

#include "cefsimple/simple_app.h"

#include <string>

#include "cefsimple/simple_handler.h"
#include "include/cef_browser.h"
#include "include/cef_command_line.h"
#include "include/wrapper/cef_helpers.h"
#include <shlwapi.h>
#include <fstream>

HWND SimpleApp::gameWindow = 0;

SimpleApp::SimpleApp() {
}

void GetDesktopResolution(int& horizontal, int& vertical)
{
	RECT desktop;
	const HWND hDesktop = GetDesktopWindow();
	GetWindowRect(hDesktop, &desktop);
	horizontal = desktop.right;
	vertical = desktop.bottom;
}

void SimpleApp::OnContextInitialized() {
  CEF_REQUIRE_UI_THREAD();

  // Information used when creating the native window.
  CefWindowInfo window_info;

#if defined(OS_WIN)
  // On Windows we need to specify certain flags that will be passed to
  // CreateWindowEx().
  window_info.SetAsPopup(NULL, "Custom Menu");
#endif

  int horizontal, vertical;
  GetDesktopResolution(horizontal, vertical);
  window_info.width = horizontal - 100;
  window_info.height = vertical - 100;

  int xPos = (horizontal - window_info.width) / 2;
  int yPos = (vertical - window_info.height) / 2;
  window_info.x = xPos;
  window_info.y = yPos;

  // SimpleHandler implements browser-level callbacks.
  CefRefPtr<SimpleHandler> handler(new SimpleHandler());

  // Specify CEF browser settings here.
  CefBrowserSettings browser_settings;

  wchar_t pathToOurDirectory[260];
  GetModuleFileName(NULL, pathToOurDirectory, 260);
  PathRemoveFileSpec(pathToOurDirectory);

  std::wstring path(pathToOurDirectory);
  path.append(L"\\mods\\menus\\default");

  CefRefPtr<CefCookieManager> manager = CefCookieManager::GetGlobalManager(NULL);
  manager->SetStoragePath(path, true, NULL);

  CefRefPtr<CefCommandLine> command_line = CefCommandLine::GetGlobalCommandLine();

  std::wstring url = L"http://eldewrito.github.io/menu/";

  std::wstring urlString = command_line->GetSwitchValue("url").ToWString();
  if (!urlString.empty())
  {
	  url = urlString;
  }

  std::string hwndString = command_line->GetSwitchValue("hwnd").ToString();
  if (!hwndString.empty())
  {
	  gameWindow = (HWND)stoi(hwndString);
	  ShowWindow(gameWindow, SW_HIDE);
  }
  else
  {
	  CefShutdown();
  }

  // Create the first browser window.
  CefBrowserHost::CreateBrowser(window_info, handler.get(), url,
	  browser_settings, NULL);
}<|endoftext|>