<commit_before>/*
Copyright (c) 2017, Vlad Meșco
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this
  list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice,
  this list of conditions and the following disclaimer in the documentation
  and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "model.h"
#include "window.h"

#include <FL/Fl.H>

#include <algorithm>
#include <cassert>

Schema drumSchemas[] = {
    /* Basic Drum */
    {
        "Mono",
        {
            { "path", Schema::STRING },
            { "volume", Schema::NUMBER },
        },
    },
    /* Stereo Drum */
    {
        "Stereo",
        {
            { "path", Schema::STRING },
            { "volume", Schema::NUMBER },
            { "stereo", Schema::READ_ONLY_STRING, {
                                                      { "pan", Schema::STUB },
                                                  }},
            { "params", Schema::SUBSCHEMA, {
                                               { "pan", Schema::NUMBER },
                                           }},
        },
    },
    /* Chorus Drum */
    {
        "Chorus",
        {
            { "path", Schema::STRING },
            { "volume", Schema::NUMBER },
            { "stereo", Schema::READ_ONLY_STRING, {
                                                      { "chorus", Schema::STUB },
                                                  }},
            { "params", Schema::SUBSCHEMA, {
                                               { "pan", Schema::NUMBER },
                                               { "delay", Schema::NUMBER },
                                               { "amount", Schema::NUMBER },
                                               { "speed", Schema::NUMBER },
                                               { "depth", Schema::NUMBER },
                                           }},
        },
    },
};

Schema whatSchemas[] = {
    {
        "Standard",
        {
            { "bpm", Schema::NUMBER },
        },
    },
};

std::list<Vindow> windows;

std::shared_ptr<Model> load_model(std::string path)
{
    return {};
}

void save_model(std::shared_ptr<Model> m)
{
}

bool is_any_model_dirty()
{
    return std::any_of(windows.begin(), windows.end(), [](Vindow& w) -> bool {
                return w.GetModel()->dirty;
            });
}

void create_window(std::shared_ptr<Model> m)
{
    windows.emplace_back(m);
    assert(m);
    assert(windows.back().GetModel());
    windows.back().show();
}

void destroy_window(Vindow* whom)
{
    auto found = std::find_if(windows.begin(), windows.end(), [whom](Vindow const& w) -> bool {
                return &w == whom;
            });
    if(found == windows.end())
    {
        fprintf(stderr, "window not found... not abort()-ing to not lose data, but it should be fixed");
        return;
    }
    windows.erase(found);
}

int main(int argc, char* argv[])
{
#if 1
    /* test code */

    std::shared_ptr<Model> m(new Model());
    m->whos.push_back({
                "kick",
                &drumSchemas[0],
                {
                    { "path", "kick.wav" },
                    { "volume", "100" },
                }
            });
    m->whats.push_back({
                "A1",
                &whatSchemas[0],
                m->columns.begin(),
                m->columns.begin()
            });
    m->output.rows.emplace_back();
    m->dirty = true;
    create_window(m);

    return Fl::run();
#endif
}
<commit_msg>done testing the dirty flag for now<commit_after>/*
Copyright (c) 2017, Vlad Meșco
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this
  list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice,
  this list of conditions and the following disclaimer in the documentation
  and/or other materials provided with the distribution.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "model.h"
#include "window.h"

#include <FL/Fl.H>

#include <algorithm>
#include <cassert>

Schema drumSchemas[] = {
    /* Basic Drum */
    {
        "Mono",
        {
            { "path", Schema::STRING },
            { "volume", Schema::NUMBER },
        },
    },
    /* Stereo Drum */
    {
        "Stereo",
        {
            { "path", Schema::STRING },
            { "volume", Schema::NUMBER },
            { "stereo", Schema::READ_ONLY_STRING, {
                                                      { "pan", Schema::STUB },
                                                  }},
            { "params", Schema::SUBSCHEMA, {
                                               { "pan", Schema::NUMBER },
                                           }},
        },
    },
    /* Chorus Drum */
    {
        "Chorus",
        {
            { "path", Schema::STRING },
            { "volume", Schema::NUMBER },
            { "stereo", Schema::READ_ONLY_STRING, {
                                                      { "chorus", Schema::STUB },
                                                  }},
            { "params", Schema::SUBSCHEMA, {
                                               { "pan", Schema::NUMBER },
                                               { "delay", Schema::NUMBER },
                                               { "amount", Schema::NUMBER },
                                               { "speed", Schema::NUMBER },
                                               { "depth", Schema::NUMBER },
                                           }},
        },
    },
};

Schema whatSchemas[] = {
    {
        "Standard",
        {
            { "bpm", Schema::NUMBER },
        },
    },
};

std::list<Vindow> windows;

std::shared_ptr<Model> load_model(std::string path)
{
    return {};
}

void save_model(std::shared_ptr<Model> m)
{
}

bool is_any_model_dirty()
{
    return std::any_of(windows.begin(), windows.end(), [](Vindow& w) -> bool {
                return w.GetModel()->dirty;
            });
}

void create_window(std::shared_ptr<Model> m)
{
    windows.emplace_back(m);
    assert(m);
    assert(windows.back().GetModel());
    windows.back().show();
}

void destroy_window(Vindow* whom)
{
    auto found = std::find_if(windows.begin(), windows.end(), [whom](Vindow const& w) -> bool {
                return &w == whom;
            });
    if(found == windows.end())
    {
        fprintf(stderr, "window not found... not abort()-ing to not lose data, but it should be fixed");
        return;
    }
    windows.erase(found);
}

int main(int argc, char* argv[])
{
#if 1
    /* test code */

    std::shared_ptr<Model> m(new Model());
    m->whos.push_back({
                "kick",
                &drumSchemas[0],
                {
                    { "path", "kick.wav" },
                    { "volume", "100" },
                }
            });
    m->whats.push_back({
                "A1",
                &whatSchemas[0],
                m->columns.begin(),
                m->columns.begin()
            });
    m->output.rows.emplace_back();
    create_window(m);

    return Fl::run();
#endif
}
<|endoftext|>


<commit_before>#ifndef POINTS_HPP_
#define POINTS_HPP_

#include <vector>

typedef unsigned long long int Int;
typedef std::vector<Int> Ints;

struct Point {
    int col;
    int row;
};

struct Points {
    Point p1;
    Point p2;
};

#endif

<commit_msg>Use vector<int> to save game desk's state<commit_after>#ifndef POINTS_HPP_
#define POINTS_HPP_

#include <vector>

typedef std::vector<int> Ints;

struct Point {
    int col;
    int row;
};

struct Points {
    Point p1;
    Point p2;
};

#endif

<|endoftext|>


<commit_before>#include "SDL/SDL.h"
#include "SDL/SDL_ttf.h"
#include "SDL/SDL_gfxPrimitives.h"
#include <vector>
#include <iostream>
using namespace std;

// ----> GUI FRAME
class GuiFrame {
  protected:
    Uint8 bpp;
    SDL_Surface *frame;
    SDL_Rect frameRect;
    SDL_Rect innerFrameRect;
    bool hasFrame;
    bool hasBorder;
    Uint8 borderWidth;
    struct stGuiFrameBorderColor {
      Uint8 r;
      Uint8 g;
      Uint8 b;
    } borderColor;
  public:
    GuiFrame(Uint8);
    void set(Uint16, Uint16, Uint16, Uint16);
    void setBorder(Uint8, Uint8, Uint8, Uint8);
    SDL_Rect *getRect();
    SDL_Rect *getInnerRect();
    SDL_Surface *getSurface();
    void bgFill(Uint8, Uint8, Uint8);
    void drawBorder();
    void unset();
    ~GuiFrame();
};
GuiFrame::GuiFrame(Uint8 _bpp) {
  bpp = _bpp;
  hasFrame = false;
  hasBorder = false;
}
void GuiFrame::set(Uint16 _x, Uint16 _y, Uint16 _w, Uint16 _h) {
  unset();
  frameRect.x = _x;
  frameRect.y = _y;
  frameRect.w = _w;
  frameRect.h = _h;
  innerFrameRect = frameRect;
  frame = SDL_CreateRGBSurface(
    0, frameRect.w, frameRect.h, bpp, 0, 0, 0, 0
  );
  hasFrame = true;
}
void GuiFrame::setBorder(Uint8 _width, Uint8 _r, Uint8 _g, Uint8 _b) {
  borderWidth = _width;
  borderColor.r = _r;
  borderColor.g = _g;
  borderColor.b = _b;
  hasBorder = true;
  innerFrameRect.x += _width;
  innerFrameRect.y += _width;
  innerFrameRect.w = frameRect.w - 1 - 2 * _width;
  innerFrameRect.h = frameRect.h - 1 - 2 * _width;
}
SDL_Rect *GuiFrame::getRect() {
  return &frameRect;
}
SDL_Rect *GuiFrame::getInnerRect() {
  return &innerFrameRect;
}
SDL_Surface *GuiFrame::getSurface() {
  return frame;
}
void GuiFrame::bgFill(Uint8 _r, Uint8 _g, Uint8 _b) {
  SDL_FillRect(
    frame, &frame->clip_rect, SDL_MapRGB(frame->format, _r, _g, _b)
  );
}
void GuiFrame::drawBorder() {
  if (hasBorder == true) {
    boxRGBA(
      frame, 0, 0, frame->clip_rect.w - 1, borderWidth,
      borderColor.r, borderColor.g, borderColor.b, 255
    ); // top
    boxRGBA(
      frame,
      0, 0,
      borderWidth, frame->clip_rect.h - 1,
      borderColor.r, borderColor.g, borderColor.b, 255
    ); // left
    boxRGBA(
      frame,
      0, frame->clip_rect.h - 1 - borderWidth,
      frame->clip_rect.w - 1, frame->clip_rect.h - 1,
      borderColor.r, borderColor.g, borderColor.b, 255
    ); // bottom
    boxRGBA(
      frame,
      frame->clip_rect.w - 1 - borderWidth, 0,
      frame->clip_rect.w - 1, frame->clip_rect.h - 1,
      borderColor.r, borderColor.g, borderColor.b, 255
    ); // bottom
  }
}
void GuiFrame::unset() {
  if (hasFrame == true) {
    SDL_FreeSurface(frame);
    hasFrame = false;
  }
}
GuiFrame::~GuiFrame() {
  unset();
}

// ----> GUI SCREEN
class GuiScreen {
  protected:
    SDL_Surface *screen;
    vector<GuiFrame *> frames;
  public:
    GuiScreen(SDL_Surface *);
    GuiFrame *addFrame(Uint16, Uint16, Uint16, Uint16);
    void bgFill(Uint8, Uint8, Uint8);
    virtual void update();
    virtual ~GuiScreen();
};
GuiScreen::GuiScreen(SDL_Surface *_screen) {
  screen = _screen;
}
GuiFrame *GuiScreen::addFrame(Uint16 _x, Uint16 _y, Uint16 _w, Uint16 _h) {
  GuiFrame *tempFrame = new GuiFrame(screen->format->BytesPerPixel * 8);
  tempFrame->set(_x, _y, _w, _h);
  frames.push_back(tempFrame);
  return tempFrame;
}
void GuiScreen::bgFill(Uint8 _r, Uint8 _g, Uint8 _b) {
  SDL_FillRect(
    screen, &screen->clip_rect, SDL_MapRGB(screen->format, _r, _g, _b)
  );
}
void GuiScreen::update() {
  if (frames.size() > 0) {
    vector<GuiFrame *>::iterator it;
    for (it = frames.begin(); it != frames.end(); it++) {
      (*it)->drawBorder();
      SDL_BlitSurface((*it)->getSurface(), NULL, screen, (*it)->getRect());
    }
  }
  SDL_Flip(screen);
}
GuiScreen::~GuiScreen() {
  vector<GuiFrame *>::iterator it;
  for (it = frames.begin(); it != frames.end(); it++) {
    delete (*it);
  }
  frames.clear();
}

// ----> GUI WINDOW
class GuiWindow: public GuiScreen {
  protected:
    int windowFrameIdx;
    Uint8 windowBorderWidth;
    int titleFrameIdx;
    SDL_Surface *titleText;
    bool hasTitleText;
    SDL_Rect *innerRect;
  public:
    GuiWindow(SDL_Surface *);
    void setTitle(string, Uint8, string, Uint8, Uint8, Uint8);
    void addWindowFrame(Uint16, Uint16, Uint16, Uint16, Uint8, Uint8, Uint8);
    void setWindowBorder(Uint8, Uint8, Uint8, Uint8);
    void addTitleFrame(Uint8, Uint8, Uint8);
    void unsetTitleText();
    virtual void update();
    virtual ~GuiWindow();
};
GuiWindow::GuiWindow(SDL_Surface *_screen) : GuiScreen(_screen) {
  hasTitleText = false;
  windowFrameIdx = -1;
  titleFrameIdx = -1;
}
void GuiWindow::setTitle(string _title, Uint8 _fontSize, string _fontFile,
                         Uint8 _r, Uint8 _g, Uint8 _b) {
  unsetTitleText();
  TTF_Font *font = TTF_OpenFont(_fontFile.c_str(), _fontSize);
  SDL_Color tmpFontColor = { _r, _g, _b };
  titleText = TTF_RenderText_Solid(font, _title.c_str(), tmpFontColor);
  TTF_CloseFont(font);
  hasTitleText = true;
}
void GuiWindow::addWindowFrame(Uint16 _x, Uint16 _y, Uint16 _w, Uint16 _h,
                               Uint8 _r, Uint8 _g, Uint8 _b) {
  addFrame(_x, _y, _w, _h);
  windowFrameIdx = frames.size() - 1;
  frames[windowFrameIdx]->bgFill(_r, _g, _b);
  innerRect = frames[windowFrameIdx]->getInnerRect();
}
void GuiWindow::setWindowBorder(Uint8 _width, Uint8 _r, Uint8 _g, Uint8 _b) {
  if (windowFrameIdx > -1) {
    windowBorderWidth = _width;
    frames[windowFrameIdx]->setBorder(_width, _r, _g, _b);
    innerRect = frames[windowFrameIdx]->getInnerRect();
  }
}
void GuiWindow::addTitleFrame(Uint8 _r, Uint8 _g, Uint8 _b) {
  if (hasTitleText == true && windowFrameIdx > -1) {
    addFrame(innerRect->x, innerRect->y, innerRect->w, titleText->h + windowBorderWidth);
    titleFrameIdx = frames.size() - 1;
    frames[titleFrameIdx]->bgFill(_r, _g, _b);
    innerRect->y += titleText->h + windowBorderWidth;
  }
}
void GuiWindow::update() {
  if (hasTitleText == true) {
    SDL_BlitSurface(titleText, NULL, frames[titleFrameIdx]->getSurface(), NULL);
  }
  GuiScreen::update();
}
void GuiWindow::unsetTitleText() {
  if (hasTitleText == true) {
    SDL_FreeSurface(titleText);
    hasTitleText = false;
  }
}
GuiWindow::~GuiWindow() {
  unsetTitleText();
}

// ----> GUI TEXT
class GuiTextWindow: public GuiWindow {
  protected:
    SDL_Surface *text;
    bool hasText;
  public:
    GuiTextWindow(SDL_Surface *);
    vector<string> wrapText(TTF_Font *, const string &, unsigned);
    void setText(string, Uint8, string, Uint8, Uint8, Uint8);
    void unsetText();
    virtual void update();
    virtual ~GuiTextWindow();
};
GuiTextWindow::GuiTextWindow(SDL_Surface *_screen) : GuiWindow(_screen) {
  hasText = false;
}
vector<string> GuiTextWindow::wrapText(
                 TTF_Font *_font, const string &_text, unsigned _maxWidth
               ) {
  vector<string> lines;
  string tmpStr;
  int linePos, pos, rfindLength, textWidth, textHeight;
  pos = linePos = 0;
  while (pos <= _text.length()) {
    tmpStr = _text.substr(linePos, pos-linePos);
    if (tmpStr.length() > 0) {
      TTF_SizeText(_font, tmpStr.c_str(), &textWidth, &textHeight);
      if (textWidth > _maxWidth) {
        rfindLength = _text.rfind(' ', pos);
        tmpStr = _text.substr(linePos, rfindLength - linePos);
        lines.push_back(tmpStr);
        linePos = rfindLength + 1;
        pos = linePos;
      } else if (pos == _text.length()) {
        lines.push_back(tmpStr);
      }
    }
    pos++;
  }
  return lines;
}
void GuiTextWindow::setText(string _text, Uint8 _fontSize, string _fontFile,
                            Uint8 _r, Uint8 _g, Uint8 _b) {
  unsetText();
  TTF_Font *font = TTF_OpenFont(_fontFile.c_str(), _fontSize);
  SDL_Color tmpFontColor = { _r, _g, _b };
  SDL_Surface *tempText = SDL_CreateRGBSurface(
    0, innerRect->w, innerRect->h - titleText->h - windowBorderWidth,
    screen->format->BytesPerPixel * 8, 0, 0, 0, 0
  );
  SDL_Rect tempTextRect;
  tempTextRect.x = 0;
  tempTextRect.y = 0;
  vector<string> lines = wrapText(font, _text, innerRect->w);
  for (Uint8 i = 0; i < lines.size(); i++) {
    if (i > 0)
      SDL_FreeSurface(text);
    text = TTF_RenderText_Solid(font, lines[i].c_str(), tmpFontColor);
    SDL_BlitSurface(text, NULL, tempText, &tempTextRect);
    tempTextRect.y += text->h;
  };
  SDL_FreeSurface(text);
  text = tempText;
  TTF_CloseFont(font);
  hasText = true;
}
void GuiTextWindow::unsetText() {
  if (hasText == true) {
    SDL_FreeSurface(text);
    hasText = false;
  }
}
void GuiTextWindow::update() {
  GuiWindow::update();
  if (hasText == true) {
    SDL_BlitSurface(text, NULL, screen, innerRect);
  }
  SDL_Flip(screen);
}
GuiTextWindow::~GuiTextWindow() {
  unsetText();
}

// ----> MAIN
int main (int argc, char *argv[]) {
  SDL_Init(SDL_INIT_VIDEO);
  TTF_Init();

  SDL_WM_SetCaption("SDL GUI", NULL);
  SDL_Surface* screen = SDL_SetVideoMode(640, 480, 32, SDL_SWSURFACE);

  GuiTextWindow *gui = new GuiTextWindow(screen);
  gui->setTitle("TEST WINDOW", 20, "libertysans.ttf", 0, 0, 0);
  gui->addWindowFrame(screen->w / 2 - 150, screen->h / 2 - 150, 300, 300, 0, 0, 0);
  gui->setWindowBorder(5, 255, 255, 255);
  gui->addTitleFrame(255, 255, 255);
  gui->setText(
    "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce maximus, diam eget congue malesuada, eros mi maximus leo, vel ultrices leo turpis tempus ligula. Nunc pharetra commodo lorem, quis pharetra ligula. Aenean vel metus commodo eros convallis euismod.",
    16, "libertysans.ttf", 255, 255, 255
  );
  gui->bgFill(120, 120, 120);
  gui->update();

  SDL_Event event;
  bool quit = false;
  while (quit == false) {
    if (SDL_PollEvent(&event)) {
      switch (event.type) {
        case SDL_QUIT:
          quit = 1;
          break;
        case SDL_KEYDOWN:
          switch (event.key.keysym.sym) {
            case SDLK_ESCAPE:
            case SDLK_q:
              quit = true;
              break;
            default:
              break;
          }
          break;
      }
    }
  }

  delete gui;
  TTF_Quit();
  SDL_Quit();
  return 0;
}
<commit_msg>improved text render mode<commit_after>#include "SDL/SDL.h"
#include "SDL/SDL_ttf.h"
#include "SDL/SDL_gfxPrimitives.h"
#include <vector>
#include <iostream>
using namespace std;

// ----> GUI FRAME
class GuiFrame {
  protected:
    Uint8 bpp;
    SDL_Surface *frame;
    SDL_Rect frameRect;
    SDL_Rect innerFrameRect;
    bool hasFrame;
    bool hasBorder;
    Uint8 borderWidth;
    struct stGuiFrameBorderColor {
      Uint8 r;
      Uint8 g;
      Uint8 b;
    } borderColor;
  public:
    GuiFrame(Uint8);
    void set(Uint16, Uint16, Uint16, Uint16);
    void setBorder(Uint8, Uint8, Uint8, Uint8);
    SDL_Rect *getRect();
    SDL_Rect *getInnerRect();
    SDL_Surface *getSurface();
    void bgFill(Uint8, Uint8, Uint8);
    void drawBorder();
    void unset();
    ~GuiFrame();
};
GuiFrame::GuiFrame(Uint8 _bpp) {
  bpp = _bpp;
  hasFrame = false;
  hasBorder = false;
}
void GuiFrame::set(Uint16 _x, Uint16 _y, Uint16 _w, Uint16 _h) {
  unset();
  frameRect.x = _x;
  frameRect.y = _y;
  frameRect.w = _w;
  frameRect.h = _h;
  innerFrameRect = frameRect;
  frame = SDL_CreateRGBSurface(
    0, frameRect.w, frameRect.h, bpp, 0, 0, 0, 0
  );
  hasFrame = true;
}
void GuiFrame::setBorder(Uint8 _width, Uint8 _r, Uint8 _g, Uint8 _b) {
  borderWidth = _width;
  borderColor.r = _r;
  borderColor.g = _g;
  borderColor.b = _b;
  hasBorder = true;
  innerFrameRect.x += _width;
  innerFrameRect.y += _width;
  innerFrameRect.w = frameRect.w - 1 - 2 * _width;
  innerFrameRect.h = frameRect.h - 1 - 2 * _width;
}
SDL_Rect *GuiFrame::getRect() {
  return &frameRect;
}
SDL_Rect *GuiFrame::getInnerRect() {
  return &innerFrameRect;
}
SDL_Surface *GuiFrame::getSurface() {
  return frame;
}
void GuiFrame::bgFill(Uint8 _r, Uint8 _g, Uint8 _b) {
  SDL_FillRect(
    frame, &frame->clip_rect, SDL_MapRGB(frame->format, _r, _g, _b)
  );
}
void GuiFrame::drawBorder() {
  if (hasBorder == true) {
    boxRGBA(
      frame, 0, 0, frame->clip_rect.w - 1, borderWidth,
      borderColor.r, borderColor.g, borderColor.b, 255
    ); // top
    boxRGBA(
      frame,
      0, 0,
      borderWidth, frame->clip_rect.h - 1,
      borderColor.r, borderColor.g, borderColor.b, 255
    ); // left
    boxRGBA(
      frame,
      0, frame->clip_rect.h - 1 - borderWidth,
      frame->clip_rect.w - 1, frame->clip_rect.h - 1,
      borderColor.r, borderColor.g, borderColor.b, 255
    ); // bottom
    boxRGBA(
      frame,
      frame->clip_rect.w - 1 - borderWidth, 0,
      frame->clip_rect.w - 1, frame->clip_rect.h - 1,
      borderColor.r, borderColor.g, borderColor.b, 255
    ); // bottom
  }
}
void GuiFrame::unset() {
  if (hasFrame == true) {
    SDL_FreeSurface(frame);
    hasFrame = false;
  }
}
GuiFrame::~GuiFrame() {
  unset();
}

// ----> GUI SCREEN
class GuiScreen {
  protected:
    SDL_Surface *screen;
    vector<GuiFrame *> frames;
  public:
    GuiScreen(SDL_Surface *);
    GuiFrame *addFrame(Uint16, Uint16, Uint16, Uint16);
    void bgFill(Uint8, Uint8, Uint8);
    virtual void update();
    virtual ~GuiScreen();
};
GuiScreen::GuiScreen(SDL_Surface *_screen) {
  screen = _screen;
}
GuiFrame *GuiScreen::addFrame(Uint16 _x, Uint16 _y, Uint16 _w, Uint16 _h) {
  GuiFrame *tempFrame = new GuiFrame(screen->format->BytesPerPixel * 8);
  tempFrame->set(_x, _y, _w, _h);
  frames.push_back(tempFrame);
  return tempFrame;
}
void GuiScreen::bgFill(Uint8 _r, Uint8 _g, Uint8 _b) {
  SDL_FillRect(
    screen, &screen->clip_rect, SDL_MapRGB(screen->format, _r, _g, _b)
  );
}
void GuiScreen::update() {
  if (frames.size() > 0) {
    vector<GuiFrame *>::iterator it;
    for (it = frames.begin(); it != frames.end(); it++) {
      (*it)->drawBorder();
      SDL_BlitSurface((*it)->getSurface(), NULL, screen, (*it)->getRect());
    }
  }
  SDL_Flip(screen);
}
GuiScreen::~GuiScreen() {
  vector<GuiFrame *>::iterator it;
  for (it = frames.begin(); it != frames.end(); it++) {
    delete (*it);
  }
  frames.clear();
}

// ----> GUI WINDOW
class GuiWindow: public GuiScreen {
  protected:
    int windowFrameIdx;
    Uint8 windowBorderWidth;
    int titleFrameIdx;
    SDL_Surface *titleText;
    bool hasTitleText;
    SDL_Rect *innerRect;
  public:
    GuiWindow(SDL_Surface *);
    void setTitle(string, Uint8, string, Uint8, Uint8, Uint8);
    void addWindowFrame(Uint16, Uint16, Uint16, Uint16, Uint8, Uint8, Uint8);
    void setWindowBorder(Uint8, Uint8, Uint8, Uint8);
    void addTitleFrame(Uint8, Uint8, Uint8);
    void unsetTitleText();
    virtual void update();
    virtual ~GuiWindow();
};
GuiWindow::GuiWindow(SDL_Surface *_screen) : GuiScreen(_screen) {
  hasTitleText = false;
  windowFrameIdx = -1;
  titleFrameIdx = -1;
}
void GuiWindow::setTitle(string _title, Uint8 _fontSize, string _fontFile,
                         Uint8 _r, Uint8 _g, Uint8 _b) {
  unsetTitleText();
  TTF_Font *font = TTF_OpenFont(_fontFile.c_str(), _fontSize);
  SDL_Color tmpFontColor = { _r, _g, _b };
  titleText = TTF_RenderText_Blended(font, _title.c_str(), tmpFontColor);
  TTF_CloseFont(font);
  hasTitleText = true;
}
void GuiWindow::addWindowFrame(Uint16 _x, Uint16 _y, Uint16 _w, Uint16 _h,
                               Uint8 _r, Uint8 _g, Uint8 _b) {
  addFrame(_x, _y, _w, _h);
  windowFrameIdx = frames.size() - 1;
  frames[windowFrameIdx]->bgFill(_r, _g, _b);
  innerRect = frames[windowFrameIdx]->getInnerRect();
}
void GuiWindow::setWindowBorder(Uint8 _width, Uint8 _r, Uint8 _g, Uint8 _b) {
  if (windowFrameIdx > -1) {
    windowBorderWidth = _width;
    frames[windowFrameIdx]->setBorder(_width, _r, _g, _b);
    innerRect = frames[windowFrameIdx]->getInnerRect();
  }
}
void GuiWindow::addTitleFrame(Uint8 _r, Uint8 _g, Uint8 _b) {
  if (hasTitleText == true && windowFrameIdx > -1) {
    addFrame(innerRect->x, innerRect->y, innerRect->w, titleText->h + windowBorderWidth);
    titleFrameIdx = frames.size() - 1;
    frames[titleFrameIdx]->bgFill(_r, _g, _b);
    innerRect->y += titleText->h + windowBorderWidth;
  }
}
void GuiWindow::update() {
  if (hasTitleText == true) {
    SDL_BlitSurface(titleText, NULL, frames[titleFrameIdx]->getSurface(), NULL);
  }
  GuiScreen::update();
}
void GuiWindow::unsetTitleText() {
  if (hasTitleText == true) {
    SDL_FreeSurface(titleText);
    hasTitleText = false;
  }
}
GuiWindow::~GuiWindow() {
  unsetTitleText();
}

// ----> GUI TEXT
class GuiTextWindow: public GuiWindow {
  protected:
    SDL_Surface *text;
    bool hasText;
  public:
    GuiTextWindow(SDL_Surface *);
    vector<string> wrapText(TTF_Font *, const string &, unsigned);
    void setText(string, Uint8, string, Uint8, Uint8, Uint8);
    void unsetText();
    virtual void update();
    virtual ~GuiTextWindow();
};
GuiTextWindow::GuiTextWindow(SDL_Surface *_screen) : GuiWindow(_screen) {
  hasText = false;
}
vector<string> GuiTextWindow::wrapText(
                 TTF_Font *_font, const string &_text, unsigned _maxWidth
               ) {
  vector<string> lines;
  string tmpStr;
  int linePos, pos, rfindLength, textWidth, textHeight;
  pos = linePos = 0;
  while (pos <= _text.length()) {
    tmpStr = _text.substr(linePos, pos-linePos);
    if (tmpStr.length() > 0) {
      TTF_SizeText(_font, tmpStr.c_str(), &textWidth, &textHeight);
      if (textWidth > _maxWidth) {
        rfindLength = _text.rfind(' ', pos);
        tmpStr = _text.substr(linePos, rfindLength - linePos);
        lines.push_back(tmpStr);
        linePos = rfindLength + 1;
        pos = linePos;
      } else if (pos == _text.length()) {
        lines.push_back(tmpStr);
      }
    }
    pos++;
  }
  return lines;
}
void GuiTextWindow::setText(string _text, Uint8 _fontSize, string _fontFile,
                            Uint8 _r, Uint8 _g, Uint8 _b) {
  unsetText();
  TTF_Font *font = TTF_OpenFont(_fontFile.c_str(), _fontSize);
  SDL_Color tmpFontColor = { _r, _g, _b };
  SDL_Surface *tempText = SDL_CreateRGBSurface(
    0, innerRect->w, innerRect->h - titleText->h - windowBorderWidth,
    screen->format->BytesPerPixel * 8, 0, 0, 0, 0
  );
  SDL_Rect tempTextRect;
  tempTextRect.x = 0;
  tempTextRect.y = 0;
  vector<string> lines = wrapText(font, _text, innerRect->w);
  for (Uint8 i = 0; i < lines.size(); i++) {
    if (i > 0)
      SDL_FreeSurface(text);
    text = TTF_RenderText_Blended(font, lines[i].c_str(), tmpFontColor);
    SDL_BlitSurface(text, NULL, tempText, &tempTextRect);
    tempTextRect.y += text->h;
  };
  SDL_FreeSurface(text);
  text = tempText;
  TTF_CloseFont(font);
  hasText = true;
}
void GuiTextWindow::unsetText() {
  if (hasText == true) {
    SDL_FreeSurface(text);
    hasText = false;
  }
}
void GuiTextWindow::update() {
  GuiWindow::update();
  if (hasText == true) {
    SDL_BlitSurface(text, NULL, screen, innerRect);
  }
  SDL_Flip(screen);
}
GuiTextWindow::~GuiTextWindow() {
  unsetText();
}

// ----> MAIN
int main (int argc, char *argv[]) {
  SDL_Init(SDL_INIT_VIDEO);
  TTF_Init();

  SDL_WM_SetCaption("SDL GUI", NULL);
  SDL_Surface* screen = SDL_SetVideoMode(640, 480, 32, SDL_SWSURFACE);

  GuiTextWindow *gui = new GuiTextWindow(screen);
  gui->setTitle("TEST WINDOW", 20, "libertysans.ttf", 0, 0, 0);
  gui->addWindowFrame(screen->w / 2 - 150, screen->h / 2 - 150, 300, 300, 0, 0, 0);
  gui->setWindowBorder(5, 255, 255, 255);
  gui->addTitleFrame(255, 255, 255);
  gui->setText(
    "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce maximus, diam eget congue malesuada, eros mi maximus leo, vel ultrices leo turpis tempus ligula. Nunc pharetra commodo lorem, quis pharetra ligula. Aenean vel metus commodo eros convallis euismod.",
    16, "libertysans.ttf", 255, 255, 255
  );
  gui->bgFill(120, 120, 120);
  gui->update();

  SDL_Event event;
  bool quit = false;
  while (quit == false) {
    if (SDL_PollEvent(&event)) {
      switch (event.type) {
        case SDL_QUIT:
          quit = 1;
          break;
        case SDL_KEYDOWN:
          switch (event.key.keysym.sym) {
            case SDLK_ESCAPE:
            case SDLK_q:
              quit = true;
              break;
            default:
              break;
          }
          break;
      }
    }
  }

  delete gui;
  TTF_Quit();
  SDL_Quit();
  return 0;
}
<|endoftext|>


<commit_before><commit_msg>Remove unused .cpp file<commit_after><|endoftext|>


<commit_before>/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "src/base/test/vm_test_utils.h"

#include "perfetto/base/build_config.h"
#include "perfetto/ext/base/utils.h"

#include <memory>

#include <errno.h>
#include <string.h>

#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
#include <vector>

#include <Windows.h>
#include <Psapi.h>
#else  // PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
#include <sys/mman.h>
#include <sys/stat.h>
#endif  // PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)

#include "perfetto/base/build_config.h"
#include "perfetto/base/logging.h"
#include "perfetto/ext/base/utils.h"

namespace perfetto {
namespace base {
namespace vm_test_utils {

bool IsMapped(void* start, size_t size) {
  const size_t page_size = GetSysPageSize();
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  int retries = 5;
  int number_of_entries = 4000;  // Just a guess.
  PSAPI_WORKING_SET_INFORMATION* ws_info = nullptr;

  std::vector<char> buffer;
  for (;;) {
    size_t buffer_size =
      sizeof(PSAPI_WORKING_SET_INFORMATION) +
      (number_of_entries * sizeof(PSAPI_WORKING_SET_BLOCK));

    buffer.resize(buffer_size);
    ws_info = reinterpret_cast<PSAPI_WORKING_SET_INFORMATION*>(&buffer[0]);

    // On success, |buffer_| is populated with info about the working set of
    // |process|. On ERROR_BAD_LENGTH failure, increase the size of the
    // buffer and try again.
    if (QueryWorkingSet(GetCurrentProcess(), &buffer[0], buffer_size))
      break;  // Success

    PERFETTO_CHECK(GetLastError() == ERROR_BAD_LENGTH);

    number_of_entries = ws_info->NumberOfEntries;

    // Maybe some entries are being added right now. Increase the buffer to
    // take that into account. Increasing by 10% should generally be enough.
    number_of_entries *= 1.1;

    PERFETTO_CHECK(--retries > 0);  // If we're looping, eventually fail.
  }

  void* end = reinterpret_cast<char*>(start) + size;
  // Now scan the working-set information looking for the addresses.
  unsigned pages_found = 0;
  for (unsigned i = 0; i < ws_info->NumberOfEntries; ++i) {
    void* address = reinterpret_cast<void*>(
        ws_info->WorkingSetInfo[i].VirtualPage * page_size);
    if (address >= start && address < end)
      ++pages_found;
  }

  if (pages_found * page_size == size)
    return true;
  return false;
#elif PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA)
  // Fuchsia doesn't yet support paging (b/119503290).
  return true;
#else
#if PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
  using PageState = char;
  static constexpr PageState kIncoreMask = MINCORE_INCORE;
#else
  using PageState = unsigned char;
  static constexpr PageState kIncoreMask = 1;
#endif
  const size_t num_pages = (size + page_size - 1) / page_size;
  std::unique_ptr<PageState[]> page_states(new PageState[num_pages]);
  memset(page_states.get(), 0, num_pages * sizeof(PageState));
  int res = mincore(start, size, page_states.get());
  // Linux returns ENOMEM when an unmapped memory range is passed.
  // MacOS instead returns 0 but leaves the page_states empty.
  if (res == -1 && errno == ENOMEM)
    return false;
  PERFETTO_CHECK(res == 0);
  for (size_t i = 0; i < num_pages; i++) {
    if (!(page_states[i] & kIncoreMask))
      return false;
  }
  return true;
#endif
}

}  // namespace vm_test_utils
}  // namespace base
}  // namespace perfetto
<commit_msg>Add ignore_result for fuchsia in vm_test_utils.cc am: c86d8fb76a am: 41e361717e am: 3374ce386d am: ba3f7fb13d am: 7f6affcc3b<commit_after>/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "src/base/test/vm_test_utils.h"

#include "perfetto/base/build_config.h"
#include "perfetto/ext/base/utils.h"

#include <memory>

#include <errno.h>
#include <string.h>

#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
#include <vector>

#include <Windows.h>
#include <Psapi.h>
#else  // PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
#include <sys/mman.h>
#include <sys/stat.h>
#endif  // PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)

#include "perfetto/base/build_config.h"
#include "perfetto/base/logging.h"
#include "perfetto/ext/base/utils.h"

namespace perfetto {
namespace base {
namespace vm_test_utils {

bool IsMapped(void* start, size_t size) {
  const size_t page_size = GetSysPageSize();
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  int retries = 5;
  int number_of_entries = 4000;  // Just a guess.
  PSAPI_WORKING_SET_INFORMATION* ws_info = nullptr;

  std::vector<char> buffer;
  for (;;) {
    size_t buffer_size =
      sizeof(PSAPI_WORKING_SET_INFORMATION) +
      (number_of_entries * sizeof(PSAPI_WORKING_SET_BLOCK));

    buffer.resize(buffer_size);
    ws_info = reinterpret_cast<PSAPI_WORKING_SET_INFORMATION*>(&buffer[0]);

    // On success, |buffer_| is populated with info about the working set of
    // |process|. On ERROR_BAD_LENGTH failure, increase the size of the
    // buffer and try again.
    if (QueryWorkingSet(GetCurrentProcess(), &buffer[0], buffer_size))
      break;  // Success

    PERFETTO_CHECK(GetLastError() == ERROR_BAD_LENGTH);

    number_of_entries = ws_info->NumberOfEntries;

    // Maybe some entries are being added right now. Increase the buffer to
    // take that into account. Increasing by 10% should generally be enough.
    number_of_entries *= 1.1;

    PERFETTO_CHECK(--retries > 0);  // If we're looping, eventually fail.
  }

  void* end = reinterpret_cast<char*>(start) + size;
  // Now scan the working-set information looking for the addresses.
  unsigned pages_found = 0;
  for (unsigned i = 0; i < ws_info->NumberOfEntries; ++i) {
    void* address = reinterpret_cast<void*>(
        ws_info->WorkingSetInfo[i].VirtualPage * page_size);
    if (address >= start && address < end)
      ++pages_found;
  }

  if (pages_found * page_size == size)
    return true;
  return false;
#elif PERFETTO_BUILDFLAG(PERFETTO_OS_FUCHSIA)
  // Fuchsia doesn't yet support paging (b/119503290).
  ignore_result(page_size);
  return true;
#else
#if PERFETTO_BUILDFLAG(PERFETTO_OS_APPLE)
  using PageState = char;
  static constexpr PageState kIncoreMask = MINCORE_INCORE;
#else
  using PageState = unsigned char;
  static constexpr PageState kIncoreMask = 1;
#endif
  const size_t num_pages = (size + page_size - 1) / page_size;
  std::unique_ptr<PageState[]> page_states(new PageState[num_pages]);
  memset(page_states.get(), 0, num_pages * sizeof(PageState));
  int res = mincore(start, size, page_states.get());
  // Linux returns ENOMEM when an unmapped memory range is passed.
  // MacOS instead returns 0 but leaves the page_states empty.
  if (res == -1 && errno == ENOMEM)
    return false;
  PERFETTO_CHECK(res == 0);
  for (size_t i = 0; i < num_pages; i++) {
    if (!(page_states[i] & kIncoreMask))
      return false;
  }
  return true;
#endif
}

}  // namespace vm_test_utils
}  // namespace base
}  // namespace perfetto
<|endoftext|>


<commit_before>/***********************************************************************************
** MIT License                                                                    **
**                                                                                **
** Copyright (c) 2017 Victor DENIS (victordenis01@gmail.com)                      **
**                                                                                **
** Permission is hereby granted, free of charge, to any person obtaining a copy   **
** of this software and associated documentation files (the "Software"), to deal  **
** in the Software without restriction, including without limitation the rights   **
** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell      **
** copies of the Software, and to permit persons to whom the Software is          **
** furnished to do so, subject to the following conditions:                       **
**                                                                                **
** The above copyright notice and this permission notice shall be included in all **
** copies or substantial portions of the Software.                                **
**                                                                                **
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR     **
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,       **
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE    **
** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER         **
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,  **
** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE  **
** SOFTWARE.                                                                      **
***********************************************************************************/

#include "Utils/Updater.hpp"

#include <QTimer>

#include <QMessageBox>

#include <QFile>
#include <QStandardPaths>
#include <QDesktopServices>

#include <QMessageBox>

#include <QNetworkRequest>
#include <QNetworkReply>

#include "Network/NetworkManager.hpp"

#include "BrowserWindow.hpp"

#include "Application.hpp"

namespace Sn {

Updater::Updater(BrowserWindow* window, QObject* parent) :
	QObject(parent),
	m_window(window)
{
	QTimer::singleShot(10 * 1000, this, &Updater::start);
}

void Updater::downloadUpdateInfoCompleted()
{
	if (!m_versionReply)
		return;

	QByteArray updateInfo = m_versionReply->readAll();
	QTextStream in{&updateInfo};
	QString newVersion{};
	bool readLastVersion{true};

	while (!in.atEnd()) {
		QString line{in.readLine()};
		QStringList versionInfo{line.split(QLatin1Char(','))};

		if (readLastVersion) {
			QString newVersion = versionInfo[0];
			readLastVersion = false;
		}

		for (int i{1}; i < versionInfo.count(); ++i) {
			if (versionInfo[i] == "fullUpdate")
				m_fullUpdate = true;
			if (versionInfo[i] == "themeUpdate")
				m_themeUpdate = true;
		}
	}

	if (newVersion != Application::currentVersion) {
#if defined(Q_OS_WIN)
		QMessageBox::information(m_window, tr("Update"), tr("A new version of Sielo will be download in background!"));
		QString updaterName{};

		if (m_fullUpdate)
			updaterName = "sielo_full_update_setup.exe";
		else if (m_themeUpdate)
			updaterName = "sielo_theme_update_setup.exe";
		else
			updaterName = "sielo_update_setup.exe";

		QUrl updaterUrl{QUrl("http://feldrise.com/Sielo/" + updaterName)};
		startDownloadNewVersion(updaterUrl);
#elif defined(Q_OS_LINUX)
		QMessageBox::information(m_window,
								 tr("Update"),
								 tr("A new version of Sielo is available! We advise you to download it."));
#endif
	}

	m_versionReply->deleteLater();

}

void Updater::downloadCompleted()
{
	QString updaterLocation{QStandardPaths::writableLocation(QStandardPaths::TempLocation)};
	QFile updater{updaterLocation + QLatin1String("/SieloUpdater.exe")};

	if (!updater.open(QIODevice::WriteOnly)) {
		QMessageBox::critical(m_window, tr("Update fail"), tr("Impossible to update Sielo... Please retry later"));
		return;
	}

	updater.write(m_updaterReply->readAll());
	updater.close();

	QDesktopServices::openUrl(QUrl(updaterLocation + QLatin1String("/SieloUpdater.exe")));

	m_updaterReply->deleteLater();
	m_window->close();
}

void Updater::start()
{
	QUrl newVersionUrl{QUrl("http://feldrise.com/Sielo/versions.txt")};

	startDownloadingUpdateInfo(newVersionUrl);
}

void Updater::startDownloadNewVersion(const QUrl& url)
{
	m_updaterReply = Application::instance()->networkManager()->get(QNetworkRequest(url));

	connect(m_updaterReply, &QNetworkReply::finished, this, &Updater::downloadCompleted);
}

void Updater::startDownloadingUpdateInfo(const QUrl& url)
{
	m_versionReply = Application::instance()->networkManager()->get(QNetworkRequest(url));

	connect(m_versionReply, &QNetworkReply::finished, this, &Updater::downloadUpdateInfoCompleted);
}

}
<commit_msg>[Fix] Updater on some Linux systems<commit_after>/***********************************************************************************
** MIT License                                                                    **
**                                                                                **
** Copyright (c) 2017 Victor DENIS (victordenis01@gmail.com)                      **
**                                                                                **
** Permission is hereby granted, free of charge, to any person obtaining a copy   **
** of this software and associated documentation files (the "Software"), to deal  **
** in the Software without restriction, including without limitation the rights   **
** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell      **
** copies of the Software, and to permit persons to whom the Software is          **
** furnished to do so, subject to the following conditions:                       **
**                                                                                **
** The above copyright notice and this permission notice shall be included in all **
** copies or substantial portions of the Software.                                **
**                                                                                **
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR     **
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,       **
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE    **
** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER         **
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,  **
** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE  **
** SOFTWARE.                                                                      **
***********************************************************************************/

#include "Utils/Updater.hpp"

#include <QTimer>

#include <QMessageBox>

#include <QFile>
#include <QStandardPaths>
#include <QDesktopServices>

#include <QMessageBox>

#include <QNetworkRequest>
#include <QNetworkReply>

#include "Network/NetworkManager.hpp"

#include "BrowserWindow.hpp"

#include "Application.hpp"

namespace Sn {

Updater::Updater(BrowserWindow* window, QObject* parent) :
	QObject(parent),
	m_window(window)
{
	QTimer::singleShot(10 * 1000, this, &Updater::start);
}

void Updater::downloadUpdateInfoCompleted()
{
	if (!m_versionReply)
		return;

	QByteArray updateInfo = m_versionReply->readAll();
	QTextStream in{&updateInfo};
	QString newVersion{};
	bool readLastVersion{true};

	while (!in.atEnd()) {
		QString line{in.readLine()};
		QStringList versionInfo{line.split(QLatin1Char(','))};

		if (readLastVersion) {
			QString newVersion = versionInfo[0];
			readLastVersion = false;
		}

		for (int i{1}; i < versionInfo.count(); ++i) {
			if (versionInfo[i] == "fullUpdate")
				m_fullUpdate = true;
			if (versionInfo[i] == "themeUpdate")
				m_themeUpdate = true;
		}
	}

	if (newVersion != Application::currentVersion) {
#if defined(Q_OS_WIN)
		QMessageBox::information(m_window, tr("Update"), tr("A new version of Sielo will be download in background!"));
		QString updaterName{};

		if (m_fullUpdate)
			updaterName = "sielo_full_update_setup.exe";
		else if (m_themeUpdate)
			updaterName = "sielo_theme_update_setup.exe";
		else
			updaterName = "sielo_update_setup.exe";

		QUrl updaterUrl{QUrl("http://www.feldrise.com/Sielo/" + updaterName)};
		startDownloadNewVersion(updaterUrl);
#elif defined(Q_OS_LINUX)
		QMessageBox::information(m_window,
								 tr("Update"),
								 tr("A new version of Sielo is available! We advise you to download it."));
#endif
	}

	m_versionReply->deleteLater();

}

void Updater::downloadCompleted()
{
	QString updaterLocation{QStandardPaths::writableLocation(QStandardPaths::TempLocation)};
	QFile updater{updaterLocation + QLatin1String("/SieloUpdater.exe")};

	if (!updater.open(QIODevice::WriteOnly)) {
		QMessageBox::critical(m_window, tr("Update fail"), tr("Impossible to update Sielo... Please retry later"));
		return;
	}

	updater.write(m_updaterReply->readAll());
	updater.close();

	QDesktopServices::openUrl(QUrl(updaterLocation + QLatin1String("/SieloUpdater.exe")));

	m_updaterReply->deleteLater();
	m_window->close();
}

void Updater::start()
{
	QUrl newVersionUrl{QUrl("http://www.feldrise.com/Sielo/versions.txt")};

	startDownloadingUpdateInfo(newVersionUrl);
}

void Updater::startDownloadNewVersion(const QUrl& url)
{
	m_updaterReply = Application::instance()->networkManager()->get(QNetworkRequest(url));

	connect(m_updaterReply, &QNetworkReply::finished, this, &Updater::downloadCompleted);
}

void Updater::startDownloadingUpdateInfo(const QUrl& url)
{
	m_versionReply = Application::instance()->networkManager()->get(QNetworkRequest(url));

	connect(m_versionReply, &QNetworkReply::finished, this, &Updater::downloadUpdateInfoCompleted);
}

}
<|endoftext|>


<commit_before>#include "gpu.h"

#include <cassert>
#include <iostream>

#ifdef __APPLE__
#  include <OpenGL/opengl.h>
#elif defined (_WIN32)
#  define NOMINMAX
#  include "Windows.h"
#else
#  include <GL/glx.h>
#endif

#include "kernel_cache.h"

namespace gpu {

static void ContextErrorCallback(const char *errinfo, const void *, size_t, void *) {
  fprintf(stderr, "Context error: %s\n", errinfo);
  assert(false);
  exit(1);
}

static void PrintDeviceInfo(cl_device_id device_id) {

  size_t strLen;
  const size_t kStrBufSz = 1024;
  union {
    char strBuf[kStrBufSz];
    cl_uint intBuf[kStrBufSz / sizeof(cl_uint)];
    size_t sizeBuf[kStrBufSz / sizeof(size_t)];
  };

  CHECK_CL(clGetDeviceInfo, device_id, CL_DEVICE_NAME, kStrBufSz, strBuf, &strLen);
  std::cout << "Device name: " << strBuf << std::endl;

  CHECK_CL(clGetDeviceInfo, device_id, CL_DEVICE_PROFILE, kStrBufSz, strBuf, &strLen);
  std::cout << "Device profile: " << strBuf << std::endl;

  CHECK_CL(clGetDeviceInfo, device_id, CL_DEVICE_VENDOR, kStrBufSz, strBuf, &strLen);
  std::cout << "Device vendor: " << strBuf << std::endl;

  CHECK_CL(clGetDeviceInfo, device_id, CL_DEVICE_VERSION, kStrBufSz, strBuf, &strLen);
  std::cout << "Device version: " << strBuf << std::endl;

  CHECK_CL(clGetDeviceInfo, device_id, CL_DRIVER_VERSION, kStrBufSz, strBuf, &strLen);
  std::cout << "Device driver version: " << strBuf << std::endl;

  CHECK_CL(clGetDeviceInfo, device_id, CL_DEVICE_ADDRESS_BITS, kStrBufSz, strBuf,
           &strLen);
  std::cout << "Device driver address bits: " << intBuf[0] << std::endl;

  CHECK_CL(clGetDeviceInfo, device_id, CL_DEVICE_MAX_WORK_GROUP_SIZE, kStrBufSz,
           strBuf, &strLen);
  std::cout << "Max work group size: " << sizeBuf[0] << std::endl;

  CHECK_CL(clGetDeviceInfo, device_id, CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS, kStrBufSz,
           strBuf, &strLen);
  std::cout << "Max work item dimensions: " << intBuf[0] << std::endl;
  assert(*(reinterpret_cast<cl_uint *>(strBuf)) >= 2);

  CHECK_CL(clGetDeviceInfo, device_id, CL_DEVICE_GLOBAL_MEM_SIZE, kStrBufSz,
           strBuf, &strLen);
  std::cout << "Total global bytes available: " << intBuf[0] << std::endl;

  CHECK_CL(clGetDeviceInfo, device_id, CL_DEVICE_LOCAL_MEM_SIZE, kStrBufSz,
           strBuf, &strLen);
  std::cout << "Total local bytes available: " << intBuf[0] << std::endl;

  CHECK_CL(clGetDeviceInfo, device_id, CL_DEVICE_MAX_MEM_ALLOC_SIZE, kStrBufSz,
           strBuf, &strLen);
  std::cout << "Total size of memory allocatable: " << intBuf[0] << std::endl;

  CHECK_CL(clGetDeviceInfo, device_id, CL_DEVICE_MAX_WORK_ITEM_SIZES, kStrBufSz, strBuf, &strLen);
  size_t nSizeElements = strLen / sizeof(size_t);
  std::cout << "Max work item sizes: (";
  size_t *dimSizes = (size_t *)(strBuf);
  for(size_t j = 0; j < nSizeElements; j++) {
    std::cout << dimSizes[j] << ((j == nSizeElements - 1)? "" : ", ");
  }
  std::cout << ")" << std::endl;

  CHECK_CL(clGetDeviceInfo, device_id, CL_DEVICE_EXTENSIONS, kStrBufSz, strBuf, &strLen);
  std::cout << "Device extensions: " << std::endl;
  for (size_t k = 0; k < strLen; ++k) {
    if (strBuf[k] == ',' || strBuf[k] == ' ') {
      strBuf[k] = '\0';
    }
  }

  std::cout << "  " << strBuf << std::endl;
  for (size_t k = 1; k < strLen; ++k) {
    if (strBuf[k] == '\0' && k < strLen - 1) {
      std::cout << "  " << (strBuf + k + 1) << std::endl;
    }
  }

  cl_device_type deviceType;
  size_t deviceTypeSz;
  CHECK_CL(clGetDeviceInfo, device_id, CL_DEVICE_TYPE, sizeof(cl_device_type), &deviceType, &deviceTypeSz);
  if(deviceType & CL_DEVICE_TYPE_CPU) {
    std::cout << "Device driver type: CPU" << std::endl;
  }
  if(deviceType & CL_DEVICE_TYPE_GPU) {
    std::cout << "Device driver type: GPU" << std::endl;
  }
  if(deviceType & CL_DEVICE_TYPE_ACCELERATOR) {
    std::cout << "Device driver type: ACCELERATOR" << std::endl;
  }
  if(deviceType & CL_DEVICE_TYPE_DEFAULT) {
    std::cout << "Device driver type: DEFAULT" << std::endl;
  }
}

static std::vector<cl_context_properties> GetSharedCLGLProps() {
  std::vector<cl_context_properties> props;
#ifdef __APPLE__
  // Get current CGL Context and CGL Share group
  CGLContextObj kCGLContext = CGLGetCurrentContext();
  CGLShareGroupObj kCGLShareGroup = CGLGetShareGroup(kCGLContext);

  props.push_back(CL_CONTEXT_PROPERTY_USE_CGL_SHAREGROUP_APPLE);
  props.push_back((cl_context_properties)kCGLShareGroup);
  props.push_back(0);

#elif defined (_WIN32)

  // OpenGL context
  props.push_back(CL_GL_CONTEXT_KHR);
  props.push_back((cl_context_properties)wglGetCurrentContext());

  // HDC used to create the OpenGL context
  props.push_back(CL_WGL_HDC_KHR);
  props.push_back((cl_context_properties)wglGetCurrentDC());

  props.push_back(0);

#else  // Linux??

  props.push_back(CL_GL_CONTEXT_KHR);
  props.push_back((cl_context_properties) glXGetCurrentContext());
  props.push_back(CL_GLX_DISPLAY_KHR);
  props.push_back((cl_context_properties) glXGetCurrentDisplay());
  props.push_back(0);

#endif

  return std::move(props);
}

static void CreateCLContext(cl_context *result, const cl_context_properties *props,
                            cl_device_id device) {
  cl_int errCreateContext;
  *result = clCreateContext(props, 1, &device, ContextErrorCallback, NULL,
                            &errCreateContext);
  CHECK_CL((cl_int), errCreateContext);
}

static cl_device_id GetDeviceForSharedContext(cl_context ctx) {
  size_t device_id_size_bytes;
  cl_device_id device;

#ifndef __APPLE__
  std::vector<cl_context_properties> props = GetSharedCLGLProps();

  typedef CL_API_ENTRY cl_int(CL_API_CALL *CtxInfoFunc)
    (const cl_context_properties *properties, cl_gl_context_info param_name,
    size_t param_value_size, void *param_value, size_t *param_value_size_ret);
  static CtxInfoFunc getCtxInfoFunc = NULL;
#ifndef CL_VERSION_1_1
  getCtxInfoFunc = reinterpret_cast<CtxInfoFunc>(
    clGetExtensionFunctionAddress("clGetGLContextInfoKHR"));
#else
  cl_platform_id platform;
  CHECK_CL(clGetPlatformIDs, 1, &platform, NULL);
  std::vector<cl_context_properties> extra_props = { CL_CONTEXT_PLATFORM, (cl_context_properties)platform };
  extra_props.insert(extra_props.end(), props.begin(), props.end());
  props = extra_props;

  getCtxInfoFunc = reinterpret_cast<CtxInfoFunc>(
    clGetExtensionFunctionAddressForPlatform(platform, "clGetGLContextInfoKHR"));
#endif  // CL_VERSION_1_1

  assert(getCtxInfoFunc);
  CHECK_CL(getCtxInfoFunc, props.data(), CL_CURRENT_DEVICE_FOR_GL_CONTEXT_KHR,
    sizeof(device), &device, &device_id_size_bytes);
#else
  // Get current CGL Context and CGL Share group
  CGLContextObj kCGLContext = CGLGetCurrentContext();
  // And now we can ask OpenCL which particular device is being used by
  // OpenGL to do the rendering, currently:
  clGetGLContextInfoAPPLE(ctx, kCGLContext,
    CL_CGL_DEVICE_FOR_CURRENT_VIRTUAL_SCREEN_APPLE,
    sizeof(device), &device, &device_id_size_bytes);
#endif  // __APPLE
  // If we're sharing an openGL context, there should really only
  // be one device ID...
  assert(device_id_size_bytes == sizeof(cl_device_id));
  return device;
}

static std::vector<cl_device_id> GetAllDevicesForContext(cl_context ctx) {
  std::vector<cl_device_id> devices(16);
  size_t nDeviceIds;
  CHECK_CL(clGetContextInfo, ctx, CL_CONTEXT_DEVICES, devices.size() * sizeof(cl_device_id),
    devices.data(), &nDeviceIds);
  nDeviceIds /= sizeof(cl_device_id);
  devices.resize(nDeviceIds);
  return std::move(devices);
}

GPUContext::~GPUContext() {
  GPUKernelCache::Instance(_ctx, _type, _device)->Clear();
  CHECK_CL(clReleaseCommandQueue, _command_queue);
  CHECK_CL(clReleaseContext, _ctx);
}

std::unique_ptr<GPUContext> GPUContext::InitializeOpenCL(bool share_opengl) {
  const cl_uint kMaxPlatforms = 8;
  cl_platform_id platforms[kMaxPlatforms];
  cl_uint nPlatforms;
  int platform_idx = -1;

#ifdef NDEBUG
  CHECK_CL(clGetPlatformIDs, kMaxPlatforms, platforms, &nPlatforms);
#else
  CHECK_CL(clGetPlatformIDs, kMaxPlatforms, NULL, &nPlatforms);
  std::cout << "OpenCL has " << nPlatforms << " platform"
            << ((nPlatforms != 1)? "s" : "")
            << " available. Querying... " << std::endl;
  CHECK_CL(clGetPlatformIDs, nPlatforms, platforms, &nPlatforms);

  size_t strLen;
  for (cl_uint i = 0; i < nPlatforms; i++) {
    char strBuf[256];

    std::cout << std::endl;
    std::cout << "Platform " << i << " info:" << std::endl;

    CHECK_CL(clGetPlatformInfo, platforms[i], CL_PLATFORM_PROFILE, 256, strBuf, &strLen);
    std::cout << "Platform profile: " << strBuf << std::endl;

    CHECK_CL(clGetPlatformInfo, platforms[i], CL_PLATFORM_VERSION, 256, strBuf, &strLen);
    std::cout << "Platform version: " << strBuf << std::endl;

    CHECK_CL(clGetPlatformInfo, platforms[i], CL_PLATFORM_NAME, 256, strBuf, &strLen);
    std::cout << "Platform name: " << strBuf << std::endl;

    bool isCPUOnly = false;
    if (strstr(strBuf, "CPU Only")) {
      isCPUOnly = true;
    }

    CHECK_CL(clGetPlatformInfo, platforms[i], CL_PLATFORM_VENDOR, 256, strBuf, &strLen);
    std::cout << "Platform vendor: " << strBuf << std::endl;

    bool isIntel = false;
    if (strstr(strBuf, "Intel")) {
      isIntel = true;
    }

    if (isCPUOnly && isIntel) {
      platform_idx = i;
    }
  }
#endif

  const cl_uint kMaxDevices = 8;
  cl_device_id devices[kMaxDevices];
  cl_uint nDevices;

  cl_device_type device_type = CL_DEVICE_TYPE_GPU;
  if (platform_idx >= 0) {
    std::cout << "========================================";
    std::cout << "========================================" << std::endl;
    std::cout << "========================================";
    std::cout << "========================================" << std::endl;
    std::cout << "WARNING: Running on the CPU" << std::endl;
    std::cout << "========================================";
    std::cout << "========================================" << std::endl;
    std::cout << "========================================";
    std::cout << "========================================" << std::endl;
    device_type = CL_DEVICE_TYPE_CPU;
  } else {
    platform_idx = 0;
  }

  cl_platform_id platform = platforms[platform_idx];
  CHECK_CL(clGetDeviceIDs, platform, device_type, kMaxDevices, devices, &nDevices);

#ifndef NDEBUG
  std::cout << std::endl;
  std::cout << "Found " << nDevices << " device" << (nDevices == 1 ? "" : "s")
    << " on platform " << platform_idx << std::endl;

  for (cl_uint i = 0; i < nDevices; i++) {
    gpu::PrintDeviceInfo(devices[i]);
  }

  std::cout << std::endl;
#endif

  // Create OpenCL context...
  cl_context ctx;
  std::vector<cl_context_properties> props = {
    CL_CONTEXT_PLATFORM, (cl_context_properties)platform
  };

  if (share_opengl) {
    std::vector<cl_context_properties> clgl_props = std::move(GetSharedCLGLProps());
    props.insert(props.end(), clgl_props.begin(), clgl_props.end());
  }
  else {
    props.push_back(0);
  }

  CreateCLContext(&ctx, props.data(), devices[0]);

  // We got the context...
  std::unique_ptr<GPUContext> gpu_ctx =
    std::unique_ptr<GPUContext>(new GPUContext);
  gpu_ctx->_ctx = ctx;

  if (device_type == CL_DEVICE_TYPE_CPU) {
    gpu_ctx->_type = eContextType_IntelCPU;
  } else {
    gpu_ctx->_type = eContextType_GenericGPU;
  }

  // The device...
  if (share_opengl) {
    gpu_ctx->_device = GetDeviceForSharedContext(ctx);
  } else {
    std::vector<cl_device_id> ds = std::move(GetAllDevicesForContext(ctx));
    assert(ds.size() > 0);
    assert(ds[0] == devices[0]);
    gpu_ctx->_device = ds[0];
  }

  // And the command queue...
  cl_int errCreateCommandQueue;
#ifndef CL_VERSION_2_0
  gpu_ctx->_command_queue = clCreateCommandQueue(ctx, gpu_ctx->_device, 0, &errCreateCommandQueue);
#else
  gpu_ctx->_command_queue = clCreateCommandQueueWithProperties(ctx, gpu_ctx->_device, 0, &errCreateCommandQueue);
#endif
  CHECK_CL((cl_int), errCreateCommandQueue);

  return std::move(gpu_ctx);
}

void GPUContext::PrintDeviceInfo() const {
  gpu::PrintDeviceInfo(_device);
}

cl_kernel GPUContext::GetOpenCLKernel(const std::string &filename, const std::string &kernel) const {
  GPUKernelCache *cache = GPUKernelCache::Instance(_ctx, _type, _device);
  return cache->GetKernel(filename, kernel);
}

}  // namespace gpu
<commit_msg>Add missing header<commit_after>#include "gpu.h"

#include <cassert>
#include <cstring>
#include <iostream>

#ifdef __APPLE__
#  include <OpenGL/opengl.h>
#elif defined (_WIN32)
#  define NOMINMAX
#  include "Windows.h"
#else
#  include <GL/glx.h>
#endif

#include "kernel_cache.h"

namespace gpu {

static void ContextErrorCallback(const char *errinfo, const void *, size_t, void *) {
  fprintf(stderr, "Context error: %s\n", errinfo);
  assert(false);
  exit(1);
}

static void PrintDeviceInfo(cl_device_id device_id) {

  size_t strLen;
  const size_t kStrBufSz = 1024;
  union {
    char strBuf[kStrBufSz];
    cl_uint intBuf[kStrBufSz / sizeof(cl_uint)];
    size_t sizeBuf[kStrBufSz / sizeof(size_t)];
  };

  CHECK_CL(clGetDeviceInfo, device_id, CL_DEVICE_NAME, kStrBufSz, strBuf, &strLen);
  std::cout << "Device name: " << strBuf << std::endl;

  CHECK_CL(clGetDeviceInfo, device_id, CL_DEVICE_PROFILE, kStrBufSz, strBuf, &strLen);
  std::cout << "Device profile: " << strBuf << std::endl;

  CHECK_CL(clGetDeviceInfo, device_id, CL_DEVICE_VENDOR, kStrBufSz, strBuf, &strLen);
  std::cout << "Device vendor: " << strBuf << std::endl;

  CHECK_CL(clGetDeviceInfo, device_id, CL_DEVICE_VERSION, kStrBufSz, strBuf, &strLen);
  std::cout << "Device version: " << strBuf << std::endl;

  CHECK_CL(clGetDeviceInfo, device_id, CL_DRIVER_VERSION, kStrBufSz, strBuf, &strLen);
  std::cout << "Device driver version: " << strBuf << std::endl;

  CHECK_CL(clGetDeviceInfo, device_id, CL_DEVICE_ADDRESS_BITS, kStrBufSz, strBuf,
           &strLen);
  std::cout << "Device driver address bits: " << intBuf[0] << std::endl;

  CHECK_CL(clGetDeviceInfo, device_id, CL_DEVICE_MAX_WORK_GROUP_SIZE, kStrBufSz,
           strBuf, &strLen);
  std::cout << "Max work group size: " << sizeBuf[0] << std::endl;

  CHECK_CL(clGetDeviceInfo, device_id, CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS, kStrBufSz,
           strBuf, &strLen);
  std::cout << "Max work item dimensions: " << intBuf[0] << std::endl;
  assert(*(reinterpret_cast<cl_uint *>(strBuf)) >= 2);

  CHECK_CL(clGetDeviceInfo, device_id, CL_DEVICE_GLOBAL_MEM_SIZE, kStrBufSz,
           strBuf, &strLen);
  std::cout << "Total global bytes available: " << intBuf[0] << std::endl;

  CHECK_CL(clGetDeviceInfo, device_id, CL_DEVICE_LOCAL_MEM_SIZE, kStrBufSz,
           strBuf, &strLen);
  std::cout << "Total local bytes available: " << intBuf[0] << std::endl;

  CHECK_CL(clGetDeviceInfo, device_id, CL_DEVICE_MAX_MEM_ALLOC_SIZE, kStrBufSz,
           strBuf, &strLen);
  std::cout << "Total size of memory allocatable: " << intBuf[0] << std::endl;

  CHECK_CL(clGetDeviceInfo, device_id, CL_DEVICE_MAX_WORK_ITEM_SIZES, kStrBufSz, strBuf, &strLen);
  size_t nSizeElements = strLen / sizeof(size_t);
  std::cout << "Max work item sizes: (";
  size_t *dimSizes = (size_t *)(strBuf);
  for(size_t j = 0; j < nSizeElements; j++) {
    std::cout << dimSizes[j] << ((j == nSizeElements - 1)? "" : ", ");
  }
  std::cout << ")" << std::endl;

  CHECK_CL(clGetDeviceInfo, device_id, CL_DEVICE_EXTENSIONS, kStrBufSz, strBuf, &strLen);
  std::cout << "Device extensions: " << std::endl;
  for (size_t k = 0; k < strLen; ++k) {
    if (strBuf[k] == ',' || strBuf[k] == ' ') {
      strBuf[k] = '\0';
    }
  }

  std::cout << "  " << strBuf << std::endl;
  for (size_t k = 1; k < strLen; ++k) {
    if (strBuf[k] == '\0' && k < strLen - 1) {
      std::cout << "  " << (strBuf + k + 1) << std::endl;
    }
  }

  cl_device_type deviceType;
  size_t deviceTypeSz;
  CHECK_CL(clGetDeviceInfo, device_id, CL_DEVICE_TYPE, sizeof(cl_device_type), &deviceType, &deviceTypeSz);
  if(deviceType & CL_DEVICE_TYPE_CPU) {
    std::cout << "Device driver type: CPU" << std::endl;
  }
  if(deviceType & CL_DEVICE_TYPE_GPU) {
    std::cout << "Device driver type: GPU" << std::endl;
  }
  if(deviceType & CL_DEVICE_TYPE_ACCELERATOR) {
    std::cout << "Device driver type: ACCELERATOR" << std::endl;
  }
  if(deviceType & CL_DEVICE_TYPE_DEFAULT) {
    std::cout << "Device driver type: DEFAULT" << std::endl;
  }
}

static std::vector<cl_context_properties> GetSharedCLGLProps() {
  std::vector<cl_context_properties> props;
#ifdef __APPLE__
  // Get current CGL Context and CGL Share group
  CGLContextObj kCGLContext = CGLGetCurrentContext();
  CGLShareGroupObj kCGLShareGroup = CGLGetShareGroup(kCGLContext);

  props.push_back(CL_CONTEXT_PROPERTY_USE_CGL_SHAREGROUP_APPLE);
  props.push_back((cl_context_properties)kCGLShareGroup);
  props.push_back(0);

#elif defined (_WIN32)

  // OpenGL context
  props.push_back(CL_GL_CONTEXT_KHR);
  props.push_back((cl_context_properties)wglGetCurrentContext());

  // HDC used to create the OpenGL context
  props.push_back(CL_WGL_HDC_KHR);
  props.push_back((cl_context_properties)wglGetCurrentDC());

  props.push_back(0);

#else  // Linux??

  props.push_back(CL_GL_CONTEXT_KHR);
  props.push_back((cl_context_properties) glXGetCurrentContext());
  props.push_back(CL_GLX_DISPLAY_KHR);
  props.push_back((cl_context_properties) glXGetCurrentDisplay());
  props.push_back(0);

#endif

  return std::move(props);
}

static void CreateCLContext(cl_context *result, const cl_context_properties *props,
                            cl_device_id device) {
  cl_int errCreateContext;
  *result = clCreateContext(props, 1, &device, ContextErrorCallback, NULL,
                            &errCreateContext);
  CHECK_CL((cl_int), errCreateContext);
}

static cl_device_id GetDeviceForSharedContext(cl_context ctx) {
  size_t device_id_size_bytes;
  cl_device_id device;

#ifndef __APPLE__
  std::vector<cl_context_properties> props = GetSharedCLGLProps();

  typedef CL_API_ENTRY cl_int(CL_API_CALL *CtxInfoFunc)
    (const cl_context_properties *properties, cl_gl_context_info param_name,
    size_t param_value_size, void *param_value, size_t *param_value_size_ret);
  static CtxInfoFunc getCtxInfoFunc = NULL;
#ifndef CL_VERSION_1_1
  getCtxInfoFunc = reinterpret_cast<CtxInfoFunc>(
    clGetExtensionFunctionAddress("clGetGLContextInfoKHR"));
#else
  cl_platform_id platform;
  CHECK_CL(clGetPlatformIDs, 1, &platform, NULL);
  std::vector<cl_context_properties> extra_props = { CL_CONTEXT_PLATFORM, (cl_context_properties)platform };
  extra_props.insert(extra_props.end(), props.begin(), props.end());
  props = extra_props;

  getCtxInfoFunc = reinterpret_cast<CtxInfoFunc>(
    clGetExtensionFunctionAddressForPlatform(platform, "clGetGLContextInfoKHR"));
#endif  // CL_VERSION_1_1

  assert(getCtxInfoFunc);
  CHECK_CL(getCtxInfoFunc, props.data(), CL_CURRENT_DEVICE_FOR_GL_CONTEXT_KHR,
    sizeof(device), &device, &device_id_size_bytes);
#else
  // Get current CGL Context and CGL Share group
  CGLContextObj kCGLContext = CGLGetCurrentContext();
  // And now we can ask OpenCL which particular device is being used by
  // OpenGL to do the rendering, currently:
  clGetGLContextInfoAPPLE(ctx, kCGLContext,
    CL_CGL_DEVICE_FOR_CURRENT_VIRTUAL_SCREEN_APPLE,
    sizeof(device), &device, &device_id_size_bytes);
#endif  // __APPLE
  // If we're sharing an openGL context, there should really only
  // be one device ID...
  assert(device_id_size_bytes == sizeof(cl_device_id));
  return device;
}

static std::vector<cl_device_id> GetAllDevicesForContext(cl_context ctx) {
  std::vector<cl_device_id> devices(16);
  size_t nDeviceIds;
  CHECK_CL(clGetContextInfo, ctx, CL_CONTEXT_DEVICES, devices.size() * sizeof(cl_device_id),
    devices.data(), &nDeviceIds);
  nDeviceIds /= sizeof(cl_device_id);
  devices.resize(nDeviceIds);
  return std::move(devices);
}

GPUContext::~GPUContext() {
  GPUKernelCache::Instance(_ctx, _type, _device)->Clear();
  CHECK_CL(clReleaseCommandQueue, _command_queue);
  CHECK_CL(clReleaseContext, _ctx);
}

std::unique_ptr<GPUContext> GPUContext::InitializeOpenCL(bool share_opengl) {
  const cl_uint kMaxPlatforms = 8;
  cl_platform_id platforms[kMaxPlatforms];
  cl_uint nPlatforms;
  int platform_idx = -1;

#ifdef NDEBUG
  CHECK_CL(clGetPlatformIDs, kMaxPlatforms, platforms, &nPlatforms);
#else
  CHECK_CL(clGetPlatformIDs, kMaxPlatforms, NULL, &nPlatforms);
  std::cout << "OpenCL has " << nPlatforms << " platform"
            << ((nPlatforms != 1)? "s" : "")
            << " available. Querying... " << std::endl;
  CHECK_CL(clGetPlatformIDs, nPlatforms, platforms, &nPlatforms);

  size_t strLen;
  for (cl_uint i = 0; i < nPlatforms; i++) {
    char strBuf[256];

    std::cout << std::endl;
    std::cout << "Platform " << i << " info:" << std::endl;

    CHECK_CL(clGetPlatformInfo, platforms[i], CL_PLATFORM_PROFILE, 256, strBuf, &strLen);
    std::cout << "Platform profile: " << strBuf << std::endl;

    CHECK_CL(clGetPlatformInfo, platforms[i], CL_PLATFORM_VERSION, 256, strBuf, &strLen);
    std::cout << "Platform version: " << strBuf << std::endl;

    CHECK_CL(clGetPlatformInfo, platforms[i], CL_PLATFORM_NAME, 256, strBuf, &strLen);
    std::cout << "Platform name: " << strBuf << std::endl;

    bool isCPUOnly = false;
    if (strstr(strBuf, "CPU Only")) {
      isCPUOnly = true;
    }

    CHECK_CL(clGetPlatformInfo, platforms[i], CL_PLATFORM_VENDOR, 256, strBuf, &strLen);
    std::cout << "Platform vendor: " << strBuf << std::endl;

    bool isIntel = false;
    if (strstr(strBuf, "Intel")) {
      isIntel = true;
    }

    if (isCPUOnly && isIntel) {
      platform_idx = i;
    }
  }
#endif

  const cl_uint kMaxDevices = 8;
  cl_device_id devices[kMaxDevices];
  cl_uint nDevices;

  cl_device_type device_type = CL_DEVICE_TYPE_GPU;
  if (platform_idx >= 0) {
    std::cout << "========================================";
    std::cout << "========================================" << std::endl;
    std::cout << "========================================";
    std::cout << "========================================" << std::endl;
    std::cout << "WARNING: Running on the CPU" << std::endl;
    std::cout << "========================================";
    std::cout << "========================================" << std::endl;
    std::cout << "========================================";
    std::cout << "========================================" << std::endl;
    device_type = CL_DEVICE_TYPE_CPU;
  } else {
    platform_idx = 0;
  }

  cl_platform_id platform = platforms[platform_idx];
  CHECK_CL(clGetDeviceIDs, platform, device_type, kMaxDevices, devices, &nDevices);

#ifndef NDEBUG
  std::cout << std::endl;
  std::cout << "Found " << nDevices << " device" << (nDevices == 1 ? "" : "s")
    << " on platform " << platform_idx << std::endl;

  for (cl_uint i = 0; i < nDevices; i++) {
    gpu::PrintDeviceInfo(devices[i]);
  }

  std::cout << std::endl;
#endif

  // Create OpenCL context...
  cl_context ctx;
  std::vector<cl_context_properties> props = {
    CL_CONTEXT_PLATFORM, (cl_context_properties)platform
  };

  if (share_opengl) {
    std::vector<cl_context_properties> clgl_props = std::move(GetSharedCLGLProps());
    props.insert(props.end(), clgl_props.begin(), clgl_props.end());
  }
  else {
    props.push_back(0);
  }

  CreateCLContext(&ctx, props.data(), devices[0]);

  // We got the context...
  std::unique_ptr<GPUContext> gpu_ctx =
    std::unique_ptr<GPUContext>(new GPUContext);
  gpu_ctx->_ctx = ctx;

  if (device_type == CL_DEVICE_TYPE_CPU) {
    gpu_ctx->_type = eContextType_IntelCPU;
  } else {
    gpu_ctx->_type = eContextType_GenericGPU;
  }

  // The device...
  if (share_opengl) {
    gpu_ctx->_device = GetDeviceForSharedContext(ctx);
  } else {
    std::vector<cl_device_id> ds = std::move(GetAllDevicesForContext(ctx));
    assert(ds.size() > 0);
    assert(ds[0] == devices[0]);
    gpu_ctx->_device = ds[0];
  }

  // And the command queue...
  cl_int errCreateCommandQueue;
#ifndef CL_VERSION_2_0
  gpu_ctx->_command_queue = clCreateCommandQueue(ctx, gpu_ctx->_device, 0, &errCreateCommandQueue);
#else
  gpu_ctx->_command_queue = clCreateCommandQueueWithProperties(ctx, gpu_ctx->_device, 0, &errCreateCommandQueue);
#endif
  CHECK_CL((cl_int), errCreateCommandQueue);

  return std::move(gpu_ctx);
}

void GPUContext::PrintDeviceInfo() const {
  gpu::PrintDeviceInfo(_device);
}

cl_kernel GPUContext::GetOpenCLKernel(const std::string &filename, const std::string &kernel) const {
  GPUKernelCache *cache = GPUKernelCache::Instance(_ctx, _type, _device);
  return cache->GetKernel(filename, kernel);
}

}  // namespace gpu
<|endoftext|>


<commit_before>/***************************************************************************
 *   Copyright (c) Alexander Golubev (Fat-Zer) <fatzer2@gmail.com> 2015    *
 *                                                                         *
 *   This file is part of the FreeCAD CAx development system.              *
 *                                                                         *
 *   This library is free software; you can redistribute it and/or         *
 *   modify it under the terms of the GNU Library General Public           *
 *   License as published by the Free Software Foundation; either          *
 *   version 2 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 Library General Public License for more details.                  *
 *                                                                         *
 *   You should have received a copy of the GNU Library General Public     *
 *   License along with this library; see the file COPYING.LIB. If not,    *
 *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
 *   Suite 330, Boston, MA  02111-1307, USA                                *
 *                                                                         *
 ***************************************************************************/

#include "PreCompiled.h"
#include "OriginGroupExtension.h"

#ifndef _PreComp_
#endif

#include <Base/Exception.h>

#include <App/Document.h>
#include "Origin.h"

#include "GeoFeature.h"

using namespace App;

EXTENSION_PROPERTY_SOURCE(App::OriginGroupExtension, App::GeoFeatureGroupExtension)

OriginGroupExtension::OriginGroupExtension () {

    initExtensionType(OriginGroupExtension::getExtensionClassTypeId());

    EXTENSION_ADD_PROPERTY_TYPE ( Origin, (0), 0, App::Prop_Hidden, "Origin linked to the group" );
    Origin.setScope(LinkScope::Child);
}

OriginGroupExtension::~OriginGroupExtension ()
{ }

App::Origin *OriginGroupExtension::getOrigin () const {
    App::DocumentObject *originObj = Origin.getValue ();

    if ( !originObj ) {
        std::stringstream err;
        err << "Can't find Origin for \"" << getExtendedObject()->getNameInDocument () << "\"";
        throw Base::RuntimeError ( err.str().c_str () );

    } else if (! originObj->isDerivedFrom ( App::Origin::getClassTypeId() ) ) {
        std::stringstream err;
        err << "Bad object \"" << originObj->getNameInDocument () << "\"(" << originObj->getTypeId().getName()
            << ") linked to the Origin of \"" << getExtendedObject()->getNameInDocument () << "\"";
        throw Base::RuntimeError ( err.str().c_str () );
    } else {
            return static_cast<App::Origin *> ( originObj );
    }
}

App::DocumentObject *OriginGroupExtension::getGroupOfObject (const DocumentObject* obj) {

    if(!obj)
        return nullptr;

    bool isOriginFeature = obj->isDerivedFrom(App::OriginFeature::getClassTypeId());

    auto list = obj->getInList();
    for (auto o : list) {
        if(o->hasExtension(App::OriginGroupExtension::getExtensionClassTypeId()))
            return o;
        else if (isOriginFeature && o->isDerivedFrom(App::Origin::getClassTypeId())) {
            auto result = getGroupOfObject(o);
            if(result)
                return result;
        }
    }

    return nullptr;
}

short OriginGroupExtension::extensionMustExecute() {
    if (Origin.isTouched ()) {
        return 1;
    } else {
        return GeoFeatureGroupExtension::extensionMustExecute();
    }
}

App::DocumentObjectExecReturn *OriginGroupExtension::extensionExecute() {
    try { // try to find all base axis and planes in the origin
        getOrigin ();
    } catch (const Base::Exception &ex) {
        //getExtendedObject()->setError ();
        return new App::DocumentObjectExecReturn ( ex.what () );
    }

    return GeoFeatureGroupExtension::extensionExecute ();
}

void OriginGroupExtension::onExtendedSetupObject () {
    App::Document *doc = getExtendedObject()->getDocument ();

    App::DocumentObject *originObj = doc->addObject ( "App::Origin", "Origin" );

    assert ( originObj && originObj->isDerivedFrom ( App::Origin::getClassTypeId () ) );
    Origin.setValue (originObj);

    GeoFeatureGroupExtension::onExtendedSetupObject ();
}

void OriginGroupExtension::onExtendedUnsetupObject () {
    App::DocumentObject *origin = Origin.getValue ();
    if (origin && !origin->isDeleting ()) {
        origin->getDocument ()->remObject (origin->getNameInDocument());
    }

    GeoFeatureGroupExtension::onExtendedUnsetupObject ();
}

void OriginGroupExtension::relinkToOrigin(App::DocumentObject* obj)
{
    //we get all links and replace the origin objects if needed (subnames need not to change, they
    //would stay the same)
    std::vector< App::DocumentObject* > result;
    std::vector<App::Property*> list;
    obj->getPropertyList(list);
    for(App::Property* prop : list) {
        if(prop->getTypeId().isDerivedFrom(App::PropertyLink::getClassTypeId())) {

            auto p = static_cast<App::PropertyLink*>(prop);
            if(!p->getValue() || !p->getValue()->isDerivedFrom(App::OriginFeature::getClassTypeId()))
                continue;

            p->setValue(getOrigin()->getOriginFeature(static_cast<OriginFeature*>(p->getValue())->Role.getValue()));
        }
        else if(prop->getTypeId().isDerivedFrom(App::PropertyLinkList::getClassTypeId())) {
            auto p = static_cast<App::PropertyLinkList*>(prop);
            auto vec = p->getValues();
            std::vector<App::DocumentObject*> result;
            bool changed = false;
            for(App::DocumentObject* o : vec) {
                if(!o || !o->isDerivedFrom(App::OriginFeature::getClassTypeId()))
                    result.push_back(o);
                else {
                    result.push_back(getOrigin()->getOriginFeature(static_cast<OriginFeature*>(o)->Role.getValue()));
                    changed = true;
                }
            }
            if(changed)
                static_cast<App::PropertyLinkList*>(prop)->setValues(result);
        }
        else if(prop->getTypeId().isDerivedFrom(App::PropertyLinkSub::getClassTypeId())) {
            auto p = static_cast<App::PropertyLinkSub*>(prop);
            if(!p->getValue() || !p->getValue()->isDerivedFrom(App::OriginFeature::getClassTypeId()))
                continue;

            std::vector<std::string> subValues = p->getSubValues();
            p->setValue(getOrigin()->getOriginFeature(static_cast<OriginFeature*>(p->getValue())->Role.getValue()), subValues);
        }
        else if(prop->getTypeId().isDerivedFrom(App::PropertyLinkSubList::getClassTypeId())) {
            auto p = static_cast<App::PropertyLinkList*>(prop);
            auto vec = p->getValues();
            std::vector<App::DocumentObject*> result;
            bool changed = false;
            for(App::DocumentObject* o : vec) {
                if(!o || !o->isDerivedFrom(App::OriginFeature::getClassTypeId()))
                    result.push_back(o);
                else {
                    result.push_back(getOrigin()->getOriginFeature(static_cast<OriginFeature*>(o)->Role.getValue()));
                    changed = true;
                }
            }
            if(changed)
                static_cast<App::PropertyLinkList*>(prop)->setValues(result);
        }
    }
}

std::vector< DocumentObject* > OriginGroupExtension::addObjects(std::vector<DocumentObject*> objs) {

    for(auto obj : objs)
        relinkToOrigin(obj);

    return App::GeoFeatureGroupExtension::addObjects(objs);
}

bool OriginGroupExtension::hasObject(const DocumentObject* obj, bool recursive) const {

    if(Origin.getValue() && (obj == getOrigin() || getOrigin()->hasObject(obj)))
        return true;

    return App::GroupExtension::hasObject(obj, recursive);
}

// Python feature ---------------------------------------------------------

namespace App {
EXTENSION_PROPERTY_SOURCE_TEMPLATE(App::OriginGroupExtensionPython, App::OriginGroupExtension)

// explicit template instantiation
template class AppExport ExtensionPythonT<GroupExtensionPythonT<OriginGroupExtension>>;
}
<commit_msg>OriginGroupExtension: fix wrong static_cast<commit_after>/***************************************************************************
 *   Copyright (c) Alexander Golubev (Fat-Zer) <fatzer2@gmail.com> 2015    *
 *                                                                         *
 *   This file is part of the FreeCAD CAx development system.              *
 *                                                                         *
 *   This library is free software; you can redistribute it and/or         *
 *   modify it under the terms of the GNU Library General Public           *
 *   License as published by the Free Software Foundation; either          *
 *   version 2 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 Library General Public License for more details.                  *
 *                                                                         *
 *   You should have received a copy of the GNU Library General Public     *
 *   License along with this library; see the file COPYING.LIB. If not,    *
 *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
 *   Suite 330, Boston, MA  02111-1307, USA                                *
 *                                                                         *
 ***************************************************************************/

#include "PreCompiled.h"
#include "OriginGroupExtension.h"

#ifndef _PreComp_
#endif

#include <Base/Exception.h>

#include <App/Document.h>
#include "Origin.h"

#include "GeoFeature.h"

using namespace App;

EXTENSION_PROPERTY_SOURCE(App::OriginGroupExtension, App::GeoFeatureGroupExtension)

OriginGroupExtension::OriginGroupExtension () {

    initExtensionType(OriginGroupExtension::getExtensionClassTypeId());

    EXTENSION_ADD_PROPERTY_TYPE ( Origin, (0), 0, App::Prop_Hidden, "Origin linked to the group" );
    Origin.setScope(LinkScope::Child);
}

OriginGroupExtension::~OriginGroupExtension ()
{ }

App::Origin *OriginGroupExtension::getOrigin () const {
    App::DocumentObject *originObj = Origin.getValue ();

    if ( !originObj ) {
        std::stringstream err;
        err << "Can't find Origin for \"" << getExtendedObject()->getNameInDocument () << "\"";
        throw Base::RuntimeError ( err.str().c_str () );

    } else if (! originObj->isDerivedFrom ( App::Origin::getClassTypeId() ) ) {
        std::stringstream err;
        err << "Bad object \"" << originObj->getNameInDocument () << "\"(" << originObj->getTypeId().getName()
            << ") linked to the Origin of \"" << getExtendedObject()->getNameInDocument () << "\"";
        throw Base::RuntimeError ( err.str().c_str () );
    } else {
            return static_cast<App::Origin *> ( originObj );
    }
}

App::DocumentObject *OriginGroupExtension::getGroupOfObject (const DocumentObject* obj) {

    if(!obj)
        return nullptr;

    bool isOriginFeature = obj->isDerivedFrom(App::OriginFeature::getClassTypeId());

    auto list = obj->getInList();
    for (auto o : list) {
        if(o->hasExtension(App::OriginGroupExtension::getExtensionClassTypeId()))
            return o;
        else if (isOriginFeature && o->isDerivedFrom(App::Origin::getClassTypeId())) {
            auto result = getGroupOfObject(o);
            if(result)
                return result;
        }
    }

    return nullptr;
}

short OriginGroupExtension::extensionMustExecute() {
    if (Origin.isTouched ()) {
        return 1;
    } else {
        return GeoFeatureGroupExtension::extensionMustExecute();
    }
}

App::DocumentObjectExecReturn *OriginGroupExtension::extensionExecute() {
    try { // try to find all base axis and planes in the origin
        getOrigin ();
    } catch (const Base::Exception &ex) {
        //getExtendedObject()->setError ();
        return new App::DocumentObjectExecReturn ( ex.what () );
    }

    return GeoFeatureGroupExtension::extensionExecute ();
}

void OriginGroupExtension::onExtendedSetupObject () {
    App::Document *doc = getExtendedObject()->getDocument ();

    App::DocumentObject *originObj = doc->addObject ( "App::Origin", "Origin" );

    assert ( originObj && originObj->isDerivedFrom ( App::Origin::getClassTypeId () ) );
    Origin.setValue (originObj);

    GeoFeatureGroupExtension::onExtendedSetupObject ();
}

void OriginGroupExtension::onExtendedUnsetupObject () {
    App::DocumentObject *origin = Origin.getValue ();
    if (origin && !origin->isDeleting ()) {
        origin->getDocument ()->remObject (origin->getNameInDocument());
    }

    GeoFeatureGroupExtension::onExtendedUnsetupObject ();
}

void OriginGroupExtension::relinkToOrigin(App::DocumentObject* obj)
{
    //we get all links and replace the origin objects if needed (subnames need not to change, they
    //would stay the same)
    std::vector< App::DocumentObject* > result;
    std::vector<App::Property*> list;
    obj->getPropertyList(list);
    for(App::Property* prop : list) {
        if(prop->getTypeId().isDerivedFrom(App::PropertyLink::getClassTypeId())) {

            auto p = static_cast<App::PropertyLink*>(prop);
            if(!p->getValue() || !p->getValue()->isDerivedFrom(App::OriginFeature::getClassTypeId()))
                continue;

            p->setValue(getOrigin()->getOriginFeature(static_cast<OriginFeature*>(p->getValue())->Role.getValue()));
        }
        else if(prop->getTypeId().isDerivedFrom(App::PropertyLinkList::getClassTypeId())) {
            auto p = static_cast<App::PropertyLinkList*>(prop);
            auto vec = p->getValues();
            std::vector<App::DocumentObject*> result;
            bool changed = false;
            for(App::DocumentObject* o : vec) {
                if(!o || !o->isDerivedFrom(App::OriginFeature::getClassTypeId()))
                    result.push_back(o);
                else {
                    result.push_back(getOrigin()->getOriginFeature(static_cast<OriginFeature*>(o)->Role.getValue()));
                    changed = true;
                }
            }
            if(changed)
                static_cast<App::PropertyLinkList*>(prop)->setValues(result);
        }
        else if(prop->getTypeId().isDerivedFrom(App::PropertyLinkSub::getClassTypeId())) {
            auto p = static_cast<App::PropertyLinkSub*>(prop);
            if(!p->getValue() || !p->getValue()->isDerivedFrom(App::OriginFeature::getClassTypeId()))
                continue;

            std::vector<std::string> subValues = p->getSubValues();
            p->setValue(getOrigin()->getOriginFeature(static_cast<OriginFeature*>(p->getValue())->Role.getValue()), subValues);
        }
        else if(prop->getTypeId().isDerivedFrom(App::PropertyLinkSubList::getClassTypeId())) {
            auto p = static_cast<App::PropertyLinkSubList*>(prop);
            auto vec = p->getSubListValues();
            bool changed = false;
            for(auto &v : vec) {
                if(v.first && v.first->isDerivedFrom(App::OriginFeature::getClassTypeId())) {
                    v.first = getOrigin()->getOriginFeature(static_cast<OriginFeature*>(v.first)->Role.getValue());
                    changed = true;
                }
            }
            if(changed)
                p->setSubListValues(vec);
        }
    }
}

std::vector< DocumentObject* > OriginGroupExtension::addObjects(std::vector<DocumentObject*> objs) {

    for(auto obj : objs)
        relinkToOrigin(obj);

    return App::GeoFeatureGroupExtension::addObjects(objs);
}

bool OriginGroupExtension::hasObject(const DocumentObject* obj, bool recursive) const {

    if(Origin.getValue() && (obj == getOrigin() || getOrigin()->hasObject(obj)))
        return true;

    return App::GroupExtension::hasObject(obj, recursive);
}

// Python feature ---------------------------------------------------------

namespace App {
EXTENSION_PROPERTY_SOURCE_TEMPLATE(App::OriginGroupExtensionPython, App::OriginGroupExtension)

// explicit template instantiation
template class AppExport ExtensionPythonT<GroupExtensionPythonT<OriginGroupExtension>>;
}
<|endoftext|>