<commit_before>//===--- Tooling.cpp - Running clang standalone tools ---------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file implements functions to run clang tools standalone instead
//  of running them as a plugin.
//
//===----------------------------------------------------------------------===//

#include "clang/Tooling/Tooling.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/Tool.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "clang/Tooling/ArgumentsAdjusters.h"
#include "clang/Tooling/CompilationDatabase.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/raw_ostream.h"

// For chdir, see the comment in ClangTool::run for more information.
#ifdef _WIN32
#  include <direct.h>
#else
#  include <unistd.h>
#endif

namespace clang {
namespace tooling {

FrontendActionFactory::~FrontendActionFactory() {}

// FIXME: This file contains structural duplication with other parts of the
// code that sets up a compiler to run tools on it, and we should refactor
// it to be based on the same framework.

/// \brief Builds a clang driver initialized for running clang tools.
static clang::driver::Driver *newDriver(clang::DiagnosticsEngine *Diagnostics,
                                        const char *BinaryName) {
  const std::string DefaultOutputName = "a.out";
  clang::driver::Driver *CompilerDriver = new clang::driver::Driver(
    BinaryName, llvm::sys::getDefaultTargetTriple(),
    DefaultOutputName, *Diagnostics);
  CompilerDriver->setTitle("clang_based_tool");
  return CompilerDriver;
}

/// \brief Retrieves the clang CC1 specific flags out of the compilation's jobs.
///
/// Returns NULL on error.
static const clang::driver::ArgStringList *getCC1Arguments(
    clang::DiagnosticsEngine *Diagnostics,
    clang::driver::Compilation *Compilation) {
  // We expect to get back exactly one Command job, if we didn't something
  // failed. Extract that job from the Compilation.
  const clang::driver::JobList &Jobs = Compilation->getJobs();
  if (Jobs.size() != 1 || !isa<clang::driver::Command>(*Jobs.begin())) {
    SmallString<256> error_msg;
    llvm::raw_svector_ostream error_stream(error_msg);
    Compilation->PrintJob(error_stream, Compilation->getJobs(), "; ", true);
    Diagnostics->Report(clang::diag::err_fe_expected_compiler_job)
        << error_stream.str();
    return NULL;
  }

  // The one job we find should be to invoke clang again.
  const clang::driver::Command *Cmd =
      cast<clang::driver::Command>(*Jobs.begin());
  if (StringRef(Cmd->getCreator().getName()) != "clang") {
    Diagnostics->Report(clang::diag::err_fe_expected_clang_command);
    return NULL;
  }

  return &Cmd->getArguments();
}

/// \brief Returns a clang build invocation initialized from the CC1 flags.
static clang::CompilerInvocation *newInvocation(
    clang::DiagnosticsEngine *Diagnostics,
    const clang::driver::ArgStringList &CC1Args) {
  assert(!CC1Args.empty() && "Must at least contain the program name!");
  clang::CompilerInvocation *Invocation = new clang::CompilerInvocation;
  clang::CompilerInvocation::CreateFromArgs(
      *Invocation, CC1Args.data() + 1, CC1Args.data() + CC1Args.size(),
      *Diagnostics);
  Invocation->getFrontendOpts().DisableFree = false;
  return Invocation;
}

bool runToolOnCode(clang::FrontendAction *ToolAction, const Twine &Code,
                   const Twine &FileName) {
  return runToolOnCodeWithArgs(
      ToolAction, Code, std::vector<std::string>(), FileName);
}

bool runToolOnCodeWithArgs(clang::FrontendAction *ToolAction, const Twine &Code,
                           const std::vector<std::string> &Args,
                           const Twine &FileName) {
  SmallString<16> FileNameStorage;
  StringRef FileNameRef = FileName.toNullTerminatedStringRef(FileNameStorage);
  std::vector<std::string> Commands;
  Commands.push_back("clang-tool");
  Commands.push_back("-fsyntax-only");
  Commands.insert(Commands.end(), Args.begin(), Args.end());
  Commands.push_back(FileNameRef.data());
  FileManager Files((FileSystemOptions()));
  ToolInvocation Invocation(Commands, ToolAction, &Files);

  SmallString<1024> CodeStorage;
  Invocation.mapVirtualFile(FileNameRef,
                            Code.toNullTerminatedStringRef(CodeStorage));
  return Invocation.run();
}

std::string getAbsolutePath(StringRef File) {
  SmallString<1024> BaseDirectory;
  if (const char *PWD = ::getenv("PWD"))
    BaseDirectory = PWD;
  else
    llvm::sys::fs::current_path(BaseDirectory);
  SmallString<1024> PathStorage;
  if (llvm::sys::path::is_absolute(File)) {
    llvm::sys::path::native(File, PathStorage);
    return PathStorage.str();
  }
  StringRef RelativePath(File);
  // FIXME: Should '.\\' be accepted on Win32?
  if (RelativePath.startswith("./")) {
    RelativePath = RelativePath.substr(strlen("./"));
  }
  SmallString<1024> AbsolutePath(BaseDirectory);
  llvm::sys::path::append(AbsolutePath, RelativePath);
  llvm::sys::path::native(Twine(AbsolutePath), PathStorage);
  return PathStorage.str();
}

ToolInvocation::ToolInvocation(
    ArrayRef<std::string> CommandLine, FrontendAction *ToolAction,
    FileManager *Files)
    : CommandLine(CommandLine.vec()), ToolAction(ToolAction), Files(Files) {
}

void ToolInvocation::mapVirtualFile(StringRef FilePath, StringRef Content) {
  SmallString<1024> PathStorage;
  llvm::sys::path::native(FilePath, PathStorage);
  MappedFileContents[PathStorage] = Content;
}

bool ToolInvocation::run() {
  std::vector<const char*> Argv;
  for (int I = 0, E = CommandLine.size(); I != E; ++I)
    Argv.push_back(CommandLine[I].c_str());
  const char *const BinaryName = Argv[0];
  IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
  TextDiagnosticPrinter DiagnosticPrinter(
      llvm::errs(), &*DiagOpts);
  DiagnosticsEngine Diagnostics(
    IntrusiveRefCntPtr<clang::DiagnosticIDs>(new DiagnosticIDs()),
    &*DiagOpts, &DiagnosticPrinter, false);

  const OwningPtr<clang::driver::Driver> Driver(
      newDriver(&Diagnostics, BinaryName));
  // Since the input might only be virtual, don't check whether it exists.
  Driver->setCheckInputsExist(false);
  const OwningPtr<clang::driver::Compilation> Compilation(
      Driver->BuildCompilation(llvm::makeArrayRef(Argv)));
  const clang::driver::ArgStringList *const CC1Args = getCC1Arguments(
      &Diagnostics, Compilation.get());
  if (CC1Args == NULL) {
    return false;
  }
  OwningPtr<clang::CompilerInvocation> Invocation(
      newInvocation(&Diagnostics, *CC1Args));
  return runInvocation(BinaryName, Compilation.get(), Invocation.take());
}

bool ToolInvocation::runInvocation(
    const char *BinaryName,
    clang::driver::Compilation *Compilation,
    clang::CompilerInvocation *Invocation) {
  // Show the invocation, with -v.
  if (Invocation->getHeaderSearchOpts().Verbose) {
    llvm::errs() << "clang Invocation:\n";
    Compilation->PrintJob(llvm::errs(), Compilation->getJobs(), "\n", true);
    llvm::errs() << "\n";
  }

  // Create a compiler instance to handle the actual work.
  clang::CompilerInstance Compiler;
  Compiler.setInvocation(Invocation);
  Compiler.setFileManager(Files);
  // FIXME: What about LangOpts?

  // ToolAction can have lifetime requirements for Compiler or its members, and
  // we need to ensure it's deleted earlier than Compiler. So we pass it to an
  // OwningPtr declared after the Compiler variable.
  OwningPtr<FrontendAction> ScopedToolAction(ToolAction.take());

  // Create the compilers actual diagnostics engine.
  Compiler.createDiagnostics();
  if (!Compiler.hasDiagnostics())
    return false;

  Compiler.createSourceManager(*Files);
  addFileMappingsTo(Compiler.getSourceManager());

  const bool Success = Compiler.ExecuteAction(*ScopedToolAction);

  Compiler.resetAndLeakFileManager();
  Files->clearStatCaches();
  return Success;
}

void ToolInvocation::addFileMappingsTo(SourceManager &Sources) {
  for (llvm::StringMap<StringRef>::const_iterator
           It = MappedFileContents.begin(), End = MappedFileContents.end();
       It != End; ++It) {
    // Inject the code as the given file name into the preprocessor options.
    const llvm::MemoryBuffer *Input =
        llvm::MemoryBuffer::getMemBuffer(It->getValue());
    // FIXME: figure out what '0' stands for.
    const FileEntry *FromFile = Files->getVirtualFile(
        It->getKey(), Input->getBufferSize(), 0);
    Sources.overrideFileContents(FromFile, Input);
  }
}

ClangTool::ClangTool(const CompilationDatabase &Compilations,
                     ArrayRef<std::string> SourcePaths)
    : Files((FileSystemOptions())),
      ArgsAdjuster(new ClangSyntaxOnlyAdjuster()) {
  for (unsigned I = 0, E = SourcePaths.size(); I != E; ++I) {
    SmallString<1024> File(getAbsolutePath(SourcePaths[I]));

    std::vector<CompileCommand> CompileCommandsForFile =
      Compilations.getCompileCommands(File.str());
    if (!CompileCommandsForFile.empty()) {
      for (int I = 0, E = CompileCommandsForFile.size(); I != E; ++I) {
        CompileCommands.push_back(std::make_pair(File.str(),
                                  CompileCommandsForFile[I]));
      }
    } else {
      // FIXME: There are two use cases here: doing a fuzzy
      // "find . -name '*.cc' |xargs tool" match, where as a user I don't care
      // about the .cc files that were not found, and the use case where I
      // specify all files I want to run over explicitly, where this should
      // be an error. We'll want to add an option for this.
      llvm::outs() << "Skipping " << File << ". Command line not found.\n";
    }
  }
}

void ClangTool::mapVirtualFile(StringRef FilePath, StringRef Content) {
  MappedFileContents.push_back(std::make_pair(FilePath, Content));
}

void ClangTool::setArgumentsAdjuster(ArgumentsAdjuster *Adjuster) {
  ArgsAdjuster.reset(Adjuster);
}

int ClangTool::run(FrontendActionFactory *ActionFactory) {
  // Exists solely for the purpose of lookup of the resource path.
  // This just needs to be some symbol in the binary.
  static int StaticSymbol;
  // The driver detects the builtin header path based on the path of the
  // executable.
  // FIXME: On linux, GetMainExecutable is independent of the value of the
  // first argument, thus allowing ClangTool and runToolOnCode to just
  // pass in made-up names here. Make sure this works on other platforms.
  std::string MainExecutable =
    llvm::sys::Path::GetMainExecutable("clang_tool", &StaticSymbol).str();

  bool ProcessingFailed = false;
  for (unsigned I = 0; I < CompileCommands.size(); ++I) {
    std::string File = CompileCommands[I].first;
    // FIXME: chdir is thread hostile; on the other hand, creating the same
    // behavior as chdir is complex: chdir resolves the path once, thus
    // guaranteeing that all subsequent relative path operations work
    // on the same path the original chdir resulted in. This makes a difference
    // for example on network filesystems, where symlinks might be switched
    // during runtime of the tool. Fixing this depends on having a file system
    // abstraction that allows openat() style interactions.
    if (chdir(CompileCommands[I].second.Directory.c_str()))
      llvm::report_fatal_error("Cannot chdir into \"" +
                               CompileCommands[I].second.Directory + "\n!");
    std::vector<std::string> CommandLine =
      ArgsAdjuster->Adjust(CompileCommands[I].second.CommandLine);
    assert(!CommandLine.empty());
    CommandLine[0] = MainExecutable;
    llvm::outs() << "Processing: " << File << ".\n";
    ToolInvocation Invocation(CommandLine, ActionFactory->create(), &Files);
    for (int I = 0, E = MappedFileContents.size(); I != E; ++I) {
      Invocation.mapVirtualFile(MappedFileContents[I].first,
                                MappedFileContents[I].second);
    }
    if (!Invocation.run()) {
      llvm::outs() << "Error while processing " << File << ".\n";
      ProcessingFailed = true;
    }
  }
  return ProcessingFailed ? 1 : 0;
}

} // end namespace tooling
} // end namespace clang
<commit_msg>ClangTool output cleanup<commit_after>//===--- Tooling.cpp - Running clang standalone tools ---------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//  This file implements functions to run clang tools standalone instead
//  of running them as a plugin.
//
//===----------------------------------------------------------------------===//

#include "clang/Tooling/Tooling.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/Tool.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "clang/Tooling/ArgumentsAdjusters.h"
#include "clang/Tooling/CompilationDatabase.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Debug.h"

// For chdir, see the comment in ClangTool::run for more information.
#ifdef _WIN32
#  include <direct.h>
#else
#  include <unistd.h>
#endif

namespace clang {
namespace tooling {

FrontendActionFactory::~FrontendActionFactory() {}

// FIXME: This file contains structural duplication with other parts of the
// code that sets up a compiler to run tools on it, and we should refactor
// it to be based on the same framework.

/// \brief Builds a clang driver initialized for running clang tools.
static clang::driver::Driver *newDriver(clang::DiagnosticsEngine *Diagnostics,
                                        const char *BinaryName) {
  const std::string DefaultOutputName = "a.out";
  clang::driver::Driver *CompilerDriver = new clang::driver::Driver(
    BinaryName, llvm::sys::getDefaultTargetTriple(),
    DefaultOutputName, *Diagnostics);
  CompilerDriver->setTitle("clang_based_tool");
  return CompilerDriver;
}

/// \brief Retrieves the clang CC1 specific flags out of the compilation's jobs.
///
/// Returns NULL on error.
static const clang::driver::ArgStringList *getCC1Arguments(
    clang::DiagnosticsEngine *Diagnostics,
    clang::driver::Compilation *Compilation) {
  // We expect to get back exactly one Command job, if we didn't something
  // failed. Extract that job from the Compilation.
  const clang::driver::JobList &Jobs = Compilation->getJobs();
  if (Jobs.size() != 1 || !isa<clang::driver::Command>(*Jobs.begin())) {
    SmallString<256> error_msg;
    llvm::raw_svector_ostream error_stream(error_msg);
    Compilation->PrintJob(error_stream, Compilation->getJobs(), "; ", true);
    Diagnostics->Report(clang::diag::err_fe_expected_compiler_job)
        << error_stream.str();
    return NULL;
  }

  // The one job we find should be to invoke clang again.
  const clang::driver::Command *Cmd =
      cast<clang::driver::Command>(*Jobs.begin());
  if (StringRef(Cmd->getCreator().getName()) != "clang") {
    Diagnostics->Report(clang::diag::err_fe_expected_clang_command);
    return NULL;
  }

  return &Cmd->getArguments();
}

/// \brief Returns a clang build invocation initialized from the CC1 flags.
static clang::CompilerInvocation *newInvocation(
    clang::DiagnosticsEngine *Diagnostics,
    const clang::driver::ArgStringList &CC1Args) {
  assert(!CC1Args.empty() && "Must at least contain the program name!");
  clang::CompilerInvocation *Invocation = new clang::CompilerInvocation;
  clang::CompilerInvocation::CreateFromArgs(
      *Invocation, CC1Args.data() + 1, CC1Args.data() + CC1Args.size(),
      *Diagnostics);
  Invocation->getFrontendOpts().DisableFree = false;
  return Invocation;
}

bool runToolOnCode(clang::FrontendAction *ToolAction, const Twine &Code,
                   const Twine &FileName) {
  return runToolOnCodeWithArgs(
      ToolAction, Code, std::vector<std::string>(), FileName);
}

bool runToolOnCodeWithArgs(clang::FrontendAction *ToolAction, const Twine &Code,
                           const std::vector<std::string> &Args,
                           const Twine &FileName) {
  SmallString<16> FileNameStorage;
  StringRef FileNameRef = FileName.toNullTerminatedStringRef(FileNameStorage);
  std::vector<std::string> Commands;
  Commands.push_back("clang-tool");
  Commands.push_back("-fsyntax-only");
  Commands.insert(Commands.end(), Args.begin(), Args.end());
  Commands.push_back(FileNameRef.data());
  FileManager Files((FileSystemOptions()));
  ToolInvocation Invocation(Commands, ToolAction, &Files);

  SmallString<1024> CodeStorage;
  Invocation.mapVirtualFile(FileNameRef,
                            Code.toNullTerminatedStringRef(CodeStorage));
  return Invocation.run();
}

std::string getAbsolutePath(StringRef File) {
  SmallString<1024> BaseDirectory;
  if (const char *PWD = ::getenv("PWD"))
    BaseDirectory = PWD;
  else
    llvm::sys::fs::current_path(BaseDirectory);
  SmallString<1024> PathStorage;
  if (llvm::sys::path::is_absolute(File)) {
    llvm::sys::path::native(File, PathStorage);
    return PathStorage.str();
  }
  StringRef RelativePath(File);
  // FIXME: Should '.\\' be accepted on Win32?
  if (RelativePath.startswith("./")) {
    RelativePath = RelativePath.substr(strlen("./"));
  }
  SmallString<1024> AbsolutePath(BaseDirectory);
  llvm::sys::path::append(AbsolutePath, RelativePath);
  llvm::sys::path::native(Twine(AbsolutePath), PathStorage);
  return PathStorage.str();
}

ToolInvocation::ToolInvocation(
    ArrayRef<std::string> CommandLine, FrontendAction *ToolAction,
    FileManager *Files)
    : CommandLine(CommandLine.vec()), ToolAction(ToolAction), Files(Files) {
}

void ToolInvocation::mapVirtualFile(StringRef FilePath, StringRef Content) {
  SmallString<1024> PathStorage;
  llvm::sys::path::native(FilePath, PathStorage);
  MappedFileContents[PathStorage] = Content;
}

bool ToolInvocation::run() {
  std::vector<const char*> Argv;
  for (int I = 0, E = CommandLine.size(); I != E; ++I)
    Argv.push_back(CommandLine[I].c_str());
  const char *const BinaryName = Argv[0];
  IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
  TextDiagnosticPrinter DiagnosticPrinter(
      llvm::errs(), &*DiagOpts);
  DiagnosticsEngine Diagnostics(
    IntrusiveRefCntPtr<clang::DiagnosticIDs>(new DiagnosticIDs()),
    &*DiagOpts, &DiagnosticPrinter, false);

  const OwningPtr<clang::driver::Driver> Driver(
      newDriver(&Diagnostics, BinaryName));
  // Since the input might only be virtual, don't check whether it exists.
  Driver->setCheckInputsExist(false);
  const OwningPtr<clang::driver::Compilation> Compilation(
      Driver->BuildCompilation(llvm::makeArrayRef(Argv)));
  const clang::driver::ArgStringList *const CC1Args = getCC1Arguments(
      &Diagnostics, Compilation.get());
  if (CC1Args == NULL) {
    return false;
  }
  OwningPtr<clang::CompilerInvocation> Invocation(
      newInvocation(&Diagnostics, *CC1Args));
  return runInvocation(BinaryName, Compilation.get(), Invocation.take());
}

bool ToolInvocation::runInvocation(
    const char *BinaryName,
    clang::driver::Compilation *Compilation,
    clang::CompilerInvocation *Invocation) {
  // Show the invocation, with -v.
  if (Invocation->getHeaderSearchOpts().Verbose) {
    llvm::errs() << "clang Invocation:\n";
    Compilation->PrintJob(llvm::errs(), Compilation->getJobs(), "\n", true);
    llvm::errs() << "\n";
  }

  // Create a compiler instance to handle the actual work.
  clang::CompilerInstance Compiler;
  Compiler.setInvocation(Invocation);
  Compiler.setFileManager(Files);
  // FIXME: What about LangOpts?

  // ToolAction can have lifetime requirements for Compiler or its members, and
  // we need to ensure it's deleted earlier than Compiler. So we pass it to an
  // OwningPtr declared after the Compiler variable.
  OwningPtr<FrontendAction> ScopedToolAction(ToolAction.take());

  // Create the compilers actual diagnostics engine.
  Compiler.createDiagnostics();
  if (!Compiler.hasDiagnostics())
    return false;

  Compiler.createSourceManager(*Files);
  addFileMappingsTo(Compiler.getSourceManager());

  const bool Success = Compiler.ExecuteAction(*ScopedToolAction);

  Compiler.resetAndLeakFileManager();
  Files->clearStatCaches();
  return Success;
}

void ToolInvocation::addFileMappingsTo(SourceManager &Sources) {
  for (llvm::StringMap<StringRef>::const_iterator
           It = MappedFileContents.begin(), End = MappedFileContents.end();
       It != End; ++It) {
    // Inject the code as the given file name into the preprocessor options.
    const llvm::MemoryBuffer *Input =
        llvm::MemoryBuffer::getMemBuffer(It->getValue());
    // FIXME: figure out what '0' stands for.
    const FileEntry *FromFile = Files->getVirtualFile(
        It->getKey(), Input->getBufferSize(), 0);
    Sources.overrideFileContents(FromFile, Input);
  }
}

ClangTool::ClangTool(const CompilationDatabase &Compilations,
                     ArrayRef<std::string> SourcePaths)
    : Files((FileSystemOptions())),
      ArgsAdjuster(new ClangSyntaxOnlyAdjuster()) {
  for (unsigned I = 0, E = SourcePaths.size(); I != E; ++I) {
    SmallString<1024> File(getAbsolutePath(SourcePaths[I]));

    std::vector<CompileCommand> CompileCommandsForFile =
      Compilations.getCompileCommands(File.str());
    if (!CompileCommandsForFile.empty()) {
      for (int I = 0, E = CompileCommandsForFile.size(); I != E; ++I) {
        CompileCommands.push_back(std::make_pair(File.str(),
                                  CompileCommandsForFile[I]));
      }
    } else {
      // FIXME: There are two use cases here: doing a fuzzy
      // "find . -name '*.cc' |xargs tool" match, where as a user I don't care
      // about the .cc files that were not found, and the use case where I
      // specify all files I want to run over explicitly, where this should
      // be an error. We'll want to add an option for this.
      llvm::outs() << "Skipping " << File << ". Command line not found.\n";
    }
  }
}

void ClangTool::mapVirtualFile(StringRef FilePath, StringRef Content) {
  MappedFileContents.push_back(std::make_pair(FilePath, Content));
}

void ClangTool::setArgumentsAdjuster(ArgumentsAdjuster *Adjuster) {
  ArgsAdjuster.reset(Adjuster);
}

int ClangTool::run(FrontendActionFactory *ActionFactory) {
  // Exists solely for the purpose of lookup of the resource path.
  // This just needs to be some symbol in the binary.
  static int StaticSymbol;
  // The driver detects the builtin header path based on the path of the
  // executable.
  // FIXME: On linux, GetMainExecutable is independent of the value of the
  // first argument, thus allowing ClangTool and runToolOnCode to just
  // pass in made-up names here. Make sure this works on other platforms.
  std::string MainExecutable =
    llvm::sys::Path::GetMainExecutable("clang_tool", &StaticSymbol).str();

  bool ProcessingFailed = false;
  for (unsigned I = 0; I < CompileCommands.size(); ++I) {
    std::string File = CompileCommands[I].first;
    // FIXME: chdir is thread hostile; on the other hand, creating the same
    // behavior as chdir is complex: chdir resolves the path once, thus
    // guaranteeing that all subsequent relative path operations work
    // on the same path the original chdir resulted in. This makes a difference
    // for example on network filesystems, where symlinks might be switched
    // during runtime of the tool. Fixing this depends on having a file system
    // abstraction that allows openat() style interactions.
    if (chdir(CompileCommands[I].second.Directory.c_str()))
      llvm::report_fatal_error("Cannot chdir into \"" +
                               CompileCommands[I].second.Directory + "\n!");
    std::vector<std::string> CommandLine =
      ArgsAdjuster->Adjust(CompileCommands[I].second.CommandLine);
    assert(!CommandLine.empty());
    CommandLine[0] = MainExecutable;
    DEBUG({
      llvm::dbgs() << "Processing: " << File << ".\n";
    });
    ToolInvocation Invocation(CommandLine, ActionFactory->create(), &Files);
    for (int I = 0, E = MappedFileContents.size(); I != E; ++I) {
      Invocation.mapVirtualFile(MappedFileContents[I].first,
                                MappedFileContents[I].second);
    }
    if (!Invocation.run()) {
      llvm::errs() << "Error while processing " << File << ".\n";
      ProcessingFailed = true;
    }
  }
  return ProcessingFailed ? 1 : 0;
}

} // end namespace tooling
} // end namespace clang
<|endoftext|>


<commit_before>//////////////////////////////////////////////////////////////////////////////////////////////////////
// AliAnalysisMultPt:
// Description: Analysis task get multiplicity
// and pT distributions
// Author: Negin Alizadehvandchali
// (negin.alizadehvandchali@cern.ch)
/////////////////////////////////////////////////////////////////////////////////////////////////////
#include "TString.h"
#include <vector>
#include <algorithm>
#include <cstdlib>
#include <ctime>
#include <math.h>
#include "TChain.h"
#include "TFile.h"
#include "TKey.h"
#include "TObject.h"
#include "TObjString.h"
#include "TList.h"
#include "TTree.h"
#include "TH1F.h"
#include "TH1D.h"
#include "TH2D.h"
#include "TH3D.h"
#include "TProfile.h"
#include "TCanvas.h"
#include "TBits.h"
#include "TRefArray.h"
#include "TAxis.h"
#include "TRandom.h"
#include "TList.h"
#include "TComplex.h"
#include "TMath.h"
#include <cmath>
#include <cstdlib>
#include "AliAODTrack.h"
#include "AliAnalysisTask.h"
#include "AliAnalysisTaskSE.h"
#include "AliAnalysisManager.h"
#include "AliAODInputHandler.h"
#include "AliAODEvent.h"
#include "AliAODMCParticle.h"
#include "AliAnalysisMultPt.h"

using namespace std;            // std namespace: so you can do things like 'cout'

ClassImp(AliAnalysisMultPt)     // classimp: necessary for root
//________________________________________________________________________

AliAnalysisMultPt::AliAnalysisMultPt() : AliAnalysisTaskSE(),
fAOD(0), fOutputList(0), fHistMultPt(0), fHistMult(0), fHistMultPtMC(0), fHistMultRatio(0), fIsMC(0), fPtmin(0.2), fPtmax(5), fEta(0.8), fBit(128)

{

}

//________________________________________________________________________
AliAnalysisMultPt::AliAnalysisMultPt(const char* name) : AliAnalysisTaskSE(name),
fAOD(0), fOutputList(0), fHistMultPt(0), fHistMult(0), fHistMultPtMC(0), fHistMultRatio(0), fIsMC(0), fPtmin(0.2), fPtmax(5), fEta(0.8), fBit(128)

{
    DefineInput(0, TChain::Class());
    DefineOutput(1, TList::Class());
}
//________________________________________________________________________
AliAnalysisMultPt::~AliAnalysisMultPt()
{
    // destructor
    if(fOutputList) {
        delete fOutputList;     // at the end of your task, it is deleted from memory by calling this function
    }
}

//________________________________________________________________________

void AliAnalysisMultPt::SetMCRead(Bool_t flag) { fIsMC = flag; }

void AliAnalysisMultPt::UserCreateOutputObjects()
    {

    fOutputList = new TList();
    fOutputList->SetOwner(kTRUE);

    fHistMult = new TH1D("fHistMult", "Mult", 3000, 0, 3000);
    fOutputList->Add(fHistMult);
    fHistMult->SetStats(0);
    fHistMult->SetTitle("Multiplicity");
    fHistMult->SetXTitle("Multiplicity");
    fHistMult->SetMarkerSize(1.2);

    fHistMultPt = new TH2D("fHistMultPt", "MultpT", 3000, 0, 3000, 50, 0, 5);
    fOutputList->Add(fHistMultPt);
    fHistMultPt->SetStats(0);
    fHistMultPt->SetTitle("pT vs Multiplicity");
    fHistMultPt->SetXTitle("Multiplicity");
    fHistMultPt->SetYTitle("pT");
    fHistMultPt->SetLineColor(2);
    fHistMultPt->SetMarkerSize(1.2);

    fHistMultPtMC = new TH2D("fHistMultPtMC", "MultPt-MC", 3000, 0, 3000, 50, 0, 5);
    fOutputList->Add(fHistMultPtMC);
    fHistMultPtMC->SetStats(0);
    fHistMultPtMC->SetTitle("pT vs Generated Multiplicity");
    fHistMultPtMC->SetXTitle("Generated N_{ch}");
    fHistMultPtMC->SetYTitle("pT");
    fHistMultPtMC->SetLineColor(2);
    fHistMultPtMC->SetMarkerSize(1.2);

    fHistMultRatio = new TH2D("fHistMultRatio", "Ratio",  3000, 0, 3000, 3000, 0, 3000);
    fOutputList->Add(fHistMultRatio);
    fHistMultRatio->SetStats(0);
    fHistMultRatio->SetTitle("Generated Multiplicity vs Reconstructed");
    fHistMultRatio->SetXTitle("Reconstructed N_{ch}");
    fHistMultRatio->SetYTitle("Generated N_{ch}");
    fHistMultRatio->SetLineColor(2);
    fHistMultRatio->SetMarkerSize(1.2);

    // add the list to our output file
    PostData(1, fOutputList);
    //PostData(1, mixer);
    }

//________________________________________________________________________

void AliAnalysisMultPt::UserExec(Option_t *)
{

////////////////////////////////////////////////////////////////////////////////Track-based part (Either data or reconstructed MC):
    // get an event from the analysis manager:
    fAOD = dynamic_cast<AliAODEvent*> (InputEvent());
    // check if there actually is an event:
    if(!fAOD) return;
    // ::Fatal("AliAnalysisTaskMultPt::UserExec", "No AOD event found, check the event handler.");
     //For charged particle
    Double_t Mult=0.0;

    // loop over all these tracks:
    for(Int_t i(0); i < fAOD->GetNumberOfTracks(); i++) {
         // get a track (type AliAODTrack) from the event:
        AliAODTrack* track = static_cast<AliAODTrack*>(fAOD->GetTrack(i));
        // if we failed, skip this track
        if(!track) continue;
        Int_t charge = track->Charge();
        if(TMath :: Abs(charge)>0) {
            if(track->Pt() < fPtmin|| track->Pt() > fPtmax) continue;
            if(fabs(track->Eta()) > fEta) continue;   //eta cut
            if(track->TestFilterBit(fBit)){
                Mult++;
            }
        }
    }
    //Number of events vs multiplicity
    fHistMult->Fill(Mult);

    for( Int_t i(0); i < fAOD->GetNumberOfTracks(); i++) {
         // get a track (type AliAODTrack) from the event:
         AliAODTrack* track = static_cast<AliAODTrack*>(fAOD->GetTrack(i));
         // if we failed, skip this track:
         if(!track) continue;
         Int_t charge = track->Charge();

         //Count the charge particles:
         if(TMath :: Abs(charge)>0) {
             if(track->Pt() < fPtmin|| track->Pt() > fPtmax) continue;
             if(fabs(track->Eta()) > fEta) continue;   //eta cut
             if(track->TestFilterBit(fBit)){
                 fHistMultPt->Fill(Mult, track->Pt());
             }
         }
    }

/////////////////////////////////////////////////////////////////////////////////// Generated part:
    if(fIsMC){
        TClonesArray *stack = 0;
        TList *lst = fAOD->GetList();
        stack = (TClonesArray*)lst->FindObject(AliAODMCParticle::StdBranchName());

        int nMCTracks;
        if (!stack) nMCTracks = 0;
        else nMCTracks = stack->GetEntries();

        Double_t mNMC  = 0.0;
        for ( Int_t i(0); i < nMCTracks; i++) {
            AliAODMCParticle *p1=(AliAODMCParticle*)stack->UncheckedAt(i);
            if (!p1) continue;
            if(!p1->IsPrimary()) continue;
            if(!p1->IsPhysicalPrimary()) continue;
            Int_t charge = p1->Charge();
            if(TMath :: Abs(charge)>0) {
                if(p1->Pt() < fPtmin|| p1->Pt() > fPtmax) continue;
                if(fabs(p1->Eta()) > fEta ) continue;
                mNMC++;
            }

        }

        for ( Int_t i(0); i < nMCTracks; i++) {
            AliAODMCParticle *p1=(AliAODMCParticle*)stack->UncheckedAt(i);
            if (!p1) continue;
            if(!p1->IsPrimary()) continue;
            if(!p1->IsPhysicalPrimary()) continue;
            Int_t charge = p1->Charge();
            if(TMath :: Abs(charge)>0) {
                if(p1->Pt() < 0.2|| p1->Pt() > 5) continue;
                if(fabs(p1->Eta()) > 0.8 ) continue;
                fHistMultPtMC->Fill(mNMC, p1->Pt());
            }
        }
        //Generated Mult vs Reconstructed Mult
        fHistMultRatio->Fill(Mult, mNMC);
    }
    PostData(1, fOutputList);
}

//________________________________________________________________________
void AliAnalysisMultPt::Terminate(Option_t *)
{
    // terminate
    // called at the END of the analysis (when all events are processed)
}

<commit_msg>Update AliAnalysisMultPt.cxx<commit_after>//////////////////////////////////////////////////////////////////////////////////////////////////////
// AliAnalysisMultPt:
// Description: Analysis task get multiplicity
// and pT distributions
// Author: Negin Alizadehvandchali
// (negin.alizadehvandchali@cern.ch)
/////////////////////////////////////////////////////////////////////////////////////////////////////
#include "TString.h"
#include <vector>
#include <algorithm>
#include <cstdlib>
#include <ctime>
#include <math.h>
#include "TChain.h"
#include "TFile.h"
#include "TKey.h"
#include "TObject.h"
#include "TObjString.h"
#include "TList.h"
#include "TTree.h"
#include "TH1F.h"
#include "TH1D.h"
#include "TH2D.h"
#include "TH3D.h"
#include "TProfile.h"
#include "TCanvas.h"
#include "TBits.h"
#include "TRefArray.h"
#include "TAxis.h"
#include "TRandom.h"
#include "TList.h"
#include "TComplex.h"
#include "TMath.h"
#include <cmath>
#include <cstdlib>
#include "AliAODTrack.h"
#include "AliAnalysisTask.h"
#include "AliAnalysisTaskSE.h"
#include "AliAnalysisManager.h"
#include "AliAODInputHandler.h"
#include "AliAODEvent.h"
#include "AliAODMCParticle.h"
#include "AliAnalysisMultPt.h"

using namespace std;            // std namespace: so you can do things like 'cout'

ClassImp(AliAnalysisMultPt)     // classimp: necessary for root
//________________________________________________________________________

AliAnalysisMultPt::AliAnalysisMultPt() : AliAnalysisTaskSE(),
fAOD(0), fOutputList(0), fHistMultPt(0), fHistMult(0), fHistMultPtMC(0), fHistMultRatio(0), fIsMC(0), fPtmin(0.2), fPtmax(5), fEta(0.8), fBit(128)

{

}

//________________________________________________________________________
AliAnalysisMultPt::AliAnalysisMultPt(const char* name) : AliAnalysisTaskSE(name),
fAOD(0), fOutputList(0), fHistMultPt(0), fHistMult(0), fHistMultPtMC(0), fHistMultRatio(0), fIsMC(0), fPtmin(0.2), fPtmax(5), fEta(0.8), fBit(128)

{
    DefineInput(0, TChain::Class());
    DefineOutput(1, TList::Class());
}
//________________________________________________________________________
AliAnalysisMultPt::~AliAnalysisMultPt()
{
    // destructor
    if(fOutputList) {
        delete fOutputList;     // at the end of your task, it is deleted from memory by calling this function
    }
}

//________________________________________________________________________

void AliAnalysisMultPt::SetMCRead(Bool_t flag) { fIsMC = flag; }

void AliAnalysisMultPt::UserCreateOutputObjects()
    {

    fOutputList = new TList();
    fOutputList->SetOwner(kTRUE);

    fHistMult = new TH1D("fHistMult", "Mult", 4000, 0, 4000);
    fOutputList->Add(fHistMult);
    fHistMult->SetStats(0);
    fHistMult->SetTitle("Multiplicity");
    fHistMult->SetXTitle("Multiplicity");
    fHistMult->SetMarkerSize(1.2);

    fHistMultPt = new TH2D("fHistMultPt", "MultpT", 4000, 0, 4000, 50, 0, 5);
    fOutputList->Add(fHistMultPt);
    fHistMultPt->SetStats(0);
    fHistMultPt->SetTitle("pT vs Multiplicity");
    fHistMultPt->SetXTitle("Multiplicity");
    fHistMultPt->SetYTitle("pT");
    fHistMultPt->SetLineColor(2);
    fHistMultPt->SetMarkerSize(1.2);

    fHistMultPtMC = new TH2D("fHistMultPtMC", "MultPt-MC", 4000, 0, 4000, 50, 0, 5);
    fOutputList->Add(fHistMultPtMC);
    fHistMultPtMC->SetStats(0);
    fHistMultPtMC->SetTitle("pT vs Generated Multiplicity");
    fHistMultPtMC->SetXTitle("Generated N_{ch}");
    fHistMultPtMC->SetYTitle("pT");
    fHistMultPtMC->SetLineColor(2);
    fHistMultPtMC->SetMarkerSize(1.2);

    fHistMultRatio = new TH2D("fHistMultRatio", "Ratio",  4000, 0, 4000, 4000, 0, 4000);
    fOutputList->Add(fHistMultRatio);
    fHistMultRatio->SetStats(0);
    fHistMultRatio->SetTitle("Generated Multiplicity vs Reconstructed");
    fHistMultRatio->SetXTitle("Reconstructed N_{ch}");
    fHistMultRatio->SetYTitle("Generated N_{ch}");
    fHistMultRatio->SetLineColor(2);
    fHistMultRatio->SetMarkerSize(1.2);

    // add the list to our output file
    PostData(1, fOutputList);
    //PostData(1, mixer);
    }

//________________________________________________________________________

void AliAnalysisMultPt::UserExec(Option_t *)
{

////////////////////////////////////////////////////////////////////////////////Track-based part (Either data or reconstructed MC):
    // get an event from the analysis manager:
    fAOD = dynamic_cast<AliAODEvent*> (InputEvent());
    // check if there actually is an event:
    if(!fAOD) return;
    // ::Fatal("AliAnalysisTaskMultPt::UserExec", "No AOD event found, check the event handler.");
     //For charged particle
    Double_t Mult=0.0;

    // loop over all these tracks:
    for(Int_t i(0); i < fAOD->GetNumberOfTracks(); i++) {
         // get a track (type AliAODTrack) from the event:
        AliAODTrack* track = static_cast<AliAODTrack*>(fAOD->GetTrack(i));
        // if we failed, skip this track
        if(!track) continue;
        Int_t charge = track->Charge();
        if(TMath :: Abs(charge)>0) {
            if(track->Pt() < fPtmin|| track->Pt() > fPtmax) continue;
            if(fabs(track->Eta()) > fEta) continue;   //eta cut
            if(track->TestFilterBit(fBit)){
                Mult++;
            }
        }
    }
    //Number of events vs multiplicity
    fHistMult->Fill(Mult);

    for( Int_t i(0); i < fAOD->GetNumberOfTracks(); i++) {
         // get a track (type AliAODTrack) from the event:
         AliAODTrack* track = static_cast<AliAODTrack*>(fAOD->GetTrack(i));
         // if we failed, skip this track:
         if(!track) continue;
         Int_t charge = track->Charge();

         //Count the charge particles:
         if(TMath :: Abs(charge)>0) {
             if(track->Pt() < fPtmin|| track->Pt() > fPtmax) continue;
             if(fabs(track->Eta()) > fEta) continue;   //eta cut
             if(track->TestFilterBit(fBit)){
                 fHistMultPt->Fill(Mult, track->Pt());
             }
         }

    }
/////////////////////////////////////////////////////////////////////////////////// Generated part:
    if(fIsMC){
        TClonesArray *stack = 0;
        TList *lst = fAOD->GetList();
        stack = (TClonesArray*)lst->FindObject(AliAODMCParticle::StdBranchName());

        int nMCTracks;
        if (!stack) nMCTracks = 0;
        else nMCTracks = stack->GetEntries();

        Double_t mNMC  = 0.0;
        for ( Int_t i(0); i < nMCTracks; i++) {
            AliAODMCParticle *p1=(AliAODMCParticle*)stack->UncheckedAt(i);
            if (!p1) continue;
            if(!p1->IsPhysicalPrimary()) continue;
            Int_t charge = p1->Charge();
            if(TMath :: Abs(charge)>0) {
                if(p1->Pt() < fPtmin|| p1->Pt() > fPtmax) continue;
                if(fabs(p1->Eta()) > fEta ) continue;
                mNMC++;
            }

        }

        for ( Int_t i(0); i < nMCTracks; i++) {
            AliAODMCParticle *p1=(AliAODMCParticle*)stack->UncheckedAt(i);
            if (!p1) continue;
            if(!p1->IsPhysicalPrimary()) continue;
            Int_t charge = p1->Charge();
            if(TMath :: Abs(charge)>0) {
                if(p1->Pt() < fPtmin|| p1->Pt() > fPtmax) continue;
                if(fabs(p1->Eta()) > fEta ) continue;
                fHistMultPtMC->Fill(mNMC, p1->Pt());
            }
        }
        //Generated Mult vs Reconstructed Mult
        fHistMultRatio->Fill(Mult, mNMC);
    }

    PostData(1, fOutputList);
}

//________________________________________________________________________
void AliAnalysisMultPt::Terminate(Option_t *)
{
    // terminate
    // called at the END of the analysis (when all events are processed)
}

<|endoftext|>


<commit_before>AliAnalysisTaskSEDplus *AddTaskDplus(Int_t system=0/*0=pp,1=PbPb*/,
				     Float_t minC=0, Float_t maxC=100,
				     Bool_t storeNtuple=kFALSE,
				     Bool_t readMC=kFALSE,
				     TString finDirname="Loose",
				     TString filename="",
				     TString finAnObjname="AnalysisCuts", TString finProdObjname="ProdCuts")
{
  //
  // Test macro for the AliAnalysisTaskSE for D+ candidates

  //Invariant mass histogram and
  // association with MC truth (using MC info in AOD)
  //  R. Bala, bala@to.infn.it
  // Get the pointer to the existing analysis manager via the static access method.
  //==============================================================================
  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
  if (!mgr) {
    ::Error("AddTaskDplus", "No analysis manager to connect to.");
  }

  Bool_t stdcuts=kFALSE;
  TFile* filecuts;
  if( filename.EqualTo("") ) {
    stdcuts=kTRUE;
  } else {
      filecuts=TFile::Open(filename.Data());
      if(!filecuts ||(filecuts&& !filecuts->IsOpen())){
	AliFatal("Input file not found : check your cut object");
      }
  }

  //Analysis Task

  AliRDHFCutsDplustoKpipi* analysiscuts=new AliRDHFCutsDplustoKpipi();
  if(stdcuts) {
    if(system==0) analysiscuts->SetStandardCutsPP2010();
    else if(system==1){
      analysiscuts->SetStandardCutsPbPb2011();
      analysiscuts->SetMinCentrality(minC);
      analysiscuts->SetMaxCentrality(maxC);
      //      analysiscuts->SetUseAOD049(kTRUE);
      analysiscuts->SetUseCentrality(AliRDHFCuts::kCentV0M);
    }
  }
  else analysiscuts = (AliRDHFCutsDplustoKpipi*)filecuts->Get(finAnObjname);

  AliRDHFCutsDplustoKpipi* prodcuts=new AliRDHFCutsDplustoKpipi();
  if(stdcuts)  {
    if(system==0) prodcuts->SetStandardCutsPP2010();
    else if(system==1) {
      prodcuts->SetStandardCutsPbPb2010();
      prodcuts->SetMinCentrality(minC);
      prodcuts->SetMaxCentrality(maxC);
      //      prodcuts->SetUseAOD049(kTRUE);
      prodcuts->SetUseCentrality(AliRDHFCuts::kCentV0M);
    }
  }
  else prodcuts = (AliRDHFCutsDplustoKpipi*)filecuts->Get(finProdObjname);

  //AliRDHFCutsDplustoKpipi *prodcuts = (AliRDHFCutsDplustoKpipi*)fileCuts->Get("ProdCuts");
  //AliRDHFCutsDplustoKpipi *analysiscuts = (AliRDHFCutsDplustoKpipi*)fileCuts->Get("AnalysisCuts");

  AliAnalysisTaskSEDplus *dplusTask = new AliAnalysisTaskSEDplus("DplusAnalysis",analysiscuts,prodcuts,storeNtuple);
  dplusTask->SetReadMC(readMC);
  dplusTask->SetDoLikeSign(kFALSE);
  //  dplusTask->SetUseTPCpid(kTRUE);
  //dplusTask->SetUseTOFpid(kTRUE);
  dplusTask->SetDebugLevel(0);
  dplusTask->SetMassLimits(0.2);
  dplusTask->SetUseBit(kTRUE);

  if (system==0) dplusTask->SetDoImpactParameterHistos(kTRUE);

  mgr->AddTask(dplusTask);

  // Create containers for input/output

  TString inname = "cinputDplus";
  TString outname = "coutputDplus";
  TString cutsname = "coutputDplusCuts";
  TString normname = "coutputDplusNorm";
  TString ntuplename = "coutputDplus2";
  inname += finDirname.Data();
  outname += finDirname.Data();
  cutsname += finDirname.Data();
  normname += finDirname.Data();
  ntuplename += finDirname.Data();
  TString centr=Form("%.0f%.0f",analysiscuts->GetMinCentrality(),analysiscuts->GetMaxCentrality());
  inname += centr;
  outname += centr;
  cutsname += centr;
  normname += centr;
  ntuplename += centr;

  AliAnalysisDataContainer *cinputDplus = mgr->CreateContainer(inname,TChain::Class(),
							       AliAnalysisManager::kInputContainer);
  TString outputfile = AliAnalysisManager::GetCommonFileName();
  outputfile += ":PWG3_D2H_InvMassDplus";

  AliAnalysisDataContainer *coutputDplusCuts = mgr->CreateContainer(cutsname,TList::Class(),
								    AliAnalysisManager::kOutputContainer,
								    outputfile.Data());

  AliAnalysisDataContainer *coutputDplus = mgr->CreateContainer(outname,TList::Class(),
								AliAnalysisManager::kOutputContainer,
								outputfile.Data());
  AliAnalysisDataContainer *coutputDplusNorm = mgr->CreateContainer(normname,AliNormalizationCounter::Class(),
								AliAnalysisManager::kOutputContainer,
								outputfile.Data());

  if(storeNtuple){
    AliAnalysisDataContainer *coutputDplus2 = mgr->CreateContainer(ntuplename,TNtuple::Class(),
								   AliAnalysisManager::kOutputContainer,
								   outputfile.Data());

    coutputDplus2->SetSpecialOutput();
  }
  mgr->ConnectInput(dplusTask,0,mgr->GetCommonInputContainer());

  mgr->ConnectOutput(dplusTask,1,coutputDplus);

  mgr->ConnectOutput(dplusTask,2,coutputDplusCuts);

  mgr->ConnectOutput(dplusTask,3,coutputDplusNorm);
  if(storeNtuple){
    mgr->ConnectOutput(dplusTask,4,coutputDplus2);
  }
  return dplusTask;
}
<commit_msg>AddTask adapted to updated D+ task (Giacomo)<commit_after>AliAnalysisTaskSEDplus *AddTaskDplus(Int_t system=0/*0=pp,1=PbPb*/,
				     Float_t minC=0, Float_t maxC=100,
				     Bool_t storeNtuple=kFALSE,
				     Bool_t readMC=kFALSE,
				     TString finDirname="Loose",
				     TString filename="",
				     TString finAnObjname="AnalysisCuts", TString finProdObjname="ProduCuts")
{
  //
  // Test macro for the AliAnalysisTaskSE for D+ candidates

  //Invariant mass histogram and
  // association with MC truth (using MC info in AOD)
  //  R. Bala, bala@to.infn.it
  // Get the pointer to the existing analysis manager via the static access method.
  //==============================================================================
  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
  if (!mgr) {
    ::Error("AddTaskDplus", "No analysis manager to connect to.");
  }

  Bool_t stdcuts=kFALSE;
  TFile* filecuts;
  if( filename.EqualTo("") ) {
    stdcuts=kTRUE;
  } else {
      filecuts=TFile::Open(filename.Data());
      if(!filecuts ||(filecuts&& !filecuts->IsOpen())){
	AliFatal("Input file not found : check your cut object");
      }
  }

  //Analysis Task

  AliRDHFCutsDplustoKpipi* analysiscuts=new AliRDHFCutsDplustoKpipi();
  if(stdcuts) {
    if(system==0) analysiscuts->SetStandardCutsPP2010();
    else if(system==1){
      analysiscuts->SetStandardCutsPbPb2011();
      analysiscuts->SetMinCentrality(minC);
      analysiscuts->SetMaxCentrality(maxC);
      //      analysiscuts->SetUseAOD049(kTRUE);
      analysiscuts->SetUseCentrality(AliRDHFCuts::kCentV0M);
    }
  }
  else analysiscuts = (AliRDHFCutsDplustoKpipi*)filecuts->Get(finAnObjname);

  AliAnalysisTaskSEDplus *dplusTask = new AliAnalysisTaskSEDplus("DplusAnalysis",analysiscuts,storeNtuple);
  dplusTask->SetReadMC(readMC);
  dplusTask->SetDoLikeSign(kFALSE);
  //  dplusTask->SetUseTPCpid(kTRUE);
  //dplusTask->SetUseTOFpid(kTRUE);
  dplusTask->SetDebugLevel(0);
  dplusTask->SetMassLimits(0.2);
  dplusTask->SetUseBit(kTRUE);

  if (system==0) dplusTask->SetDoImpactParameterHistos(kTRUE);

  mgr->AddTask(dplusTask);

  // Create containers for input/output

  TString inname = "cinputDplus";
  TString outname = "coutputDplus";
  TString cutsname = "coutputDplusCuts";
  TString normname = "coutputDplusNorm";
  TString ntuplename = "coutputDplus2";
  inname += finDirname.Data();
  outname += finDirname.Data();
  cutsname += finDirname.Data();
  normname += finDirname.Data();
  ntuplename += finDirname.Data();
  TString centr=Form("%.0f%.0f",analysiscuts->GetMinCentrality(),analysiscuts->GetMaxCentrality());
  inname += centr;
  outname += centr;
  cutsname += centr;
  normname += centr;
  ntuplename += centr;

  AliAnalysisDataContainer *cinputDplus = mgr->CreateContainer(inname,TChain::Class(),
							       AliAnalysisManager::kInputContainer);
  TString outputfile = AliAnalysisManager::GetCommonFileName();
  outputfile += ":PWG3_D2H_InvMassDplus";

  AliAnalysisDataContainer *coutputDplusCuts = mgr->CreateContainer(cutsname,TList::Class(),
								    AliAnalysisManager::kOutputContainer,
								    outputfile.Data());

  AliAnalysisDataContainer *coutputDplus = mgr->CreateContainer(outname,TList::Class(),
								AliAnalysisManager::kOutputContainer,
								outputfile.Data());
  AliAnalysisDataContainer *coutputDplusNorm = mgr->CreateContainer(normname,AliNormalizationCounter::Class(),
								AliAnalysisManager::kOutputContainer,
								outputfile.Data());

  if(storeNtuple){
    AliAnalysisDataContainer *coutputDplus2 = mgr->CreateContainer(ntuplename,TNtuple::Class(),
								   AliAnalysisManager::kOutputContainer,
								   "InvMassDplus_nt1.root");

    coutputDplus2->SetSpecialOutput();
  }
  mgr->ConnectInput(dplusTask,0,mgr->GetCommonInputContainer());

  mgr->ConnectOutput(dplusTask,1,coutputDplus);

  mgr->ConnectOutput(dplusTask,2,coutputDplusCuts);

  mgr->ConnectOutput(dplusTask,3,coutputDplusNorm);
  if(storeNtuple){
    mgr->ConnectOutput(dplusTask,4,coutputDplus2);
  }
  return dplusTask;
}
<|endoftext|>


<commit_before>#include "vtk.h"
#include "SaveImage.h"

int main( int argc, char *argv[] )
{
  vtkRenderer *renderer = vtkRenderer::New();
  vtkRenderWindow *renWin = vtkRenderWindow::New();
    renWin->AddRenderer(renderer);
  vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New();
    iren->SetRenderWindow(renWin);

  vtkSphereSource *sphere = vtkSphereSource::New();
    sphere->SetThetaResolution(8); sphere->SetPhiResolution(8);
  vtkPolyDataMapper *sphereMapper = vtkPolyDataMapper::New();
    sphereMapper->SetInput(sphere->GetOutput());
  vtkActor *sphereActor = vtkActor::New();
    sphereActor->SetMapper(sphereMapper);

  vtkConeSource *cone = vtkConeSource::New();
    cone->SetResolution(6);

  vtkGlyph3D *glyph = vtkGlyph3D::New();
    glyph->SetInput(sphere->GetOutput());
    glyph->SetSource(cone->GetOutput());
    glyph->SetVectorModeToUseNormal();
    glyph->SetScaleModeToScaleByVector();
    glyph->SetScaleFactor(0.25);

  vtkPolyDataMapper *spikeMapper = vtkPolyDataMapper::New();
    spikeMapper->SetInput(glyph->GetOutput());

  vtkActor *spikeActor = vtkActor::New();
    spikeActor->SetMapper(spikeMapper);

  renderer->AddActor(sphereActor);
  renderer->AddActor(spikeActor);
  renderer->SetBackground(1,1,1);
  renWin->SetSize(300,300);

  // interact with data
  renWin->Render();

  SAVEIMAGE( renWin );

  iren->Start();

  // Clean up
  renderer->Delete();
  renWin->Delete();
  iren->Delete();
  sphere->Delete();
  sphereMapper->Delete();
  sphereActor->Delete();
  cone->Delete();
  glyph->Delete();
  spikeMapper->Delete();
  spikeActor->Delete();

  exit(1);
}
<commit_msg>ENH: removed vtk.h<commit_after>#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkSphereSource.h"
#include "vtkPolyDataMapper.h"
#include "vtkActor.h"
#include "vtkConeSource.h"
#include "vtkGlyph3D.h"
#include "vtkPolyDataMapper.h"

#include "SaveImage.h"

int main( int argc, char *argv[] )
{
  vtkRenderer *renderer = vtkRenderer::New();
  vtkRenderWindow *renWin = vtkRenderWindow::New();
    renWin->AddRenderer(renderer);
  vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New();
    iren->SetRenderWindow(renWin);

  vtkSphereSource *sphere = vtkSphereSource::New();
    sphere->SetThetaResolution(8); sphere->SetPhiResolution(8);
  vtkPolyDataMapper *sphereMapper = vtkPolyDataMapper::New();
    sphereMapper->SetInput(sphere->GetOutput());
  vtkActor *sphereActor = vtkActor::New();
    sphereActor->SetMapper(sphereMapper);

  vtkConeSource *cone = vtkConeSource::New();
    cone->SetResolution(6);

  vtkGlyph3D *glyph = vtkGlyph3D::New();
    glyph->SetInput(sphere->GetOutput());
    glyph->SetSource(cone->GetOutput());
    glyph->SetVectorModeToUseNormal();
    glyph->SetScaleModeToScaleByVector();
    glyph->SetScaleFactor(0.25);

  vtkPolyDataMapper *spikeMapper = vtkPolyDataMapper::New();
    spikeMapper->SetInput(glyph->GetOutput());

  vtkActor *spikeActor = vtkActor::New();
    spikeActor->SetMapper(spikeMapper);

  renderer->AddActor(sphereActor);
  renderer->AddActor(spikeActor);
  renderer->SetBackground(1,1,1);
  renWin->SetSize(300,300);

  // interact with data
  renWin->Render();

  SAVEIMAGE( renWin );

  iren->Start();

  // Clean up
  renderer->Delete();
  renWin->Delete();
  iren->Delete();
  sphere->Delete();
  sphereMapper->Delete();
  sphereActor->Delete();
  cone->Delete();
  glyph->Delete();
  spikeMapper->Delete();
  spikeActor->Delete();

  exit(1);
}
<|endoftext|>


<commit_before>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2014 Gael Guennebaud <gael.guennebaud@inria.fr>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

#include "lapack_common.h"
#include <Eigen/SVD>
#include <unsupported/Eigen/BDCSVD>

// computes the singular values/vectors a general M-by-N matrix A using divide-and-conquer
EIGEN_LAPACK_FUNC(gesdd,(char *jobz, int *m, int* n, Scalar* a, int *lda, RealScalar *s, Scalar *u, int *ldu, Scalar *vt, int *ldvt, Scalar* /*work*/, int* lwork,
                         EIGEN_LAPACK_ARG_IF_COMPLEX(RealScalar */*rwork*/) int * /*iwork*/, int *info))
{
  // TODO exploit the work buffer
  bool query_size = *lwork==-1;
  int diag_size = (std::min)(*m,*n);

  *info = 0;
        if(*jobz!='A' && *jobz!='S' && *jobz!='O' && *jobz!='N')  *info = -1;
  else  if(*m<0)                                                  *info = -2;
  else  if(*n<0)                                                  *info = -3;
  else  if(*lda<std::max(1,*m))                                   *info = -5;
  else  if(*lda<std::max(1,*m))                                   *info = -8;
  else  if(*ldu <1 || (*jobz=='A' && *ldu <*m)
                   || (*jobz=='O' && *m<*n && *ldu<*m))           *info = -8;
  else  if(*ldvt<1 || (*jobz=='A' && *ldvt<*n)
                   || (*jobz=='S' && *ldvt<diag_size)
                   || (*jobz=='O' && *m>=*n && *ldvt<*n))         *info = -10;

  if(*info!=0)
  {
    int e = -*info;
    return xerbla_(SCALAR_SUFFIX_UP"GESDD ", &e, 6);
  }

  if(query_size)
  {
    *lwork = 0;
    return 0;
  }

  if(*n==0 || *m==0)
    return 0;

  PlainMatrixType mat(*m,*n);
  mat = matrix(a,*m,*n,*lda);

  int option = *jobz=='A' ? ComputeFullU|ComputeFullV
             : *jobz=='S' ? ComputeThinU|ComputeThinV
             : *jobz=='O' ? ComputeThinU|ComputeThinV
             : 0;

  BDCSVD<PlainMatrixType> svd(mat,option);

  make_vector(s,diag_size) = svd.singularValues().head(diag_size);

  if(*jobz=='A')
  {
    matrix(u,*m,*m,*ldu)   = svd.matrixU();
    matrix(vt,*n,*n,*ldvt) = svd.matrixV().adjoint();
  }
  else if(*jobz=='S')
  {
    matrix(u,*m,diag_size,*ldu)   = svd.matrixU();
    matrix(vt,diag_size,*n,*ldvt) = svd.matrixV().adjoint();
  }
  else if(*jobz=='O' && *m>=*n)
  {
    matrix(a,*m,*n,*lda)   = svd.matrixU();
    matrix(vt,*n,*n,*ldvt) = svd.matrixV().adjoint();
  }
  else if(*jobz=='O')
  {
    matrix(u,*m,*m,*ldu)        = svd.matrixU();
    matrix(a,diag_size,*n,*lda) = svd.matrixV().adjoint();
  }

  return 0;
}

// computes the singular values/vectors a general M-by-N matrix A using two sided jacobi algorithm
EIGEN_LAPACK_FUNC(gesvd,(char *jobu, char *jobv, int *m, int* n, Scalar* a, int *lda, RealScalar *s, Scalar *u, int *ldu, Scalar *vt, int *ldvt, Scalar* /*work*/, int* lwork,
                         EIGEN_LAPACK_ARG_IF_COMPLEX(RealScalar */*rwork*/) int *info))
{
  // TODO exploit the work buffer
  bool query_size = *lwork==-1;
  int diag_size = (std::min)(*m,*n);

  *info = 0;
        if( *jobu!='A' && *jobu!='S' && *jobu!='O' && *jobu!='N') *info = -1;
  else  if((*jobv!='A' && *jobv!='S' && *jobv!='O' && *jobv!='N')
           || (*jobu=='O' && *jobv=='O'))                         *info = -2;
  else  if(*m<0)                                                  *info = -3;
  else  if(*n<0)                                                  *info = -4;
  else  if(*lda<std::max(1,*m))                                   *info = -6;
  else  if(*ldu <1 || ((*jobu=='A' || *jobu=='S') && *ldu<*m))    *info = -9;
  else  if(*ldvt<1 || (*jobv=='A' && *ldvt<*n)
                   || (*jobv=='S' && *ldvt<diag_size))            *info = -11;

  if(*info!=0)
  {
    int e = -*info;
    return xerbla_(SCALAR_SUFFIX_UP"GESVD ", &e, 6);
  }

  if(query_size)
  {
    *lwork = 0;
    return 0;
  }

  if(*n==0 || *m==0)
    return 0;

  PlainMatrixType mat(*m,*n);
  mat = matrix(a,*m,*n,*lda);

  int option = (*jobu=='A' ? ComputeFullU : *jobu=='S' || *jobu=='O' ? ComputeThinU : 0)
             | (*jobv=='A' ? ComputeFullV : *jobv=='S' || *jobv=='O' ? ComputeThinV : 0);

  JacobiSVD<PlainMatrixType> svd(mat,option);

  make_vector(s,diag_size) = svd.singularValues().head(diag_size);

        if(*jobu=='A') matrix(u,*m,*m,*ldu)           = svd.matrixU();
  else  if(*jobu=='S') matrix(u,*m,diag_size,*ldu)    = svd.matrixU();
  else  if(*jobu=='O') matrix(a,*m,diag_size,*lda)           = svd.matrixU();

        if(*jobv=='A') matrix(vt,*n,*n,*ldvt)         = svd.matrixV().adjoint();
  else  if(*jobv=='S') matrix(vt,diag_size,*n,*ldvt)  = svd.matrixV().adjoint();
  else  if(*jobv=='O') matrix(a,diag_size,*n,*lda)    = svd.matrixV().adjoint();

  return 0;
}
<commit_msg>Removed deprecated header (unsupported/Eigen/BDCSVD is included in Eigen/SVD now)<commit_after>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2014 Gael Guennebaud <gael.guennebaud@inria.fr>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

#include "lapack_common.h"
#include <Eigen/SVD>

// computes the singular values/vectors a general M-by-N matrix A using divide-and-conquer
EIGEN_LAPACK_FUNC(gesdd,(char *jobz, int *m, int* n, Scalar* a, int *lda, RealScalar *s, Scalar *u, int *ldu, Scalar *vt, int *ldvt, Scalar* /*work*/, int* lwork,
                         EIGEN_LAPACK_ARG_IF_COMPLEX(RealScalar */*rwork*/) int * /*iwork*/, int *info))
{
  // TODO exploit the work buffer
  bool query_size = *lwork==-1;
  int diag_size = (std::min)(*m,*n);

  *info = 0;
        if(*jobz!='A' && *jobz!='S' && *jobz!='O' && *jobz!='N')  *info = -1;
  else  if(*m<0)                                                  *info = -2;
  else  if(*n<0)                                                  *info = -3;
  else  if(*lda<std::max(1,*m))                                   *info = -5;
  else  if(*lda<std::max(1,*m))                                   *info = -8;
  else  if(*ldu <1 || (*jobz=='A' && *ldu <*m)
                   || (*jobz=='O' && *m<*n && *ldu<*m))           *info = -8;
  else  if(*ldvt<1 || (*jobz=='A' && *ldvt<*n)
                   || (*jobz=='S' && *ldvt<diag_size)
                   || (*jobz=='O' && *m>=*n && *ldvt<*n))         *info = -10;

  if(*info!=0)
  {
    int e = -*info;
    return xerbla_(SCALAR_SUFFIX_UP"GESDD ", &e, 6);
  }

  if(query_size)
  {
    *lwork = 0;
    return 0;
  }

  if(*n==0 || *m==0)
    return 0;

  PlainMatrixType mat(*m,*n);
  mat = matrix(a,*m,*n,*lda);

  int option = *jobz=='A' ? ComputeFullU|ComputeFullV
             : *jobz=='S' ? ComputeThinU|ComputeThinV
             : *jobz=='O' ? ComputeThinU|ComputeThinV
             : 0;

  BDCSVD<PlainMatrixType> svd(mat,option);

  make_vector(s,diag_size) = svd.singularValues().head(diag_size);

  if(*jobz=='A')
  {
    matrix(u,*m,*m,*ldu)   = svd.matrixU();
    matrix(vt,*n,*n,*ldvt) = svd.matrixV().adjoint();
  }
  else if(*jobz=='S')
  {
    matrix(u,*m,diag_size,*ldu)   = svd.matrixU();
    matrix(vt,diag_size,*n,*ldvt) = svd.matrixV().adjoint();
  }
  else if(*jobz=='O' && *m>=*n)
  {
    matrix(a,*m,*n,*lda)   = svd.matrixU();
    matrix(vt,*n,*n,*ldvt) = svd.matrixV().adjoint();
  }
  else if(*jobz=='O')
  {
    matrix(u,*m,*m,*ldu)        = svd.matrixU();
    matrix(a,diag_size,*n,*lda) = svd.matrixV().adjoint();
  }

  return 0;
}

// computes the singular values/vectors a general M-by-N matrix A using two sided jacobi algorithm
EIGEN_LAPACK_FUNC(gesvd,(char *jobu, char *jobv, int *m, int* n, Scalar* a, int *lda, RealScalar *s, Scalar *u, int *ldu, Scalar *vt, int *ldvt, Scalar* /*work*/, int* lwork,
                         EIGEN_LAPACK_ARG_IF_COMPLEX(RealScalar */*rwork*/) int *info))
{
  // TODO exploit the work buffer
  bool query_size = *lwork==-1;
  int diag_size = (std::min)(*m,*n);

  *info = 0;
        if( *jobu!='A' && *jobu!='S' && *jobu!='O' && *jobu!='N') *info = -1;
  else  if((*jobv!='A' && *jobv!='S' && *jobv!='O' && *jobv!='N')
           || (*jobu=='O' && *jobv=='O'))                         *info = -2;
  else  if(*m<0)                                                  *info = -3;
  else  if(*n<0)                                                  *info = -4;
  else  if(*lda<std::max(1,*m))                                   *info = -6;
  else  if(*ldu <1 || ((*jobu=='A' || *jobu=='S') && *ldu<*m))    *info = -9;
  else  if(*ldvt<1 || (*jobv=='A' && *ldvt<*n)
                   || (*jobv=='S' && *ldvt<diag_size))            *info = -11;

  if(*info!=0)
  {
    int e = -*info;
    return xerbla_(SCALAR_SUFFIX_UP"GESVD ", &e, 6);
  }

  if(query_size)
  {
    *lwork = 0;
    return 0;
  }

  if(*n==0 || *m==0)
    return 0;

  PlainMatrixType mat(*m,*n);
  mat = matrix(a,*m,*n,*lda);

  int option = (*jobu=='A' ? ComputeFullU : *jobu=='S' || *jobu=='O' ? ComputeThinU : 0)
             | (*jobv=='A' ? ComputeFullV : *jobv=='S' || *jobv=='O' ? ComputeThinV : 0);

  JacobiSVD<PlainMatrixType> svd(mat,option);

  make_vector(s,diag_size) = svd.singularValues().head(diag_size);

        if(*jobu=='A') matrix(u,*m,*m,*ldu)           = svd.matrixU();
  else  if(*jobu=='S') matrix(u,*m,diag_size,*ldu)    = svd.matrixU();
  else  if(*jobu=='O') matrix(a,*m,diag_size,*lda)           = svd.matrixU();

        if(*jobv=='A') matrix(vt,*n,*n,*ldvt)         = svd.matrixV().adjoint();
  else  if(*jobv=='S') matrix(vt,diag_size,*n,*ldvt)  = svd.matrixV().adjoint();
  else  if(*jobv=='O') matrix(a,diag_size,*n,*lda)    = svd.matrixV().adjoint();

  return 0;
}
<|endoftext|>


<commit_before>#include <SkinningPlugin.hpp>

#include <Engine/RadiumEngine.hpp>

#include <SkinningSystem.hpp>
#include <GuiBase/SelectionManager/SelectionManager.hpp>

namespace SkinningPlugin
{

    SkinningPluginC::~SkinningPluginC()
    {
    }

    void SkinningPluginC::registerPlugin( const Ra::PluginContext& context )
    {
        m_system = new SkinningSystem;
        m_selectionManager = context.m_selectionManager;
        context.m_engine->registerSystem( "SkinningSystem", m_system );
        m_widget = new SkinningWidget;
        connect( m_selectionManager, &Ra::GuiBase::SelectionManager::currentChanged, this, &SkinningPluginC::onCurrentChanged );
    }

    bool SkinningPluginC::doAddWidget( QString &name )
    {
        name = "Skinning";
        return true;
    }

    QWidget* SkinningPluginC::getWidget()
    {
        return m_widget;
    }

    bool SkinningPluginC::doAddMenu()
    {
        return false;
    }

    QMenu* SkinningPluginC::getMenu()
    {
        return nullptr;
    }

    bool SkinningPluginC::doAddAction( int& nb )
    {
        nb = 3;
        return true;
    }

    QAction* SkinningPluginC::getAction( int id )
    {
        switch (id){
        case 0:
        {
            return m_widget->m_actionLBS;
        }
        case 1:
        {
            return m_widget->m_actionDQ;
        }
        case 2:
        {
            return m_widget->m_actionCoR;
        }
        default:
            return nullptr;
        }
    }

    void SkinningPluginC::onCurrentChanged( const QModelIndex& current, const QModelIndex& prev )
    {
        Ra::Engine::ItemEntry it = m_selectionManager->currentItem();
        if (it.m_entity)
        {
            const std::vector< std::unique_ptr<Ra::Engine::Component> >& comps = it.m_entity->getComponents();
            for (size_t i = 0; i<comps.size(); ++i)
            {
                auto skinComp = dynamic_cast<SkinningPlugin::SkinningComponent*>(comps[i].get());
                if(skinComp)
                {
                    m_widget->setCurrent(it, static_cast<SkinningComponent*>(skinComp));
                    break;
                }
            }
        }
    }

    // Class SkinningWidget

    SkinningWidget::SkinningWidget( QWidget * parent ) : QFrame( parent ),
        m_current( nullptr )
    {
        m_skinningSelect = new QComboBox( this );
        m_skinningSelect->setMaxVisibleItems( 3 );
        m_skinningSelect->setMaxCount( 3 );
        m_skinningSelect->setDuplicatesEnabled( false );
        m_skinningSelect->setCurrentIndex( 1 );

        m_skinningSelect->insertItems( 0, QStringList()
            << "Linear Blend Skinning" << "Dual Quaternion Skinning" << "Center of Rotation skinning" );
        m_skinningSelect->setEnabled( false );

        m_actionLBS = new QAction(QIcon(":/Assets/Images/LB.png"), QString("Linear Blending"));
        m_actionDQ  = new QAction(QIcon(":/Assets/Images/DQ_on.png"), QString("Dual Quaternion"));
        m_actionCoR = new QAction(QIcon(":/Assets/Images/CoR.png"), QString("Center of Rotation"));

        connect( m_skinningSelect,
            static_cast< void (QComboBox::*) (int)>(&QComboBox::currentIndexChanged),
            this,
            &SkinningWidget::onSkinningChanged );

        connect( m_actionLBS, &QAction::triggered, this, &SkinningWidget::onLSBActionTriggered );
        connect( m_actionDQ,  &QAction::triggered, this, &SkinningWidget::onDQActionTriggered );
        connect( m_actionCoR, &QAction::triggered, this, &SkinningWidget::onCoRActionTriggered );
    }

    void SkinningWidget::onLSBActionTriggered()
    {
        m_skinningSelect->setCurrentIndex(0);
    }

    void SkinningWidget::onDQActionTriggered()
    {
        m_skinningSelect->setCurrentIndex(1);
    }

    void SkinningWidget::onCoRActionTriggered()
    {
        m_skinningSelect->setCurrentIndex(2);
    }

    void SkinningWidget::setCurrent( const Ra::Engine::ItemEntry& entry, SkinningComponent* comp )
    {
        m_current = comp;
        if ( comp )
        {
            m_skinningSelect->setEnabled( true );
            m_actionLBS->setEnabled( true );
            m_actionDQ->setEnabled( true );
            m_actionCoR->setEnabled( true );
            m_skinningSelect->setCurrentIndex( int( comp->getSkinningType() ) );
        }
        else
        {
            m_skinningSelect->setEnabled( false );
            m_actionLBS->setEnabled( false );
            m_actionDQ->setEnabled( false );
            m_actionCoR->setEnabled( false );
        }
    }

    void SkinningWidget::onSkinningChanged( int newType )
    {
        CORE_ASSERT( m_current, "should be disabled" );
        CORE_ASSERT( newType >= 0 && newType < 3, "Invalid Skinning Type" );
        m_current->setSkinningType( SkinningComponent::SkinningType( newType ) );
        switch (newType) {
        case 0:
        {
            m_actionLBS->setIcon(QIcon(":/Assets/Images/LB_on.png"));
            m_actionDQ->setIcon(QIcon(":/Assets/Images/DQ.png"));
            m_actionCoR->setIcon(QIcon(":/Assets/Images/CoR.png"));
            break;
        }
        case 1:
        {
            m_actionLBS->setIcon(QIcon(":/Assets/Images/LB.png"));
            m_actionDQ->setIcon(QIcon(":/Assets/Images/DQ_on.png"));
            m_actionCoR->setIcon(QIcon(":/Assets/Images/CoR.png"));
            break;
        }
        case 2:
        {
            m_actionLBS->setIcon(QIcon(":/Assets/Images/LB.png"));
            m_actionDQ->setIcon(QIcon(":/Assets/Images/DQ.png"));
            m_actionCoR->setIcon(QIcon(":/Assets/Images/CoR_on.png"));
            break;
        }
        default:
        {
            break;
        }
        }
    }

}
<commit_msg>Fix Skinning Plugin actions behavior<commit_after>#include <SkinningPlugin.hpp>

#include <Engine/RadiumEngine.hpp>

#include <SkinningSystem.hpp>
#include <GuiBase/SelectionManager/SelectionManager.hpp>

namespace SkinningPlugin
{

    SkinningPluginC::~SkinningPluginC()
    {
    }

    void SkinningPluginC::registerPlugin( const Ra::PluginContext& context )
    {
        m_system = new SkinningSystem;
        m_selectionManager = context.m_selectionManager;
        context.m_engine->registerSystem( "SkinningSystem", m_system );
        m_widget = new SkinningWidget;
        connect( m_selectionManager, &Ra::GuiBase::SelectionManager::currentChanged, this, &SkinningPluginC::onCurrentChanged );
    }

    bool SkinningPluginC::doAddWidget( QString &name )
    {
        name = "Skinning";
        return true;
    }

    QWidget* SkinningPluginC::getWidget()
    {
        return m_widget;
    }

    bool SkinningPluginC::doAddMenu()
    {
        return false;
    }

    QMenu* SkinningPluginC::getMenu()
    {
        return nullptr;
    }

    bool SkinningPluginC::doAddAction( int& nb )
    {
        nb = 3;
        return true;
    }

    QAction* SkinningPluginC::getAction( int id )
    {
        switch (id){
        case 0:
        {
            return m_widget->m_actionLBS;
        }
        case 1:
        {
            return m_widget->m_actionDQ;
        }
        case 2:
        {
            return m_widget->m_actionCoR;
        }
        default:
            return nullptr;
        }
    }

    void SkinningPluginC::onCurrentChanged( const QModelIndex& current, const QModelIndex& prev )
    {
        Ra::Engine::ItemEntry it = m_selectionManager->currentItem();
        if (it.m_entity)
        {
            const std::vector< std::unique_ptr<Ra::Engine::Component> >& comps = it.m_entity->getComponents();
            size_t i = 0;
            for ( ; i<comps.size(); ++i)
            {
                auto skinComp = dynamic_cast<SkinningPlugin::SkinningComponent*>(comps[i].get());
                if(skinComp)
                {
                    m_widget->setCurrent(it, static_cast<SkinningComponent*>(skinComp));
                    break;
                }
            }
            if (i >= comps.size())
            {
                m_widget->setCurrent(it, nullptr);
            }
        } else {
            m_widget->setCurrent(it, nullptr);
        }
    }

    // Class SkinningWidget

    SkinningWidget::SkinningWidget( QWidget * parent ) : QFrame( parent ),
        m_current( nullptr )
    {
        m_skinningSelect = new QComboBox( this );
        m_skinningSelect->setMaxVisibleItems( 3 );
        m_skinningSelect->setMaxCount( 3 );
        m_skinningSelect->setDuplicatesEnabled( false );
        m_skinningSelect->setCurrentIndex( 1 );

        m_skinningSelect->insertItems( 0, QStringList()
            << "Linear Blend Skinning" << "Dual Quaternion Skinning" << "Center of Rotation skinning" );
        m_skinningSelect->setEnabled( false );

        m_actionLBS = new QAction(QIcon(":/Assets/Images/LB.png"), QString("Linear Blending"));
        m_actionDQ  = new QAction(QIcon(":/Assets/Images/DQ_on.png"), QString("Dual Quaternion"));
        m_actionCoR = new QAction(QIcon(":/Assets/Images/CoR.png"), QString("Center of Rotation"));
        m_actionLBS->setEnabled( false );
        m_actionDQ->setEnabled( false );
        m_actionCoR->setEnabled( false );

        connect( m_skinningSelect,
            static_cast< void (QComboBox::*) (int)>(&QComboBox::currentIndexChanged),
            this,
            &SkinningWidget::onSkinningChanged );

        connect( m_actionLBS, &QAction::triggered, this, &SkinningWidget::onLSBActionTriggered );
        connect( m_actionDQ,  &QAction::triggered, this, &SkinningWidget::onDQActionTriggered );
        connect( m_actionCoR, &QAction::triggered, this, &SkinningWidget::onCoRActionTriggered );
    }

    void SkinningWidget::onLSBActionTriggered()
    {
        m_skinningSelect->setCurrentIndex(0);
    }

    void SkinningWidget::onDQActionTriggered()
    {
        m_skinningSelect->setCurrentIndex(1);
    }

    void SkinningWidget::onCoRActionTriggered()
    {
        m_skinningSelect->setCurrentIndex(2);
    }

    void SkinningWidget::setCurrent( const Ra::Engine::ItemEntry& entry, SkinningComponent* comp )
    {
        m_current = comp;
        if ( comp )
        {
            m_skinningSelect->setEnabled( true );
            m_actionLBS->setEnabled( true );
            m_actionDQ->setEnabled( true );
            m_actionCoR->setEnabled( true );
            m_skinningSelect->setCurrentIndex( int( comp->getSkinningType() ) );
        }
        else
        {
            m_skinningSelect->setEnabled( false );
            m_actionLBS->setEnabled( false );
            m_actionDQ->setEnabled( false );
            m_actionCoR->setEnabled( false );
        }
    }

    void SkinningWidget::onSkinningChanged( int newType )
    {
        CORE_ASSERT( m_current, "should be disabled" );
        CORE_ASSERT( newType >= 0 && newType < 3, "Invalid Skinning Type" );
        m_current->setSkinningType( SkinningComponent::SkinningType( newType ) );
        switch (newType) {
        case 0:
        {
            m_actionLBS->setIcon(QIcon(":/Assets/Images/LB_on.png"));
            m_actionDQ->setIcon(QIcon(":/Assets/Images/DQ.png"));
            m_actionCoR->setIcon(QIcon(":/Assets/Images/CoR.png"));
            break;
        }
        case 1:
        {
            m_actionLBS->setIcon(QIcon(":/Assets/Images/LB.png"));
            m_actionDQ->setIcon(QIcon(":/Assets/Images/DQ_on.png"));
            m_actionCoR->setIcon(QIcon(":/Assets/Images/CoR.png"));
            break;
        }
        case 2:
        {
            m_actionLBS->setIcon(QIcon(":/Assets/Images/LB.png"));
            m_actionDQ->setIcon(QIcon(":/Assets/Images/DQ.png"));
            m_actionCoR->setIcon(QIcon(":/Assets/Images/CoR_on.png"));
            break;
        }
        default:
        {
            break;
        }
        }
    }

}
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2016-2017 metaverse core developers (see MVS-AUTHORS)
 *
 * This file is part of metaverse.
 *
 * metaverse is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License with
 * additional permissions to the one published by the Free Software
 * Foundation, either version 3 of the License, or (at your option)
 * any later version. For more information see LICENSE.
 *
 * 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
#include <metaverse/bitcoin/utility/path.hpp>
#include <boost/thread/once.hpp>

#ifdef _WIN32
#include <Shlobj.h>
#endif

namespace libbitcoin{

const boost::filesystem::path& default_data_path()
{
    static boost::filesystem::path default_path("");
    static boost::once_flag once = BOOST_ONCE_INIT;
    auto path_init = []() {
        namespace fs = boost::filesystem;
        // Windows < Vista: C:\Documents and Settings\Username\Application Data\Metaverse
        // Windows >= Vista: C:\Users\Username\AppData\Roaming\Metaverse
        // Mac: ~/Library/Application Support/Metaverse
        // Unix: ~/.metaverse
#ifdef _WIN32
        // Windows
#ifdef UNICODE
        wchar_t file_path[MAX_PATH] = { 0 };
#else
        char file_path[MAX_PATH] = { 0 };
#endif
        SHGetSpecialFolderPath(NULL, file_path, CSIDL_APPDATA, true);
        fs::path pathRet = boost::filesystem::path(file_path) / "Metaverse";
        fs::create_directories(pathRet);
        default_path = pathRet;
#else
        fs::path pathRet;
        char* pszHome = getenv("HOME");
        if (pszHome == nullptr || strlen(pszHome) == 0)
            pathRet = fs::path("/");
        else
            pathRet = fs::path(pszHome);
#ifdef MAC_OSX
        // Mac
        pathRet /= "Library/Application Support";
        fs::create_directories(pathRet / "Metaverse");
        default_path = pathRet / "Metaverse";
#else
        // Unix
        fs::create_directories(pathRet / ".metaverse");
        default_path = pathRet / ".metaverse";
#endif
#endif
    };
    boost::call_once(path_init, once);
    return default_path;
}

boost::filesystem::path webpage_path()
{
#ifdef _MSC_VER
    return "./mvs-htmls";
#else
    return default_data_path() / "mvs-htmls";
#endif
}

}//namespace libbitcoin

<commit_msg>#139 modify windows webpath dir -- file mode<commit_after>/**
 * Copyright (c) 2016-2017 metaverse core developers (see MVS-AUTHORS)
 *
 * This file is part of metaverse.
 *
 * metaverse is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License with
 * additional permissions to the one published by the Free Software
 * Foundation, either version 3 of the License, or (at your option)
 * any later version. For more information see LICENSE.
 *
 * 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
#include <metaverse/bitcoin/utility/path.hpp>
#include <boost/thread/once.hpp>

#ifdef _WIN32
#include <Shlobj.h>
#endif

namespace libbitcoin{

const boost::filesystem::path& default_data_path()
{
    static boost::filesystem::path default_path("");
    static boost::once_flag once = BOOST_ONCE_INIT;
    auto path_init = []() {
        namespace fs = boost::filesystem;
        // Windows < Vista: C:\Documents and Settings\Username\Application Data\Metaverse
        // Windows >= Vista: C:\Users\Username\AppData\Roaming\Metaverse
        // Mac: ~/Library/Application Support/Metaverse
        // Unix: ~/.metaverse
#ifdef _WIN32
        // Windows
#ifdef UNICODE
        wchar_t file_path[MAX_PATH] = { 0 };
#else
        char file_path[MAX_PATH] = { 0 };
#endif
        SHGetSpecialFolderPath(NULL, file_path, CSIDL_APPDATA, true);
        fs::path pathRet = boost::filesystem::path(file_path) / "Metaverse";
        fs::create_directories(pathRet);
        default_path = pathRet;
#else
        fs::path pathRet;
        char* pszHome = getenv("HOME");
        if (pszHome == nullptr || strlen(pszHome) == 0)
            pathRet = fs::path("/");
        else
            pathRet = fs::path(pszHome);
#ifdef MAC_OSX
        // Mac
        pathRet /= "Library/Application Support";
        fs::create_directories(pathRet / "Metaverse");
        default_path = pathRet / "Metaverse";
#else
        // Unix
        fs::create_directories(pathRet / ".metaverse");
        default_path = pathRet / ".metaverse";
#endif
#endif
    };
    boost::call_once(path_init, once);
    return default_path;
}

boost::filesystem::path webpage_path()
{
#ifdef _MSC_VER
    return "./mvs-htmls";
#else
    return default_data_path() / "mvs-htmls";
#endif
}

}//namespace libbitcoin

<|endoftext|>


<commit_before>/*
 * Copyright 2011 Intel Corporation.
 *
 * This program is licensed under the terms and conditions of the
 * Apache License, version 2.0.  The full text of the Apache License is at
 * http://www.apache.org/licenses/LICENSE-2.0
 */

#include "memoryleak.h"

#include <QDebug>

#include "aggregatedmodel.h"
#include "adapter.h"

#include "memoryleak-defines.h"

//
// instance methods
//

McaAggregatedModel::McaAggregatedModel(QObject *parent):
        QAbstractListModel(parent)
{
    QHash<int, QByteArray> hash = roleNames();
    hash.insert(SourceModelRole, "sourcemodel");
    setRoleNames(hash);
}

McaAggregatedModel::~McaAggregatedModel()
{
}

void McaAggregatedModel::addSourceModel(QAbstractItemModel *model)
{
#ifdef THREADING
    connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)),
            this, SLOT(sourceRowsInserted(QModelIndex,int,int)), Qt::BlockingQueuedConnection);
    connect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
            this, SLOT(sourceRowsRemoved(QModelIndex,int,int)), Qt::BlockingQueuedConnection);
    connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
            this, SLOT(sourceDataChanged(QModelIndex,QModelIndex)), Qt::BlockingQueuedConnection);

    McaAdapter *adapter_model = qobject_cast<McaAdapter*>(model);
    if (adapter_model) {
        qDebug() << "Got adapter: " << adapter_model;
        // Alternative: Pass this object as a argument, use invokeMethod,
        connect(adapter_model, SIGNAL(syncUpdate(McaAdapter*,int,int)),
                this, SLOT(syncUpdate(McaAdapter*,int,int)), Qt::BlockingQueuedConnection);
        connect(adapter_model, SIGNAL(syncRemoval(McaAdapter*,int,int)),
                this, SLOT(syncRemoval(McaAdapter*,int,int)), Qt::BlockingQueuedConnection);

        // TODO: Make sure this doesn't cause issues if it gets between begin/end updates
        // as the handling is split in McaAdapter.
        QMetaObject::invokeMethod(adapter_model, "triggerSyncUpdate", Qt::QueuedConnection);
    } else {
        qWarning() << "McaAggregatedModel: Recieved an unknown model, threading might break.";
        rowsInserted(model, 0, model->rowCount() - 1);
    }
#else
    connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)),
            this, SLOT(sourceRowsInserted(QModelIndex,int,int)));
    connect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
            this, SLOT(sourceRowsRemoved(QModelIndex,int,int)));
    connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
            this, SLOT(sourceDataChanged(QModelIndex,QModelIndex)));

    rowsInserted(model, 0, model->rowCount() - 1);
#endif

    // TODO: handle model reset
}

void McaAggregatedModel::removeSourceModel(QAbstractItemModel *model)
{
#ifdef THREADING
    McaAdapter *adapter_model = qobject_cast<McaAdapter*>(model);
    if (adapter_model) {
        // TODO: Make sure this doesn't cause issues if it gets between begin/end updates
        // as the handling is split in McaAdapter.
        QMetaObject::invokeMethod(adapter_model, "triggerSyncRemoval", Qt::QueuedConnection);
    } else {
        qWarning() << "McaAggregatedModel: Recieved an unknown model, threading might break.";

        disconnect(model, SIGNAL(rowsInserted(QModelIndex,int,int)),
               this, SLOT(sourceRowsInserted(QModelIndex,int,int)));
        disconnect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
               this, SLOT(sourceRowsRemoved(QModelIndex,int,int)));
        disconnect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
               this, SLOT(sourceDataChanged(QModelIndex,QModelIndex)));

        rowsRemoved(model, 0, model->rowCount() - 1);
    }
#else
    rowsRemoved(model, 0, model->rowCount() - 1);
#endif
}

int McaAggregatedModel::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return m_indexList.count();
}

QVariant McaAggregatedModel::data(const QModelIndex &index, int role) const
{
    // TODO: fix the const_cast hack here
    int row = index.row();
    if (row < m_indexList.count()) {
        QAbstractItemModel *model = const_cast<QAbstractItemModel *>(m_indexList.at(row).model());
        if (role == SourceModelRole)
            return QVariant::fromValue<QObject *>(model);
        return m_indexList.at(row).data(role);
    }

    return QVariant();
}

#ifdef THREADING

void McaAggregatedModel::syncUpdate(McaAdapter *model, int start, int end)
{
    rowsInserted(model, start, end);
}

void McaAggregatedModel::syncRemoval(McaAdapter *model, int start, int end)
{
    rowsRemoved(model, start, end);

    disconnect(model, SIGNAL(rowsInserted(QModelIndex,int,int)),
           this, SLOT(sourceRowsInserted(QModelIndex,int,int)));
    disconnect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
           this, SLOT(sourceRowsRemoved(QModelIndex,int,int)));
    disconnect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
           this, SLOT(sourceDataChanged(QModelIndex,QModelIndex)));

    disconnect(model, SIGNAL(syncUpdate(McaAdapter*,int,int)),
            this, SLOT(syncUpdate(McaAdapter*,int,int)));
    disconnect(model, SIGNAL(syncRemoval(McaAdapter*,int,int)),
            this, SLOT(syncRemoval(McaAdapter*,int,int)));
}
#endif

//
// helper functions
//

static QList< QPair<int,int> > findAffectedRows(const QList<QPersistentModelIndex> &list,
                                                const QAbstractItemModel *sourceModel,
                                                int start, int end)
{
    // effects: identifies items in list that come from rows between start and
    //            end (inclusive) in the model matching sourceModel
    // returns: a list of pairs of first row and last row of blocks of
    //            consecutive affected rows in the list

    // affected rows in order they are found
    QList<int> affectedRows;

    int i=0;
    foreach (QModelIndex sourceIndex, list) {
        if (sourceIndex.model() == sourceModel) {
            // index is from the affected model, check to see if row affected
            int row = sourceIndex.row();
            if (row >= start && row <= end)
                affectedRows.append(i);
        }
        i++;
    }

    QList< QPair<int,int> > affectedBlocks;
    QPair<int,int> block(-1, -1);

    foreach (int row, affectedRows) {
        // first time through, just initialize
        if (block.first == -1) {
            block.first = row;
            block.second = row;
            continue;
        }

        // if this row is consecutive, just bump last
        if (row == block.second + 1) {
            block.second = row;
            continue;
        }

        // otherwise record block and start next one
        affectedBlocks.append(block);
        block.first = block.second = row;
    }

    // append final block
    if (block.first != -1)
        affectedBlocks.append(block);

    return affectedBlocks;
}

//
// protected slots
//

void McaAggregatedModel::sourceRowsInserted(const QModelIndex& parent,
                                            int start, int end)
{
    Q_UNUSED(parent)

    QAbstractListModel *model = qobject_cast<QAbstractListModel *>(sender());
    if (model)
        rowsInserted(model, start, end);
}

void McaAggregatedModel::sourceRowsRemoved(const QModelIndex& parent,
                                           int start, int end)
{
    Q_UNUSED(parent)

    QAbstractListModel *model = qobject_cast<QAbstractListModel *>(sender());
    if (model)
        rowsRemoved(model, start, end);
}

void McaAggregatedModel::sourceDataChanged(const QModelIndex& topLeft,
                                           const QModelIndex& bottomRight)
{
    QList< QPair<int,int> > affectedRows;
    affectedRows = findAffectedRows(m_indexList, topLeft.model(),
                                    topLeft.row(), bottomRight.row());

    // emit dataChanged for each affected block
    for (int i = affectedRows.count() - 1; i >= 0; i--) {
        QPair<int,int> block = affectedRows[i];
        QModelIndex first = index(block.first);
        QModelIndex last = index(block.second);
        emit dataChanged(first, last);
    }
}

//
// protected members
//

void McaAggregatedModel::rowsInserted(const QAbstractItemModel *sourceModel,
                                      int start, int end)
{
    if (end < start)
        return;

    // simply append the new source rows to our list in one block
    int myCount = m_indexList.count();
    int newRows = end - start + 1;

    beginInsertRows(QModelIndex(), myCount, myCount + newRows - 1);
    for (int i=start; i<=end; i++) {
        QModelIndex sourceIndex = sourceModel->index(i, 0);
        m_indexList.append(sourceIndex);
    }
    endInsertRows();
}

void McaAggregatedModel::rowsRemoved(const QAbstractItemModel *sourceModel,
                                     int start, int end)
{

    if (end < start)
        return;

    QList< QPair<int,int> > affectedRows;
    affectedRows = findAffectedRows(m_indexList, sourceModel, start, end);

    // walk through rows in reverse order so removing won't affect indices
    for (int i = affectedRows.count() - 1; i >= 0; i--) {
        QPair<int,int> block = affectedRows[i];
        beginRemoveRows(QModelIndex(), block.first, block.second);
        for (int j = block.first; j <= block.second; j++)
            m_indexList.removeAt(block.first);
        endRemoveRows();
    }
}
<commit_msg>Fixes a issue with doubling data<commit_after>/*
 * Copyright 2011 Intel Corporation.
 *
 * This program is licensed under the terms and conditions of the
 * Apache License, version 2.0.  The full text of the Apache License is at
 * http://www.apache.org/licenses/LICENSE-2.0
 */

#include "memoryleak.h"

#include <QDebug>

#include "aggregatedmodel.h"
#include "adapter.h"

#include "memoryleak-defines.h"

//
// instance methods
//

McaAggregatedModel::McaAggregatedModel(QObject *parent):
        QAbstractListModel(parent)
{
    QHash<int, QByteArray> hash = roleNames();
    hash.insert(SourceModelRole, "sourcemodel");
    setRoleNames(hash);
}

McaAggregatedModel::~McaAggregatedModel()
{
}

void McaAggregatedModel::addSourceModel(QAbstractItemModel *model)
{
#ifdef THREADING
    McaAdapter *adapter_model = qobject_cast<McaAdapter*>(model);
    if (adapter_model) {
        // Alternative: Pass this object as a argument, use invokeMethod,
        connect(adapter_model, SIGNAL(syncUpdate(McaAdapter*,int,int)),
                this, SLOT(syncUpdate(McaAdapter*,int,int)), Qt::BlockingQueuedConnection);
        connect(adapter_model, SIGNAL(syncRemoval(McaAdapter*,int,int)),
                this, SLOT(syncRemoval(McaAdapter*,int,int)), Qt::BlockingQueuedConnection);

        // TODO: Make sure this doesn't cause issues if it gets between begin/end updates
        // as the handling is split in McaAdapter.
        QMetaObject::invokeMethod(adapter_model, "triggerSyncUpdate", Qt::QueuedConnection);
    } else {
        qWarning() << "McaAggregatedModel: Recieved an unknown model, threading might break.";
        rowsInserted(model, 0, model->rowCount() - 1);

        connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)),
                this, SLOT(sourceRowsInserted(QModelIndex,int,int)), Qt::BlockingQueuedConnection);
        connect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
                this, SLOT(sourceRowsRemoved(QModelIndex,int,int)), Qt::BlockingQueuedConnection);
        connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
                this, SLOT(sourceDataChanged(QModelIndex,QModelIndex)), Qt::BlockingQueuedConnection);
    }
#else
    connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)),
            this, SLOT(sourceRowsInserted(QModelIndex,int,int)));
    connect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
            this, SLOT(sourceRowsRemoved(QModelIndex,int,int)));
    connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
            this, SLOT(sourceDataChanged(QModelIndex,QModelIndex)));

    rowsInserted(model, 0, model->rowCount() - 1);
#endif

    // TODO: handle model reset
}

void McaAggregatedModel::removeSourceModel(QAbstractItemModel *model)
{
#ifdef THREADING
    McaAdapter *adapter_model = qobject_cast<McaAdapter*>(model);
    if (adapter_model) {
        // TODO: Make sure this doesn't cause issues if it gets between begin/end updates
        // as the handling is split in McaAdapter.
        QMetaObject::invokeMethod(adapter_model, "triggerSyncRemoval", Qt::QueuedConnection);
    } else {
        qWarning() << "McaAggregatedModel: Recieved an unknown model, threading might break.";

        disconnect(model, SIGNAL(rowsInserted(QModelIndex,int,int)),
               this, SLOT(sourceRowsInserted(QModelIndex,int,int)));
        disconnect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
               this, SLOT(sourceRowsRemoved(QModelIndex,int,int)));
        disconnect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
               this, SLOT(sourceDataChanged(QModelIndex,QModelIndex)));

        rowsRemoved(model, 0, model->rowCount() - 1);
    }
#else
    rowsRemoved(model, 0, model->rowCount() - 1);
#endif
}

int McaAggregatedModel::rowCount(const QModelIndex &parent) const
{
    Q_UNUSED(parent);
    return m_indexList.count();
}

QVariant McaAggregatedModel::data(const QModelIndex &index, int role) const
{
    // TODO: fix the const_cast hack here
    int row = index.row();
    if (row < m_indexList.count()) {
        QAbstractItemModel *model = const_cast<QAbstractItemModel *>(m_indexList.at(row).model());
        if (role == SourceModelRole)
            return QVariant::fromValue<QObject *>(model);
        return m_indexList.at(row).data(role);
    }

    return QVariant();
}

#ifdef THREADING

void McaAggregatedModel::syncUpdate(McaAdapter *model, int start, int end)
{
    rowsInserted(model, start, end);

    connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)),
            this, SLOT(sourceRowsInserted(QModelIndex,int,int)), Qt::BlockingQueuedConnection);
    connect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
            this, SLOT(sourceRowsRemoved(QModelIndex,int,int)), Qt::BlockingQueuedConnection);
    connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
            this, SLOT(sourceDataChanged(QModelIndex,QModelIndex)), Qt::BlockingQueuedConnection);
}

void McaAggregatedModel::syncRemoval(McaAdapter *model, int start, int end)
{
    rowsRemoved(model, start, end);

    disconnect(model, SIGNAL(rowsInserted(QModelIndex,int,int)),
           this, SLOT(sourceRowsInserted(QModelIndex,int,int)));
    disconnect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
           this, SLOT(sourceRowsRemoved(QModelIndex,int,int)));
    disconnect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
           this, SLOT(sourceDataChanged(QModelIndex,QModelIndex)));

    disconnect(model, SIGNAL(syncUpdate(McaAdapter*,int,int)),
            this, SLOT(syncUpdate(McaAdapter*,int,int)));
    disconnect(model, SIGNAL(syncRemoval(McaAdapter*,int,int)),
            this, SLOT(syncRemoval(McaAdapter*,int,int)));
}
#endif

//
// helper functions
//

static QList< QPair<int,int> > findAffectedRows(const QList<QPersistentModelIndex> &list,
                                                const QAbstractItemModel *sourceModel,
                                                int start, int end)
{
    // effects: identifies items in list that come from rows between start and
    //            end (inclusive) in the model matching sourceModel
    // returns: a list of pairs of first row and last row of blocks of
    //            consecutive affected rows in the list

    // affected rows in order they are found
    QList<int> affectedRows;

    int i=0;
    foreach (QModelIndex sourceIndex, list) {
        if (sourceIndex.model() == sourceModel) {
            // index is from the affected model, check to see if row affected
            int row = sourceIndex.row();
            if (row >= start && row <= end)
                affectedRows.append(i);
        }
        i++;
    }

    QList< QPair<int,int> > affectedBlocks;
    QPair<int,int> block(-1, -1);

    foreach (int row, affectedRows) {
        // first time through, just initialize
        if (block.first == -1) {
            block.first = row;
            block.second = row;
            continue;
        }

        // if this row is consecutive, just bump last
        if (row == block.second + 1) {
            block.second = row;
            continue;
        }

        // otherwise record block and start next one
        affectedBlocks.append(block);
        block.first = block.second = row;
    }

    // append final block
    if (block.first != -1)
        affectedBlocks.append(block);

    return affectedBlocks;
}

//
// protected slots
//

void McaAggregatedModel::sourceRowsInserted(const QModelIndex& parent,
                                            int start, int end)
{
    Q_UNUSED(parent)

    QAbstractListModel *model = qobject_cast<QAbstractListModel *>(sender());
    if (model)
        rowsInserted(model, start, end);
}

void McaAggregatedModel::sourceRowsRemoved(const QModelIndex& parent,
                                           int start, int end)
{
    Q_UNUSED(parent)

    QAbstractListModel *model = qobject_cast<QAbstractListModel *>(sender());
    if (model)
        rowsRemoved(model, start, end);
}

void McaAggregatedModel::sourceDataChanged(const QModelIndex& topLeft,
                                           const QModelIndex& bottomRight)
{
    QList< QPair<int,int> > affectedRows;
    affectedRows = findAffectedRows(m_indexList, topLeft.model(),
                                    topLeft.row(), bottomRight.row());

    // emit dataChanged for each affected block
    for (int i = affectedRows.count() - 1; i >= 0; i--) {
        QPair<int,int> block = affectedRows[i];
        QModelIndex first = index(block.first);
        QModelIndex last = index(block.second);
        emit dataChanged(first, last);
    }
}

//
// protected members
//

void McaAggregatedModel::rowsInserted(const QAbstractItemModel *sourceModel,
                                      int start, int end)
{
    if (end < start)
        return;

    // simply append the new source rows to our list in one block
    int myCount = m_indexList.count();
    int newRows = end - start + 1;

    beginInsertRows(QModelIndex(), myCount, myCount + newRows - 1);
    for (int i=start; i<=end; i++) {
        QModelIndex sourceIndex = sourceModel->index(i, 0);
        m_indexList.append(sourceIndex);
    }
    endInsertRows();
}

void McaAggregatedModel::rowsRemoved(const QAbstractItemModel *sourceModel,
                                     int start, int end)
{

    if (end < start)
        return;

    QList< QPair<int,int> > affectedRows;
    affectedRows = findAffectedRows(m_indexList, sourceModel, start, end);

    // walk through rows in reverse order so removing won't affect indices
    for (int i = affectedRows.count() - 1; i >= 0; i--) {
        QPair<int,int> block = affectedRows[i];
        beginRemoveRows(QModelIndex(), block.first, block.second);
        for (int j = block.first; j <= block.second; j++)
            m_indexList.removeAt(block.first);
        endRemoveRows();
    }
}
<|endoftext|>