<commit_before>// Jubatus: Online machine learning framework for distributed environment
// Copyright (C) 2011,2012 Preferred Infrastracture and Nippon Telegraph and Telephone 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 Street, Fifth Floor, Boston, MA  02110-1301  USA

#include "jubatus_serv.hpp"
#include "../common/util.hpp"
#include "../common/cht.hpp"
#include "../common/exception.hpp"
#include "server_util.hpp"

#include <fstream>
#include <sstream>
#include <pficommon/system/time_util.h>

using std::vector;
using std::string;
using pfi::network::mprpc::rpc_client;
using pfi::lang::function;

using pfi::system::time::clock_time;
using pfi::system::time::get_clock_time;

namespace jubatus { namespace framework {

    jubatus_serv::jubatus_serv(const server_argv& a, const std::string& base_path):
      a_(a),
      update_count_(0),
#ifdef HAVE_ZOOKEEPER_H
      mixer_(new mixer(a_.name, a_.interval_count, a_.interval_sec,
                       pfi::lang::bind(&jubatus_serv::do_mix, this, pfi::lang::_1))),
      use_cht_(false),
#endif
      base_path_(a_.tmpdir)
    {
    };

    int jubatus_serv::start(pfi::network::mprpc::rpc_server& serv){

#ifdef HAVE_ZOOKEEPER_H
    if(! a_.is_standalone()){
      zk_ = pfi::lang::shared_ptr<jubatus::common::lock_service>
	(common::create_lock_service("zk", a_.z, a_.timeout, "logfile_jubatus_serv"));
      ls = zk_;
      jubatus::common::prepare_jubatus(*zk_);

      if( a_.join ){ // join to the existing cluster with -j option
        join_to_cluster(zk_);
      }

      if( use_cht_ ){

        jubatus::common::cht::setup_cht_dir(*zk_, a_.name);
        jubatus::common::cht ht(zk_, a_.name);
        ht.register_node(a_.eth, a_.port);
      }

      mixer_->set_zk(zk_);
      register_actor(*zk_, a_.name, a_.eth, a_.port);
      mixer_->start();
    }
#endif

    { LOG(INFO) << "running in port=" << a_.port; }
    return serv.serv(a_.port, a_.threadnum);

    }

    void jubatus_serv::register_mixable(mixable0* m){
#ifdef HAVE_ZOOKEEPER_H
      mixables_.push_back(m);
#endif
    };

    void jubatus_serv::use_cht(){
#ifdef HAVE_ZOOKEEPER_H
      use_cht_ = true;
#endif
    };

  std::map<std::string, std::map<std::string,std::string> > jubatus_serv::get_status(int) const {
    std::map<std::string, std::string> data;
    util::get_machine_status(data);

    data["timeout"] = pfi::lang::lexical_cast<std::string>(a_.timeout);
    data["threadnum"] = pfi::lang::lexical_cast<std::string>(a_.threadnum);
    data["tmpdir"] = a_.tmpdir;
    data["interval_sec"] = pfi::lang::lexical_cast<std::string>(a_.interval_sec);
    data["interval_count"] = pfi::lang::lexical_cast<std::string>(a_.interval_count);
    data["is_standalone"] = pfi::lang::lexical_cast<std::string>(a_.is_standalone());
    data["VERSION"] = JUBATUS_VERSION;
    data["PROGNAME"] = JUBATUS_APPNAME;

    data["update_count"] = pfi::lang::lexical_cast<std::string>(update_count_);

#ifdef HAVE_ZOOKEEPER_H
    mixer_->get_status(data);
    data["zk"] = a_.z;
    data["use_cht"] = pfi::lang::lexical_cast<std::string>(use_cht_);
#endif

    std::map<std::string, std::map<std::string,std::string> > ret;
    ret[get_server_identifier()] = data;
    return ret;
  };

    std::string jubatus_serv::get_server_identifier()const{
      std::stringstream ss;
      ss << a_.eth;
      ss << "_";
      ss << a_.port;
      return ss.str();
    };

    //here
#ifdef HAVE_ZOOKEEPER_H
    void jubatus_serv::join_to_cluster(pfi::lang::shared_ptr<jubatus::common::lock_service> z){
    std::vector<std::string> list;
    std::string path = common::ACTOR_BASE_PATH + "/" + a_.name + "/nodes";
    z->list(path, list);
    if(not list.empty()){
      common::lock_service_mutex zlk(*z, common::ACTOR_BASE_PATH + "/" + a_.name + "/master_lock");
      while(not zlk.try_lock()){ ; }
      size_t i = rand() % list.size();
      std::string ip;
      int port;
      common::revert(list[i], ip, port);
      pfi::network::mprpc::rpc_client c(ip, port, a_.timeout);

      pfi::lang::function<std::string()> f = c.call<std::string()>("get_storage");
      std::stringstream ss( f() );
      for(size_t i = 0;i<mixables_.size(); ++i){
        mixables_[i]->clear();
        mixables_[i]->load(ss);
      }
    }
  };

    std::string jubatus_serv::get_storage(int i){
    std::stringstream ss;
    for(size_t i=0; i<mixables_.size(); ++i){
      mixables_[i]->save(ss);
    }
    return ss.str();
  }

    std::vector<std::string> jubatus_serv::get_diff_impl(int){
    // if(mixables_.empty()){
    //   //throw config_not_set(); nothing to mix
    // }
    std::vector<std::string> o;
    {
      scoped_lock lk(rlock(m_));
      for(size_t i=0; i<mixables_.size(); ++i){
        o.push_back(mixables_[i]->get_diff());
      }
    }
    return o;
  };

    int jubatus_serv::put_diff_impl(std::vector<std::string> unpacked){
    scoped_lock lk(wlock(m_));
    if(unpacked.size() != mixables_.size()){
      //deserialization error
    }
    for(size_t i=0; i<mixables_.size(); ++i){
      mixables_[i]->put_diff(unpacked[i]);
    }
    return 0;
  };

    void jubatus_serv::do_mix(const std::vector<std::pair<std::string,int> >& v){
      vector<string> accs;
      vector<string> serialized_diffs;
      clock_time start = get_clock_time();
      for(size_t s = 0; s < v.size(); ++s ){
        try{
          rpc_client c(v[s].first, v[s].second, a_.timeout);
          function<vector<string>(int)> get_diff_fun = c.call<vector<string>(int)>("get_diff");
          serialized_diffs = get_diff_fun(0);
        }catch(std::exception& e){
          LOG(ERROR) << e.what();
          continue;
        }
        scoped_lock lk(rlock(m_)); // model_ should not be in mix (reduce)?
        if(accs.empty()){
          accs = serialized_diffs;
        }else{
          for(size_t i=0; i<mixables_.size(); ++i){
            // FIXME: very inefficient but what sucks is type system of C++
            mixables_[i]->reduce(serialized_diffs[i], accs[i]);
          }
        }
      }

      for(size_t s = 0; s < v.size(); ++s ){
        try{
          rpc_client c(v[s].first, v[s].second, a_.timeout);
          function<int(vector<string>)> put_diff_fun = c.call<int(vector<string>)>("put_diff");
          put_diff_fun(accs);
        }catch(std::exception& e){
          LOG(ERROR) << e.what();
          continue;
        }
      }
      clock_time end = get_clock_time();
      DLOG(INFO) << "mixed with " << v.size() << " servers in " << (double)(end - start) << " secs.";
      size_t s = 0;
      for(size_t i=0; i<accs.size(); ++i){
        s+=accs[i].size();
      }
      DLOG(INFO) << s << " bytes (serialized data) has been put.";
    }
#endif

    int jubatus_serv::save(std::string id)  {
      std::string ofile;
      build_local_path_(ofile, "jubatus", id);

      std::ofstream ofs(ofile.c_str(), std::ios::trunc|std::ios::binary);
      if(!ofs){
        throw std::runtime_error(ofile + ": cannot open (" + pfi::lang::lexical_cast<std::string>(errno) + ")" );
      }
      try{
        for(size_t i=0; i<mixables_.size(); ++i){
          mixables_[i]->save(ofs);
        }
        ofs.close();
        LOG(INFO) << "saved to " << ofile;
        return 0;
      }catch(const std::exception& e){
        return -1;
      }
    }

    int jubatus_serv::load(std::string id) {
      std::string ifile;
      build_local_path_(ifile, "jubatus", id);

      std::ifstream ifs(ifile.c_str(), std::ios::binary);
      if(!ifs)throw std::runtime_error(ifile + ": cannot open (" + pfi::lang::lexical_cast<std::string>(errno) + ")" );
      try{
        for(size_t i = 0;i<mixables_.size(); ++i){
          mixables_[i]->clear();
          mixables_[i]->load(ifs);
        }
        ifs.close();
        this->after_load();
        return 0;
      }catch(const std::exception& e){
        ifs.close();
      }
      return -1; //expected never reaching here.
    }

}}
<commit_msg>add safety check in case of bad pointer passed to mixable set. (fixes #22)<commit_after>// Jubatus: Online machine learning framework for distributed environment
// Copyright (C) 2011,2012 Preferred Infrastracture and Nippon Telegraph and Telephone 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 Street, Fifth Floor, Boston, MA  02110-1301  USA

#include "jubatus_serv.hpp"
#include "../common/util.hpp"
#include "../common/cht.hpp"
#include "../common/exception.hpp"
#include "server_util.hpp"

#include <fstream>
#include <sstream>
#include <pficommon/system/time_util.h>

using std::vector;
using std::string;
using pfi::network::mprpc::rpc_client;
using pfi::lang::function;

using pfi::system::time::clock_time;
using pfi::system::time::get_clock_time;

namespace jubatus { namespace framework {

    jubatus_serv::jubatus_serv(const server_argv& a, const std::string& base_path):
      a_(a),
      update_count_(0),
#ifdef HAVE_ZOOKEEPER_H
      mixer_(new mixer(a_.name, a_.interval_count, a_.interval_sec,
                       pfi::lang::bind(&jubatus_serv::do_mix, this, pfi::lang::_1))),
      use_cht_(false),
#endif
      base_path_(a_.tmpdir)
    {
    };

    int jubatus_serv::start(pfi::network::mprpc::rpc_server& serv){

#ifdef HAVE_ZOOKEEPER_H
    if(! a_.is_standalone()){
      zk_ = pfi::lang::shared_ptr<jubatus::common::lock_service>
	(common::create_lock_service("zk", a_.z, a_.timeout, "logfile_jubatus_serv"));
      ls = zk_;
      jubatus::common::prepare_jubatus(*zk_);

      if( a_.join ){ // join to the existing cluster with -j option
        join_to_cluster(zk_);
      }

      if( use_cht_ ){

        jubatus::common::cht::setup_cht_dir(*zk_, a_.name);
        jubatus::common::cht ht(zk_, a_.name);
        ht.register_node(a_.eth, a_.port);
      }

      mixer_->set_zk(zk_);
      register_actor(*zk_, a_.name, a_.eth, a_.port);
      mixer_->start();
    }
#endif

    { LOG(INFO) << "running in port=" << a_.port; }
    return serv.serv(a_.port, a_.threadnum);

    }

    void jubatus_serv::register_mixable(mixable0* m){
#ifdef HAVE_ZOOKEEPER_H
      m->get_diff(); // #22 ensure m is good pointer at process startup

      mixables_.push_back(m);
#endif
    };

    void jubatus_serv::use_cht(){
#ifdef HAVE_ZOOKEEPER_H
      use_cht_ = true;
#endif
    };

  std::map<std::string, std::map<std::string,std::string> > jubatus_serv::get_status(int) const {
    std::map<std::string, std::string> data;
    util::get_machine_status(data);

    data["timeout"] = pfi::lang::lexical_cast<std::string>(a_.timeout);
    data["threadnum"] = pfi::lang::lexical_cast<std::string>(a_.threadnum);
    data["tmpdir"] = a_.tmpdir;
    data["interval_sec"] = pfi::lang::lexical_cast<std::string>(a_.interval_sec);
    data["interval_count"] = pfi::lang::lexical_cast<std::string>(a_.interval_count);
    data["is_standalone"] = pfi::lang::lexical_cast<std::string>(a_.is_standalone());
    data["VERSION"] = JUBATUS_VERSION;
    data["PROGNAME"] = JUBATUS_APPNAME;

    data["update_count"] = pfi::lang::lexical_cast<std::string>(update_count_);

#ifdef HAVE_ZOOKEEPER_H
    mixer_->get_status(data);
    data["zk"] = a_.z;
    data["use_cht"] = pfi::lang::lexical_cast<std::string>(use_cht_);
#endif

    std::map<std::string, std::map<std::string,std::string> > ret;
    ret[get_server_identifier()] = data;
    return ret;
  };

    std::string jubatus_serv::get_server_identifier()const{
      std::stringstream ss;
      ss << a_.eth;
      ss << "_";
      ss << a_.port;
      return ss.str();
    };

    //here
#ifdef HAVE_ZOOKEEPER_H
    void jubatus_serv::join_to_cluster(pfi::lang::shared_ptr<jubatus::common::lock_service> z){
    std::vector<std::string> list;
    std::string path = common::ACTOR_BASE_PATH + "/" + a_.name + "/nodes";
    z->list(path, list);
    if(not list.empty()){
      common::lock_service_mutex zlk(*z, common::ACTOR_BASE_PATH + "/" + a_.name + "/master_lock");
      while(not zlk.try_lock()){ ; }
      size_t i = rand() % list.size();
      std::string ip;
      int port;
      common::revert(list[i], ip, port);
      pfi::network::mprpc::rpc_client c(ip, port, a_.timeout);

      pfi::lang::function<std::string()> f = c.call<std::string()>("get_storage");
      std::stringstream ss( f() );
      for(size_t i = 0;i<mixables_.size(); ++i){
        mixables_[i]->clear();
        mixables_[i]->load(ss);
      }
    }
  };

    std::string jubatus_serv::get_storage(int i){
    std::stringstream ss;
    for(size_t i=0; i<mixables_.size(); ++i){
      mixables_[i]->save(ss);
    }
    return ss.str();
  }

    std::vector<std::string> jubatus_serv::get_diff_impl(int){
    // if(mixables_.empty()){
    //   //throw config_not_set(); nothing to mix
    // }
    std::vector<std::string> o;
    {
      scoped_lock lk(rlock(m_));
      for(size_t i=0; i<mixables_.size(); ++i){
        o.push_back(mixables_[i]->get_diff());
      }
    }
    return o;
  };

    int jubatus_serv::put_diff_impl(std::vector<std::string> unpacked){
    scoped_lock lk(wlock(m_));
    if(unpacked.size() != mixables_.size()){
      //deserialization error
    }
    for(size_t i=0; i<mixables_.size(); ++i){
      mixables_[i]->put_diff(unpacked[i]);
    }
    return 0;
  };

    void jubatus_serv::do_mix(const std::vector<std::pair<std::string,int> >& v){
      vector<string> accs;
      vector<string> serialized_diffs;
      clock_time start = get_clock_time();
      for(size_t s = 0; s < v.size(); ++s ){
        try{
          rpc_client c(v[s].first, v[s].second, a_.timeout);
          function<vector<string>(int)> get_diff_fun = c.call<vector<string>(int)>("get_diff");
          serialized_diffs = get_diff_fun(0);
        }catch(std::exception& e){
          LOG(ERROR) << e.what();
          continue;
        }
        scoped_lock lk(rlock(m_)); // model_ should not be in mix (reduce)?
        if(accs.empty()){
          accs = serialized_diffs;
        }else{
          for(size_t i=0; i<mixables_.size(); ++i){
            // FIXME: very inefficient but what sucks is type system of C++
            mixables_[i]->reduce(serialized_diffs[i], accs[i]);
          }
        }
      }

      for(size_t s = 0; s < v.size(); ++s ){
        try{
          rpc_client c(v[s].first, v[s].second, a_.timeout);
          function<int(vector<string>)> put_diff_fun = c.call<int(vector<string>)>("put_diff");
          put_diff_fun(accs);
        }catch(std::exception& e){
          LOG(ERROR) << e.what();
          continue;
        }
      }
      clock_time end = get_clock_time();
      DLOG(INFO) << "mixed with " << v.size() << " servers in " << (double)(end - start) << " secs.";
      size_t s = 0;
      for(size_t i=0; i<accs.size(); ++i){
        s+=accs[i].size();
      }
      DLOG(INFO) << s << " bytes (serialized data) has been put.";
    }
#endif

    int jubatus_serv::save(std::string id)  {
      std::string ofile;
      build_local_path_(ofile, "jubatus", id);

      std::ofstream ofs(ofile.c_str(), std::ios::trunc|std::ios::binary);
      if(!ofs){
        throw std::runtime_error(ofile + ": cannot open (" + pfi::lang::lexical_cast<std::string>(errno) + ")" );
      }
      try{
        for(size_t i=0; i<mixables_.size(); ++i){
          mixables_[i]->save(ofs);
        }
        ofs.close();
        LOG(INFO) << "saved to " << ofile;
        return 0;
      }catch(const std::exception& e){
        return -1;
      }
    }

    int jubatus_serv::load(std::string id) {
      std::string ifile;
      build_local_path_(ifile, "jubatus", id);

      std::ifstream ifs(ifile.c_str(), std::ios::binary);
      if(!ifs)throw std::runtime_error(ifile + ": cannot open (" + pfi::lang::lexical_cast<std::string>(errno) + ")" );
      try{
        for(size_t i = 0;i<mixables_.size(); ++i){
          mixables_[i]->clear();
          mixables_[i]->load(ifs);
        }
        ifs.close();
        this->after_load();
        return 0;
      }catch(const std::exception& e){
        ifs.close();
      }
      return -1; //expected never reaching here.
    }

}}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: appchild.cxx,v $
 *
 *  $Revision: 1.9 $
 *
 *  last change: $Author: hr $ $Date: 2007-06-27 22:55:19 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sfx2.hxx"

#ifndef GCC
#endif

#ifndef _SFX_WHITER_HXX //autogen
#include <svtools/whiter.hxx>
#endif
#ifndef _SFXENUMITEM_HXX //autogen
#include <svtools/eitem.hxx>
#endif

#include <sfx2/app.hxx>
#include "appdata.hxx"
#include "workwin.hxx"
#include <sfx2/childwin.hxx>
#include "arrdecl.hxx"
#include <sfx2/templdlg.hxx>
#include <sfx2/request.hxx>
#include <sfx2/bindings.hxx>
#include <sfx2/dispatch.hxx>
#include "sfxtypes.hxx"
#include <sfx2/module.hxx>
#include <sfx2/sfxsids.hrc>

//=========================================================================

void SfxApplication::RegisterChildWindow_Impl( SfxModule *pMod, SfxChildWinFactory *pFact )
{
    if ( pMod )
    {
        pMod->RegisterChildWindow( pFact );
        return;
    }

    if (!pAppData_Impl->pFactArr)
        pAppData_Impl->pFactArr = new SfxChildWinFactArr_Impl;

//#ifdef DBG_UTIL
    for (USHORT nFactory=0; nFactory<pAppData_Impl->pFactArr->Count(); ++nFactory)
    {
        if (pFact->nId ==  (*pAppData_Impl->pFactArr)[nFactory]->nId)
        {
            pAppData_Impl->pFactArr->Remove( nFactory );
//          DBG_ERROR("ChildWindow mehrfach registriert!");
//          return;
        }
    }
//#endif

    pAppData_Impl->pFactArr->C40_INSERT(
        SfxChildWinFactory, pFact, pAppData_Impl->pFactArr->Count() );
}

void SfxApplication::RegisterChildWindowContext_Impl( SfxModule *pMod, USHORT nId,
        SfxChildWinContextFactory *pFact)
{
    SfxChildWinFactArr_Impl *pFactories;
    SfxChildWinFactory *pF = NULL;
    if ( pMod )
    {
        // Modul "ubergeben, ChildwindowFactory dort suchen
        pFactories = pMod->GetChildWinFactories_Impl();
        if ( pFactories )
        {
            USHORT nCount = pFactories->Count();
            for (USHORT nFactory=0; nFactory<nCount; ++nFactory)
            {
                SfxChildWinFactory *pFac = (*pFactories)[nFactory];
                if ( nId == pFac->nId )
                {
                    // Factory gefunden, Context dort registrieren
                    pF = pFac;
                    break;
                }
            }
        }
    }

    if ( !pF )
    {
        // Factory an der Application suchen
        DBG_ASSERT( pAppData_Impl, "Keine AppDaten!" );
        DBG_ASSERT( pAppData_Impl->pFactArr, "Keine Factories!" );

        pFactories = pAppData_Impl->pFactArr;
        USHORT nCount = pFactories->Count();
        for (USHORT nFactory=0; nFactory<nCount; ++nFactory)
        {
            SfxChildWinFactory *pFac = (*pFactories)[nFactory];
            if ( nId == pFac->nId )
            {
                if ( pMod )
                {
                    // Wenn der Context von einem Modul registriert wurde,
                    // mu\s die ChildwindowFactory auch dort zur Verf"ugung
                    // stehen, sonst m"u\ste sich die Contextfactory im DLL-Exit
                    // wieder abmelden !
                    pF = new SfxChildWinFactory( pFac->pCtor, pFac->nId,
                            pFac->nPos );
                    pMod->RegisterChildWindow( pF );
                }
                else
                    pF = pFac;
                break;
            }
        }
    }

    if ( pF )
    {
        if ( !pF->pArr )
            pF->pArr = new SfxChildWinContextArr_Impl;
        pF->pArr->C40_INSERT( SfxChildWinContextFactory, pFact, pF->pArr->Count() );
        return;
    }

    DBG_ERROR( "Kein ChildWindow fuer diesen Context!" );
}

//--------------------------------------------------------------------

SfxChildWinFactArr_Impl& SfxApplication::GetChildWinFactories_Impl() const
{
    return ( *(pAppData_Impl->pFactArr));
}

//--------------------------------------------------------------------

SfxTemplateDialog* SfxApplication::GetTemplateDialog()
{
    if ( pAppData_Impl->pViewFrame )
    {
        SfxChildWindow *pChild = pAppData_Impl->pViewFrame->GetChildWindow(SfxTemplateDialogWrapper::GetChildWindowId());
        return pChild ? (SfxTemplateDialog*) pChild->GetWindow() : 0;
    }

    return NULL;
}

//--------------------------------------------------------------------

SfxWorkWindow* SfxApplication::GetWorkWindow_Impl(const SfxViewFrame *pFrame) const
{
    if ( pFrame )
        return pFrame->GetFrame()->GetWorkWindow_Impl();
    else if ( pAppData_Impl->pViewFrame )
        return pAppData_Impl->pViewFrame->GetFrame()->GetWorkWindow_Impl();
    else
        return NULL;
}

<commit_msg>INTEGRATION: CWS changefileheader (1.9.216); FILE MERGED 2008/04/01 15:38:39 thb 1.9.216.2: #i85898# Stripping all external header guards 2008/03/31 13:38:00 rt 1.9.216.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: appchild.cxx,v $
 * $Revision: 1.10 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sfx2.hxx"

#ifndef GCC
#endif
#include <svtools/whiter.hxx>
#include <svtools/eitem.hxx>

#include <sfx2/app.hxx>
#include "appdata.hxx"
#include "workwin.hxx"
#include <sfx2/childwin.hxx>
#include "arrdecl.hxx"
#include <sfx2/templdlg.hxx>
#include <sfx2/request.hxx>
#include <sfx2/bindings.hxx>
#include <sfx2/dispatch.hxx>
#include "sfxtypes.hxx"
#include <sfx2/module.hxx>
#include <sfx2/sfxsids.hrc>

//=========================================================================

void SfxApplication::RegisterChildWindow_Impl( SfxModule *pMod, SfxChildWinFactory *pFact )
{
    if ( pMod )
    {
        pMod->RegisterChildWindow( pFact );
        return;
    }

    if (!pAppData_Impl->pFactArr)
        pAppData_Impl->pFactArr = new SfxChildWinFactArr_Impl;

//#ifdef DBG_UTIL
    for (USHORT nFactory=0; nFactory<pAppData_Impl->pFactArr->Count(); ++nFactory)
    {
        if (pFact->nId ==  (*pAppData_Impl->pFactArr)[nFactory]->nId)
        {
            pAppData_Impl->pFactArr->Remove( nFactory );
//          DBG_ERROR("ChildWindow mehrfach registriert!");
//          return;
        }
    }
//#endif

    pAppData_Impl->pFactArr->C40_INSERT(
        SfxChildWinFactory, pFact, pAppData_Impl->pFactArr->Count() );
}

void SfxApplication::RegisterChildWindowContext_Impl( SfxModule *pMod, USHORT nId,
        SfxChildWinContextFactory *pFact)
{
    SfxChildWinFactArr_Impl *pFactories;
    SfxChildWinFactory *pF = NULL;
    if ( pMod )
    {
        // Modul "ubergeben, ChildwindowFactory dort suchen
        pFactories = pMod->GetChildWinFactories_Impl();
        if ( pFactories )
        {
            USHORT nCount = pFactories->Count();
            for (USHORT nFactory=0; nFactory<nCount; ++nFactory)
            {
                SfxChildWinFactory *pFac = (*pFactories)[nFactory];
                if ( nId == pFac->nId )
                {
                    // Factory gefunden, Context dort registrieren
                    pF = pFac;
                    break;
                }
            }
        }
    }

    if ( !pF )
    {
        // Factory an der Application suchen
        DBG_ASSERT( pAppData_Impl, "Keine AppDaten!" );
        DBG_ASSERT( pAppData_Impl->pFactArr, "Keine Factories!" );

        pFactories = pAppData_Impl->pFactArr;
        USHORT nCount = pFactories->Count();
        for (USHORT nFactory=0; nFactory<nCount; ++nFactory)
        {
            SfxChildWinFactory *pFac = (*pFactories)[nFactory];
            if ( nId == pFac->nId )
            {
                if ( pMod )
                {
                    // Wenn der Context von einem Modul registriert wurde,
                    // mu\s die ChildwindowFactory auch dort zur Verf"ugung
                    // stehen, sonst m"u\ste sich die Contextfactory im DLL-Exit
                    // wieder abmelden !
                    pF = new SfxChildWinFactory( pFac->pCtor, pFac->nId,
                            pFac->nPos );
                    pMod->RegisterChildWindow( pF );
                }
                else
                    pF = pFac;
                break;
            }
        }
    }

    if ( pF )
    {
        if ( !pF->pArr )
            pF->pArr = new SfxChildWinContextArr_Impl;
        pF->pArr->C40_INSERT( SfxChildWinContextFactory, pFact, pF->pArr->Count() );
        return;
    }

    DBG_ERROR( "Kein ChildWindow fuer diesen Context!" );
}

//--------------------------------------------------------------------

SfxChildWinFactArr_Impl& SfxApplication::GetChildWinFactories_Impl() const
{
    return ( *(pAppData_Impl->pFactArr));
}

//--------------------------------------------------------------------

SfxTemplateDialog* SfxApplication::GetTemplateDialog()
{
    if ( pAppData_Impl->pViewFrame )
    {
        SfxChildWindow *pChild = pAppData_Impl->pViewFrame->GetChildWindow(SfxTemplateDialogWrapper::GetChildWindowId());
        return pChild ? (SfxTemplateDialog*) pChild->GetWindow() : 0;
    }

    return NULL;
}

//--------------------------------------------------------------------

SfxWorkWindow* SfxApplication::GetWorkWindow_Impl(const SfxViewFrame *pFrame) const
{
    if ( pFrame )
        return pFrame->GetFrame()->GetWorkWindow_Impl();
    else if ( pAppData_Impl->pViewFrame )
        return pAppData_Impl->pViewFrame->GetFrame()->GetWorkWindow_Impl();
    else
        return NULL;
}

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: imagemgr.cxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: pb $ $Date: 2001-05-14 10:10:37 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  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
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

// includes --------------------------------------------------------------
#ifndef _COM_SUN_STAR_UNO_REFERENCE_HXX_
#include <com/sun/star/uno/Reference.hxx>
#endif
#ifndef _COM_SUN_STAR_FRAME_XCONTROLLER_HPP_
#include <com/sun/star/frame/XController.hpp>
#endif
#ifndef _COM_SUN_STAR_FRAME_XFRAME_HPP_
#include <com/sun/star/frame/XFrame.hpp>
#endif

#include <tools/urlobj.hxx>
#include <svtools/imagemgr.hxx>
#include <comphelper/processfactory.hxx>

#include "imgmgr.hxx"
#include "app.hxx"
#include "unoctitm.hxx"
#include "dispatch.hxx"
#include "msg.hxx"
#include "msgpool.hxx"
#include "viewfrm.hxx"
#include "module.hxx"
#include "objsh.hxx"

using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::frame;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::util;

Image SAL_CALL GetImage( ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& rFrame, const ::rtl::OUString& aURL, BOOL bBig )
{
    INetURLObject aObj( aURL );
    INetProtocol nProtocol = aObj.GetProtocol();
    switch ( nProtocol )
    {
        case INET_PROT_UNO :
        case INET_PROT_SLOT :
        {
            URL aTargetURL;
            SfxViewFrame* pViewFrame = NULL;
            Reference < XController > xController;
            if ( rFrame.is() )
                xController = rFrame->getController();

            Reference < XDispatchProvider > xProvider( xController, UNO_QUERY );
            if ( xProvider.is() )
            {
                aTargetURL.Complete = aURL;
                Reference < XURLTransformer > xTrans( ::comphelper::getProcessServiceFactory()->createInstance( rtl::OUString::createFromAscii("com.sun.star.util.URLTransformer" )), UNO_QUERY );
                xTrans->parseStrict( aTargetURL );

                Reference < XDispatch > xDisp = xProvider->queryDispatch( aTargetURL, ::rtl::OUString(), 0 );
                if ( xDisp.is() )
                {
                    Reference< XUnoTunnel > xTunnel( xDisp, UNO_QUERY );
                    SfxOfficeDispatch* pDisp = NULL;
                    if ( xTunnel.is() )
                    {
                        sal_Int64 nImplementation = xTunnel->getSomething(SfxOfficeDispatch::impl_getStaticIdentifier());
                        pDisp = (SfxOfficeDispatch*)(nImplementation);
                    }

                    if ( pDisp )
                        pViewFrame = pDisp->GetDispatcher_Impl()->GetFrame();
                }
            }

            USHORT nId;
            if ( nProtocol == INET_PROT_UNO )
            {
                SfxSlotPool& rPool = SFX_APP()->GetSlotPool( pViewFrame );
                const SfxSlot* pSlot = rPool.GetUnoSlot( aTargetURL.Path );
                if ( pSlot )
                    nId = pSlot->GetSlotId();
            }
            else
                nId = ( USHORT ) aTargetURL.Path.toInt32();

            SfxModule* pModule = pViewFrame ? pViewFrame->GetObjectShell()->GetModule() : NULL;
            if ( nId )
                return SFX_IMAGEMANAGER()->SeekImage( nId, pModule );
            break;
        }

        case INET_PROT_NOT_VALID :
        {
            return Image();
            break;
        }
    }

    return SvFileInformationManager::GetImage( aObj, bBig );
}

<commit_msg>#87722#: no global access for ImageManager<commit_after>/*************************************************************************
 *
 *  $RCSfile: imagemgr.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: mba $ $Date: 2001-06-11 09:53:01 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  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
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

// includes --------------------------------------------------------------
#ifndef _COM_SUN_STAR_UNO_REFERENCE_HXX_
#include <com/sun/star/uno/Reference.hxx>
#endif
#ifndef _COM_SUN_STAR_FRAME_XCONTROLLER_HPP_
#include <com/sun/star/frame/XController.hpp>
#endif
#ifndef _COM_SUN_STAR_FRAME_XFRAME_HPP_
#include <com/sun/star/frame/XFrame.hpp>
#endif

#include <tools/urlobj.hxx>
#include <svtools/imagemgr.hxx>
#include <comphelper/processfactory.hxx>

#include "imgmgr.hxx"
#include "app.hxx"
#include "unoctitm.hxx"
#include "dispatch.hxx"
#include "msg.hxx"
#include "msgpool.hxx"
#include "viewfrm.hxx"
#include "module.hxx"
#include "objsh.hxx"

using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::frame;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::util;

Image SAL_CALL GetImage( ::com::sun::star::uno::Reference< ::com::sun::star::frame::XFrame >& rFrame, const ::rtl::OUString& aURL, BOOL bBig )
{
    INetURLObject aObj( aURL );
    INetProtocol nProtocol = aObj.GetProtocol();
    switch ( nProtocol )
    {
        case INET_PROT_UNO :
        case INET_PROT_SLOT :
        {
            URL aTargetURL;
            SfxViewFrame* pViewFrame = NULL;
            Reference < XController > xController;
            if ( rFrame.is() )
                xController = rFrame->getController();

            Reference < XDispatchProvider > xProvider( xController, UNO_QUERY );
            if ( xProvider.is() )
            {
                aTargetURL.Complete = aURL;
                Reference < XURLTransformer > xTrans( ::comphelper::getProcessServiceFactory()->createInstance( rtl::OUString::createFromAscii("com.sun.star.util.URLTransformer" )), UNO_QUERY );
                xTrans->parseStrict( aTargetURL );

                Reference < XDispatch > xDisp = xProvider->queryDispatch( aTargetURL, ::rtl::OUString(), 0 );
                if ( xDisp.is() )
                {
                    Reference< XUnoTunnel > xTunnel( xDisp, UNO_QUERY );
                    SfxOfficeDispatch* pDisp = NULL;
                    if ( xTunnel.is() )
                    {
                        sal_Int64 nImplementation = xTunnel->getSomething(SfxOfficeDispatch::impl_getStaticIdentifier());
                        pDisp = (SfxOfficeDispatch*)(nImplementation);
                    }

                    if ( pDisp )
                        pViewFrame = pDisp->GetDispatcher_Impl()->GetFrame();
                }
            }

            USHORT nId;
            if ( nProtocol == INET_PROT_UNO )
            {
                SfxSlotPool& rPool = SFX_APP()->GetSlotPool( pViewFrame );
                const SfxSlot* pSlot = rPool.GetUnoSlot( aTargetURL.Path );
                if ( pSlot )
                    nId = pSlot->GetSlotId();
            }
            else
                nId = ( USHORT ) aTargetURL.Path.toInt32();

            SfxModule* pModule = pViewFrame ? pViewFrame->GetObjectShell()->GetModule() : NULL;
            if ( nId )
            {
                if ( pViewFrame )
                    return pViewFrame->GetImageManager()->GetImage( nId, pModule, bBig );
                else
                {
                    return SFX_APP()->GetImageManager_Impl()->GetImage( nId, NULL, bBig );
                }
            }
            break;
        }

        case INET_PROT_NOT_VALID :
        {
            return Image();
            break;
        }
    }

    return SvFileInformationManager::GetImage( aObj, bBig );
}

<|endoftext|>


<commit_before>/*
 * Part of HTTPP.
 *
 * Distributed under the 3-clause BSD licence (See LICENCE.TXT file at the
 * project root).
 *
 * Copyright (c) 2013 Thomas Sanchez.  All rights reserved.
 *
 */

#include "httpp/utils/ThreadPool.hpp"

#include <atomic>

#include <boost/log/trivial.hpp>

namespace HTTPP
{
namespace UTILS
{

static void empty_deleter(boost::asio::io_service*)
{}

ThreadPool::ThreadPool(size_t nb_thread, const std::string& name)
: service_(std::make_shared<boost::asio::io_service>(nb_thread))
, nb_thread_(nb_thread)
, name_(name)
{
}

ThreadPool::ThreadPool(size_t nb_thread,
                       boost::asio::io_service& service,
                       const std::string& name)
: service_(std::addressof(service), &empty_deleter)
, nb_thread_(nb_thread)
, name_(name)
{
}

ThreadPool::~ThreadPool()
{
    if (running_)
    {
        stop();
    }
}

ThreadPool::ThreadPool(ThreadPool&& pool)
: service_(pool.service_)
, running_(pool.running_)
, nb_thread_(pool.nb_thread_)
, work_(std::move(pool.work_))
, threads_(std::move(pool.threads_))
, name_(std::move(name_))
{
    running_threads_.store(pool.running_threads_.load());
    pool.running_ = false;
}

void ThreadPool::start(ThreadInit fct)
{
    if (running_)
    {
        return;
    }

    work_.reset(new boost::asio::io_service::work(*service_));
    for (size_t i = 0; i < nb_thread_; ++i)
    {
        threads_.emplace_back(std::bind(&ThreadPool::run, this,
                    [this, fct, i]
                    {
                        if (name_.empty())
                        {
                            setCurrentThreadName("Pool thread #" +
                                                 std::to_string(i));
                        }
                        else
                        {
                            setCurrentThreadName(name_ + " #" + std::to_string(i));
                        }

                        if (fct)
                        {
                            BOOST_LOG_TRIVIAL(debug) << "call init fct " << name_;
                            fct();
                        }
                    }
                    ));
    }

    while (running_threads_ != nb_thread_)
    {
        std::this_thread::yield();
    }

    running_ = true;
}

void ThreadPool::run(ThreadInit fct)
{
    BOOST_LOG_TRIVIAL(debug) << "start thread";

    if (fct)
    {
        fct();
    }

    BOOST_LOG_TRIVIAL(debug) << "call run()";
    ++running_threads_;

    this->service_->reset();
    this->service_->run();
    BOOST_LOG_TRIVIAL(debug) << "is stopping";
    --running_threads_;
}

void ThreadPool::stop()
{
    if (!running_)
    {
        return;
    }

    running_ = false;
    work_.reset();
    service_->stop();
    for (auto& th : threads_)
    {
        if (th.joinable())
        {
            th.join();
        }
    }

    threads_.clear();
}

bool ThreadPool::runningInPool() const noexcept
{
    auto current_id = std::this_thread::get_id();
    for (const auto& thread : threads_)
    {
        if (thread.get_id() == current_id)
        {
            return true;
        }
    }

    return false;
}

} // namespace UTILS
} // namespace HTTPP
<commit_msg>Fix bug in ThreadPool's move constructor.<commit_after>/*
 * Part of HTTPP.
 *
 * Distributed under the 3-clause BSD licence (See LICENCE.TXT file at the
 * project root).
 *
 * Copyright (c) 2013 Thomas Sanchez.  All rights reserved.
 *
 */

#include "httpp/utils/ThreadPool.hpp"

#include <atomic>

#include <boost/log/trivial.hpp>

namespace HTTPP
{
namespace UTILS
{

static void empty_deleter(boost::asio::io_service*)
{}

ThreadPool::ThreadPool(size_t nb_thread, const std::string& name)
: service_(std::make_shared<boost::asio::io_service>(nb_thread))
, nb_thread_(nb_thread)
, name_(name)
{
}

ThreadPool::ThreadPool(size_t nb_thread,
                       boost::asio::io_service& service,
                       const std::string& name)
: service_(std::addressof(service), &empty_deleter)
, nb_thread_(nb_thread)
, name_(name)
{
}

ThreadPool::~ThreadPool()
{
    if (running_)
    {
        stop();
    }
}

ThreadPool::ThreadPool(ThreadPool&& pool)
: service_(pool.service_)
, running_(pool.running_)
, nb_thread_(pool.nb_thread_)
, work_(std::move(pool.work_))
, threads_(std::move(pool.threads_))
, name_(std::move(pool.name_))
{
    running_threads_.store(pool.running_threads_.load());
    pool.running_ = false;
}

void ThreadPool::start(ThreadInit fct)
{
    if (running_)
    {
        return;
    }

    work_.reset(new boost::asio::io_service::work(*service_));
    for (size_t i = 0; i < nb_thread_; ++i)
    {
        threads_.emplace_back(std::bind(&ThreadPool::run, this,
                    [this, fct, i]
                    {
                        if (name_.empty())
                        {
                            setCurrentThreadName("Pool thread #" +
                                                 std::to_string(i));
                        }
                        else
                        {
                            setCurrentThreadName(name_ + " #" + std::to_string(i));
                        }

                        if (fct)
                        {
                            BOOST_LOG_TRIVIAL(debug) << "call init fct " << name_;
                            fct();
                        }
                    }
                    ));
    }

    while (running_threads_ != nb_thread_)
    {
        std::this_thread::yield();
    }

    running_ = true;
}

void ThreadPool::run(ThreadInit fct)
{
    BOOST_LOG_TRIVIAL(debug) << "start thread";

    if (fct)
    {
        fct();
    }

    BOOST_LOG_TRIVIAL(debug) << "call run()";
    ++running_threads_;

    this->service_->reset();
    this->service_->run();
    BOOST_LOG_TRIVIAL(debug) << "is stopping";
    --running_threads_;
}

void ThreadPool::stop()
{
    if (!running_)
    {
        return;
    }

    running_ = false;
    work_.reset();
    service_->stop();
    for (auto& th : threads_)
    {
        if (th.joinable())
        {
            th.join();
        }
    }

    threads_.clear();
}

bool ThreadPool::runningInPool() const noexcept
{
    auto current_id = std::this_thread::get_id();
    for (const auto& thread : threads_)
    {
        if (thread.get_id() == current_id)
        {
            return true;
        }
    }

    return false;
}

} // namespace UTILS
} // namespace HTTPP
<|endoftext|>


<commit_before>/***************************************************************************
 *   Copyright (C) 2003 by Unai Garro                                      *
 *   ugarro@users.sourceforge.net                                          *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 ***************************************************************************/
#include "ingredientpropertylist.h"
#include <iostream>
IngredientPropertyList::IngredientPropertyList()
{
}

IngredientPropertyList::~IngredientPropertyList()
{
}

void IngredientPropertyList::add(IngredientProperty &property)
{
list.append (new IngredientProperty(property));
}

IngredientProperty* IngredientPropertyList::getFirst(void){
return(list.first());
}

IngredientProperty* IngredientPropertyList::getNext(void){
return(list.next());
}

IngredientProperty* IngredientPropertyList::getElement(int index){
return(list.at(index));
}

void IngredientPropertyList::clear(void)
{
list.clear();
}

bool IngredientPropertyList::isEmpty(void)
{
return(list.isEmpty());
}

int IngredientPropertyList::find(IngredientProperty* it)
{
return(list.find(it));
}

int IngredientPropertyList::find(int id)
{
IngredientProperty ip; ip.id=id;
return(list.find(&ip));
}

IngredientProperty* IngredientPropertyList::at(int pos)
{
return(list.at(pos));
}

void IngredientPropertyList::append(IngredientProperty *property)
{
list.append (property);
}

void IngredientPropertyList::divide(int persons)
{
for (IngredientProperty* ip=getFirst();ip;ip=getNext())
	ip->amount/=persons;
}

void IngredientPropertyList::filter(int ingredientID,IngredientPropertyList *filteredList)
{
filteredList->clear();
for (IngredientProperty* ip=getFirst();ip;ip=getNext())
	if (ip->ingredientID==ingredientID) filteredList->add(*ip);

}

int IngredientPropertyList::count(void)
{
return (list.count());
}

void IngredientPropertyList::remove(IngredientProperty* ip)
{
list->remove(ip);
}<commit_msg>oops, small mistake<commit_after>/***************************************************************************
 *   Copyright (C) 2003 by Unai Garro                                      *
 *   ugarro@users.sourceforge.net                                          *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 ***************************************************************************/
#include "ingredientpropertylist.h"
#include <iostream>
IngredientPropertyList::IngredientPropertyList()
{
}

IngredientPropertyList::~IngredientPropertyList()
{
}

void IngredientPropertyList::add(IngredientProperty &property)
{
list.append (new IngredientProperty(property));
}

IngredientProperty* IngredientPropertyList::getFirst(void){
return(list.first());
}

IngredientProperty* IngredientPropertyList::getNext(void){
return(list.next());
}

IngredientProperty* IngredientPropertyList::getElement(int index){
return(list.at(index));
}

void IngredientPropertyList::clear(void)
{
list.clear();
}

bool IngredientPropertyList::isEmpty(void)
{
return(list.isEmpty());
}

int IngredientPropertyList::find(IngredientProperty* it)
{
return(list.find(it));
}

int IngredientPropertyList::find(int id)
{
IngredientProperty ip; ip.id=id;
return(list.find(&ip));
}

IngredientProperty* IngredientPropertyList::at(int pos)
{
return(list.at(pos));
}

void IngredientPropertyList::append(IngredientProperty *property)
{
list.append (property);
}

void IngredientPropertyList::divide(int persons)
{
for (IngredientProperty* ip=getFirst();ip;ip=getNext())
	ip->amount/=persons;
}

void IngredientPropertyList::filter(int ingredientID,IngredientPropertyList *filteredList)
{
filteredList->clear();
for (IngredientProperty* ip=getFirst();ip;ip=getNext())
	if (ip->ingredientID==ingredientID) filteredList->add(*ip);

}

int IngredientPropertyList::count(void)
{
return (list.count());
}

void IngredientPropertyList::remove(IngredientProperty* ip)
{
list.remove(ip);
}<|endoftext|>


<commit_before>/*

Copyright (c) 2006, Arvid Norberg & Daniel Wallin
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.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

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 OWNER 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 "libtorrent/pch.hpp"

#include <libtorrent/kademlia/closest_nodes.hpp>
#include <libtorrent/kademlia/routing_table.hpp>
#include <libtorrent/kademlia/rpc_manager.hpp>
#include "libtorrent/assert.hpp"

namespace libtorrent { namespace dht
{

using asio::ip::udp;

closest_nodes_observer::~closest_nodes_observer()
{
	if (m_algorithm) m_algorithm->failed(m_self, true);
}

void closest_nodes_observer::reply(msg const& in)
{
	if (!m_algorithm)
	{
		TORRENT_ASSERT(false);
		return;
	}

	if (!in.nodes.empty())
	{
		for (msg::nodes_t::const_iterator i = in.nodes.begin()
			, end(in.nodes.end()); i != end; ++i)
		{
			m_algorithm->traverse(i->id, i->addr);
		}
	}
	m_algorithm->finished(m_self);
	m_algorithm = 0;
}

void closest_nodes_observer::timeout()
{
	if (!m_algorithm) return;
	m_algorithm->failed(m_self);
	m_algorithm = 0;
}

closest_nodes::closest_nodes(
	node_id target
	, int branch_factor
	, int max_results
	, routing_table& table
	, rpc_manager& rpc
	, done_callback const& callback
)
	: traversal_algorithm(
		target
		, branch_factor
		, max_results
		, table
		, rpc
		, table.begin()
		, table.end()
	)
	, m_done_callback(callback)
{
	boost::intrusive_ptr<closest_nodes> self(this);
	add_requests();
}

void closest_nodes::invoke(node_id const& id, udp::endpoint addr)
{
	TORRENT_ASSERT(m_rpc.allocation_size() >= sizeof(closest_nodes_observer));
	observer_ptr o(new (m_rpc.allocator().malloc()) closest_nodes_observer(this, id, m_target));
#ifndef NDEBUG
	o->m_in_constructor = false;
#endif
	m_rpc.invoke(messages::find_node, addr, o);
}

void closest_nodes::done()
{
	std::vector<node_entry> results;
	int num_results = m_table.bucket_size();
	for (std::vector<result>::iterator i = m_max_results
		, end(m_results.end()); i != end && num_results >= 0; ++i)
	{
		if (i->flags & result::no_id) continue;
		if ((i->flags & result::queried) == 0) continue;
		results.push_back(node_entry(i->id, i->addr));
		--num_results;
	}
	m_done_callback(results);
}

void closest_nodes::initiate(
	node_id target
	, int branch_factor
	, int max_results
	, routing_table& table
	, rpc_manager& rpc
	, done_callback const& callback
)
{
	new closest_nodes(target, branch_factor, max_results, table, rpc, callback);
}

} } // namespace libtorrent::dht

<commit_msg>fixed typo in previous dht checkin<commit_after>/*

Copyright (c) 2006, Arvid Norberg & Daniel Wallin
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.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

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 OWNER 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 "libtorrent/pch.hpp"

#include <libtorrent/kademlia/closest_nodes.hpp>
#include <libtorrent/kademlia/routing_table.hpp>
#include <libtorrent/kademlia/rpc_manager.hpp>
#include "libtorrent/assert.hpp"

namespace libtorrent { namespace dht
{

using asio::ip::udp;

closest_nodes_observer::~closest_nodes_observer()
{
	if (m_algorithm) m_algorithm->failed(m_self, true);
}

void closest_nodes_observer::reply(msg const& in)
{
	if (!m_algorithm)
	{
		TORRENT_ASSERT(false);
		return;
	}

	if (!in.nodes.empty())
	{
		for (msg::nodes_t::const_iterator i = in.nodes.begin()
			, end(in.nodes.end()); i != end; ++i)
		{
			m_algorithm->traverse(i->id, i->addr);
		}
	}
	m_algorithm->finished(m_self);
	m_algorithm = 0;
}

void closest_nodes_observer::timeout()
{
	if (!m_algorithm) return;
	m_algorithm->failed(m_self);
	m_algorithm = 0;
}

closest_nodes::closest_nodes(
	node_id target
	, int branch_factor
	, int max_results
	, routing_table& table
	, rpc_manager& rpc
	, done_callback const& callback
)
	: traversal_algorithm(
		target
		, branch_factor
		, max_results
		, table
		, rpc
		, table.begin()
		, table.end()
	)
	, m_done_callback(callback)
{
	boost::intrusive_ptr<closest_nodes> self(this);
	add_requests();
}

void closest_nodes::invoke(node_id const& id, udp::endpoint addr)
{
	TORRENT_ASSERT(m_rpc.allocation_size() >= sizeof(closest_nodes_observer));
	observer_ptr o(new (m_rpc.allocator().malloc()) closest_nodes_observer(this, id, m_target));
#ifndef NDEBUG
	o->m_in_constructor = false;
#endif
	m_rpc.invoke(messages::find_node, addr, o);
}

void closest_nodes::done()
{
	std::vector<node_entry> results;
	int num_results = m_max_results;
	for (std::vector<result>::iterator i = m_results.begin()
		, end(m_results.end()); i != end && num_results >= 0; ++i)
	{
		if (i->flags & result::no_id) continue;
		if ((i->flags & result::queried) == 0) continue;
		results.push_back(node_entry(i->id, i->addr));
		--num_results;
	}
	m_done_callback(results);
}

void closest_nodes::initiate(
	node_id target
	, int branch_factor
	, int max_results
	, routing_table& table
	, rpc_manager& rpc
	, done_callback const& callback
)
{
	new closest_nodes(target, branch_factor, max_results, table, rpc, callback);
}

} } // namespace libtorrent::dht

<|endoftext|>


<commit_before>/*

Copyright (c) 2006, Arvid Norberg & Daniel Wallin
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.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

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 OWNER 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 "libtorrent/pch.hpp"

#include <libtorrent/kademlia/closest_nodes.hpp>
#include <libtorrent/kademlia/routing_table.hpp>
#include <libtorrent/kademlia/rpc_manager.hpp>
#include "libtorrent/assert.hpp"

namespace libtorrent { namespace dht
{

using asio::ip::udp;

closest_nodes_observer::~closest_nodes_observer()
{
	if (m_algorithm) m_algorithm->failed(m_self, true);
}

void closest_nodes_observer::reply(msg const& in)
{
	if (!m_algorithm)
	{
		TORRENT_ASSERT(false);
		return;
	}

	if (!in.nodes.empty())
	{
		for (msg::nodes_t::const_iterator i = in.nodes.begin()
			, end(in.nodes.end()); i != end; ++i)
		{
			m_algorithm->traverse(i->id, i->addr);
		}
	}
	m_algorithm->finished(m_self);
	m_algorithm = 0;
}

void closest_nodes_observer::timeout()
{
	if (!m_algorithm) return;
	m_algorithm->failed(m_self);
	m_algorithm = 0;
}

closest_nodes::closest_nodes(
	node_id target
	, int branch_factor
	, int max_results
	, routing_table& table
	, rpc_manager& rpc
	, done_callback const& callback
)
	: traversal_algorithm(
		target
		, branch_factor
		, max_results
		, table
		, rpc
		, table.begin()
		, table.end()
	)
	, m_done_callback(callback)
{
	boost::intrusive_ptr<closest_nodes> self(this);
	add_requests();
}

void closest_nodes::invoke(node_id const& id, udp::endpoint addr)
{
	TORRENT_ASSERT(m_rpc.allocation_size() >= sizeof(closest_nodes_observer));
	observer_ptr o(new (m_rpc.allocator().malloc()) closest_nodes_observer(this, id, m_target));
#ifndef NDEBUG
	o->m_in_constructor = false;
#endif
	m_rpc.invoke(messages::find_node, addr, o);
}

void closest_nodes::done()
{
	std::vector<node_entry> results;
	int num_results = m_table.bucket_size();
	for (std::vector<result>::iterator i = m_results.begin()
		, end(m_results.end()); i != end && num_results >= 0; ++i)
	{
		if (i->flags & result::no_id) continue;
		results.push_back(node_entry(i->id, i->addr));
		--num_results;
	}
	m_done_callback(results);
}

void closest_nodes::initiate(
	node_id target
	, int branch_factor
	, int max_results
	, routing_table& table
	, rpc_manager& rpc
	, done_callback const& callback
)
{
	new closest_nodes(target, branch_factor, max_results, table, rpc, callback);
}

} } // namespace libtorrent::dht

<commit_msg>dht fix<commit_after>/*

Copyright (c) 2006, Arvid Norberg & Daniel Wallin
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.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

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 OWNER 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 "libtorrent/pch.hpp"

#include <libtorrent/kademlia/closest_nodes.hpp>
#include <libtorrent/kademlia/routing_table.hpp>
#include <libtorrent/kademlia/rpc_manager.hpp>
#include "libtorrent/assert.hpp"

namespace libtorrent { namespace dht
{

using asio::ip::udp;

closest_nodes_observer::~closest_nodes_observer()
{
	if (m_algorithm) m_algorithm->failed(m_self, true);
}

void closest_nodes_observer::reply(msg const& in)
{
	if (!m_algorithm)
	{
		TORRENT_ASSERT(false);
		return;
	}

	if (!in.nodes.empty())
	{
		for (msg::nodes_t::const_iterator i = in.nodes.begin()
			, end(in.nodes.end()); i != end; ++i)
		{
			m_algorithm->traverse(i->id, i->addr);
		}
	}
	m_algorithm->finished(m_self);
	m_algorithm = 0;
}

void closest_nodes_observer::timeout()
{
	if (!m_algorithm) return;
	m_algorithm->failed(m_self);
	m_algorithm = 0;
}

closest_nodes::closest_nodes(
	node_id target
	, int branch_factor
	, int max_results
	, routing_table& table
	, rpc_manager& rpc
	, done_callback const& callback
)
	: traversal_algorithm(
		target
		, branch_factor
		, max_results
		, table
		, rpc
		, table.begin()
		, table.end()
	)
	, m_done_callback(callback)
{
	boost::intrusive_ptr<closest_nodes> self(this);
	add_requests();
}

void closest_nodes::invoke(node_id const& id, udp::endpoint addr)
{
	TORRENT_ASSERT(m_rpc.allocation_size() >= sizeof(closest_nodes_observer));
	observer_ptr o(new (m_rpc.allocator().malloc()) closest_nodes_observer(this, id, m_target));
#ifndef NDEBUG
	o->m_in_constructor = false;
#endif
	m_rpc.invoke(messages::find_node, addr, o);
}

void closest_nodes::done()
{
	std::vector<node_entry> results;
	int num_results = m_table.bucket_size();
	for (std::vector<result>::iterator i = m_max_results
		, end(m_results.end()); i != end && num_results >= 0; ++i)
	{
		if (i->flags & result::no_id) continue;
		if ((i->flags & result::queried) == 0) continue;
		results.push_back(node_entry(i->id, i->addr));
		--num_results;
	}
	m_done_callback(results);
}

void closest_nodes::initiate(
	node_id target
	, int branch_factor
	, int max_results
	, routing_table& table
	, rpc_manager& rpc
	, done_callback const& callback
)
{
	new closest_nodes(target, branch_factor, max_results, table, rpc, callback);
}

} } // namespace libtorrent::dht

<|endoftext|>


<commit_before>//
// This file is part of the Marble Virtual Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2009      Bastian Holst <bastianholst@gmx.de>
//

// Self
#include "AbstractDataPlugin.h"

// Marble
#include "AbstractDataPluginModel.h"
#include "AbstractDataPluginItem.h"
#include "GeoPainter.h"
#include "GeoSceneLayer.h"
#include "MarbleModel.h"
#include "ViewportParams.h"
#include "MarbleDebug.h"

// Qt
#include <QtCore/QEvent>
#include <QtGui/QMouseEvent>
#include <QtGui/QRegion>
#include <QtDeclarative/QDeclarativeComponent>
#include <QtDeclarative/QDeclarativeItem>
#include <QtDeclarative/QDeclarativeContext>

namespace Marble
{

class AbstractDataPluginPrivate
{
 public:
    AbstractDataPluginPrivate()
        : m_model( 0 ),
          m_numberOfItems( 10 ),
          m_delegate( 0 ),
          m_delegateParent( 0 )
    {
    }

    ~AbstractDataPluginPrivate() {
        delete m_model;
    }

    AbstractDataPluginModel *m_model;
    quint32 m_numberOfItems;
    QDeclarativeComponent* m_delegate;
    QGraphicsItem* m_delegateParent;
    QMap<AbstractDataPluginItem*,QDeclarativeItem*> m_delegateInstances;
};

AbstractDataPlugin::AbstractDataPlugin( const MarbleModel *marbleModel )
    : RenderPlugin( marbleModel ),
      d( new AbstractDataPluginPrivate )
{
}

AbstractDataPlugin::~AbstractDataPlugin()
{
    delete d;
}

bool AbstractDataPlugin::isInitialized() const
{
    return model() != 0;
}

QStringList AbstractDataPlugin::backendTypes() const
{
    return QStringList( name() );
}

QString AbstractDataPlugin::renderPolicy() const
{
    return QString( "ALWAYS" );
}

QStringList AbstractDataPlugin::renderPosition() const
{
    return QStringList( "ALWAYS_ON_TOP" );
}

bool AbstractDataPlugin::render( GeoPainter *painter, ViewportParams *viewport,
             const QString& renderPos, GeoSceneLayer * layer)
{
    Q_UNUSED( renderPos );
    Q_UNUSED( layer );

    if ( !d->m_model || !isInitialized() ) {
        return true;
    }

    if ( d->m_delegate ) {
        handleViewportChange( viewport );
    } else {
        QList<AbstractDataPluginItem*> items = d->m_model->items( viewport,
                                                                  marbleModel(),
                                                                  numberOfItems() );
        painter->save();

        // Paint the most important item at last
        for( int i = items.size() - 1; i >= 0; --i ) {
            items.at( i )->paintEvent( painter, viewport );
        }

        painter->restore();
    }

    return true;
}

AbstractDataPluginModel *AbstractDataPlugin::model() const
{
    return d->m_model;
}

void AbstractDataPlugin::setModel( AbstractDataPluginModel* model )
{
    if ( d->m_model ) {
        disconnect( d->m_model, SIGNAL( itemsUpdated() ), this, SIGNAL( repaintNeeded() ) );
        delete d->m_model;
    }
    d->m_model = model;

    connect( d->m_model, SIGNAL( itemsUpdated() ), this, SIGNAL( repaintNeeded() ) );
    connect( d->m_model, SIGNAL( favoriteItemsChanged( const QStringList& ) ), this,
             SLOT( favoriteItemsChanged( const QStringList& ) ) );
    connect( d->m_model, SIGNAL( favoriteItemsOnlyChanged() ), this,
                         SIGNAL( favoriteItemsOnlyChanged() ) );

    emit favoritesModelChanged();
}

const PluginManager* AbstractDataPlugin::pluginManager() const
{
    return marbleModel()->pluginManager();
}

quint32 AbstractDataPlugin::numberOfItems() const
{
    return d->m_numberOfItems;
}

void AbstractDataPlugin::setNumberOfItems( quint32 number )
{
    bool changed = ( number != d->m_numberOfItems );
    d->m_numberOfItems = number;

    if ( changed )
        emit changedNumberOfItems( number );
}

QList<AbstractDataPluginItem *> AbstractDataPlugin::whichItemAt( const QPoint& curpos )
{
    if ( d->m_model && enabled() && visible()) {
        return d->m_model->whichItemAt( curpos );
    }
    else {
        return QList<AbstractDataPluginItem *>();
    }
}

RenderPlugin::RenderType AbstractDataPlugin::renderType() const
{
    return Online;
}

void AbstractDataPlugin::setDelegate( QDeclarativeComponent *delegate, QGraphicsItem* parent )
{
    qDeleteAll( d->m_delegateInstances.values() );
    d->m_delegateInstances.clear();

    d->m_delegate = delegate;
    d->m_delegateParent = parent;
}

void AbstractDataPlugin::setFavoriteItemsOnly( bool favoriteOnly )
{
    if ( d->m_model && d->m_model->isFavoriteItemsOnly() != favoriteOnly ) {
        d->m_model->setFavoriteItemsOnly( favoriteOnly );
    }
}

bool AbstractDataPlugin::isFavoriteItemsOnly() const
{
    return d->m_model && d->m_model->isFavoriteItemsOnly();
}

QObject *AbstractDataPlugin::favoritesModel()
{
    return d->m_model ? d->m_model->favoritesModel() : 0;
}

void AbstractDataPlugin::handleViewportChange( ViewportParams* viewport )
{
    QList<AbstractDataPluginItem*> orphane = d->m_delegateInstances.keys();
    QList<AbstractDataPluginItem*> const items = d->m_model->items( viewport, marbleModel(), numberOfItems() );
    foreach( AbstractDataPluginItem* item, items ) {
        qreal x, y;
        Marble::GeoDataCoordinates const coordinates = item->coordinate();
        bool const visible = viewport->screenCoordinates( coordinates.longitude(), coordinates.latitude(), x, y );

        if ( !d->m_delegateInstances.contains( item ) ) {
            if ( !visible ) {
                // We don't have, but don't need it either. Shouldn't happen though as the model checks for it already.
                continue;
            }

            // Create a new QML object instance using the delegate as the factory. The original
            // data plugin item is set as the context object, i.e. all its properties are available
            // to QML directly with their names
            QDeclarativeContext *context = new QDeclarativeContext( qmlContext( d->m_delegate ) );
            context->setContextObject( item );
            QObject* component = d->m_delegate->create( context );
            QDeclarativeItem* newItem = qobject_cast<QDeclarativeItem*>( component );
            QGraphicsItem* graphicsItem = qobject_cast<QGraphicsItem*>( component );
            if ( graphicsItem && newItem ) {
                graphicsItem->setParentItem( d->m_delegateParent );
            }

            if ( newItem ) {
                d->m_delegateInstances[item] = newItem;
            } else {
                mDebug() << "Failed to create delegate";
                continue;
            }
        } else if ( !visible ) {
            // Previously visible but not anymore => needs to be deleted. Orphane list takes care of it later.
            // Shouldn't happen though as the model checks for it already.
            continue;
        }

        Q_ASSERT( visible );
        QDeclarativeItem* declarativeItem = d->m_delegateInstances[item];
        Q_ASSERT( declarativeItem );

        // Make sure we have a valid bounding rect for collision detection
        item->setProjection( viewport );
        item->setSize( QSizeF( declarativeItem->boundingRect().size() ) );

        int shiftX( 0 ), shiftY( 0 );
        switch( declarativeItem->transformOrigin() ) {
        case QDeclarativeItem::TopLeft:
        case QDeclarativeItem::Top:
        case QDeclarativeItem::TopRight:
            break;
        case QDeclarativeItem::Left:
        case QDeclarativeItem::Center:
        case QDeclarativeItem::Right:
            shiftY = declarativeItem->height() / 2;
            break;
        case QDeclarativeItem::BottomLeft:
        case QDeclarativeItem::Bottom:
        case QDeclarativeItem::BottomRight:
            shiftY = declarativeItem->height();
            break;
        }

        switch( declarativeItem->transformOrigin() ) {
        case QDeclarativeItem::TopLeft:
        case QDeclarativeItem::Left:
        case QDeclarativeItem::BottomLeft:
            break;
        case QDeclarativeItem::Top:
        case QDeclarativeItem::Center:
        case QDeclarativeItem::Bottom:
            shiftX = declarativeItem->width() / 2;
            break;
        case QDeclarativeItem::TopRight:
        case QDeclarativeItem::Right:
        case QDeclarativeItem::BottomRight:
            shiftX = declarativeItem->width();
            break;
        }

        declarativeItem->setPos( x - shiftX, y - shiftY );
        orphane.removeOne( item );
    }

    // Cleanup
    foreach( AbstractDataPluginItem* item, orphane ) {
        Q_ASSERT( d->m_delegateInstances.contains( item ) );
        delete d->m_delegateInstances[item];
        d->m_delegateInstances.remove( item );
    }
}

void AbstractDataPlugin::favoriteItemsChanged( const QStringList& favoriteItems )
{
    Q_UNUSED( favoriteItems )
}

} // namespace Marble

#include "AbstractDataPlugin.moc"
<commit_msg>Make dynamic object properties available to QML.<commit_after>//
// This file is part of the Marble Virtual Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2009      Bastian Holst <bastianholst@gmx.de>
//

// Self
#include "AbstractDataPlugin.h"

// Marble
#include "AbstractDataPluginModel.h"
#include "AbstractDataPluginItem.h"
#include "GeoPainter.h"
#include "GeoSceneLayer.h"
#include "MarbleModel.h"
#include "ViewportParams.h"
#include "MarbleDebug.h"

// Qt
#include <QtCore/QEvent>
#include <QtGui/QMouseEvent>
#include <QtGui/QRegion>
#include <QtDeclarative/QDeclarativeComponent>
#include <QtDeclarative/QDeclarativeItem>
#include <QtDeclarative/QDeclarativeContext>

namespace Marble
{

class AbstractDataPluginPrivate
{
 public:
    AbstractDataPluginPrivate()
        : m_model( 0 ),
          m_numberOfItems( 10 ),
          m_delegate( 0 ),
          m_delegateParent( 0 )
    {
    }

    ~AbstractDataPluginPrivate() {
        delete m_model;
    }

    AbstractDataPluginModel *m_model;
    quint32 m_numberOfItems;
    QDeclarativeComponent* m_delegate;
    QGraphicsItem* m_delegateParent;
    QMap<AbstractDataPluginItem*,QDeclarativeItem*> m_delegateInstances;
};

AbstractDataPlugin::AbstractDataPlugin( const MarbleModel *marbleModel )
    : RenderPlugin( marbleModel ),
      d( new AbstractDataPluginPrivate )
{
}

AbstractDataPlugin::~AbstractDataPlugin()
{
    delete d;
}

bool AbstractDataPlugin::isInitialized() const
{
    return model() != 0;
}

QStringList AbstractDataPlugin::backendTypes() const
{
    return QStringList( name() );
}

QString AbstractDataPlugin::renderPolicy() const
{
    return QString( "ALWAYS" );
}

QStringList AbstractDataPlugin::renderPosition() const
{
    return QStringList( "ALWAYS_ON_TOP" );
}

bool AbstractDataPlugin::render( GeoPainter *painter, ViewportParams *viewport,
             const QString& renderPos, GeoSceneLayer * layer)
{
    Q_UNUSED( renderPos );
    Q_UNUSED( layer );

    if ( !d->m_model || !isInitialized() ) {
        return true;
    }

    if ( d->m_delegate ) {
        handleViewportChange( viewport );
    } else {
        QList<AbstractDataPluginItem*> items = d->m_model->items( viewport,
                                                                  marbleModel(),
                                                                  numberOfItems() );
        painter->save();

        // Paint the most important item at last
        for( int i = items.size() - 1; i >= 0; --i ) {
            items.at( i )->paintEvent( painter, viewport );
        }

        painter->restore();
    }

    return true;
}

AbstractDataPluginModel *AbstractDataPlugin::model() const
{
    return d->m_model;
}

void AbstractDataPlugin::setModel( AbstractDataPluginModel* model )
{
    if ( d->m_model ) {
        disconnect( d->m_model, SIGNAL( itemsUpdated() ), this, SIGNAL( repaintNeeded() ) );
        delete d->m_model;
    }
    d->m_model = model;

    connect( d->m_model, SIGNAL( itemsUpdated() ), this, SIGNAL( repaintNeeded() ) );
    connect( d->m_model, SIGNAL( favoriteItemsChanged( const QStringList& ) ), this,
             SLOT( favoriteItemsChanged( const QStringList& ) ) );
    connect( d->m_model, SIGNAL( favoriteItemsOnlyChanged() ), this,
                         SIGNAL( favoriteItemsOnlyChanged() ) );

    emit favoritesModelChanged();
}

const PluginManager* AbstractDataPlugin::pluginManager() const
{
    return marbleModel()->pluginManager();
}

quint32 AbstractDataPlugin::numberOfItems() const
{
    return d->m_numberOfItems;
}

void AbstractDataPlugin::setNumberOfItems( quint32 number )
{
    bool changed = ( number != d->m_numberOfItems );
    d->m_numberOfItems = number;

    if ( changed )
        emit changedNumberOfItems( number );
}

QList<AbstractDataPluginItem *> AbstractDataPlugin::whichItemAt( const QPoint& curpos )
{
    if ( d->m_model && enabled() && visible()) {
        return d->m_model->whichItemAt( curpos );
    }
    else {
        return QList<AbstractDataPluginItem *>();
    }
}

RenderPlugin::RenderType AbstractDataPlugin::renderType() const
{
    return Online;
}

void AbstractDataPlugin::setDelegate( QDeclarativeComponent *delegate, QGraphicsItem* parent )
{
    qDeleteAll( d->m_delegateInstances.values() );
    d->m_delegateInstances.clear();

    d->m_delegate = delegate;
    d->m_delegateParent = parent;
}

void AbstractDataPlugin::setFavoriteItemsOnly( bool favoriteOnly )
{
    if ( d->m_model && d->m_model->isFavoriteItemsOnly() != favoriteOnly ) {
        d->m_model->setFavoriteItemsOnly( favoriteOnly );
    }
}

bool AbstractDataPlugin::isFavoriteItemsOnly() const
{
    return d->m_model && d->m_model->isFavoriteItemsOnly();
}

QObject *AbstractDataPlugin::favoritesModel()
{
    return d->m_model ? d->m_model->favoritesModel() : 0;
}

void AbstractDataPlugin::handleViewportChange( ViewportParams* viewport )
{
    QList<AbstractDataPluginItem*> orphane = d->m_delegateInstances.keys();
    QList<AbstractDataPluginItem*> const items = d->m_model->items( viewport, marbleModel(), numberOfItems() );
    foreach( AbstractDataPluginItem* item, items ) {
        qreal x, y;
        Marble::GeoDataCoordinates const coordinates = item->coordinate();
        bool const visible = viewport->screenCoordinates( coordinates.longitude(), coordinates.latitude(), x, y );

        if ( !d->m_delegateInstances.contains( item ) ) {
            if ( !visible ) {
                // We don't have, but don't need it either. Shouldn't happen though as the model checks for it already.
                continue;
            }

            // Create a new QML object instance using the delegate as the factory. The original
            // data plugin item is set as the context object, i.e. all its properties are available
            // to QML directly with their names
            QDeclarativeContext *context = new QDeclarativeContext( qmlContext( d->m_delegate ) );
            context->setContextObject( item );
            QList<QByteArray> const dynamicProperties = item->dynamicPropertyNames();
            foreach( const QByteArray &property, dynamicProperties ) {
                context->setContextProperty( property, item->property( property ) );
            }

            QObject* component = d->m_delegate->create( context );
            QDeclarativeItem* newItem = qobject_cast<QDeclarativeItem*>( component );
            QGraphicsItem* graphicsItem = qobject_cast<QGraphicsItem*>( component );
            if ( graphicsItem && newItem ) {
                graphicsItem->setParentItem( d->m_delegateParent );
            }

            if ( newItem ) {
                d->m_delegateInstances[item] = newItem;
            } else {
                mDebug() << "Failed to create delegate";
                continue;
            }
        } else if ( !visible ) {
            // Previously visible but not anymore => needs to be deleted. Orphane list takes care of it later.
            // Shouldn't happen though as the model checks for it already.
            continue;
        }

        Q_ASSERT( visible );
        QDeclarativeItem* declarativeItem = d->m_delegateInstances[item];
        Q_ASSERT( declarativeItem );

        // Make sure we have a valid bounding rect for collision detection
        item->setProjection( viewport );
        item->setSize( QSizeF( declarativeItem->boundingRect().size() ) );

        int shiftX( 0 ), shiftY( 0 );
        switch( declarativeItem->transformOrigin() ) {
        case QDeclarativeItem::TopLeft:
        case QDeclarativeItem::Top:
        case QDeclarativeItem::TopRight:
            break;
        case QDeclarativeItem::Left:
        case QDeclarativeItem::Center:
        case QDeclarativeItem::Right:
            shiftY = declarativeItem->height() / 2;
            break;
        case QDeclarativeItem::BottomLeft:
        case QDeclarativeItem::Bottom:
        case QDeclarativeItem::BottomRight:
            shiftY = declarativeItem->height();
            break;
        }

        switch( declarativeItem->transformOrigin() ) {
        case QDeclarativeItem::TopLeft:
        case QDeclarativeItem::Left:
        case QDeclarativeItem::BottomLeft:
            break;
        case QDeclarativeItem::Top:
        case QDeclarativeItem::Center:
        case QDeclarativeItem::Bottom:
            shiftX = declarativeItem->width() / 2;
            break;
        case QDeclarativeItem::TopRight:
        case QDeclarativeItem::Right:
        case QDeclarativeItem::BottomRight:
            shiftX = declarativeItem->width();
            break;
        }

        declarativeItem->setPos( x - shiftX, y - shiftY );
        orphane.removeOne( item );
    }

    // Cleanup
    foreach( AbstractDataPluginItem* item, orphane ) {
        Q_ASSERT( d->m_delegateInstances.contains( item ) );
        delete d->m_delegateInstances[item];
        d->m_delegateInstances.remove( item );
    }
}

void AbstractDataPlugin::favoriteItemsChanged( const QStringList& favoriteItems )
{
    Q_UNUSED( favoriteItems )
}

} // namespace Marble

#include "AbstractDataPlugin.moc"
<|endoftext|>


<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**************************************************************************/

#include "Dumpers.h"

#include <Overview.h>
#include <Literals.h>
#include <Scope.h>
#include <LookupContext.h>
#include <QDebug>

#include <typeinfo>

static QString indent(QString s, int level = 2)
{
    QString indentString(level, QLatin1Char(' '));
    QString result;
    int last = 0;
    for (int i = 0; i < s.length(); ++i) {
        if (s.at(i) == QLatin1Char('\n') || i == s.length() - 1) {
            result.append(indentString);
            result.append(s.midRef(last, i + 1));
            last = i + 1;
        }
    }
    return result;
}

QString CPlusPlus::toString(const Name *name, QString id)
{
    Overview oo;
    return QString("%0: %1").arg(id, name ? oo(name) : QLatin1String("(null)"));
}

QString CPlusPlus::toString(FullySpecifiedType ty, QString id)
{
    Overview oo;
    return QString("%0: %1 (a %2)").arg(id, oo(ty), ty.type() ? typeid(*ty.type()).name() : "(null)");
}

QString CPlusPlus::toString(const Symbol *s, QString id)
{
    if (!s)
        return QString("%0: (null)").arg(id);

    return QString("%0: %1 (%2) at %3:%4:%5\n%6").arg(
                id,
                QString::fromLatin1(typeid(*s).name()),
                QString::fromUtf8(s->identifier()->chars()),
                QString::fromLatin1(s->fileName()),
                QString::number(s->line()),
                QString::number(s->column()),
                indent(toString(s->type())));
}

QString CPlusPlus::toString(LookupItem it, QString id)
{
    QString result = QString("%1:").arg(id);
    if (it.declaration()) {
        result.append(QString("\n%1").arg(indent(toString(it.declaration(), QLatin1String("Decl")))));
    }
    if (it.type().isValid()) {
        result.append(QString("\n%1").arg(indent(toString(it.type()))));
    }
    if (it.scope()) {
        result.append(QString("\n%1").arg(indent(toString(it.scope(), QLatin1String("Scope")))));
    }
    if (it.binding()) {
        result.append(QString("\n%1").arg(indent(toString(it.binding(), QLatin1String("Binding")))));
    }
    return result;
}

QString CPlusPlus::toString(const ClassOrNamespace *binding, QString id)
{
    if (!binding)
        return QString("%0: (null)").arg(id);

    QString result = QString("%0: %1 symbols").arg(
                id,
                QString::number(binding->symbols().length()));
    if (binding->templateId()) {
        result.append(QString("\n%1").arg(indent(toString(binding->templateId(), QLatin1String("Template")))));
    }
    return result;
}

void CPlusPlus::dump(const Name *name)
{
    qDebug() << qPrintable(toString(name));
}

void CPlusPlus::dump(FullySpecifiedType ty)
{
    qDebug() << qPrintable(toString(ty));
}

void CPlusPlus::dump(const Symbol *s)
{
    qDebug() << qPrintable(toString(s));
}

void CPlusPlus::dump(LookupItem it)
{
    qDebug() << qPrintable(toString(it));
}

void CPlusPlus::dump(const ClassOrNamespace *binding)
{
    qDebug() << qPrintable(toString(binding));
}
<commit_msg>C++: Fix dumpers when symbol has no identifier.<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**************************************************************************/

#include "Dumpers.h"

#include <Overview.h>
#include <Literals.h>
#include <Scope.h>
#include <LookupContext.h>
#include <QDebug>

#include <typeinfo>

static QString indent(QString s, int level = 2)
{
    QString indentString(level, QLatin1Char(' '));
    QString result;
    int last = 0;
    for (int i = 0; i < s.length(); ++i) {
        if (s.at(i) == QLatin1Char('\n') || i == s.length() - 1) {
            result.append(indentString);
            result.append(s.midRef(last, i + 1));
            last = i + 1;
        }
    }
    return result;
}

QString CPlusPlus::toString(const Name *name, QString id)
{
    Overview oo;
    return QString("%0: %1").arg(id, name ? oo(name) : QLatin1String("(null)"));
}

QString CPlusPlus::toString(FullySpecifiedType ty, QString id)
{
    Overview oo;
    return QString("%0: %1 (a %2)").arg(id, oo(ty), ty.type() ? typeid(*ty.type()).name() : "(null)");
}

QString CPlusPlus::toString(const Symbol *s, QString id)
{
    if (!s)
        return QString("%0: (null)").arg(id);

    return QString("%0: %1 (%2) at %3:%4:%5\n%6").arg(
                id,
                QString::fromLatin1(typeid(*s).name()),
                s->identifier() ? QString::fromUtf8(s->identifier()->chars()) : "no id",
                QString::fromLatin1(s->fileName()),
                QString::number(s->line()),
                QString::number(s->column()),
                indent(toString(s->type())));
}

QString CPlusPlus::toString(LookupItem it, QString id)
{
    QString result = QString("%1:").arg(id);
    if (it.declaration()) {
        result.append(QString("\n%1").arg(indent(toString(it.declaration(), QLatin1String("Decl")))));
    }
    if (it.type().isValid()) {
        result.append(QString("\n%1").arg(indent(toString(it.type()))));
    }
    if (it.scope()) {
        result.append(QString("\n%1").arg(indent(toString(it.scope(), QLatin1String("Scope")))));
    }
    if (it.binding()) {
        result.append(QString("\n%1").arg(indent(toString(it.binding(), QLatin1String("Binding")))));
    }
    return result;
}

QString CPlusPlus::toString(const ClassOrNamespace *binding, QString id)
{
    if (!binding)
        return QString("%0: (null)").arg(id);

    QString result = QString("%0: %1 symbols").arg(
                id,
                QString::number(binding->symbols().length()));
    if (binding->templateId()) {
        result.append(QString("\n%1").arg(indent(toString(binding->templateId(), QLatin1String("Template")))));
    }
    return result;
}

void CPlusPlus::dump(const Name *name)
{
    qDebug() << qPrintable(toString(name));
}

void CPlusPlus::dump(FullySpecifiedType ty)
{
    qDebug() << qPrintable(toString(ty));
}

void CPlusPlus::dump(const Symbol *s)
{
    qDebug() << qPrintable(toString(s));
}

void CPlusPlus::dump(LookupItem it)
{
    qDebug() << qPrintable(toString(it));
}

void CPlusPlus::dump(const ClassOrNamespace *binding)
{
    qDebug() << qPrintable(toString(binding));
}
<|endoftext|>