<commit_before>//
// file : memory_allocator.hpp
// in : file:///home/tim/projects/persistence/persistence/tools/memory_allocator.hpp
//
// created by : Timothée Feuillet on linux.site
// date: 22/09/2014 11:00:31
//
//
// Copyright (C) 2014 Timothée Feuillet
//
// 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.
//
// This program 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//

#ifndef __N_2080522430493415542_1720253011__MEMORY_ALLOCATOR_HPP__
# define __N_2080522430493415542_1720253011__MEMORY_ALLOCATOR_HPP__

#include <cstdlib>
#include <new>
#include <cstddef>
#include <cstring>

namespace neam
{
  namespace cr
  {
    /// \brief a chunked memory pool that can produce contiguous output.
    class memory_allocator
    {
      public:
        memory_allocator()
        {
        }

        ~memory_allocator()
        {
          clear();
        }

        /// \brief allocate \e count bytes at the end of the pool
        /// \return \b nullptr if allocation failed.
        void *allocate(size_t count)
        {
          if (!first || last->end_offset + count > last->size) // allocate a chunk (no chunk or no place in the last chunk)
          {
            memory_chunk *nchk = new memory_chunk;
            nchk->size = count > chunk_size ? count : chunk_size;
            nchk->data = reinterpret_cast<uint8_t *>(operator new(nchk->size, std::nothrow));
            if (!nchk->data)
            {
              delete nchk;
              return nullptr;
            }

            nchk->end_offset = count;
            if (first)
            {
              last->next = nchk;
              nchk->prev = last;
              last = nchk;
            }
            else
            {
              first = nchk;
              last = nchk;
            }
            pool_size += count;
            return nchk->data;
          }

          // there is enough room in the last chunk
          void *data = last->data + last->end_offset;
          last->end_offset += count;
          pool_size += count;
          return data;
        }

        /// \brief allocate \e count bytes at the front of the pool
        /// \return \b nullptr if allocation failed.
        void *allocate_front(size_t count)
        {
          if (!first || first->start_offset < count) // allocate a chunk (no chunk or no place left in the first chunk)
          {
            memory_chunk *nchk = new memory_chunk;
            nchk->size = count > chunk_size ? count : chunk_size;
            nchk->data = reinterpret_cast<uint8_t *>(operator new(nchk->size, std::nothrow));
            if (!nchk->data)
            {
              delete nchk;
              return nullptr;
            }

            nchk->end_offset = nchk->size;
            nchk->start_offset = count;
            if (first)
            {
              first->prev = nchk;
              nchk->next = first;
              first = nchk;
            }
            else
            {
              first = nchk;
              last = nchk;
            }
            pool_size += count;
            return nchk->data;
          }

          // there is enough room in the last chunk
          first->start_offset -= count;
          pool_size += count;
          return first->data + first->start_offset;
        }

        /// \brief remove \e count bytes at the end of the pool
        void pop(size_t count)
        {
          if (!last)
            return;
          if (count >= pool_size)
            return clear();

          while (count)
          {
            if (last != first && (last->end_offset - last->start_offset) < count)
            {
              pool_size -= last->end_offset - last->start_offset;
              count -= last->end_offset - last->start_offset;
              last->prev->next = nullptr;
              memory_chunk *lst = last;
              last = last->prev;
              delete lst;
            }
            else if (last == first && (last->end_offset - last->start_offset) < count)
            {
              delete first;
              first = nullptr;
              last = nullptr;
              pool_size = 0;
              return;
            }
            else
            {
              last->end_offset -= count;
              pool_size -= count;
              return;
            }
          }
        }

        /// \brief remove \e count bytes at the start of the pool
        void pop_front(size_t count)
        {
          if (!first || !pool_size)
            return;
          if (count >= pool_size)
            return clear();

          while (count)
          {
            if (last != first && (first->end_offset - first->start_offset) < count)
            {
              pool_size -= first->end_offset - first->start_offset;
              count -= first->end_offset - first->start_offset;
              first->prev->next = nullptr;
              memory_chunk *lst = first;
              first = first->prev;
              delete lst;
            }
            else if (last == first && (last->end_offset - last->start_offset) < count)
            {
              delete first;
              first = nullptr;
              last = nullptr;
              pool_size = 0;
              return;
            }
            else
            {
              first->start_offset += count;
              pool_size -= count;
              return;
            }
          }
        }

        /// \brief make the data contiguous.
        /// \note don't free the memory !!!
        void *get_contiguous_data()
        {
          // easy cases:
          if (!first)
            return nullptr;
          if (!first->next && first->start_offset == 0) // already contiguous
            return first->data;

          memory_chunk *new_chk = new memory_chunk;
          new_chk->data = reinterpret_cast<uint8_t *>(operator new(pool_size, std::nothrow));
          if (!new_chk->data)
          {
            delete new_chk;
            return nullptr;
          }

          new_chk->size = pool_size;
          new_chk->start_offset = 0;
          new_chk->end_offset = pool_size;

          size_t idx = 0;
          memory_chunk *next = nullptr;
          for (memory_chunk *chr = first; chr; chr = next)
          {
            memcpy(new_chk->data + idx, chr->data + chr->start_offset, chr->end_offset - chr->start_offset);
            idx += chr->end_offset - chr->start_offset;
            next = chr->next;
            delete chr;
          }

          first = new_chk;
          last = new_chk;
          return new_chk->data;
        }

        /// \brief give the the data ownership, return the pointer to the data and clear the pool
        /// \note it's up to the user to delete this pointer.
        /// \see get_contiguous_data()
        /// \see clear()
        void *give_up_data()
        {
          void *ret = get_contiguous_data();
          if (first)
            first->data = nullptr;
          clear();
          return ret;
        }

        /// \brief empty the memory pool, delete every allocated memory.
        void clear()
        {
          memory_chunk *next = nullptr;
          for (memory_chunk *chr = first; chr; chr = next)
          {
            next = chr->next;
            delete chr;
          }
          first = nullptr;
          last = nullptr;
          pool_size = 0;
        }

        /// \brief return the size of the pool
        size_t size() const
        {
          return pool_size;
        }

      private:
        struct memory_chunk
        {
          uint8_t *data = nullptr;

          size_t start_offset = 0;
          size_t end_offset = 0;
          size_t size = 0;

          memory_chunk *next = nullptr;
          memory_chunk *prev = nullptr;

          ~memory_chunk()
          {
            delete data;
          }
        };

      private:
        constexpr static size_t chunk_size = 8192;

      private:
        memory_chunk *first = nullptr;
        memory_chunk *last = nullptr;
        size_t pool_size = 0;
    };
  } // namespace cr
} // namespace neam

#endif /*__N_2080522430493415542_1720253011__MEMORY_ALLOCATOR_HPP__*/

// kate: indent-mode cstyle; indent-width 2; replace-tabs on;

<commit_msg>[ALLOCATOR]: never fail on small memory allocations<commit_after>//
// file : memory_allocator.hpp
// in : file:///home/tim/projects/persistence/persistence/tools/memory_allocator.hpp
//
// created by : Timothée Feuillet on linux.site
// date: 22/09/2014 11:00:31
//
//
// Copyright (C) 2014 Timothée Feuillet
//
// 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.
//
// This program 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//

#ifndef __N_2080522430493415542_1720253011__MEMORY_ALLOCATOR_HPP__
# define __N_2080522430493415542_1720253011__MEMORY_ALLOCATOR_HPP__

#include <cstdlib>
#include <new>
#include <cstddef>
#include <cstring>

namespace neam
{
  namespace cr
  {
    /// \brief a chunked memory pool that can produce contiguous output.
    /// \note if an allocation size is < sizeof(uint64_t), then you could assume the allocation will never fail:
    ///       if the allocation fails, the function return a pointer to a valid area (an internal field) and set the \e failed flag to true.
    ///       so allocation of very small size will alway give a valid pointer.
    class memory_allocator
    {
      public:
        memory_allocator()
        {
          failed = false;
        }

        ~memory_allocator()
        {
          clear();
        }

        /// \brief return whether or not an allocation has failed.
        bool has_failed() const
        {
          return failed;
        }

        void clear_failed()
        {
          failed = false;
        }

        /// \brief allocate \e count bytes at the end of the pool
        /// \return \b nullptr if allocation failed.
        void *allocate(size_t count)
        {
          if (!first || last->end_offset + count > last->size) // allocate a chunk (no chunk or no place in the last chunk)
          {
            memory_chunk *nchk = new(std::nothrow) memory_chunk;
            if (nchk)
            {
              nchk->size = count > chunk_size ? count : chunk_size;
              nchk->data = reinterpret_cast<uint8_t *>(operator new(nchk->size, std::nothrow));
            }
            if (!nchk || !nchk->data)
            {
              failed = true;
              delete nchk;

              // never fail for small allocations
              if (count <= sizeof(fallback_small))
                return &fallback_small;
              return nullptr;
            }

            nchk->end_offset = count;
            if (first)
            {
              last->next = nchk;
              nchk->prev = last;
              last = nchk;
            }
            else
            {
              first = nchk;
              last = nchk;
            }
            pool_size += count;
            return nchk->data;
          }

          // there is enough room in the last chunk
          void *data = last->data + last->end_offset;
          last->end_offset += count;
          pool_size += count;
          return data;
        }

        /// \brief allocate \e count bytes at the front of the pool
        /// \return \b nullptr if allocation failed.
        void *allocate_front(size_t count)
        {
          if (!first || first->start_offset < count) // allocate a chunk (no chunk or no place left in the first chunk)
          {
            memory_chunk *nchk = new(std::nothrow) memory_chunk;
            if (nchk)
            {
              nchk->size = count > chunk_size ? count : chunk_size;
              nchk->data = reinterpret_cast<uint8_t *>(operator new(nchk->size, std::nothrow));
            }
            if (!nchk || !nchk->data)
            {
              failed = true;
              delete nchk;

              // never fail for small allocations
              if (count <= sizeof(fallback_small))
                return &fallback_small;

              return nullptr;
            }

            nchk->end_offset = nchk->size;
            nchk->start_offset = count;
            if (first)
            {
              first->prev = nchk;
              nchk->next = first;
              first = nchk;
            }
            else
            {
              first = nchk;
              last = nchk;
            }
            pool_size += count;
            return nchk->data;
          }

          // there is enough room in the last chunk
          first->start_offset -= count;
          pool_size += count;
          return first->data + first->start_offset;
        }

        /// \brief remove \e count bytes at the end of the pool
        void pop(size_t count)
        {
          if (!last)
            return;
          if (count >= pool_size)
            return clear();

          while (count)
          {
            if (last != first && (last->end_offset - last->start_offset) < count)
            {
              pool_size -= last->end_offset - last->start_offset;
              count -= last->end_offset - last->start_offset;
              last->prev->next = nullptr;
              memory_chunk *lst = last;
              last = last->prev;
              delete lst;
            }
            else if (last == first && (last->end_offset - last->start_offset) < count)
            {
              delete first;
              first = nullptr;
              last = nullptr;
              pool_size = 0;
              return;
            }
            else
            {
              last->end_offset -= count;
              pool_size -= count;
              return;
            }
          }
        }

        /// \brief remove \e count bytes at the start of the pool
        void pop_front(size_t count)
        {
          if (!first || !pool_size)
            return;
          if (count >= pool_size)
            return clear();

          while (count)
          {
            if (last != first && (first->end_offset - first->start_offset) < count)
            {
              pool_size -= first->end_offset - first->start_offset;
              count -= first->end_offset - first->start_offset;
              first->prev->next = nullptr;
              memory_chunk *lst = first;
              first = first->prev;
              delete lst;
            }
            else if (last == first && (last->end_offset - last->start_offset) < count)
            {
              delete first;
              first = nullptr;
              last = nullptr;
              pool_size = 0;
              return;
            }
            else
            {
              first->start_offset += count;
              pool_size -= count;
              return;
            }
          }
        }

        /// \brief make the data contiguous.
        /// \note don't free the memory !!!
        void *get_contiguous_data()
        {
          // easy cases:
          if (!first)
            return nullptr;
          if (!first->next && first->start_offset == 0) // already contiguous
            return first->data;

          memory_chunk *new_chk = new memory_chunk;
          new_chk->data = reinterpret_cast<uint8_t *>(operator new(pool_size, std::nothrow));
          if (!new_chk->data)
          {
            delete new_chk;
            return nullptr;
          }

          new_chk->size = pool_size;
          new_chk->start_offset = 0;
          new_chk->end_offset = pool_size;

          size_t idx = 0;
          memory_chunk *next = nullptr;
          for (memory_chunk *chr = first; chr; chr = next)
          {
            memcpy(new_chk->data + idx, chr->data + chr->start_offset, chr->end_offset - chr->start_offset);
            idx += chr->end_offset - chr->start_offset;
            next = chr->next;
            delete chr;
          }

          first = new_chk;
          last = new_chk;
          return new_chk->data;
        }

        /// \brief give the the data ownership, return the pointer to the data and clear the pool
        /// \note it's up to the user to delete this pointer.
        /// \see get_contiguous_data()
        /// \see clear()
        void *give_up_data()
        {
          void *ret = get_contiguous_data();
          if (first)
            first->data = nullptr;
          clear();
          return ret;
        }

        /// \brief empty the memory pool, delete every allocated memory.
        void clear()
        {
          memory_chunk *next = nullptr;
          for (memory_chunk *chr = first; chr; chr = next)
          {
            next = chr->next;
            delete chr;
          }
          first = nullptr;
          last = nullptr;
          pool_size = 0;
          failed = false;
        }

        /// \brief return the size of the pool
        size_t size() const
        {
          return pool_size;
        }

      private:
        struct memory_chunk
        {
          uint8_t *data = nullptr;

          size_t start_offset = 0;
          size_t end_offset = 0;
          size_t size = 0;

          memory_chunk *next = nullptr;
          memory_chunk *prev = nullptr;

          ~memory_chunk()
          {
            delete data;
          }
        };

      private:
        constexpr static size_t chunk_size = 8192;

      private:
        memory_chunk *first = nullptr;
        memory_chunk *last = nullptr;
        size_t pool_size = 0;
        bool failed = false;
        uint64_t fallback_small;
    };
  } // namespace cr
} // namespace neam

#endif /*__N_2080522430493415542_1720253011__MEMORY_ALLOCATOR_HPP__*/

// kate: indent-mode cstyle; indent-width 2; replace-tabs on;

<|endoftext|>


<commit_before>#include <boost/shared_ptr.hpp>

#include "ff.h"
#include "ff_spans.h"
#include "ff_lm.h"
#include "ff_klm.h"
#include "ff_ngrams.h"
#include "ff_csplit.h"
#include "ff_wordalign.h"
#include "ff_tagger.h"
#include "ff_factory.h"
#include "ff_rules.h"
#include "ff_ruleshape.h"
#include "ff_bleu.h"
#include "ff_lm_fsa.h"
#include "ff_sample_fsa.h"
#include "ff_source_syntax.h"
#include "ff_register.h"
#include "ff_charset.h"
#include "ff_wordset.h"
#include "ff_dwarf.h"

#ifdef HAVE_GLC
#include <cdec/ff_glc.h>
#endif

void register_feature_functions() {
  static bool registered = false;
  if (registered) {
    assert(!"register_feature_functions() called twice!");
  }
  registered = true;

  //TODO: these are worthless example target FSA ffs.  remove later
  RegisterFsaImpl<SameFirstLetter>(true);
  RegisterFsaImpl<LongerThanPrev>(true);
  RegisterFsaImpl<ShorterThanPrev>(true);
//  ff_registry.Register("LanguageModelFsaDynamic",new FFFactory<FeatureFunctionFromFsa<FsaFeatureFunctionDynamic<LanguageModelFsa> > >); // to test correctness of FsaFeatureFunctionDynamic erasure
  RegisterFsaDynToFF<LanguageModelFsa>();
  RegisterFsaImpl<LanguageModelFsa>(true); // same as LM but using fsa wrapper
  RegisterFsaDynToFF<SameFirstLetter>();

  RegisterFF<LanguageModel>();

  RegisterFF<WordPenalty>();
  RegisterFF<SourceWordPenalty>();
  RegisterFF<ArityPenalty>();
  RegisterFF<BLEUModel>();

  ff_registry.Register(new FFFactory<WordPenaltyFromFsa>); // same as WordPenalty, but implemented using ff_fsa

  //TODO: use for all features the new Register which requires static FF::usage(false,false) give name
#ifdef HAVE_RANDLM
  ff_registry.Register("RandLM", new FFFactory<LanguageModelRandLM>);
#endif
  ff_registry.Register("SpanFeatures", new FFFactory<SpanFeatures>());
  ff_registry.Register("NgramFeatures", new FFFactory<NgramDetector>());
  ff_registry.Register("RuleIdentityFeatures", new FFFactory<RuleIdentityFeatures>());
  ff_registry.Register("SourceSyntaxFeatures", new FFFactory<SourceSyntaxFeatures>);
  ff_registry.Register("RuleNgramFeatures", new FFFactory<RuleNgramFeatures>());
  ff_registry.Register("CMR2008ReorderingFeatures", new FFFactory<CMR2008ReorderingFeatures>());
  ff_registry.Register("KLanguageModel", new KLanguageModelFactory());
  ff_registry.Register("NonLatinCount", new FFFactory<NonLatinCount>);
  ff_registry.Register("RuleShape", new FFFactory<RuleShapeFeatures>);
  ff_registry.Register("RelativeSentencePosition", new FFFactory<RelativeSentencePosition>);
  ff_registry.Register("LexNullJump", new FFFactory<LexNullJump>);
  ff_registry.Register("NewJump", new FFFactory<NewJump>);
  ff_registry.Register("SourceBigram", new FFFactory<SourceBigram>);
  ff_registry.Register("Fertility", new FFFactory<Fertility>);
  ff_registry.Register("BlunsomSynchronousParseHack", new FFFactory<BlunsomSynchronousParseHack>);
  ff_registry.Register("CSplit_BasicFeatures", new FFFactory<BasicCSplitFeatures>);
  ff_registry.Register("CSplit_ReverseCharLM", new FFFactory<ReverseCharLMCSplitFeature>);
  ff_registry.Register("Tagger_BigramIndicator", new FFFactory<Tagger_BigramIndicator>);
  ff_registry.Register("LexicalPairIndicator", new FFFactory<LexicalPairIndicator>);
  ff_registry.Register("OutputIndicator", new FFFactory<OutputIndicator>);
  ff_registry.Register("IdentityCycleDetector", new FFFactory<IdentityCycleDetector>);
  ff_registry.Register("InputIndicator", new FFFactory<InputIndicator>);
  ff_registry.Register("LexicalTranslationTrigger", new FFFactory<LexicalTranslationTrigger>);
  ff_registry.Register("WordPairFeatures", new FFFactory<WordPairFeatures>);
  ff_registry.Register("WordSet", new FFFactory<WordSet>);
  ff_registry.Register("Dwarf", new FFFactory<Dwarf>);
#ifdef HAVE_GLC
  ff_registry.Register("ContextCRF", new FFFactory<Model1Features>);
#endif
}

<commit_msg>enable sss features<commit_after>#include <boost/shared_ptr.hpp>

#include "ff.h"
#include "ff_spans.h"
#include "ff_lm.h"
#include "ff_klm.h"
#include "ff_ngrams.h"
#include "ff_csplit.h"
#include "ff_wordalign.h"
#include "ff_tagger.h"
#include "ff_factory.h"
#include "ff_rules.h"
#include "ff_ruleshape.h"
#include "ff_bleu.h"
#include "ff_lm_fsa.h"
#include "ff_sample_fsa.h"
#include "ff_source_syntax.h"
#include "ff_register.h"
#include "ff_charset.h"
#include "ff_wordset.h"
#include "ff_dwarf.h"

#ifdef HAVE_GLC
#include <cdec/ff_glc.h>
#endif

void register_feature_functions() {
  static bool registered = false;
  if (registered) {
    assert(!"register_feature_functions() called twice!");
  }
  registered = true;

  //TODO: these are worthless example target FSA ffs.  remove later
  RegisterFsaImpl<SameFirstLetter>(true);
  RegisterFsaImpl<LongerThanPrev>(true);
  RegisterFsaImpl<ShorterThanPrev>(true);
//  ff_registry.Register("LanguageModelFsaDynamic",new FFFactory<FeatureFunctionFromFsa<FsaFeatureFunctionDynamic<LanguageModelFsa> > >); // to test correctness of FsaFeatureFunctionDynamic erasure
  RegisterFsaDynToFF<LanguageModelFsa>();
  RegisterFsaImpl<LanguageModelFsa>(true); // same as LM but using fsa wrapper
  RegisterFsaDynToFF<SameFirstLetter>();

  RegisterFF<LanguageModel>();

  RegisterFF<WordPenalty>();
  RegisterFF<SourceWordPenalty>();
  RegisterFF<ArityPenalty>();
  RegisterFF<BLEUModel>();

  ff_registry.Register(new FFFactory<WordPenaltyFromFsa>); // same as WordPenalty, but implemented using ff_fsa

  //TODO: use for all features the new Register which requires static FF::usage(false,false) give name
#ifdef HAVE_RANDLM
  ff_registry.Register("RandLM", new FFFactory<LanguageModelRandLM>);
#endif
  ff_registry.Register("SpanFeatures", new FFFactory<SpanFeatures>());
  ff_registry.Register("NgramFeatures", new FFFactory<NgramDetector>());
  ff_registry.Register("RuleIdentityFeatures", new FFFactory<RuleIdentityFeatures>());
  ff_registry.Register("SourceSyntaxFeatures", new FFFactory<SourceSyntaxFeatures>);
  ff_registry.Register("SourceSpanSizeFeatures", new FFFactory<SourceSpanSizeFeatures>);
  ff_registry.Register("RuleNgramFeatures", new FFFactory<RuleNgramFeatures>());
  ff_registry.Register("CMR2008ReorderingFeatures", new FFFactory<CMR2008ReorderingFeatures>());
  ff_registry.Register("KLanguageModel", new KLanguageModelFactory());
  ff_registry.Register("NonLatinCount", new FFFactory<NonLatinCount>);
  ff_registry.Register("RuleShape", new FFFactory<RuleShapeFeatures>);
  ff_registry.Register("RelativeSentencePosition", new FFFactory<RelativeSentencePosition>);
  ff_registry.Register("LexNullJump", new FFFactory<LexNullJump>);
  ff_registry.Register("NewJump", new FFFactory<NewJump>);
  ff_registry.Register("SourceBigram", new FFFactory<SourceBigram>);
  ff_registry.Register("Fertility", new FFFactory<Fertility>);
  ff_registry.Register("BlunsomSynchronousParseHack", new FFFactory<BlunsomSynchronousParseHack>);
  ff_registry.Register("CSplit_BasicFeatures", new FFFactory<BasicCSplitFeatures>);
  ff_registry.Register("CSplit_ReverseCharLM", new FFFactory<ReverseCharLMCSplitFeature>);
  ff_registry.Register("Tagger_BigramIndicator", new FFFactory<Tagger_BigramIndicator>);
  ff_registry.Register("LexicalPairIndicator", new FFFactory<LexicalPairIndicator>);
  ff_registry.Register("OutputIndicator", new FFFactory<OutputIndicator>);
  ff_registry.Register("IdentityCycleDetector", new FFFactory<IdentityCycleDetector>);
  ff_registry.Register("InputIndicator", new FFFactory<InputIndicator>);
  ff_registry.Register("LexicalTranslationTrigger", new FFFactory<LexicalTranslationTrigger>);
  ff_registry.Register("WordPairFeatures", new FFFactory<WordPairFeatures>);
  ff_registry.Register("WordSet", new FFFactory<WordSet>);
  ff_registry.Register("Dwarf", new FFFactory<Dwarf>);
#ifdef HAVE_GLC
  ff_registry.Register("ContextCRF", new FFFactory<Model1Features>);
#endif
}

<|endoftext|>


<commit_before>// Copyright (C) 2007-2015  CEA/DEN, EDF R&D, OPEN CASCADE
//
// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
//
// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
//

#include "SalomeApp_VisualState.h"

#include "SalomeApp_Module.h"
#include "SalomeApp_Study.h"
#include "SalomeApp_Application.h"

//#include <SUIT_ResourceMgr.h>
#include <SUIT_ViewManager.h>
#include <SUIT_ViewWindow.h>
#include <QtxWorkstack.h>

#include <STD_TabDesktop.h>

#include <QList>
#include <QApplication>
#include <QMultiHash>

#include <SALOMEDSClient_ClientFactory.hxx>//?
#include <SALOMEDSClient_IParameters.hxx>//?

#include <vector>//?
#include <string>//?
#include <cstdio>

/*!
  Constructor.
*/
SalomeApp_VisualState::SalomeApp_VisualState( SalomeApp_Application* app )
  : QObject(),
    myApp( app )
{
}

/*!
  Destructor.
*/
SalomeApp_VisualState::~SalomeApp_VisualState()
{
}

/*!
  Sets names of all view windows in given list.  This is used
  in order to apply the same naming algorithm when saving and restoring
  view windows.  Names of view windows must be the same before saving
  workstack (splitters) information, and before its restoring!
  Naming rule: ViewerType_IndexOfViewerOfThisType_IndexOfViewInThisViewer
               VTKViewer_0_0
               OCCViewer_0_0  OCCViewer_0_1  OCCViewer_0_2
               VTKViewer_1_0
*/
void nameViewWindows( const ViewManagerList& lst )
{
  QMap<QString, int> viewersCounter;
  for ( QList<SUIT_ViewManager*>::const_iterator it = lst.begin(); it != lst.end(); ++it )
  {
    SUIT_ViewManager* aVM = *it;
    if ( !aVM )
      continue;

    int view_count = aVM->getViewsCount();
    QString vType = aVM->getType();
    if ( !view_count )
      continue; //No views is opened in the viewer

    if ( !viewersCounter.contains( vType ) )
      viewersCounter.insert( vType, 0 );

    int& viewerID = viewersCounter[vType];

    QVector<SUIT_ViewWindow*> views = aVM->getViews();
    for ( int i = 0; i < view_count; i++ )
    {
      QString vName = QString( "%1_%2_%3" ).arg( vType ).arg( viewerID ).arg( i );
      views[i]->setObjectName( vName );
    }
    viewerID++;
  }
}

/*!
  Stores the visual parameters of the viewers
*/
int SalomeApp_VisualState::storeState()
{
  SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( myApp->activeStudy() );
  if ( !study )
    return -1;

  // unlock study if it is locked
  bool aLocked = study->studyDS()->GetProperties()->IsLocked();
  if (aLocked) study->studyDS()->GetProperties()->SetLocked(false);

  int savePoint = 1;
  std::vector<int> savePoints = study->getSavePoints();
  //Calculate a new savePoint number = the last save point number + 1
  if ( savePoints.size() > 0)
    savePoint = savePoints[savePoints.size()-1] + 1;

  _PTR(AttributeParameter) ap = study->studyDS()->GetCommonParameters( study->getVisualComponentName().toLatin1().constData(),
								       savePoint );
  _PTR(IParameters) ip = ClientFactory::getIParameters( ap );

  ViewManagerList lst;
  myApp->viewManagers( lst );

  // setting unique names for view windows in order to save this view inside
  // workstack's structure (see below).  On restore the views with the same names will
  // be placed to the same place inside the workstack's splitters.
  nameViewWindows( lst );

  // store active window's name
  SUIT_ViewWindow* win = myApp->desktop()->activeWindow();
  if ( win )
    ip->setProperty("AP_ACTIVE_VIEW", win->objectName().toStdString() );

  int viewerID = 0;
  SUIT_ViewManager* vm = 0;
  QListIterator<SUIT_ViewManager*> it( lst );
  while ( it.hasNext() ) {
    vm = it.next();
    if ( !vm ) continue;

    int view_count = vm->getViewsCount();
    if ( !view_count )
      continue; //No views is opened in the viewer

    std::string viewerEntry = QString( "%1_%2" ).arg( vm->getType() ).arg( ++viewerID ).toStdString();
    ip->append("AP_VIEWERS_LIST", viewerEntry);

    QVector<SUIT_ViewWindow*> views = vm->getViews();
    for(int i = 0; i<view_count; i++) {
      ip->append( viewerEntry, views[i]->windowTitle().toStdString() );
      ip->append( viewerEntry, views[i]->getVisualParameters().toStdString() );
    }
  }

  //Save information about split areas
  if ( myApp->desktop()->inherits( "STD_TabDesktop" ) )
  {
    QString workstackInfo;
    QtxWorkstack* workstack = ((STD_TabDesktop*)myApp->desktop())->workstack();
    QByteArray geomState = workstack->saveState( 0 );
    ip->setProperty( "AP_WORKSTACK_INFO", QString( geomState.toHex() ).toStdString() );
  }

  //Save a name of the active module
  if ( CAM_Module* activeModule = myApp->activeModule() )
    ip->setProperty( "AP_ACTIVE_MODULE", activeModule->moduleName().toStdString() );

  //Store visual parameters of the modules
  QList<CAM_Module*> mlist;
  myApp->modules( mlist );
  QListIterator<CAM_Module*> itM( mlist );
  CAM_Module* module = 0;
  while ( itM.hasNext() ) {
    module = itM.next();
    if ( !module ) continue;

    if ( SalomeApp_Module* sModule = dynamic_cast<SalomeApp_Module*>( module ) ) {
      ip->append( "AP_MODULES_LIST", sModule->moduleName().toStdString() );
      sModule->storeVisualParameters( savePoint );
    }
  }

  // set default name of new savePoint
  study->setNameOfSavePoint( savePoint, QObject::tr( "SAVE_POINT_DEF_NAME" ) + QString::number( savePoint ) );

  if (aLocked) study->studyDS()->GetProperties()->SetLocked(true);

  return savePoint;
}

/*!
  Restores the visual parameters of the viewers
*/
void SalomeApp_VisualState::restoreState(int savePoint)
{
  SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( myApp->activeStudy() );
  if ( !study )
    return;

  _PTR(AttributeParameter) ap = study->studyDS()->GetCommonParameters( study->getVisualComponentName().toLatin1().constData(),
								       savePoint );
  _PTR(IParameters) ip = ClientFactory::getIParameters(ap);

  qApp->installEventFilter( this );

  //Remove all already existent veiwers and their views
  //myApp->clearViewManagers();
  myApp->clearKnownViewManagers();

  //Restore the viewers and view windows
  int nbViewers = ip->nbValues( "AP_VIEWERS_LIST" );
  SUIT_ViewWindow* viewWin = 0;

  // parameters of view windows are stored in a map for restoring after restoring of the workstack
  QMap<SUIT_ViewWindow*, QString> viewersParameters;

  for ( int i = 0; i < nbViewers; i++ )
  {
    std::string viewerEntry = ip->getValue( "AP_VIEWERS_LIST", i );
    std::vector<std::string> veiewerParams = ip->parseValue(viewerEntry,'_');
    std::string type = veiewerParams[0];
    std::string viewerID = veiewerParams[1];
    SUIT_ViewManager* vm = myApp->newViewManager( type.c_str() );
    if ( !vm )
      continue; //Unknown viewer

    int nbViews = (ip->nbValues(viewerEntry))/2;

    //Create nbViews-1 view (-1 because 1 view is created by createViewManager)
    for ( int i = 1; i< nbViews; i++ )
    {
      SUIT_ViewWindow* aView = vm->createViewWindow();
      aView->show();
    }

    int viewCount = vm->getViewsCount();
    if ( viewCount != nbViews )
    {
      printf( "\nRestore visual state: Unknow error, Can't create a view!\n" );
      continue;
    }

    //Resize the views, set their captions and apply visual parameters.
    QVector<SUIT_ViewWindow*> views = vm->getViews();
    for ( int i = 0, j = 0; i<viewCount; i++, j+=2 )
    {
      viewWin = views[i];
      if ( !viewWin )
        continue;

      // wait untill the window is really shown.  This step fixes MANY bugs..
      //      while ( !vm->isVisible() )
      //        qApp->processEvents();

      viewWin->setWindowTitle( ip->getValue( viewerEntry, j ).c_str() );

      //      printf ( "VP for viewWin \"%s\": %s\n", viewerEntry.c_str(), ip->getValue(viewerEntry, j+1).c_str() );
      viewersParameters[ viewWin ] = ip->getValue( viewerEntry, j + 1 ).c_str();
      //viewWin->setVisualParameters(ip->getValue(viewerEntry, j+1).c_str());
    }
  }

  qApp->processEvents( QEventLoop::ExcludeUserInputEvents, 5000 );

  // restore modules' visual parameters
  std::vector<std::string> v = ip->getValues( "AP_MODULES_LIST" );
  for ( int i = 0; i < v.size(); i++ )
  {
    myApp->activateModule( v[i].c_str() );
    if ( SalomeApp_Module* module = dynamic_cast<SalomeApp_Module*>( myApp->activeModule() ) )
      module->restoreVisualParameters( savePoint );
  }

  // new view windows may have been created in  module->restoreVisualParameters() [GAUSS]
  // so here we store their visual parameters for later restoring..
  QList<SUIT_ViewManager*> lst;
  myApp->viewManagers( lst );
  for ( QList<SUIT_ViewManager*>::iterator itVM = lst.begin(); itVM != lst.end(); ++itVM )
  {
    SUIT_ViewManager* aVM = *itVM;
    if ( !aVM )
      continue;

    int view_count = aVM->getViewsCount();
    QVector<SUIT_ViewWindow*> views = aVM->getViews();
    for ( int i = 0; i < view_count; i++ )
    {
      if ( !viewersParameters.contains( views[i] ) )
      {
        viewersParameters[ views[i] ] = views[i]->getVisualParameters();
        //      printf ( "store VP for viewWin \"%s\": %s\n", views[i]->name(), views[i]->getVisualParameters().toLatin1().constData() );
      }
    }
  }

  // activate module that was active on save
  QString activeModuleName( ip->getProperty("AP_ACTIVE_MODULE" ).c_str() );
  if ( !activeModuleName.isEmpty() )
    myApp->activateModule( activeModuleName );

  // setting unique names for view windows in order to restore positions of view windows inside
  // workstack's structure (see below).  During save the same naming algorithm was used,
  // so the same views will get the same names.
  nameViewWindows( lst );

  qApp->processEvents( QEventLoop::ExcludeUserInputEvents, 5000 );

  // restore workstack parameters.  should be done after module's restoreVisualParameters(), because
  // some modules can create their own viewers (like VISU creates GaussViewers)
  if ( myApp->desktop()->inherits( "STD_TabDesktop" ) )
  {
    QtxWorkstack* workstack = ((STD_TabDesktop*)myApp->desktop())->workstack();
    workstack->restoreState( QByteArray::fromHex( QByteArray( ip->getProperty( "AP_WORKSTACK_INFO" ).c_str() ) ), 0 );
  }

  // restore visual parameters of view windows.  it must be done AFTER restoring workstack.
  // also set active view
  std::string activeViewName = ip->getProperty("AP_ACTIVE_VIEW");
  QMap<SUIT_ViewWindow*, QString>::Iterator mapIt;
  for ( mapIt = viewersParameters.begin(); mapIt != viewersParameters.end(); ++mapIt ) {
    mapIt.key()->setVisualParameters( mapIt.value() );
    if ( activeViewName == mapIt.key()->objectName().toStdString() )
      mapIt.key()->setFocus();
  }

  qApp->removeEventFilter( this );

  //  for ( it.toFirst(); it.current(); ++it ) {
  //    int view_count = it.current()->getViewsCount();
  //    QPtrVector<SUIT_ViewWindow> views = it.current()->getViews();
  //    for ( int i = 0; i < view_count; i++ )
  //      views[i]->setVisualParameters( viewersParameters[ views[i]->name() ] );
  //  }

  // set focus to previously saved active view window
  //  std::string activeViewName = ip->getProperty("AP_ACTIVE_VIEW");
  //  for ( it.toFirst(); it.current(); ++it ) {
  //    int view_count = it.current()->getViewsCount();
  //    QPtrVector<SUIT_ViewWindow> views = it.current()->getViews();
  //    for ( int i = 0; i < view_count; i++ )  {
  //      if ( activeViewName == views[i]->name() )
  //    views[i]->setFocus();
  //    }
  //  }
}

/*!
  Custom event filter
*/
bool SalomeApp_VisualState::eventFilter( QObject* o, QEvent* e )
{
  // eat keyboard and mouse events
  QEvent::Type aType = e->type();
  if ( aType == QEvent::MouseButtonDblClick ||
       aType == QEvent::MouseButtonPress ||
       aType == QEvent::MouseButtonRelease ||
       aType == QEvent::MouseMove ||
       aType == QEvent::KeyPress ||
       aType == QEvent::KeyRelease )
    return true;

  return QObject::eventFilter( o, e );
}
<commit_msg>allow auto loading of light modules when opening study file<commit_after>// Copyright (C) 2007-2015  CEA/DEN, EDF R&D, OPEN CASCADE
//
// Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
//
// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
//

#include "SalomeApp_VisualState.h"

#include "SalomeApp_Module.h"
#include "SalomeApp_Study.h"
#include "SalomeApp_Application.h"

//#include <SUIT_ResourceMgr.h>
#include <SUIT_ViewManager.h>
#include <SUIT_ViewWindow.h>
#include <QtxWorkstack.h>

#include <STD_TabDesktop.h>

#include <QList>
#include <QApplication>
#include <QMultiHash>

#include <SALOMEDSClient_ClientFactory.hxx>//?
#include <SALOMEDSClient_IParameters.hxx>//?

#include <vector>//?
#include <string>//?
#include <cstdio>

/*!
  Constructor.
*/
SalomeApp_VisualState::SalomeApp_VisualState( SalomeApp_Application* app )
  : QObject(),
    myApp( app )
{
}

/*!
  Destructor.
*/
SalomeApp_VisualState::~SalomeApp_VisualState()
{
}

/*!
  Sets names of all view windows in given list.  This is used
  in order to apply the same naming algorithm when saving and restoring
  view windows.  Names of view windows must be the same before saving
  workstack (splitters) information, and before its restoring!
  Naming rule: ViewerType_IndexOfViewerOfThisType_IndexOfViewInThisViewer
               VTKViewer_0_0
               OCCViewer_0_0  OCCViewer_0_1  OCCViewer_0_2
               VTKViewer_1_0
*/
void nameViewWindows( const ViewManagerList& lst )
{
  QMap<QString, int> viewersCounter;
  for ( QList<SUIT_ViewManager*>::const_iterator it = lst.begin(); it != lst.end(); ++it )
  {
    SUIT_ViewManager* aVM = *it;
    if ( !aVM )
      continue;

    int view_count = aVM->getViewsCount();
    QString vType = aVM->getType();
    if ( !view_count )
      continue; //No views is opened in the viewer

    if ( !viewersCounter.contains( vType ) )
      viewersCounter.insert( vType, 0 );

    int& viewerID = viewersCounter[vType];

    QVector<SUIT_ViewWindow*> views = aVM->getViews();
    for ( int i = 0; i < view_count; i++ )
    {
      QString vName = QString( "%1_%2_%3" ).arg( vType ).arg( viewerID ).arg( i );
      views[i]->setObjectName( vName );
    }
    viewerID++;
  }
}

/*!
  Stores the visual parameters of the viewers
*/
int SalomeApp_VisualState::storeState()
{
  SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( myApp->activeStudy() );
  if ( !study )
    return -1;

  // unlock study if it is locked
  bool aLocked = study->studyDS()->GetProperties()->IsLocked();
  if (aLocked) study->studyDS()->GetProperties()->SetLocked(false);

  int savePoint = 1;
  std::vector<int> savePoints = study->getSavePoints();
  //Calculate a new savePoint number = the last save point number + 1
  if ( savePoints.size() > 0)
    savePoint = savePoints[savePoints.size()-1] + 1;

  _PTR(AttributeParameter) ap = study->studyDS()->GetCommonParameters( study->getVisualComponentName().toLatin1().constData(),
								       savePoint );
  _PTR(IParameters) ip = ClientFactory::getIParameters( ap );

  ViewManagerList lst;
  myApp->viewManagers( lst );

  // setting unique names for view windows in order to save this view inside
  // workstack's structure (see below).  On restore the views with the same names will
  // be placed to the same place inside the workstack's splitters.
  nameViewWindows( lst );

  // store active window's name
  SUIT_ViewWindow* win = myApp->desktop()->activeWindow();
  if ( win )
    ip->setProperty("AP_ACTIVE_VIEW", win->objectName().toStdString() );

  int viewerID = 0;
  SUIT_ViewManager* vm = 0;
  QListIterator<SUIT_ViewManager*> it( lst );
  while ( it.hasNext() ) {
    vm = it.next();
    if ( !vm ) continue;

    int view_count = vm->getViewsCount();
    if ( !view_count )
      continue; //No views is opened in the viewer

    std::string viewerEntry = QString( "%1_%2" ).arg( vm->getType() ).arg( ++viewerID ).toStdString();
    ip->append("AP_VIEWERS_LIST", viewerEntry);

    QVector<SUIT_ViewWindow*> views = vm->getViews();
    for(int i = 0; i<view_count; i++) {
      ip->append( viewerEntry, views[i]->windowTitle().toStdString() );
      ip->append( viewerEntry, views[i]->getVisualParameters().toStdString() );
    }
  }

  //Save information about split areas
  if ( myApp->desktop()->inherits( "STD_TabDesktop" ) )
  {
    QString workstackInfo;
    QtxWorkstack* workstack = ((STD_TabDesktop*)myApp->desktop())->workstack();
    QByteArray geomState = workstack->saveState( 0 );
    ip->setProperty( "AP_WORKSTACK_INFO", QString( geomState.toHex() ).toStdString() );
  }

  //Save a name of the active module
  if ( CAM_Module* activeModule = myApp->activeModule() )
    ip->setProperty( "AP_ACTIVE_MODULE", activeModule->moduleName().toStdString() );

  //Store visual parameters of the modules
  QList<CAM_Module*> mlist;
  myApp->modules( mlist );
  QListIterator<CAM_Module*> itM( mlist );
  CAM_Module* module = 0;
  while ( itM.hasNext() ) {
    module = itM.next();
    //DEBTRACE("---");
    if ( !module ) continue;
    //DEBTRACE("--- " << module->name().toStdString());

    if ( LightApp_Module* lModule = dynamic_cast<LightApp_Module*>( module ) ) {
      //DEBTRACE("AP_MODULES_LIST append " << lModule->moduleName().toStdString());
      ip->append( "AP_MODULES_LIST", lModule->moduleName().toStdString() );
      if ( SalomeApp_Module* sModule = dynamic_cast<SalomeApp_Module*>( module ) )
        sModule->storeVisualParameters( savePoint );
    }
  }

  // set default name of new savePoint
  study->setNameOfSavePoint( savePoint, QObject::tr( "SAVE_POINT_DEF_NAME" ) + QString::number( savePoint ) );

  if (aLocked) study->studyDS()->GetProperties()->SetLocked(true);

  return savePoint;
}

/*!
  Restores the visual parameters of the viewers
*/
void SalomeApp_VisualState::restoreState(int savePoint)
{
  SalomeApp_Study* study = dynamic_cast<SalomeApp_Study*>( myApp->activeStudy() );
  if ( !study )
    return;

  _PTR(AttributeParameter) ap = study->studyDS()->GetCommonParameters( study->getVisualComponentName().toLatin1().constData(),
								       savePoint );
  _PTR(IParameters) ip = ClientFactory::getIParameters(ap);

  qApp->installEventFilter( this );

  //Remove all already existent veiwers and their views
  //myApp->clearViewManagers();
  myApp->clearKnownViewManagers();

  //Restore the viewers and view windows
  int nbViewers = ip->nbValues( "AP_VIEWERS_LIST" );
  SUIT_ViewWindow* viewWin = 0;

  // parameters of view windows are stored in a map for restoring after restoring of the workstack
  QMap<SUIT_ViewWindow*, QString> viewersParameters;

  for ( int i = 0; i < nbViewers; i++ )
  {
    std::string viewerEntry = ip->getValue( "AP_VIEWERS_LIST", i );
    std::vector<std::string> veiewerParams = ip->parseValue(viewerEntry,'_');
    std::string type = veiewerParams[0];
    std::string viewerID = veiewerParams[1];
    SUIT_ViewManager* vm = myApp->newViewManager( type.c_str() );
    if ( !vm )
      continue; //Unknown viewer

    int nbViews = (ip->nbValues(viewerEntry))/2;

    //Create nbViews-1 view (-1 because 1 view is created by createViewManager)
    for ( int i = 1; i< nbViews; i++ )
    {
      SUIT_ViewWindow* aView = vm->createViewWindow();
      aView->show();
    }

    int viewCount = vm->getViewsCount();
    if ( viewCount != nbViews )
    {
      printf( "\nRestore visual state: Unknow error, Can't create a view!\n" );
      continue;
    }

    //Resize the views, set their captions and apply visual parameters.
    QVector<SUIT_ViewWindow*> views = vm->getViews();
    for ( int i = 0, j = 0; i<viewCount; i++, j+=2 )
    {
      viewWin = views[i];
      if ( !viewWin )
        continue;

      // wait untill the window is really shown.  This step fixes MANY bugs..
      //      while ( !vm->isVisible() )
      //        qApp->processEvents();

      viewWin->setWindowTitle( ip->getValue( viewerEntry, j ).c_str() );

      //      printf ( "VP for viewWin \"%s\": %s\n", viewerEntry.c_str(), ip->getValue(viewerEntry, j+1).c_str() );
      viewersParameters[ viewWin ] = ip->getValue( viewerEntry, j + 1 ).c_str();
      //viewWin->setVisualParameters(ip->getValue(viewerEntry, j+1).c_str());
    }
  }

  qApp->processEvents( QEventLoop::ExcludeUserInputEvents, 5000 );

  // restore modules' visual parameters
  std::vector<std::string> v = ip->getValues( "AP_MODULES_LIST" );
  for ( int i = 0; i < v.size(); i++ )
  {
    myApp->activateModule( v[i].c_str() );
    if ( SalomeApp_Module* module = dynamic_cast<SalomeApp_Module*>( myApp->activeModule() ) )
      module->restoreVisualParameters( savePoint );
  }

  // new view windows may have been created in  module->restoreVisualParameters() [GAUSS]
  // so here we store their visual parameters for later restoring..
  QList<SUIT_ViewManager*> lst;
  myApp->viewManagers( lst );
  for ( QList<SUIT_ViewManager*>::iterator itVM = lst.begin(); itVM != lst.end(); ++itVM )
  {
    SUIT_ViewManager* aVM = *itVM;
    if ( !aVM )
      continue;

    int view_count = aVM->getViewsCount();
    QVector<SUIT_ViewWindow*> views = aVM->getViews();
    for ( int i = 0; i < view_count; i++ )
    {
      if ( !viewersParameters.contains( views[i] ) )
      {
        viewersParameters[ views[i] ] = views[i]->getVisualParameters();
        //      printf ( "store VP for viewWin \"%s\": %s\n", views[i]->name(), views[i]->getVisualParameters().toLatin1().constData() );
      }
    }
  }

  // activate module that was active on save
  QString activeModuleName( ip->getProperty("AP_ACTIVE_MODULE" ).c_str() );
  if ( !activeModuleName.isEmpty() )
    myApp->activateModule( activeModuleName );

  // setting unique names for view windows in order to restore positions of view windows inside
  // workstack's structure (see below).  During save the same naming algorithm was used,
  // so the same views will get the same names.
  nameViewWindows( lst );

  qApp->processEvents( QEventLoop::ExcludeUserInputEvents, 5000 );

  // restore workstack parameters.  should be done after module's restoreVisualParameters(), because
  // some modules can create their own viewers (like VISU creates GaussViewers)
  if ( myApp->desktop()->inherits( "STD_TabDesktop" ) )
  {
    QtxWorkstack* workstack = ((STD_TabDesktop*)myApp->desktop())->workstack();
    workstack->restoreState( QByteArray::fromHex( QByteArray( ip->getProperty( "AP_WORKSTACK_INFO" ).c_str() ) ), 0 );
  }

  // restore visual parameters of view windows.  it must be done AFTER restoring workstack.
  // also set active view
  std::string activeViewName = ip->getProperty("AP_ACTIVE_VIEW");
  QMap<SUIT_ViewWindow*, QString>::Iterator mapIt;
  for ( mapIt = viewersParameters.begin(); mapIt != viewersParameters.end(); ++mapIt ) {
    mapIt.key()->setVisualParameters( mapIt.value() );
    if ( activeViewName == mapIt.key()->objectName().toStdString() )
      mapIt.key()->setFocus();
  }

  qApp->removeEventFilter( this );

  //  for ( it.toFirst(); it.current(); ++it ) {
  //    int view_count = it.current()->getViewsCount();
  //    QPtrVector<SUIT_ViewWindow> views = it.current()->getViews();
  //    for ( int i = 0; i < view_count; i++ )
  //      views[i]->setVisualParameters( viewersParameters[ views[i]->name() ] );
  //  }

  // set focus to previously saved active view window
  //  std::string activeViewName = ip->getProperty("AP_ACTIVE_VIEW");
  //  for ( it.toFirst(); it.current(); ++it ) {
  //    int view_count = it.current()->getViewsCount();
  //    QPtrVector<SUIT_ViewWindow> views = it.current()->getViews();
  //    for ( int i = 0; i < view_count; i++ )  {
  //      if ( activeViewName == views[i]->name() )
  //    views[i]->setFocus();
  //    }
  //  }
}

/*!
  Custom event filter
*/
bool SalomeApp_VisualState::eventFilter( QObject* o, QEvent* e )
{
  // eat keyboard and mouse events
  QEvent::Type aType = e->type();
  if ( aType == QEvent::MouseButtonDblClick ||
       aType == QEvent::MouseButtonPress ||
       aType == QEvent::MouseButtonRelease ||
       aType == QEvent::MouseMove ||
       aType == QEvent::KeyPress ||
       aType == QEvent::KeyRelease )
    return true;

  return QObject::eventFilter( o, e );
}
<|endoftext|>


<commit_before>/* RTcmix  - Copyright (C) 2004  The RTcmix Development Team
   See ``AUTHORS'' for a list of contributors. See ``LICENSE'' for
   the license to this software and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <rtcmix_types.h>
#include <PField.h>
#include <RTcmixMIDI.h>
#include <RTMidiPField.h>
#include <ugens.h>		// for warn, die

//FIXME: better to have a struct with one field a string, the other type

#define NAME_VARIANTS 4
static char *_midi_type_name[][NAME_VARIANTS] = {
	// NB: Order of these must correspond to indices given by MIDIType enum!
	{ "cntl", "control", NULL, NULL },
	{ "noteon", NULL, NULL, NULL },
	{ "noteoff", NULL, NULL, NULL },
	{ "bend", "pitchbend", NULL, NULL },
	{ "prog", "program", NULL, NULL },
	{ "chanpress", "monopress", "at", "aftertouch" },
	{ "polypress", "keypress", "polyat", "polyaftertouch" },
	{ NULL, NULL, NULL, NULL }
};

static char *_midi_controller_name[][NAME_VARIANTS] = {
	{ "banksel", NULL, NULL, NULL },
	{ "mod", "modwheel", "modulation", NULL },
	{ "breath", NULL, NULL, NULL },
	{ NULL, NULL, NULL, NULL },
	{ "foot", NULL, NULL, NULL },
	{ "port time", "portamento time", NULL, NULL },
	{ "data", NULL, NULL, NULL },
	{ "vol", "volume", NULL, NULL },
	{ "bal", "balance", NULL, NULL },
	{ NULL, NULL, NULL, NULL },
	{ "pan", NULL, NULL, NULL },
	{ "exp", "expression", NULL, NULL },
	{ NULL, NULL, NULL, NULL }
};

// -------------------------------------------------------- _midi_connection ---
//
//    midi = makeconnection("midi", min, max, default, lag, chan, type,
//                                                                [subtype])
//
//    <chan>      MIDI channel (1-16)
//
//    <type>      "noteon", "noteoff", "cntl", "prog", "bend", "chanpress",
//                "polypress"
//
//    <subtype>   depends on <type>:
//                   noteon     "note", "velocity"
//                   noteoff    "note", "velocity"
//                   cntl       controller number or string symbol, such as
//                              "mod", "foot", "breath", "data", "volume", "pan"
//                   prog       not applicable
//                   bend       not applicable
//                   monopress  not applicable
//                   polypress  MIDI note number
//
//

static RTNumberPField *
_midi_usage()
{
	die("makeconnection (midi)",
		"Usage: makeconnection(\"midi\", min, max, default, lag, "
		"chan, type[, subtype])");
	return NULL;
}

static MIDIType
_string_to_type(const char *type)
{
	for (int i = 0; _midi_type_name[i][0] != NULL; i++) {
		for (int j = 0; j < NAME_VARIANTS; j++) {
			const char *name = _midi_type_name[i][j];
			if (name == NULL)
				break;
			if (strcasecmp(type, name) == 0)
				return (MIDIType) i;
		}
	}
	return kMIDIInvalidType;
}

static MIDISubType
_string_to_subtype(const MIDIType type, const char *subtype)
{
	if (type == kMIDIControlType) {
//FIXME
	}
	else if (type == kMIDINoteOnType || type == kMIDINoteOffType) {
		if (strcmp(subtype, "note") == 0)
			return kMIDINoteSubType;
		else if (strncmp(subtype, "vel", 3) == 0)
			return kMIDIVelocitySubType;
	}
	return kMIDIInvalidSubType;
}

RTNumberPField *
midi_connection(const Arg args[], const int nargs)
{
	static RTcmixMIDI *midiport = NULL;
	if (midiport == NULL)				// first time, so init midi system
		midiport = createMIDIPort();

	double minval, maxval, defaultval, lag;
	int chan;
	MIDIType type;
	MIDISubType subtype;

	if (args[1].isType(DoubleType))
		minval = args[1];
	else
		return _midi_usage();

	if (args[2].isType(DoubleType))
		maxval = args[2];
	else
		return _midi_usage();

	if (args[3].isType(DoubleType))
		defaultval = args[3];
	else
		return _midi_usage();

	if (args[4].isType(DoubleType))
		lag = args[4];
	else
		return _midi_usage();

	if (args[5].isType(DoubleType))
		chan = (int) args[5] - 1;		// convert to zero-based channel
	else
		return _midi_usage();

	if (args[6].isType(StringType))
		type = _string_to_type(args[6]);
	else
		return _midi_usage();
	if (type == kMIDIInvalidType)
		return _midi_usage();

	if (nargs > 7) {
		if (args[7].isType(StringType))
			subtype = _string_to_subtype(type, args[7]);
		else if (args[7].isType(DoubleType))
			// NB: this can be a code or a literal int, e.g. note or controller num
			subtype = (MIDISubType) (int) args[7];
		else
			return _midi_usage();
		if (subtype == kMIDIInvalidSubType)
			return _midi_usage();
	}

	return new RTMidiPField(midiport, minval, maxval, defaultval, lag, chan,
																		type, subtype);
}

<commit_msg>Fix potential uninited var; flesh out subtype string conversion.<commit_after>/* RTcmix  - Copyright (C) 2004  The RTcmix Development Team
   See ``AUTHORS'' for a list of contributors. See ``LICENSE'' for
   the license to this software and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <rtcmix_types.h>
#include <PField.h>
#include <RTcmixMIDI.h>
#include <RTMidiPField.h>
#include <ugens.h>		// for warn, die

//FIXME: better to have a struct with one field a string, the other type

#define NAME_VARIANTS 4
static char *_midi_type_name[][NAME_VARIANTS] = {
	// NB: Order of these must correspond to indices given by MIDIType enum!
	{ "cntl", "control", NULL, NULL },
	{ "noteon", NULL, NULL, NULL },
	{ "noteoff", NULL, NULL, NULL },
	{ "bend", "pitchbend", NULL, NULL },
	{ "prog", "program", NULL, NULL },
	{ "chanpress", "monopress", "at", "aftertouch" },
	{ "polypress", "keypress", "polyat", "polyaftertouch" },
	{ NULL, NULL, NULL, NULL }
};

static char *_midi_controller_name[][NAME_VARIANTS] = {
	{ "banksel", NULL, NULL, NULL },
	{ "mod", "modwheel", "modulation", NULL },
	{ "breath", NULL, NULL, NULL },
	{ NULL, NULL, NULL, NULL },
	{ "foot", NULL, NULL, NULL },
	{ "port time", "portamento time", NULL, NULL },
	{ "data", NULL, NULL, NULL },
	{ "vol", "volume", NULL, NULL },
	{ "bal", "balance", NULL, NULL },
	{ NULL, NULL, NULL, NULL },
	{ "pan", NULL, NULL, NULL },
	{ "exp", "expression", NULL, NULL },
	{ NULL, NULL, NULL, NULL }
//FIXME: add others
};

// -------------------------------------------------------- _midi_connection ---
//
//    midi = makeconnection("midi", min, max, default, lag, chan, type,
//                                                                [subtype])
//
//    <chan>      MIDI channel (1-16)
//
//    <type>      "noteon", "noteoff", "cntl", "prog", "bend", "chanpress",
//                "polypress"
//
//    <subtype>   depends on <type>:
//                   noteon     "note", "velocity"
//                   noteoff    "note", "velocity"
//                   cntl       controller number or string symbol, such as
//                              "mod", "foot", "breath", "data", "volume", "pan"
//                   prog       not applicable
//                   bend       not applicable
//                   monopress  not applicable
//                   polypress  MIDI note number
//
//

static RTNumberPField *
_midi_usage()
{
	die("makeconnection (midi)",
		"Usage: makeconnection(\"midi\", min, max, default, lag, "
		"chan, type[, subtype])");
	return NULL;
}

static MIDIType
_string_to_type(const char *type)
{
	for (int i = 0; _midi_type_name[i][0] != NULL; i++) {
		for (int j = 0; j < NAME_VARIANTS; j++) {
			const char *name = _midi_type_name[i][j];
			if (name == NULL)
				break;
			if (strcasecmp(type, name) == 0)
				return (MIDIType) i;
		}
	}
	return kMIDIInvalidType;
}

static MIDISubType
_string_to_subtype(const MIDIType type, const char *subtype)
{
	if (type == kMIDIControlType) {
		for (int i = 0; _midi_controller_name[i][0] != NULL; i++) {
			for (int j = 0; j < NAME_VARIANTS; j++) {
				const char *name = _midi_controller_name[i][j];
				if (name == NULL)
					break;
				if (strcasecmp(type, name) == 0)
					return (MIDISubType) i;
			}
		}
	}
	else if (type == kMIDINoteOnType || type == kMIDINoteOffType) {
		if (strcmp(subtype, "note") == 0)
			return kMIDINoteSubType;
		else if (strncmp(subtype, "vel", 3) == 0)
			return kMIDIVelocitySubType;
	}
	return kMIDIInvalidSubType;
}

RTNumberPField *
midi_connection(const Arg args[], const int nargs)
{
	static RTcmixMIDI *midiport = NULL;
	if (midiport == NULL)				// first time, so init midi system
		midiport = createMIDIPort();

	double minval, maxval, defaultval, lag;
	int chan;
	MIDIType type = kMIDIInvalidType;
	MIDISubType subtype = kMIDIInvalidSubType;

	if (args[1].isType(DoubleType))
		minval = args[1];
	else
		return _midi_usage();

	if (args[2].isType(DoubleType))
		maxval = args[2];
	else
		return _midi_usage();

	if (args[3].isType(DoubleType))
		defaultval = args[3];
	else
		return _midi_usage();

	if (args[4].isType(DoubleType))
		lag = args[4];
	else
		return _midi_usage();

	if (args[5].isType(DoubleType))
		chan = (int) args[5] - 1;		// convert to zero-based channel
	else
		return _midi_usage();

	if (args[6].isType(StringType))
		type = _string_to_type(args[6]);
	else
		return _midi_usage();
	if (type == kMIDIInvalidType)
		return _midi_usage();

	if (nargs > 7) {
		if (args[7].isType(StringType))
			subtype = _string_to_subtype(type, args[7]);
		else if (args[7].isType(DoubleType))
			// NB: this can be a code or a literal int, e.g. note or controller num
			subtype = (MIDISubType) (int) args[7];
		else
			return _midi_usage();
		if (subtype == kMIDIInvalidSubType)
			return _midi_usage();
	}

	return new RTMidiPField(midiport, minval, maxval, defaultval, lag, chan,
																		type, subtype);
}

<|endoftext|>