<commit_before>#include "pouarquick.h"

PouarQuick::PouarQuick(QObject *parent) : QObject(parent)
{
}

QImageProvider::QImageProvider() : QQuickImageProvider(QQuickImageProvider::Image)
{
}

QImage QImageProvider::requestImage(const QString &id, QSize *size, const QSize &requestedSize)
{
	Q_UNUSED(size);
	QUrl dir(id);
	GError *error = NULL;
	RsvgHandle *rsvg = NULL;
	cairo_surface_t *surface = NULL;
	cairo_t *cr = NULL;
	RsvgDimensionData dimensions;
	int width = requestedSize.width();
	int height = requestedSize.height();
	/* Set the locale so that UTF-8 filenames work */
	setlocale(LC_ALL, "");

	rsvg_set_default_dpi_x_y (-1, -1);

	rsvg = rsvg_handle_new_from_file(dir.toLocalFile().toStdString().c_str(),&error);

	rsvg_handle_get_dimensions(rsvg, &dimensions);
	width = (width < 1) ? (double)height / (double)dimensions.height * dimensions.width : width ;
	height = (height < 1) ? (double)width / (double)dimensions.width * dimensions.height : height ;
	double zoom = (width > height) ? (double)width / (double)dimensions.width : (double)height / (double)dimensions.height;
	surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);

	cr = cairo_create(surface);
	cairo_scale(cr, zoom, zoom);

	rsvg_handle_render_cairo(rsvg, cr);
	QImage *source = new QImage(
		cairo_image_surface_get_data(surface),
		cairo_image_surface_get_width(surface),
		cairo_image_surface_get_height(surface),
		cairo_image_surface_get_stride(surface),
		QImage::Format_ARGB32
	);
	QImage image(cairo_image_surface_get_width(surface), cairo_image_surface_get_height(surface), QImage::Format_ARGB32);
	image.fill(qRgba(0, 0, 0, 0));
	QPainter painter(&image);
	painter.drawImage(QPoint(0, 0), *source);

	delete source;
    g_object_unref(rsvg);
    cairo_destroy(cr);
	cairo_surface_destroy(surface);
	return image;
}

QUrl PouarQuick::randomfile(QUrl url)
{
	QDir dir(url.toLocalFile());
	QFileInfoList dirs = QFileInfoList(dir.entryInfoList(QDir::Files));
	dir.setPath(dirs.at(arc4random_uniform(dirs.size())).filePath());
	url.setUrl(dir.absolutePath());
	return url;
}

QObject *singleton(QQmlEngine *engine, QJSEngine *scriptEngine)
{
	Q_UNUSED(engine);
	Q_UNUSED(scriptEngine);
	PouarQuick *pouarquick = new PouarQuick();
	return pouarquick;
}<commit_msg>ok, now it's production quality<commit_after>#include "pouarquick.h"

PouarQuick::PouarQuick(QObject *parent) : QObject(parent)
{
}

QImageProvider::QImageProvider() : QQuickImageProvider(QQuickImageProvider::Image)
{
}

QImage QImageProvider::requestImage(const QString &id, QSize *size, const QSize &requestedSize)
{
	Q_UNUSED(size);
	QUrl dir(id);
	GError *error = NULL;
	RsvgDimensionData dimensions;
	int width = 1;
	int height = 1;
	/* Set the locale so that UTF-8 filenames work */
	setlocale(LC_ALL, "");
	double zoom = 1.0;

	rsvg_set_default_dpi_x_y (-1, -1);

	RsvgHandle *rsvg = rsvg_handle_new_from_file(dir.toLocalFile().toStdString().c_str(),&error);
	if(rsvg!=NULL)
	{
		width = requestedSize.width();
		height = requestedSize.height();
		rsvg_handle_get_dimensions(rsvg, &dimensions);
		width = (width < 1) ? (double)height / (double)dimensions.height * dimensions.width : width ;
		height = (height < 1) ? (double)width / (double)dimensions.width * dimensions.height : height ;
		zoom = (width > height) ? (double)width / (double)dimensions.width : (double)height / (double)dimensions.height;
	}
	cairo_surface_t *surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);

	cairo_t *cr = cairo_create(surface);
	cairo_scale(cr, zoom, zoom);

	rsvg_handle_render_cairo(rsvg, cr);
	QImage *source = new QImage(
		cairo_image_surface_get_data(surface),
		cairo_image_surface_get_width(surface),
		cairo_image_surface_get_height(surface),
		cairo_image_surface_get_stride(surface),
		QImage::Format_ARGB32
	);
	QImage image(cairo_image_surface_get_width(surface), cairo_image_surface_get_height(surface), QImage::Format_ARGB32);
	image.fill(qRgba(0, 0, 0, 0));
	QPainter painter(&image);
	painter.drawImage(QPoint(0, 0), *source);

	delete source;
    g_object_unref(rsvg);
    cairo_destroy(cr);
	cairo_surface_destroy(surface);
	return image;
}

QUrl PouarQuick::randomfile(QUrl url)
{
	QDir dir(url.toLocalFile());
	QFileInfoList dirs = QFileInfoList(dir.entryInfoList(QDir::Files));
	dir.setPath(dirs.at(arc4random_uniform(dirs.size())).filePath());
	url.setUrl(dir.absolutePath());
	return url;
}

QObject *singleton(QQmlEngine *engine, QJSEngine *scriptEngine)
{
	Q_UNUSED(engine);
	Q_UNUSED(scriptEngine);
	PouarQuick *pouarquick = new PouarQuick();
	return pouarquick;
}<|endoftext|>


<commit_before>//-----------------------------------------------------------
//
//    Copyright (C) 2015 by the deal2lkit authors
//
//    This file is part of the deal2lkit library.
//
//    The deal2lkit library is free software; you can use it, redistribute
//    it, and/or modify it under the terms of the GNU Lesser General
//    Public License as published by the Free Software Foundation; either
//    version 2.1 of the License, or (at your option) any later version.
//    The full text of the license can be found in the file LICENSE at
//    the top level of the deal2lkit distribution.
//
//-----------------------------------------------------------

#include <deal2lkit/utilities.h>
#include <vector>
#include <fstream>
#include <thread>

#include <stdlib.h>
#include <sys/stat.h>

D2K_NAMESPACE_OPEN

namespace
{
  struct handle
  {
    char *p;
    handle(char *ptr) : p(ptr) { }
    ~handle()
    {
      delete p;
    }
  };
}

std::string demangle(const char *name)
{
  int status = -4; // some arbitrary value to eliminate the compiler warning
  handle result( abi::__cxa_demangle(name, NULL, NULL, &status) );
  return (status==0) ? result.p : name ;
}

void TimeUtilities::sleep(unsigned int t)
{
  std::this_thread::sleep_for(std::chrono::milliseconds(t));
}

void TimeUtilities::get_start_time()
{
  AssertThrow(status == true,
              ExcMessage("Use get_end_time() before reuse get_start_time().") );

  t_start = std::chrono::high_resolution_clock::now();

  status = false;
}

void TimeUtilities::get_end_time()
{
  AssertThrow(status == false,
              ExcMessage("Use get_start_time() before get_end_time().") );

  t_end = std::chrono::high_resolution_clock::now();
  std::chrono::duration<double> time_span = std::chrono::duration_cast<std::chrono::duration<double>>(t_end - t_start);
  times.push_back( time_span.count() );

  status = true;
}

int TimeUtilities::get_num_measures()
{
  return times.size();
}

void append_to_file(const std::string &in_file, const std::string &out_file)
{
  std::ifstream ifile(in_file,  std::ios::in);
  std::ofstream ofile(out_file, std::ios::out | std::ios::app);
  if (ifile.is_open())
    ofile << ifile.rdbuf();

  return;
}

bool file_exists(const std::string &file)
{
  struct stat st;
  return (stat (file.c_str(), &st) == 0);
}

bool dir_exists(const std::string &dir)
{
  struct stat st;
  return (stat (dir.c_str(), &st) == 0);
}

unsigned int get_next_available_index_directory_name(const std::string &base, int n_digits, unsigned int start, unsigned int index_max)
{
  if (start<index_max)
    {
      if ( dir_exists( base + dealii::Utilities::int_to_string (start, n_digits) ) )
        return get_next_available_index_directory_name(base, n_digits, ++start, index_max);
      else
        return start;
    }
  else
    return index_max;
}

std::string get_next_available_directory_name(const std::string &base, int n_digits, unsigned int start, unsigned int index_max)
{
  unsigned int index = get_next_available_index_directory_name(base, n_digits, start, index_max);
  return base + dealii::Utilities::int_to_string (index, n_digits);
}

bool create_directory(const std::string &name)
{
  Assert((std::find(name.begin(), name.end(), ' ') == name.end()),
         ExcMessage("Invalid name of directory."));
  std::string cmd = "mkdir -p " + name;
  int status;
  status = std::system(cmd.c_str());
  AssertThrow(status == 0, ExcCannottExecuteCommand(cmd));
  return dir_exists(name);
}

bool copy_files(const std::string &files, const std::string &destination)
{
  create_directory("./"+destination);
  bool result = true;
  int status;
  std::vector<std::string> strs;
  std::string new_file;
  strs = dealii::Utilities::split_string_list(files, ' ');
  for (size_t i = 0; i < strs.size(); i++)
    {
      Assert(file_exists(strs[i]), ExcMessage("Invalid name of file"));
      new_file = destination+"/"+strs[i];
      std::string cmd = "cp " + strs[i] + " " + new_file;
      status = std::system( cmd.c_str() );
      AssertThrow(status == 0, ExcCannottExecuteCommand(cmd));
      result &= file_exists(new_file);
    }
  return result;
}

bool copy_file(const std::string &file, const std::string &new_file)
{
  Assert(file_exists(file),ExcMessage("No such file or directory"));
  std::string cmd = "cp " + file + " " + new_file ;
  int status;
  status = std::system(cmd.c_str());
  AssertThrow(status == 0, ExcCannottExecuteCommand(cmd));
  return file_exists(new_file);
}

bool rename_file(const std::string &file, const std::string &new_file)
{
  Assert(file_exists(file),ExcMessage("No such file or directory"));
  std::string cmd = "mv " + file + " " + new_file;
  int status;
  status = std::system(cmd.c_str());
  AssertThrow(status == 0, ExcCannottExecuteCommand(cmd));
  return file_exists(new_file);
}

D2K_NAMESPACE_CLOSE

<commit_msg>fix doxy doc<commit_after>//-----------------------------------------------------------
//
//    Copyright (C) 2015 by the deal2lkit authors
//
//    This file is part of the deal2lkit library.
//
//    The deal2lkit library is free software; you can use it, redistribute
//    it, and/or modify it under the terms of the GNU Lesser General
//    Public License as published by the Free Software Foundation; either
//    version 2.1 of the License, or (at your option) any later version.
//    The full text of the license can be found in the file LICENSE at
//    the top level of the deal2lkit distribution.
//
//-----------------------------------------------------------

#include <deal2lkit/utilities.h>
#include <vector>
#include <fstream>
#include <thread>

#include <stdlib.h>
#include <sys/stat.h>

D2K_NAMESPACE_OPEN

struct handle
{
  char *p;
  handle(char *ptr) : p(ptr) { }
  ~handle()
  {
    delete p;
  }
};

std::string demangle(const char *name)
{
  int status = -4; // some arbitrary value to eliminate the compiler warning
  handle result( abi::__cxa_demangle(name, NULL, NULL, &status) );
  return (status==0) ? result.p : name ;
}

void TimeUtilities::sleep(unsigned int t)
{
  std::this_thread::sleep_for(std::chrono::milliseconds(t));
}

void TimeUtilities::get_start_time()
{
  AssertThrow(status == true,
              ExcMessage("Use get_end_time() before reuse get_start_time().") );

  t_start = std::chrono::high_resolution_clock::now();

  status = false;
}

void TimeUtilities::get_end_time()
{
  AssertThrow(status == false,
              ExcMessage("Use get_start_time() before get_end_time().") );

  t_end = std::chrono::high_resolution_clock::now();
  std::chrono::duration<double> time_span = std::chrono::duration_cast<std::chrono::duration<double>>(t_end - t_start);
  times.push_back( time_span.count() );

  status = true;
}

int TimeUtilities::get_num_measures()
{
  return times.size();
}

void append_to_file(const std::string &in_file, const std::string &out_file)
{
  std::ifstream ifile(in_file,  std::ios::in);
  std::ofstream ofile(out_file, std::ios::out | std::ios::app);
  if (ifile.is_open())
    ofile << ifile.rdbuf();

  return;
}

bool file_exists(const std::string &file)
{
  struct stat st;
  return (stat (file.c_str(), &st) == 0);
}

bool dir_exists(const std::string &dir)
{
  struct stat st;
  return (stat (dir.c_str(), &st) == 0);
}

unsigned int get_next_available_index_directory_name(const std::string &base, int n_digits, unsigned int start, unsigned int index_max)
{
  if (start<index_max)
    {
      if ( dir_exists( base + dealii::Utilities::int_to_string (start, n_digits) ) )
        return get_next_available_index_directory_name(base, n_digits, ++start, index_max);
      else
        return start;
    }
  else
    return index_max;
}

std::string get_next_available_directory_name(const std::string &base, int n_digits, unsigned int start, unsigned int index_max)
{
  unsigned int index = get_next_available_index_directory_name(base, n_digits, start, index_max);
  return base + dealii::Utilities::int_to_string (index, n_digits);
}

bool create_directory(const std::string &name)
{
  Assert((std::find(name.begin(), name.end(), ' ') == name.end()),
         ExcMessage("Invalid name of directory."));
  std::string cmd = "mkdir -p " + name;
  int status;
  status = std::system(cmd.c_str());
  AssertThrow(status == 0, ExcCannottExecuteCommand(cmd));
  return dir_exists(name);
}

bool copy_files(const std::string &files, const std::string &destination)
{
  create_directory("./"+destination);
  bool result = true;
  int status;
  std::vector<std::string> strs;
  std::string new_file;
  strs = dealii::Utilities::split_string_list(files, ' ');
  for (size_t i = 0; i < strs.size(); i++)
    {
      Assert(file_exists(strs[i]), ExcMessage("Invalid name of file"));
      new_file = destination+"/"+strs[i];
      std::string cmd = "cp " + strs[i] + " " + new_file;
      status = std::system( cmd.c_str() );
      AssertThrow(status == 0, ExcCannottExecuteCommand(cmd));
      result &= file_exists(new_file);
    }
  return result;
}

bool copy_file(const std::string &file, const std::string &new_file)
{
  Assert(file_exists(file),ExcMessage("No such file or directory"));
  std::string cmd = "cp " + file + " " + new_file ;
  int status;
  status = std::system(cmd.c_str());
  AssertThrow(status == 0, ExcCannottExecuteCommand(cmd));
  return file_exists(new_file);
}

bool rename_file(const std::string &file, const std::string &new_file)
{
  Assert(file_exists(file),ExcMessage("No such file or directory"));
  std::string cmd = "mv " + file + " " + new_file;
  int status;
  status = std::system(cmd.c_str());
  AssertThrow(status == 0, ExcCannottExecuteCommand(cmd));
  return file_exists(new_file);
}

D2K_NAMESPACE_CLOSE

<|endoftext|>


<commit_before>/// \file
/// \ingroup tutorial_eve
/// Demonstrates how to combine Timur's GL plots with other scene elements.
///
/// \image html eve_glplot_geom.png
/// \macro_code
///
/// \author Matevz Tadel

void glplot_geom()
{
   TEveManager::Create();

   TEveUtil::Macro("show_extract.C");

   TH3F *h31 = new TH3F("h31", "h31", 20, -3, 3, 20, -3, 3, 20, -3, 3);
   h31->FillRandom("gaus", 20*20*20);
   h31->SetFillColor(2);
   x = new TEvePlot3D("EvePlot - TH3F");
   x->SetPlot(h31, "glbox");
   x->RefMainTrans().Scale(800, 800, 1000);
   x->RefMainTrans().RotateLF(1, 3, TMath::PiOver2());
   gEve->AddElement(x);

   gEve->Redraw3D(kTRUE);
}
<commit_msg>Fix undefined variable with ROOT 6<commit_after>/// \file
/// \ingroup tutorial_eve
/// Demonstrates how to combine Timur's GL plots with other scene elements.
///
/// \image html eve_glplot_geom.png
/// \macro_code
///
/// \author Matevz Tadel

void glplot_geom()
{
   TEveManager::Create();

   TEveUtil::Macro("show_extract.C");

   TH3F *h31 = new TH3F("h31", "h31", 20, -3, 3, 20, -3, 3, 20, -3, 3);
   h31->FillRandom("gaus", 20*20*20);
   h31->SetFillColor(2);
   auto x = new TEvePlot3D("EvePlot - TH3F");
   x->SetPlot(h31, "glbox");
   x->RefMainTrans().Scale(800, 800, 1000);
   x->RefMainTrans().RotateLF(1, 3, TMath::PiOver2());
   gEve->AddElement(x);

   gEve->Redraw3D(kTRUE);
}
<|endoftext|>


<commit_before>// script post-processing the file generated by TMemStat (default memstat.root)
//
// To use the class TMemStat, add the following statement at the beginning
// of your script or program
//     TMemStat mm("gnubuiltin");
// or in an interactive session do something like:
//    root > TMemStat mm("gnubuiltin");
//    root > .x somescript.C
//    root > .q
// TMemStat records all the calls to malloc and free and write a TTree
// with the position where the memory is allocated/freed , as well as
// the number of bytes.
//
// This script makes a dynamic histogram showing for pages (10 kbytes by default)
// the percentage of the page used.
// A summary pave shows the total memory still in use when the TMemStat object
// goes out of scope and the average occupancy of the pages.
// The average occupancy gives a good indication of the memory fragmentation.
//
// The script can be executed simply as
//   root > .x memstat.C   (or via ACLIC  .x memstat.C+ )
// or specifying arguments
//   root > .x memstat.C+(0.01,"mydir/mymemstat.root");
//
//Author: Rene Brun 7 July 2010

#include "TMath.h"
#include "TFile.h"
#include "TTree.h"
#include "TCanvas.h"
#include "TStyle.h"
#include "TH1.h"
#include "TPaveText.h"
#include "TPaveLabel.h"
#include "TSystem.h"

void memstat(double update=0.1, const char* fname="memstat.root") {
   // Open the memstat data file, then call TTree::Draw to precompute
   // the arrays of positions and nbytes per entry.
   // update is the time interval in the data file  in seconds after which
   // the display is updated. For example is the job producing the memstat.root file
   // took 100s to execute, an update of 0.1s will generate 1000 time views of
   // the memory use.

   TFile *f = TFile::Open(fname);
   if (!f) {
      printf("Cannot open file %s\n",fname);
      return;
   }
   TTree *T = (TTree*)f->Get("T");
   if (!T) {
      printf("cannot find the TMemStat TTree named T in file %s\n",fname);
      return;
   }
   if (update <= 0) {
      printf("Illegal update value %g, changed to 0.01\n",update);
      update = 0.01;
   }
   if (update < 0.001) printf("Warning update parameter is very small, processing may be slow\n");

   Long64_t nentries = T->GetEntries();
   T->SetEstimate(nentries+10);
   Long64_t nsel = T->Draw("pos:nbytes:time","","goff");

   //now we compute the best binning for the histogram
   Int_t nbytes;
   Double_t pos;
   Double_t *V1 = T->GetV1();
   Double_t *V2 = T->GetV2();
   Double_t *V3 = T->GetV3();
   Long64_t imean = (Long64_t)TMath::Mean(nsel,V1);
   Long64_t irms = (Long64_t)TMath::RMS(nsel,V1);
   Long64_t bw = 10000;
   imean = imean - imean%bw;
   irms = irms -irms%bw;
   Int_t nbins = Int_t(4*irms/bw);
   Double_t vmin = imean -bw*nbins/2;
   Double_t vmax = vmin+bw*nbins;
   if (vmax > 2e9 && vmin <2e9) {
      //the data set has been likely generated on a 32 bits machine
      //we are mostly interested by the small allocations, so we select
      //only values below 2 GBytes
      printf("memory locations above 2GBytes will be ignored\n");
      nsel = T->Draw("pos:nbytes:time","pos <2e9","goff");
      imean = (Long64_t)TMath::Mean(nsel,V1);
      irms = (Long64_t)TMath::RMS(nsel,V1);
      bw = 10000;
      imean = imean - imean%bw;
      irms = irms -irms%bw;
      nbins = Int_t(4*irms/bw);
      vmin = imean -bw*nbins/2;
      vmax = vmin+bw*nbins;
   }
   Long64_t nvm = Long64_t(vmax-vmin+1);
   Long64_t *nbold = new Long64_t[nvm];
   memset(nbold,0,nvm*8);
   Double_t dv = (vmax-vmin)/nbins;
   TH1D *h = new TH1D("h",Form("%s;pos;per cent of pages used",fname),nbins,vmin,vmax);
   TAxis *axis = h->GetXaxis();
   gStyle->SetOptStat("ie");
   h->SetFillColor(kRed);
   h->SetMinimum(0);
   h->SetMaximum(100);
   //open a canvas and draw the empty histogram
   TCanvas *c1 = new TCanvas("c1","c1",1200,600);
   c1->SetFrameFillColor(kYellow-3);
   c1->SetGridx();
   c1->SetGridy();
   h->Draw();
   //create a TPaveText to show the summary results
   TPaveText *pvt = new TPaveText(.5,.9,.75,.99,"brNDC");
   pvt->Draw();
   //create a TPaveLabel to show the time
   TPaveLabel *ptime = new TPaveLabel(.905,.7,.995,.76,"time","brNDC");
   ptime->SetFillColor(kYellow-3);
   ptime->Draw();
   //draw producer identifier
   TNamed *named = (TNamed*)T->GetUserInfo()->FindObject("SysInfo");
   TText tmachine;
   tmachine.SetTextSize(0.02);
   tmachine.SetNDC();
   tmachine.DrawText(0.01,0.01,named->GetTitle());

   //start loop on selected rows
   Int_t bin,nb,j;
   Long64_t ipos;
   Double_t dbin,rest,time;
   Double_t updateLast = 0;
   for (Int_t i=0;i<nsel;i++) {
      pos    = V1[i];
      ipos = (Long64_t)(pos-vmin);
      nbytes = (Int_t)V2[i];
      time = 0.0001*V3[i];
      bin = axis->FindBin(pos);
      if (bin<1 || bin>nbins) continue;
      dbin = axis->GetBinUpEdge(bin)-pos;
      if (nbytes > 0) {
         if (dbin > nbytes) dbin = nbytes;
         //fill bytes in the first page
         h->AddBinContent(bin,100*dbin/dv);
	 //fill bytes in full following pages
         nb = Int_t((nbytes-dbin)/dv);
	 if (bin+nb >nbins) nb = nbins-bin;
         for (j=1;j<=nb;j++) h->AddBinContent(bin+j,100);
	 //fill the bytes remaining in last page
         rest = nbytes-nb*dv-dbin;
	 if (rest > 0) h->AddBinContent(bin+nb+1,100*rest/dv);
	 //we save nbytes at pos. This info will be used when we free this slot
         nbold[ipos] = nbytes;
      } else {
         nbytes = nbold[ipos];
	 if (bin+nb >nbins) nb = nbins-bin;
	 nbold[ipos] = 0;
	 if (nbytes <= 0) continue;
         //fill bytes free in the first page
         if (dbin > nbytes) dbin = nbytes;
	 h->AddBinContent(bin,-100*dbin/dv);
	 //fill bytes free in full following pages
	 nb = Int_t((nbytes-dbin)/dv);
	 if (bin+nb >nbins) nb = nbins-bin;
         for (j=1;j<=nb;j++) h->AddBinContent(bin+j,-100);
	 //fill the bytes free in  in last page
	 rest = nbytes-nb*dv-dbin;
	 if (rest > 0) h->AddBinContent(bin+nb+1,-100*rest/dv);

      }
      if (time -updateLast > update) {
         //update canvas at regular intervals
	 updateLast = time;
         h->SetEntries(i);
	 c1->Modified();
         pvt->GetListOfLines()->Delete();
         Double_t mbytes = 0;
         Int_t nonEmpty = 0;
         Double_t w;
         for (Int_t k=1;k<nbins;k++) {
            w = h->GetBinContent(k);
            if (w > 0) {
               nonEmpty++;
               mbytes += 0.01*w*dv;
            }
         }
         Double_t occupancy = mbytes/(nonEmpty*0.01*dv);
         pvt->AddText(Form("memory used = %g Mbytes",mbytes*1e-6));
         pvt->AddText(Form("page occupancy = %f per cent",occupancy));
         pvt->AddText("(for non empty pages only)");
         ptime->SetLabel(Form("%g sec",time));

	 c1->Update();
         gSystem->ProcessEvents();
      }
   }
   h->SetEntries(nsel);
}
<commit_msg>New version of the tutorial showing a second canvas showing the memory leaks in decreasing order of leak size. A tooltip shows the complete backtrace corresponding to the mouse positio n.<commit_after>// script post-processing the file generated by TMemStat (default memstat.root)
//
// To use the class TMemStat, add the following statement at the beginning
// of your script or program
//     TMemStat mm("gnubuiltin");
// or in an interactive session do something like:
//    root > TMemStat mm("gnubuiltin");
//    root > .x somescript.C
//    root > .q
// TMemStat records all the calls to malloc and free and write a TTree
// with the position where the memory is allocated/freed , as well as
// the number of bytes.
//
// This script creates 2 canvases.
// -In canvas1 it displays a dynamic histogram showing for pages (10 kbytes by default)
//  the percentage of the page used.
//  A summary pave shows the total memory still in use when the TMemStat object
//  goes out of scope and the average occupancy of the pages.
//  The average occupancy gives a good indication of the memory fragmentation.
//
// -In canvas2 it displays the histogram of memory leaks in decreasing order.
//  when moving the mouse on this canvas, a tooltip shows the backtrace for the leak
//  in the bin below the mouse.
//
// The script can be executed simply as
//   root > .x memstat.C   (or via ACLIC  .x memstat.C+ )
// or specifying arguments
//   root > .x memstat.C+(0.01,"mydir/mymemstat.root");
//
//Author: Rene Brun 7 July 2010

#include "TMath.h"
#include "TFile.h"
#include "TTree.h"
#include "TCanvas.h"
#include "TStyle.h"
#include "TH1.h"
#include "TPaveText.h"
#include "TPaveLabel.h"
#include "TSystem.h"
#include "TGClient.h"
#include "TGToolTip.h"
#include "TRootCanvas.h"

TFile *f;
TTree *T;
TH1D *h;
TH1D *halloc, *hfree;
TH1I *hleaks, *hentry;
TGToolTip *gTip = 0;
TObjArray *btidlist=0;
Double_t *V1, *V2, *V3, *V4;

void EventInfo(Int_t event, Int_t px, Int_t py, TObject *selected);

void memstat(double update=0.1, const char* fname="memstat.root") {
   // Open the memstat data file, then call TTree::Draw to precompute
   // the arrays of positions and nbytes per entry.
   // update is the time interval in the data file  in seconds after which
   // the display is updated. For example is the job producing the memstat.root file
   // took 100s to execute, an update of 0.1s will generate 1000 time views of
   // the memory use.

   f = TFile::Open(fname);
   if (!f) {
      printf("Cannot open file %s\n",fname);
      return;
   }
   T = (TTree*)f->Get("T");
   if (!T) {
      printf("cannot find the TMemStat TTree named T in file %s\n",fname);
      return;
   }
   if (update <= 0) {
      printf("Illegal update value %g, changed to 0.01\n",update);
      update = 0.01;
   }
   if (update < 0.001) printf("Warning update parameter is very small, processing may be slow\n");

   Long64_t nentries = T->GetEntries();
   T->SetEstimate(nentries+10);
   Long64_t nsel = T->Draw("pos:nbytes:time:btid","","goff");

   //now we compute the best binning for the histogram
   Int_t nbytes;
   Double_t pos;
   V1 = T->GetV1();
   V2 = T->GetV2();
   V3 = T->GetV3();
   V4 = T->GetV4();
   Long64_t imean = (Long64_t)TMath::Mean(nsel,V1);
   Long64_t irms  = (Long64_t)TMath::RMS(nsel,V1);
   //Long64_t bw = 10000;
   Long64_t bw = 1000;
   imean = imean - imean%bw;
   irms = irms -irms%bw;
   Int_t nbins = Int_t(4*irms/bw);
   Long64_t ivmin = imean -bw*nbins/2;
   Long64_t ivmax = ivmin+bw*nbins;
   if (ivmax > 2000000000 && ivmin <2000000000) {
      //the data set has been likely generated on a 32 bits machine
      //we are mostly interested by the small allocations, so we select
      //only values below 2 GBytes
      printf("memory locations above 2GBytes will be ignored\n");
      nsel = T->Draw("pos:nbytes:time:btid","pos <2e9","goff");
      V1 = T->GetV1();
      V2 = T->GetV2();
      V3 = T->GetV3();
      V4 = T->GetV4();
      imean = (Long64_t)TMath::Mean(nsel,V1);
      irms = (Long64_t)TMath::RMS(nsel,V1);
      bw = 10000;
      imean = imean - imean%bw;
      irms = irms -irms%bw;
      nbins = Int_t(4*irms/bw);
      ivmin = imean -bw*nbins/2;
      ivmax = ivmin+bw*nbins;
   }
   Long64_t nvm = Long64_t(ivmax-ivmin+1);
   Long64_t *nbold = new Long64_t[nvm];
   Int_t *ientry  = new Int_t[nvm];
   memset(nbold,0,nvm*8);
   Double_t dv = (ivmax-ivmin)/nbins;
   h = new TH1D("h",Form("%s;pos;per cent of pages used",fname),nbins,ivmin,ivmax);
   TAxis *axis = h->GetXaxis();
   gStyle->SetOptStat("ie");
   h->SetFillColor(kRed);
   h->SetMinimum(0);
   h->SetMaximum(100);
   halloc = new TH1D("halloc",Form("%s;pos;number of mallocs",fname),nbins,ivmin,ivmax);
   hfree  = new TH1D("hfree", Form("%s;pos;number of frees",fname),nbins,ivmin,ivmax);
   //open a canvas and draw the empty histogram
   TCanvas *c1 = new TCanvas("c1","c1",1200,600);
   c1->SetFrameFillColor(kYellow-3);
   c1->SetGridx();
   c1->SetGridy();
   h->Draw();
   //create a TPaveText to show the summary results
   TPaveText *pvt = new TPaveText(.5,.9,.75,.99,"brNDC");
   pvt->Draw();
   //create a TPaveLabel to show the time
   TPaveLabel *ptime = new TPaveLabel(.905,.7,.995,.76,"time","brNDC");
   ptime->SetFillColor(kYellow-3);
   ptime->Draw();
   //draw producer identifier
   TNamed *named = (TNamed*)T->GetUserInfo()->FindObject("SysInfo");
   TText tmachine;
   tmachine.SetTextSize(0.02);
   tmachine.SetNDC();
   if (named) tmachine.DrawText(0.01,0.01,named->GetTitle());

   //start loop on selected rows
   Int_t bin,nb=0,j;
   Long64_t ipos;
   Double_t dbin,rest,time;
   Double_t updateLast = 0;
   Int_t nleaks = 0;
   Int_t i;
   for (i=0;i<nsel;i++) {
      pos    = V1[i];
      ipos = (Long64_t)(pos-ivmin);
      nbytes = (Int_t)V2[i];
      time = 0.0001*V3[i];
      bin = axis->FindBin(pos);
      if (bin<1 || bin>nbins) continue;
      dbin = axis->GetBinUpEdge(bin)-pos;
      if (nbytes > 0) {
         halloc->Fill(pos);
         if (dbin > nbytes) dbin = nbytes;
         //fill bytes in the first page
         h->AddBinContent(bin,100*dbin/dv);
	 //fill bytes in full following pages
         nb = Int_t((nbytes-dbin)/dv);
	 if (bin+nb >nbins) nb = nbins-bin;
         for (j=1;j<=nb;j++) h->AddBinContent(bin+j,100);
	 //fill the bytes remaining in last page
         rest = nbytes-nb*dv-dbin;
	 if (rest > 0) h->AddBinContent(bin+nb+1,100*rest/dv);
	 //we save nbytes at pos. This info will be used when we free this slot
         if (nbold[ipos] > 0) printf("reallocating %d bytes (was %lld) at %lld, entry=%d\n",nbytes,nbold[ipos],ipos,i);
         if (nbold[ipos] == 0) {
            nleaks++;
            //save the Tree entry number where we made this allocation
            ientry[ipos] = i;
         }
         nbold[ipos] = nbytes;
      } else {
         hfree->Fill(pos);
         nbytes = nbold[ipos];
	 if (bin+nb >nbins) nb = nbins-bin;
	 nbold[ipos] = 0; nleaks--;
	 if (nbytes <= 0) continue;
         //fill bytes free in the first page
         if (dbin > nbytes) dbin = nbytes;
	 h->AddBinContent(bin,-100*dbin/dv);
	 //fill bytes free in full following pages
	 nb = Int_t((nbytes-dbin)/dv);
	 if (bin+nb >nbins) nb = nbins-bin;
         for (j=1;j<=nb;j++) h->AddBinContent(bin+j,-100);
	 //fill the bytes free in  in last page
	 rest = nbytes-nb*dv-dbin;
	 if (rest > 0) h->AddBinContent(bin+nb+1,-100*rest/dv);

      }
      if (time -updateLast > update) {
         //update canvas at regular intervals
	 updateLast = time;
         h->SetEntries(i);
	 c1->Modified();
         pvt->GetListOfLines()->Delete();
         Double_t mbytes = 0;
         Int_t nonEmpty = 0;
         Double_t w;
         for (Int_t k=1;k<nbins;k++) {
            w = h->GetBinContent(k);
            if (w > 0) {
               nonEmpty++;
               mbytes += 0.01*w*dv;
            }
         }
         Double_t occupancy = mbytes/(nonEmpty*0.01*dv);
         pvt->AddText(Form("memory used = %g Mbytes",mbytes*1e-6));
         pvt->AddText(Form("page occupancy = %f per cent",occupancy));
         pvt->AddText("(for non empty pages only)");
         ptime->SetLabel(Form("%g sec",time));

	 c1->Update();
         gSystem->ProcessEvents();
      }
   }
   h->SetEntries(nsel);
   Int_t nlmax = nleaks;
   nleaks += 1000;
   Int_t *lindex  = new Int_t[nleaks];
   Int_t *entry   = new Int_t[nleaks];
   Int_t *ileaks  = new Int_t[nleaks];

   nleaks =0;
   for (Int_t ii=0;ii<nvm;ii++) {
      if (nbold[ii] > 0) {
         ileaks[nleaks] = (Int_t)nbold[ii];
         entry[nleaks]  = ientry[ii];
         nleaks++;
         if (nleaks > nlmax) break;
      }
   }

   TMath::Sort(nleaks,ileaks,lindex);
   hentry = new TH1I("hentry","leak entry index",nleaks,0,nleaks);
   hleaks = new TH1I("hleaks","leaks;leak number;nbytes in leak",nleaks,0,nleaks);
   for (Int_t k=0;k<nleaks;k++) {
      Int_t kk = lindex[k];
      i = entry[kk];
      hentry->SetBinContent(k+1,i);
      hleaks->SetBinContent(k+1,ileaks[kk]);
   }
   hentry->SetEntries(nleaks);
   hleaks->SetEntries(nleaks);

   //open a second canvas and draw the histogram with leaks in decreasing order
   TCanvas *c2 = new TCanvas("c2","c2",1200,600);
   c2->SetFrameFillColor(kCyan-6);
   c2->SetGridx();
   c2->SetGridy();
   c2->SetLogy();
   hleaks->SetFillColor(kRed-3);
   if (nleaks > 1000) hleaks->GetXaxis()->SetRange(1,1000);
   hleaks->Draw();
   //draw producer identifier
   if (named) tmachine.DrawText(0.01,0.01,named->GetTitle());

   //construct the tooltip
   TRootCanvas *rc = (TRootCanvas *)c2->GetCanvasImp();
   TGMainFrame *frm = dynamic_cast<TGMainFrame *>(rc);
   // create the tooltip with a timeout of 250 ms
   if (!gTip) gTip = new TGToolTip(gClient->GetDefaultRoot(), frm, "", 250);
   c2->Connect("ProcessedEvent(Int_t, Int_t, Int_t, TObject*)",
               0, 0, "EventInfo(Int_t, Int_t, Int_t, TObject*)");

}

//______________________________________________________________________
void EventInfo(Int_t event, Int_t px, Int_t py, TObject *selected)
{

   if (!gTip) return;
   gTip->Hide();
   if (event == kMouseLeave)
      return;
   Double_t xpx  = gPad->AbsPixeltoX(px);
   Int_t bin = hleaks->GetXaxis()->FindBin(xpx);
   if (bin <=0 || bin > hleaks->GetXaxis()->GetNbins()) return;
   Int_t nbytes = (Int_t)hleaks->GetBinContent(bin);
   Int_t entry  = (Int_t)hentry->GetBinContent(bin);
   Int_t btid   = (Int_t)V4[entry];
   Double_t  time = 0.0001*V3[entry];
   TH1I *hbtids = (TH1I*)T->GetUserInfo()->FindObject("btids");
   if (!hbtids) return;
   if (!btidlist) btidlist = (TObjArray*)f->Get("FAddrsList");
   if (!btidlist) return;
   Int_t nbt = (Int_t)hbtids->GetBinContent(btid-1);
   TString ttip;
   for (Int_t i=0;i<nbt;i++) {
      Int_t j = (Int_t)hbtids->GetBinContent(btid+i);
      TNamed *nm = (TNamed*)btidlist->At(j);
      if (nm==0) break;
      const char *title = nm->GetTitle();
      if (strlen(title) < 20) continue;
      const char *bar = strstr(title,"| ");
      if (!bar) continue;
      if (strstr(bar,"operator new")) continue;
      if (strstr(bar,"libMemStat")) continue;
      if (strstr(bar,"G__Exception")) continue;
      ttip += TString::Format("%2d %s\n",i,bar+1);
   }

   if (selected) {
      const char *form1 = TString::Format("Leak number=%d, leaking bytes=%d at entry=%d    time=%gseconds\n",bin,nbytes,entry,time);
      const char *form2 = ttip.Data();
      gTip->SetText(TString::Format("%s\n%s",form1,form2));
      gTip->SetPosition(px+15, py+35);
      gTip->Reset();
   }
}
<|endoftext|>


<commit_before><commit_msg>Fix another typo in a comment<commit_after><|endoftext|>


<commit_before>//
// This file is part of the Marble Virtual Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2008 Torsten Rahn <tackat@kde.org>
// Copyright 2008 Jens-Michael Hoffmann <jensmh@gmx.de>
//

// Own
#include "MapThemeManager.h"

// Qt
#include <QtCore/QDir>
#include <QtCore/QFile>
#include <QtCore/QFileInfo>
#include <QtCore/QFileSystemWatcher>
#include <QtCore/QString>
#include <QtCore/QStringList>
#include <QtCore/QTimer>
#include <QtGui/QStandardItemModel>

// Local dir
#include "GeoSceneDocument.h"
#include "GeoSceneHead.h"
#include "GeoSceneIcon.h"
#include "GeoSceneParser.h"
#include "MarbleDebug.h"
#include "MarbleDirs.h"

namespace
{
    static const QString mapDirName = "maps";
    static const int columnRelativePath = 1;
}

namespace Marble
{

// The sole purpose of the class is to expose the protected
// setRoleNames method and use it later on
class StandardItemModelWithRoleNames: public QStandardItemModel
{
public:
    StandardItemModelWithRoleNames( int rows, int columns, QObject *parent = 0 );

    void setRoleNames( const QHash<int, QByteArray> &roleNames );
};

class MapThemeManagerPrivate
{
public:
    MapThemeManagerPrivate();
    ~MapThemeManagerPrivate();
    StandardItemModelWithRoleNames* m_mapThemeModel;
    QFileSystemWatcher* m_fileSystemWatcher;
    bool m_isInitialized;
};

StandardItemModelWithRoleNames::StandardItemModelWithRoleNames( int rows, int columns, QObject *parent ) :
    QStandardItemModel( rows, columns, parent )
{
    // nothing to do
}

void StandardItemModelWithRoleNames::setRoleNames( const QHash<int, QByteArray> &roleNames )
{
    QStandardItemModel::setRoleNames( roleNames );
}

MapThemeManagerPrivate::MapThemeManagerPrivate()
    : m_mapThemeModel( new StandardItemModelWithRoleNames( 0, 3 ) ),
      m_fileSystemWatcher( new QFileSystemWatcher ),
      m_isInitialized( false )
{
    QHash<int,QByteArray> roleNames = m_mapThemeModel->roleNames();
    roleNames[ Qt::DecorationRole ] = "icon";
    roleNames[ Qt::UserRole + 1 ] = "mapThemeId";
    m_mapThemeModel->setRoleNames( roleNames );
}

MapThemeManagerPrivate::~MapThemeManagerPrivate()
{
    delete m_mapThemeModel;
    delete m_fileSystemWatcher;
}

MapThemeManager::MapThemeManager( QObject *parent )
    : QObject( parent ),
      d( new MapThemeManagerPrivate )
{
    initFileSystemWatcher();
}

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

QList<GeoSceneDocument const*> MapThemeManager::mapThemes() const
{
    QList<GeoSceneDocument const*> result;
    const QStringList mapThemes = findMapThemes();
    QStringList::const_iterator pos = mapThemes.constBegin();
    QStringList::const_iterator const end = mapThemes.constEnd();
    for (; pos != end; ++pos ) {
        GeoSceneDocument* document = loadMapTheme( *pos );
        if ( document ) {
            result.append( document );
        }
    }
    return result;
}

void MapThemeManager::initialize()
{
    // Delayed model initialization
    updateMapThemeModel();
    d->m_isInitialized = true;
}

void MapThemeManager::initFileSystemWatcher()
{
    const QStringList paths = pathsToWatch();
/*
    foreach(const QString& path, paths)
        mDebug() << "path to watch: " << path;
*/
    d->m_fileSystemWatcher->addPaths( paths );
    connect( d->m_fileSystemWatcher, SIGNAL( directoryChanged( const QString& )),
             this, SLOT( directoryChanged( const QString& )));
    connect( d->m_fileSystemWatcher, SIGNAL( fileChanged( const QString& )),
             this, SLOT( fileChanged( const QString& )));
}

GeoSceneDocument* MapThemeManager::loadMapTheme( const QString& mapThemeStringID )
{
    if ( mapThemeStringID.isEmpty() )
        return 0;

    const QString mapThemePath = mapDirName + '/' + mapThemeStringID;
    return loadMapThemeFile( mapThemePath );
}

GeoSceneDocument* MapThemeManager::loadMapThemeFile( const QString& mapThemePath )
{
    const QString dgmlPath = MarbleDirs::path( mapThemePath );

    // Check whether file exists
    QFile file( dgmlPath );
    if ( !file.exists() ) {
        qWarning() << "Map theme file does not exist:" << dgmlPath;
        return 0;
    }

    // Open file in right mode
    const bool fileReadable = file.open( QIODevice::ReadOnly );

    if ( !fileReadable ) {
        qWarning() << "Map theme file not readable:" << dgmlPath;
        return 0;
    }

    GeoSceneParser parser( GeoScene_DGML );

    if ( !parser.read( &file )) {
        qWarning() << "Map theme file not well-formed:" << dgmlPath;
        return 0;
    }

    mDebug() << "Map theme file successfully loaded:" << dgmlPath;

    // Get result document
    GeoSceneDocument* document = static_cast<GeoSceneDocument*>( parser.releaseDocument() );
    Q_ASSERT( document );
    return document;
}

QStringList MapThemeManager::pathsToWatch()
{
    QStringList result;
    const QString localMapPathName = MarbleDirs::localPath() + '/' + mapDirName;
    const QString systemMapPathName = MarbleDirs::systemPath() + '/' + mapDirName;

    if( !QDir().exists( localMapPathName ) ) {
        QDir().mkpath( localMapPathName );
    }

    result << localMapPathName;
    result << systemMapPathName;
    addMapThemePaths( localMapPathName, result );
    addMapThemePaths( systemMapPathName, result );
    return result;
}

QStringList MapThemeManager::findMapThemes( const QString& basePath )
{
    const QString mapPathName = basePath + '/' + mapDirName;

    QDir paths = QDir( mapPathName );

    QStringList mapPaths = paths.entryList( QStringList( "*" ),
                                            QDir::AllDirs
                                            | QDir::NoSymLinks
                                            | QDir::NoDotAndDotDot );
    QStringList mapDirs;

    for ( int planet = 0; planet < mapPaths.size(); ++planet ) {
        QDir themeDir = QDir( mapPathName + '/' + mapPaths.at( planet ) );
        QStringList themeMapPaths = themeDir.entryList(
                                     QStringList( "*" ),
                                     QDir::AllDirs |
                                     QDir::NoSymLinks |
                                     QDir::NoDotAndDotDot );
        for ( int theme = 0; theme < themeMapPaths.size(); ++theme ) {
            mapDirs << mapPathName + '/' + mapPaths.at( planet ) + '/'
                + themeMapPaths.at( theme );
        }
    }

    QStringList mapFiles;
    QStringListIterator it( mapDirs );
    while ( it.hasNext() ) {
        QString themeDir = it.next() + '/';
        QString themeDirName = QDir( themeDir ).path().section( '/', -2, -1 );
        QStringList tmp = QDir( themeDir ).entryList( QStringList( "*.dgml" ),
                                                      QDir::Files | QDir::NoSymLinks );
        if ( !tmp.isEmpty() ) {
            QStringListIterator k( tmp );
            while ( k.hasNext() ) {
                QString themeXml = k.next();
                mapFiles << themeDirName + '/' + themeXml;
            }
        }
    }

    return mapFiles;
}

QStringList MapThemeManager::findMapThemes()
{
    QStringList mapFilesLocal = findMapThemes( MarbleDirs::localPath() );
    QStringList mapFilesSystem = findMapThemes( MarbleDirs::systemPath() );
    QStringList allMapFiles( mapFilesLocal );
    allMapFiles << mapFilesSystem;

    // remove duplicate entries
    allMapFiles.sort();
    for ( int i = 1; i < allMapFiles.size(); ++i ) {
        if ( allMapFiles.at(i) == allMapFiles.at( i-1 ) ) {
            allMapFiles.removeAt( i );
            --i;
        }
    }

    return allMapFiles;
}

QStandardItemModel* MapThemeManager::mapThemeModel()
{
    if ( !d->m_isInitialized ) {
        initialize();
    }
    return d->m_mapThemeModel;
}

QList<QStandardItem *> MapThemeManager::createMapThemeRow( QString const& mapThemeID )
{
    QList<QStandardItem *> itemList;

    GeoSceneDocument *mapTheme = loadMapTheme( mapThemeID );
    if ( !mapTheme || !mapTheme->head()->visible() ) {
        return itemList;
    }

    QPixmap themeIconPixmap;
    QString relativePath;

    relativePath = mapDirName + '/'
        + mapTheme->head()->target() + '/' + mapTheme->head()->theme() + '/'
        + mapTheme->head()->icon()->pixmap();
    themeIconPixmap.load( MarbleDirs::path( relativePath ) );

    if ( themeIconPixmap.isNull() ) {
        relativePath = "svg/application-x-marble-gray.png";
        themeIconPixmap.load( MarbleDirs::path( relativePath ) );
    }
    else {
        // Make sure we don't keep excessively large previews in memory
        // TODO: Scale the icon down to the default icon size in MarbleSelectView.
        //       For now maxIconSize already equals what's expected by the listview.
        QSize maxIconSize( 136, 136 );
        if ( themeIconPixmap.size() != maxIconSize ) {
            mDebug() << "Smooth scaling theme icon";
            themeIconPixmap = themeIconPixmap.scaled( maxIconSize,
                                                      Qt::KeepAspectRatio,
                                                      Qt::SmoothTransformation );
        }
    }

    QIcon mapThemeIcon =  QIcon( themeIconPixmap );

    QString name = mapTheme->head()->name();
    QString description = mapTheme->head()->description();

    QStandardItem *item = new QStandardItem( name );
    item->setData( tr( name.toUtf8() ), Qt::DisplayRole );
    item->setData( mapThemeIcon, Qt::DecorationRole );
    item->setData( QString( "<span style=\" max-width: 150 px;\"> "
                            + tr( description.toUtf8() ) + " </span>" ), Qt::ToolTipRole );
    item->setData( mapThemeID, Qt::UserRole + 1 );

    itemList << item;
    itemList << new QStandardItem( mapTheme->head()->target() + '/'
                                   + mapTheme->head()->theme() + '/'
                                   + mapTheme->head()->theme() + ".dgml" );
    itemList << new QStandardItem( tr( description.toUtf8() ) );

    delete mapTheme;

    return itemList;
}

void MapThemeManager::updateMapThemeModel()
{
    mDebug() << "updateMapThemeModel";
    d->m_mapThemeModel->clear();

    d->m_mapThemeModel->setHeaderData(0, Qt::Horizontal, tr("Name"));
    d->m_mapThemeModel->setHeaderData(1, Qt::Horizontal, tr("Path"));
    d->m_mapThemeModel->setHeaderData(2, Qt::Horizontal, tr("Description"));

    QStringList stringlist = findMapThemes();
    QStringListIterator it( stringlist );

    while ( it.hasNext() ) {
        QString mapThemeID = it.next();

    	QList<QStandardItem *> itemList = createMapThemeRow( mapThemeID );
        if ( !itemList.empty() ) {
            d->m_mapThemeModel->appendRow( itemList );
        }
    }
}

void MapThemeManager::directoryChanged( const QString& path )
{
    mDebug() << "directoryChanged:" << path;

    QStringList paths = pathsToWatch();
    d->m_fileSystemWatcher->addPaths( paths );

    mDebug() << "Emitting themesChanged()";
    emit themesChanged();
    updateMapThemeModel();
}

void MapThemeManager::fileChanged( const QString& path )
{
    mDebug() << "fileChanged:" << path;

    // 1. if the file does not (anymore) exist, it got deleted and we
    //    have to delete the corresponding item from the model
    // 2. if the file exists it is changed and we have to replace
    //    the item with a new one.

    QString mapThemeId = path.section( '/', -3 );
    mDebug() << "mapThemeId:" << mapThemeId;
    QList<QStandardItem *> matchingItems = d->m_mapThemeModel->findItems( mapThemeId,
                                                                          Qt::MatchFixedString
                                                                          | Qt::MatchCaseSensitive,
                                                                          columnRelativePath );
    mDebug() << "matchingItems:" << matchingItems.size();
    Q_ASSERT( matchingItems.size() <= 1 );
    int insertAtRow = 0;

    if ( matchingItems.size() == 1 ) {
        const int row = matchingItems.front()->row();
	insertAtRow = row;
        QList<QStandardItem *> toBeDeleted = d->m_mapThemeModel->takeRow( row );
	while ( !toBeDeleted.isEmpty() ) {
            delete toBeDeleted.takeFirst();
        }
    }

    QFileInfo fileInfo( path );
    if ( fileInfo.exists() ) {
        QList<QStandardItem *> newMapThemeRow = createMapThemeRow( mapThemeId );
        if ( !newMapThemeRow.empty() ) {
            d->m_mapThemeModel->insertRow( insertAtRow, newMapThemeRow );
        }
    }

    emit themesChanged();
}

//
// <mapPathName>/<orbDirName>/<themeDirName>
//
void MapThemeManager::addMapThemePaths( const QString& mapPathName, QStringList& result )
{
    QDir mapPath( mapPathName );
    QStringList orbDirNames = mapPath.entryList( QStringList( "*" ),
                                                 QDir::AllDirs
                                                 | QDir::NoSymLinks
                                                 | QDir::NoDotAndDotDot );
    QStringListIterator itOrb( orbDirNames );
    while ( itOrb.hasNext() ) {
        QString orbPathName = mapPathName + '/' + itOrb.next();
        result << orbPathName;

        QDir orbPath( orbPathName );
        QStringList themeDirNames = orbPath.entryList( QStringList( "*" ),
                                                       QDir::AllDirs
                                                       | QDir::NoSymLinks
                                                       | QDir::NoDotAndDotDot );
        QStringListIterator itThemeDir( themeDirNames );
        while ( itThemeDir.hasNext() ) {
            QString themePathName = orbPathName + '/' + itThemeDir.next();
            result << themePathName;

            QDir themePath( themePathName );
	    QStringList themeFileNames = themePath.entryList( QStringList( "*.dgml" ),
                                                              QDir::Files
                                                              | QDir::NoSymLinks );
            QStringListIterator itThemeFile( themeFileNames );
            while ( itThemeFile.hasNext() ) {
                QString themeFilePathName = themePathName + '/' + itThemeFile.next();
                result << themeFilePathName;
            }
        }
    }
}

}

#include "MapThemeManager.moc"
<commit_msg>MapThemeManager: turn some pointers into values<commit_after>//
// This file is part of the Marble Virtual Globe.
//
// This program is free software licensed under the GNU LGPL. You can
// find a copy of this license in LICENSE.txt in the top directory of
// the source code.
//
// Copyright 2008 Torsten Rahn <tackat@kde.org>
// Copyright 2008 Jens-Michael Hoffmann <jensmh@gmx.de>
//

// Own
#include "MapThemeManager.h"

// Qt
#include <QtCore/QDir>
#include <QtCore/QFile>
#include <QtCore/QFileInfo>
#include <QtCore/QFileSystemWatcher>
#include <QtCore/QString>
#include <QtCore/QStringList>
#include <QtCore/QTimer>
#include <QtGui/QStandardItemModel>

// Local dir
#include "GeoSceneDocument.h"
#include "GeoSceneHead.h"
#include "GeoSceneIcon.h"
#include "GeoSceneParser.h"
#include "MarbleDebug.h"
#include "MarbleDirs.h"

namespace
{
    static const QString mapDirName = "maps";
    static const int columnRelativePath = 1;
}

namespace Marble
{

// The sole purpose of the class is to expose the protected
// setRoleNames method and use it later on
class StandardItemModelWithRoleNames: public QStandardItemModel
{
public:
    StandardItemModelWithRoleNames( int rows, int columns, QObject *parent = 0 );

    void setRoleNames( const QHash<int, QByteArray> &roleNames );
};

class MapThemeManagerPrivate
{
public:
    MapThemeManagerPrivate();
    ~MapThemeManagerPrivate();
    StandardItemModelWithRoleNames m_mapThemeModel;
    QFileSystemWatcher m_fileSystemWatcher;
    bool m_isInitialized;
};

StandardItemModelWithRoleNames::StandardItemModelWithRoleNames( int rows, int columns, QObject *parent ) :
    QStandardItemModel( rows, columns, parent )
{
    // nothing to do
}

void StandardItemModelWithRoleNames::setRoleNames( const QHash<int, QByteArray> &roleNames )
{
    QStandardItemModel::setRoleNames( roleNames );
}

MapThemeManagerPrivate::MapThemeManagerPrivate()
    : m_mapThemeModel( 0, 3 ),
      m_fileSystemWatcher(),
      m_isInitialized( false )
{
    QHash<int,QByteArray> roleNames = m_mapThemeModel.roleNames();
    roleNames[ Qt::DecorationRole ] = "icon";
    roleNames[ Qt::UserRole + 1 ] = "mapThemeId";
    m_mapThemeModel.setRoleNames( roleNames );
}

MapThemeManagerPrivate::~MapThemeManagerPrivate()
{
}

MapThemeManager::MapThemeManager( QObject *parent )
    : QObject( parent ),
      d( new MapThemeManagerPrivate )
{
    initFileSystemWatcher();
}

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

QList<GeoSceneDocument const*> MapThemeManager::mapThemes() const
{
    QList<GeoSceneDocument const*> result;
    const QStringList mapThemes = findMapThemes();
    QStringList::const_iterator pos = mapThemes.constBegin();
    QStringList::const_iterator const end = mapThemes.constEnd();
    for (; pos != end; ++pos ) {
        GeoSceneDocument* document = loadMapTheme( *pos );
        if ( document ) {
            result.append( document );
        }
    }
    return result;
}

void MapThemeManager::initialize()
{
    // Delayed model initialization
    updateMapThemeModel();
    d->m_isInitialized = true;
}

void MapThemeManager::initFileSystemWatcher()
{
    const QStringList paths = pathsToWatch();
/*
    foreach(const QString& path, paths)
        mDebug() << "path to watch: " << path;
*/
    d->m_fileSystemWatcher.addPaths( paths );
    connect( &d->m_fileSystemWatcher, SIGNAL( directoryChanged( const QString& )),
             this, SLOT( directoryChanged( const QString& )));
    connect( &d->m_fileSystemWatcher, SIGNAL( fileChanged( const QString& )),
             this, SLOT( fileChanged( const QString& )));
}

GeoSceneDocument* MapThemeManager::loadMapTheme( const QString& mapThemeStringID )
{
    if ( mapThemeStringID.isEmpty() )
        return 0;

    const QString mapThemePath = mapDirName + '/' + mapThemeStringID;
    return loadMapThemeFile( mapThemePath );
}

GeoSceneDocument* MapThemeManager::loadMapThemeFile( const QString& mapThemePath )
{
    const QString dgmlPath = MarbleDirs::path( mapThemePath );

    // Check whether file exists
    QFile file( dgmlPath );
    if ( !file.exists() ) {
        qWarning() << "Map theme file does not exist:" << dgmlPath;
        return 0;
    }

    // Open file in right mode
    const bool fileReadable = file.open( QIODevice::ReadOnly );

    if ( !fileReadable ) {
        qWarning() << "Map theme file not readable:" << dgmlPath;
        return 0;
    }

    GeoSceneParser parser( GeoScene_DGML );

    if ( !parser.read( &file )) {
        qWarning() << "Map theme file not well-formed:" << dgmlPath;
        return 0;
    }

    mDebug() << "Map theme file successfully loaded:" << dgmlPath;

    // Get result document
    GeoSceneDocument* document = static_cast<GeoSceneDocument*>( parser.releaseDocument() );
    Q_ASSERT( document );
    return document;
}

QStringList MapThemeManager::pathsToWatch()
{
    QStringList result;
    const QString localMapPathName = MarbleDirs::localPath() + '/' + mapDirName;
    const QString systemMapPathName = MarbleDirs::systemPath() + '/' + mapDirName;

    if( !QDir().exists( localMapPathName ) ) {
        QDir().mkpath( localMapPathName );
    }

    result << localMapPathName;
    result << systemMapPathName;
    addMapThemePaths( localMapPathName, result );
    addMapThemePaths( systemMapPathName, result );
    return result;
}

QStringList MapThemeManager::findMapThemes( const QString& basePath )
{
    const QString mapPathName = basePath + '/' + mapDirName;

    QDir paths = QDir( mapPathName );

    QStringList mapPaths = paths.entryList( QStringList( "*" ),
                                            QDir::AllDirs
                                            | QDir::NoSymLinks
                                            | QDir::NoDotAndDotDot );
    QStringList mapDirs;

    for ( int planet = 0; planet < mapPaths.size(); ++planet ) {
        QDir themeDir = QDir( mapPathName + '/' + mapPaths.at( planet ) );
        QStringList themeMapPaths = themeDir.entryList(
                                     QStringList( "*" ),
                                     QDir::AllDirs |
                                     QDir::NoSymLinks |
                                     QDir::NoDotAndDotDot );
        for ( int theme = 0; theme < themeMapPaths.size(); ++theme ) {
            mapDirs << mapPathName + '/' + mapPaths.at( planet ) + '/'
                + themeMapPaths.at( theme );
        }
    }

    QStringList mapFiles;
    QStringListIterator it( mapDirs );
    while ( it.hasNext() ) {
        QString themeDir = it.next() + '/';
        QString themeDirName = QDir( themeDir ).path().section( '/', -2, -1 );
        QStringList tmp = QDir( themeDir ).entryList( QStringList( "*.dgml" ),
                                                      QDir::Files | QDir::NoSymLinks );
        if ( !tmp.isEmpty() ) {
            QStringListIterator k( tmp );
            while ( k.hasNext() ) {
                QString themeXml = k.next();
                mapFiles << themeDirName + '/' + themeXml;
            }
        }
    }

    return mapFiles;
}

QStringList MapThemeManager::findMapThemes()
{
    QStringList mapFilesLocal = findMapThemes( MarbleDirs::localPath() );
    QStringList mapFilesSystem = findMapThemes( MarbleDirs::systemPath() );
    QStringList allMapFiles( mapFilesLocal );
    allMapFiles << mapFilesSystem;

    // remove duplicate entries
    allMapFiles.sort();
    for ( int i = 1; i < allMapFiles.size(); ++i ) {
        if ( allMapFiles.at(i) == allMapFiles.at( i-1 ) ) {
            allMapFiles.removeAt( i );
            --i;
        }
    }

    return allMapFiles;
}

QStandardItemModel* MapThemeManager::mapThemeModel()
{
    if ( !d->m_isInitialized ) {
        initialize();
    }
    return &d->m_mapThemeModel;
}

QList<QStandardItem *> MapThemeManager::createMapThemeRow( QString const& mapThemeID )
{
    QList<QStandardItem *> itemList;

    GeoSceneDocument *mapTheme = loadMapTheme( mapThemeID );
    if ( !mapTheme || !mapTheme->head()->visible() ) {
        return itemList;
    }

    QPixmap themeIconPixmap;
    QString relativePath;

    relativePath = mapDirName + '/'
        + mapTheme->head()->target() + '/' + mapTheme->head()->theme() + '/'
        + mapTheme->head()->icon()->pixmap();
    themeIconPixmap.load( MarbleDirs::path( relativePath ) );

    if ( themeIconPixmap.isNull() ) {
        relativePath = "svg/application-x-marble-gray.png";
        themeIconPixmap.load( MarbleDirs::path( relativePath ) );
    }
    else {
        // Make sure we don't keep excessively large previews in memory
        // TODO: Scale the icon down to the default icon size in MarbleSelectView.
        //       For now maxIconSize already equals what's expected by the listview.
        QSize maxIconSize( 136, 136 );
        if ( themeIconPixmap.size() != maxIconSize ) {
            mDebug() << "Smooth scaling theme icon";
            themeIconPixmap = themeIconPixmap.scaled( maxIconSize,
                                                      Qt::KeepAspectRatio,
                                                      Qt::SmoothTransformation );
        }
    }

    QIcon mapThemeIcon =  QIcon( themeIconPixmap );

    QString name = mapTheme->head()->name();
    QString description = mapTheme->head()->description();

    QStandardItem *item = new QStandardItem( name );
    item->setData( tr( name.toUtf8() ), Qt::DisplayRole );
    item->setData( mapThemeIcon, Qt::DecorationRole );
    item->setData( QString( "<span style=\" max-width: 150 px;\"> "
                            + tr( description.toUtf8() ) + " </span>" ), Qt::ToolTipRole );
    item->setData( mapThemeID, Qt::UserRole + 1 );

    itemList << item;
    itemList << new QStandardItem( mapTheme->head()->target() + '/'
                                   + mapTheme->head()->theme() + '/'
                                   + mapTheme->head()->theme() + ".dgml" );
    itemList << new QStandardItem( tr( description.toUtf8() ) );

    delete mapTheme;

    return itemList;
}

void MapThemeManager::updateMapThemeModel()
{
    mDebug() << "updateMapThemeModel";
    d->m_mapThemeModel.clear();

    d->m_mapThemeModel.setHeaderData(0, Qt::Horizontal, tr("Name"));
    d->m_mapThemeModel.setHeaderData(1, Qt::Horizontal, tr("Path"));
    d->m_mapThemeModel.setHeaderData(2, Qt::Horizontal, tr("Description"));

    QStringList stringlist = findMapThemes();
    QStringListIterator it( stringlist );

    while ( it.hasNext() ) {
        QString mapThemeID = it.next();

    	QList<QStandardItem *> itemList = createMapThemeRow( mapThemeID );
        if ( !itemList.empty() ) {
            d->m_mapThemeModel.appendRow( itemList );
        }
    }
}

void MapThemeManager::directoryChanged( const QString& path )
{
    mDebug() << "directoryChanged:" << path;

    QStringList paths = pathsToWatch();
    d->m_fileSystemWatcher.addPaths( paths );

    mDebug() << "Emitting themesChanged()";
    emit themesChanged();
    updateMapThemeModel();
}

void MapThemeManager::fileChanged( const QString& path )
{
    mDebug() << "fileChanged:" << path;

    // 1. if the file does not (anymore) exist, it got deleted and we
    //    have to delete the corresponding item from the model
    // 2. if the file exists it is changed and we have to replace
    //    the item with a new one.

    QString mapThemeId = path.section( '/', -3 );
    mDebug() << "mapThemeId:" << mapThemeId;
    QList<QStandardItem *> matchingItems = d->m_mapThemeModel.findItems( mapThemeId,
                                                                          Qt::MatchFixedString
                                                                          | Qt::MatchCaseSensitive,
                                                                          columnRelativePath );
    mDebug() << "matchingItems:" << matchingItems.size();
    Q_ASSERT( matchingItems.size() <= 1 );
    int insertAtRow = 0;

    if ( matchingItems.size() == 1 ) {
        const int row = matchingItems.front()->row();
	insertAtRow = row;
        QList<QStandardItem *> toBeDeleted = d->m_mapThemeModel.takeRow( row );
	while ( !toBeDeleted.isEmpty() ) {
            delete toBeDeleted.takeFirst();
        }
    }

    QFileInfo fileInfo( path );
    if ( fileInfo.exists() ) {
        QList<QStandardItem *> newMapThemeRow = createMapThemeRow( mapThemeId );
        if ( !newMapThemeRow.empty() ) {
            d->m_mapThemeModel.insertRow( insertAtRow, newMapThemeRow );
        }
    }

    emit themesChanged();
}

//
// <mapPathName>/<orbDirName>/<themeDirName>
//
void MapThemeManager::addMapThemePaths( const QString& mapPathName, QStringList& result )
{
    QDir mapPath( mapPathName );
    QStringList orbDirNames = mapPath.entryList( QStringList( "*" ),
                                                 QDir::AllDirs
                                                 | QDir::NoSymLinks
                                                 | QDir::NoDotAndDotDot );
    QStringListIterator itOrb( orbDirNames );
    while ( itOrb.hasNext() ) {
        QString orbPathName = mapPathName + '/' + itOrb.next();
        result << orbPathName;

        QDir orbPath( orbPathName );
        QStringList themeDirNames = orbPath.entryList( QStringList( "*" ),
                                                       QDir::AllDirs
                                                       | QDir::NoSymLinks
                                                       | QDir::NoDotAndDotDot );
        QStringListIterator itThemeDir( themeDirNames );
        while ( itThemeDir.hasNext() ) {
            QString themePathName = orbPathName + '/' + itThemeDir.next();
            result << themePathName;

            QDir themePath( themePathName );
	    QStringList themeFileNames = themePath.entryList( QStringList( "*.dgml" ),
                                                              QDir::Files
                                                              | QDir::NoSymLinks );
            QStringListIterator itThemeFile( themeFileNames );
            while ( itThemeFile.hasNext() ) {
                QString themeFilePathName = themePathName + '/' + itThemeFile.next();
                result << themeFilePathName;
            }
        }
    }
}

}

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


<commit_before>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// NOTE: These tests are run as part of "unit_tests" (in chrome/test/unit)
// rather than as part of test_shell_tests because they rely on being able
// to instantiate a MessageLoop of type TYPE_IO.  test_shell_tests uses
// TYPE_UI, which URLRequest doesn't allow.
//

#include "webkit/fileapi/file_system_operation.h"

#include "base/message_loop.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/scoped_temp_dir.h"
#include "base/message_loop.h"
#include "googleurl/src/gurl.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_job.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "webkit/blob/blob_data.h"
#include "webkit/blob/blob_storage_controller.h"
#include "webkit/blob/blob_url_request_job.h"
#include "webkit/fileapi/file_system_callback_dispatcher.h"
#include "webkit/fileapi/file_system_file_util.h"

namespace fileapi {
namespace {
class MockDispatcher;
}  // namespace (anonymous)

class FileSystemOperationWriteTest : public testing::Test {
 public:
  FileSystemOperationWriteTest()
      : loop_(MessageLoop::TYPE_IO),
        status_(base::PLATFORM_FILE_OK),
        bytes_written_(0),
        complete_(false) {}

  FileSystemOperation* operation();

  void set_failure_status(base::PlatformFileError status) {
    EXPECT_FALSE(complete_);
    EXPECT_EQ(status_, base::PLATFORM_FILE_OK);
    EXPECT_NE(status, base::PLATFORM_FILE_OK);
    complete_ = true;
    status_ = status;
  }
  base::PlatformFileError status() const { return status_; }
  void add_bytes_written(int64 bytes, bool complete) {
    bytes_written_ += bytes;
    EXPECT_FALSE(complete_);
    complete_ = complete;
  }
  int64 bytes_written() const { return bytes_written_; }
  bool complete() const { return complete_; }

  virtual void SetUp();
  virtual void TearDown();

 protected:
  GURL URLForRelativePath(const std::string& path) const {
    // Only the path will actually get used.
    return GURL("file://").Resolve(file_.value()).Resolve(path);
  }

  GURL URLForPath(const FilePath& path) const {
    // Only the path will actually get used.
    return GURL("file://").Resolve(path.value());
  }

  MessageLoop loop_;

  ScopedTempDir dir_;
  FilePath file_;

  // For post-operation status.
  base::PlatformFileError status_;
  int64 bytes_written_;
  bool complete_;

  DISALLOW_COPY_AND_ASSIGN(FileSystemOperationWriteTest);
};

namespace {

class TestURLRequestContext : public net::URLRequestContext {
 public:
  webkit_blob::BlobStorageController* blob_storage_controller() {
    return &blob_storage_controller_;
  }

 private:
  webkit_blob::BlobStorageController blob_storage_controller_;
};

static net::URLRequestJob* BlobURLRequestJobFactory(net::URLRequest* request,
                                                    const std::string& scheme) {
  webkit_blob::BlobStorageController* blob_storage_controller =
      static_cast<TestURLRequestContext*>(request->context())->
          blob_storage_controller();
  return new webkit_blob::BlobURLRequestJob(
      request,
      blob_storage_controller->GetBlobDataFromUrl(request->url()),
      base::MessageLoopProxy::CreateForCurrentThread());
}

class MockDispatcher : public FileSystemCallbackDispatcher {
 public:
  MockDispatcher(FileSystemOperationWriteTest* test) : test_(test) { }

  virtual void DidFail(base::PlatformFileError status) {
    test_->set_failure_status(status);
    MessageLoop::current()->Quit();
  }

  virtual void DidSucceed() {
    ADD_FAILURE();
  }

  virtual void DidReadMetadata(
      const base::PlatformFileInfo& info,
      const FilePath& platform_path) {
    ADD_FAILURE();
  }

  virtual void DidReadDirectory(
      const std::vector<base::FileUtilProxy::Entry>& entries,
      bool /* has_more */) {
    ADD_FAILURE();
  }

  virtual void DidOpenFileSystem(const std::string&, const GURL&) {
    ADD_FAILURE();
  }

  virtual void DidWrite(int64 bytes, bool complete) {
    test_->add_bytes_written(bytes, complete);
    MessageLoop::current()->Quit();
  }

 private:
  FileSystemOperationWriteTest* test_;
};

}  // namespace (anonymous)

void FileSystemOperationWriteTest::SetUp() {
  ASSERT_TRUE(dir_.CreateUniqueTempDir());
  file_util::CreateTemporaryFileInDir(dir_.path(), &file_);
  net::URLRequest::RegisterProtocolFactory("blob", &BlobURLRequestJobFactory);
}

void FileSystemOperationWriteTest::TearDown() {
  net::URLRequest::RegisterProtocolFactory("blob", NULL);
}

FileSystemOperation* FileSystemOperationWriteTest::operation() {
  FileSystemOperation* operation = new FileSystemOperation(
      new MockDispatcher(this),
      base::MessageLoopProxy::CreateForCurrentThread(),
      NULL,
      FileSystemFileUtil::GetInstance());
  operation->file_system_operation_context()->set_src_type(
      kFileSystemTypeTemporary);
  operation->file_system_operation_context()->set_dest_type(
      kFileSystemTypeTemporary);
  return operation;
}

TEST_F(FileSystemOperationWriteTest, TestWriteSuccess) {
  GURL blob_url("blob:success");
  scoped_refptr<webkit_blob::BlobData> blob_data(new webkit_blob::BlobData());
  blob_data->AppendData("Hello, world!\n");

  scoped_refptr<TestURLRequestContext> url_request_context(
      new TestURLRequestContext());
  url_request_context->blob_storage_controller()->
      RegisterBlobUrl(blob_url, blob_data);

  operation()->Write(url_request_context, URLForPath(file_), blob_url, 0);
  MessageLoop::current()->Run();

  url_request_context->blob_storage_controller()->UnregisterBlobUrl(blob_url);

  EXPECT_EQ(14, bytes_written());
  EXPECT_EQ(base::PLATFORM_FILE_OK, status());
  EXPECT_TRUE(complete());
}

TEST_F(FileSystemOperationWriteTest, TestWriteZero) {
  GURL blob_url("blob:zero");
  scoped_refptr<webkit_blob::BlobData> blob_data(new webkit_blob::BlobData());
  blob_data->AppendData("");

  scoped_refptr<TestURLRequestContext> url_request_context(
      new TestURLRequestContext());
  url_request_context->blob_storage_controller()->
      RegisterBlobUrl(blob_url, blob_data);

  operation()->Write(url_request_context, URLForPath(file_), blob_url, 0);
  MessageLoop::current()->Run();

  url_request_context->blob_storage_controller()->UnregisterBlobUrl(blob_url);

  EXPECT_EQ(0, bytes_written());
  EXPECT_EQ(base::PLATFORM_FILE_OK, status());
  EXPECT_TRUE(complete());
}

TEST_F(FileSystemOperationWriteTest, TestWriteInvalidBlobUrl) {
  scoped_refptr<TestURLRequestContext> url_request_context(
      new TestURLRequestContext());

  operation()->Write(url_request_context, URLForPath(file_),
      GURL("blob:invalid"), 0);
  MessageLoop::current()->Run();

  EXPECT_EQ(0, bytes_written());
  EXPECT_EQ(base::PLATFORM_FILE_OK, status());
  EXPECT_TRUE(complete());
}

TEST_F(FileSystemOperationWriteTest, TestWriteInvalidFile) {
  GURL blob_url("blob:writeinvalidfile");
  scoped_refptr<webkit_blob::BlobData> blob_data(new webkit_blob::BlobData());
  blob_data->AppendData("It\'ll not be written.");

  scoped_refptr<TestURLRequestContext> url_request_context(
      new TestURLRequestContext());
  url_request_context->blob_storage_controller()->
      RegisterBlobUrl(blob_url, blob_data);

  operation()->Write(url_request_context,
                     URLForRelativePath("nonexist"), blob_url, 0);
  MessageLoop::current()->Run();

  url_request_context->blob_storage_controller()->UnregisterBlobUrl(blob_url);

  EXPECT_EQ(0, bytes_written());
  EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, status());
  EXPECT_TRUE(complete());
}

TEST_F(FileSystemOperationWriteTest, TestWriteDir) {
  GURL blob_url("blob:writedir");
  scoped_refptr<webkit_blob::BlobData> blob_data(new webkit_blob::BlobData());
  blob_data->AppendData("It\'ll not be written, too.");

  scoped_refptr<TestURLRequestContext> url_request_context(
      new TestURLRequestContext());
  url_request_context->blob_storage_controller()->
      RegisterBlobUrl(blob_url, blob_data);

  operation()->Write(url_request_context, URLForPath(dir_.path()), blob_url, 0);
  MessageLoop::current()->Run();

  url_request_context->blob_storage_controller()->UnregisterBlobUrl(blob_url);

  EXPECT_EQ(0, bytes_written());
  EXPECT_EQ(base::PLATFORM_FILE_ERROR_ACCESS_DENIED, status());
  EXPECT_TRUE(complete());
}

// TODO(ericu,dmikurube): Add tests for Cancel.

}  // namespace fileapi
<commit_msg>Nit fix FileSystemOperationWriteTest about when exiting the thread and remove unnecessary lines.<commit_after>// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// NOTE: These tests are run as part of "unit_tests" (in chrome/test/unit)
// rather than as part of test_shell_tests because they rely on being able
// to instantiate a MessageLoop of type TYPE_IO.  test_shell_tests uses
// TYPE_UI, which URLRequest doesn't allow.
//

#include "base/message_loop.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/scoped_temp_dir.h"
#include "base/message_loop.h"
#include "googleurl/src/gurl.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_job.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "webkit/blob/blob_data.h"
#include "webkit/blob/blob_storage_controller.h"
#include "webkit/blob/blob_url_request_job.h"
#include "webkit/fileapi/file_system_callback_dispatcher.h"
#include "webkit/fileapi/file_system_file_util.h"
#include "webkit/fileapi/file_system_operation.h"

namespace fileapi {

class FileSystemOperationWriteTest : public testing::Test {
 public:
  FileSystemOperationWriteTest()
      : loop_(MessageLoop::TYPE_IO),
        status_(base::PLATFORM_FILE_OK),
        bytes_written_(0),
        complete_(false) {}

  FileSystemOperation* operation();

  void set_failure_status(base::PlatformFileError status) {
    EXPECT_FALSE(complete_);
    EXPECT_EQ(status_, base::PLATFORM_FILE_OK);
    EXPECT_NE(status, base::PLATFORM_FILE_OK);
    complete_ = true;
    status_ = status;
  }
  base::PlatformFileError status() const { return status_; }
  void add_bytes_written(int64 bytes, bool complete) {
    bytes_written_ += bytes;
    EXPECT_FALSE(complete_);
    complete_ = complete;
  }
  int64 bytes_written() const { return bytes_written_; }
  bool complete() const { return complete_; }

  virtual void SetUp();
  virtual void TearDown();

 protected:
  GURL URLForRelativePath(const std::string& path) const {
    // Only the path will actually get used.
    return GURL("file://").Resolve(file_.value()).Resolve(path);
  }

  GURL URLForPath(const FilePath& path) const {
    // Only the path will actually get used.
    return GURL("file://").Resolve(path.value());
  }

  MessageLoop loop_;

  ScopedTempDir dir_;
  FilePath file_;

  // For post-operation status.
  base::PlatformFileError status_;
  int64 bytes_written_;
  bool complete_;

  DISALLOW_COPY_AND_ASSIGN(FileSystemOperationWriteTest);
};

namespace {

class TestURLRequestContext : public net::URLRequestContext {
 public:
  webkit_blob::BlobStorageController* blob_storage_controller() {
    return &blob_storage_controller_;
  }

 private:
  webkit_blob::BlobStorageController blob_storage_controller_;
};

static net::URLRequestJob* BlobURLRequestJobFactory(net::URLRequest* request,
                                                    const std::string& scheme) {
  webkit_blob::BlobStorageController* blob_storage_controller =
      static_cast<TestURLRequestContext*>(request->context())->
          blob_storage_controller();
  return new webkit_blob::BlobURLRequestJob(
      request,
      blob_storage_controller->GetBlobDataFromUrl(request->url()),
      base::MessageLoopProxy::CreateForCurrentThread());
}

class MockDispatcher : public FileSystemCallbackDispatcher {
 public:
  MockDispatcher(FileSystemOperationWriteTest* test) : test_(test) { }

  virtual void DidFail(base::PlatformFileError status) {
    test_->set_failure_status(status);
    MessageLoop::current()->Quit();
  }

  virtual void DidSucceed() {
    ADD_FAILURE();
  }

  virtual void DidReadMetadata(
      const base::PlatformFileInfo& info,
      const FilePath& platform_path) {
    ADD_FAILURE();
  }

  virtual void DidReadDirectory(
      const std::vector<base::FileUtilProxy::Entry>& entries,
      bool /* has_more */) {
    ADD_FAILURE();
  }

  virtual void DidOpenFileSystem(const std::string&, const GURL&) {
    ADD_FAILURE();
  }

  virtual void DidWrite(int64 bytes, bool complete) {
    test_->add_bytes_written(bytes, complete);
    if (complete)
      MessageLoop::current()->Quit();
  }

 private:
  FileSystemOperationWriteTest* test_;
};

}  // namespace (anonymous)

void FileSystemOperationWriteTest::SetUp() {
  ASSERT_TRUE(dir_.CreateUniqueTempDir());
  file_util::CreateTemporaryFileInDir(dir_.path(), &file_);
  net::URLRequest::RegisterProtocolFactory("blob", &BlobURLRequestJobFactory);
}

void FileSystemOperationWriteTest::TearDown() {
  net::URLRequest::RegisterProtocolFactory("blob", NULL);
}

FileSystemOperation* FileSystemOperationWriteTest::operation() {
  FileSystemOperation* operation = new FileSystemOperation(
      new MockDispatcher(this),
      base::MessageLoopProxy::CreateForCurrentThread(),
      NULL,
      FileSystemFileUtil::GetInstance());
  operation->file_system_operation_context()->set_src_type(
      kFileSystemTypeTemporary);
  operation->file_system_operation_context()->set_dest_type(
      kFileSystemTypeTemporary);
  return operation;
}

TEST_F(FileSystemOperationWriteTest, TestWriteSuccess) {
  GURL blob_url("blob:success");
  scoped_refptr<webkit_blob::BlobData> blob_data(new webkit_blob::BlobData());
  blob_data->AppendData("Hello, world!\n");

  scoped_refptr<TestURLRequestContext> url_request_context(
      new TestURLRequestContext());
  url_request_context->blob_storage_controller()->
      RegisterBlobUrl(blob_url, blob_data);

  operation()->Write(url_request_context, URLForPath(file_), blob_url, 0);
  MessageLoop::current()->Run();

  url_request_context->blob_storage_controller()->UnregisterBlobUrl(blob_url);

  EXPECT_EQ(14, bytes_written());
  EXPECT_EQ(base::PLATFORM_FILE_OK, status());
  EXPECT_TRUE(complete());
}

TEST_F(FileSystemOperationWriteTest, TestWriteZero) {
  GURL blob_url("blob:zero");
  scoped_refptr<webkit_blob::BlobData> blob_data(new webkit_blob::BlobData());
  blob_data->AppendData("");

  scoped_refptr<TestURLRequestContext> url_request_context(
      new TestURLRequestContext());
  url_request_context->blob_storage_controller()->
      RegisterBlobUrl(blob_url, blob_data);

  operation()->Write(url_request_context, URLForPath(file_), blob_url, 0);
  MessageLoop::current()->Run();

  url_request_context->blob_storage_controller()->UnregisterBlobUrl(blob_url);

  EXPECT_EQ(0, bytes_written());
  EXPECT_EQ(base::PLATFORM_FILE_OK, status());
  EXPECT_TRUE(complete());
}

TEST_F(FileSystemOperationWriteTest, TestWriteInvalidBlobUrl) {
  scoped_refptr<TestURLRequestContext> url_request_context(
      new TestURLRequestContext());

  operation()->Write(url_request_context, URLForPath(file_),
      GURL("blob:invalid"), 0);
  MessageLoop::current()->Run();

  EXPECT_EQ(0, bytes_written());
  EXPECT_EQ(base::PLATFORM_FILE_OK, status());
  EXPECT_TRUE(complete());
}

TEST_F(FileSystemOperationWriteTest, TestWriteInvalidFile) {
  GURL blob_url("blob:writeinvalidfile");
  scoped_refptr<webkit_blob::BlobData> blob_data(new webkit_blob::BlobData());
  blob_data->AppendData("It\'ll not be written.");

  scoped_refptr<TestURLRequestContext> url_request_context(
      new TestURLRequestContext());
  url_request_context->blob_storage_controller()->
      RegisterBlobUrl(blob_url, blob_data);

  operation()->Write(url_request_context,
                     URLForRelativePath("nonexist"), blob_url, 0);
  MessageLoop::current()->Run();

  url_request_context->blob_storage_controller()->UnregisterBlobUrl(blob_url);

  EXPECT_EQ(0, bytes_written());
  EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, status());
  EXPECT_TRUE(complete());
}

TEST_F(FileSystemOperationWriteTest, TestWriteDir) {
  GURL blob_url("blob:writedir");
  scoped_refptr<webkit_blob::BlobData> blob_data(new webkit_blob::BlobData());
  blob_data->AppendData("It\'ll not be written, too.");

  scoped_refptr<TestURLRequestContext> url_request_context(
      new TestURLRequestContext());
  url_request_context->blob_storage_controller()->
      RegisterBlobUrl(blob_url, blob_data);

  operation()->Write(url_request_context, URLForPath(dir_.path()), blob_url, 0);
  MessageLoop::current()->Run();

  url_request_context->blob_storage_controller()->UnregisterBlobUrl(blob_url);

  EXPECT_EQ(0, bytes_written());
  EXPECT_EQ(base::PLATFORM_FILE_ERROR_ACCESS_DENIED, status());
  EXPECT_TRUE(complete());
}

// TODO(ericu,dmikurube): Add tests for Cancel.

}  // namespace fileapi
<|endoftext|>


<commit_before>#include "i_render.h"
#include "text_uimodel.h"
#include "main/window.h"
#include "engine/engine.h"
#include "text.h"
#include "font.h"

namespace {
void scale( float& x, float& y, float ratio )
{
    if( ratio >= 1.0f )
    {
        x /= ratio;
    }
    else
    {
        y *= ratio;
    }
}
}

bool TextUiModel::CalcRequiredSize( Widget const& Wdg, glm::vec2& OutReqSize, std::string& OutBuf, float Ratio )
{
    Text text( Wdg( Widget::PT_FontSize ), Wdg.GetDimensions(), GetColor( Wdg ), Wdg( Widget::PT_Text ), glm::vec2( 0.0, 0.0 ), false );
    return CalcRequiredSize( text, OutReqSize, OutBuf, Ratio );
}

bool TextUiModel::CalcRequiredSize( Text const& text, glm::vec2& OutReqSize, std::string& OutBuf, float Ratio )
{
    static Font& Fnt( Font::Get() );
    double FontSize = text.mFontSize;
    double TexFontSize = Fnt.GetFontSize();
    glm::vec4 const& Dim = text.mDimensions;
    if( TexFontSize <= std::numeric_limits<float>::epsilon() )
    {
        return false;
    }
    glm::vec2 RequiredSize;
    glm::vec2 TexDim;
    std::string Buf = text.mText;
    do
    {
        if( Buf.empty() )
        {
            return false;
        }
        TexDim = Fnt.GetDim( Buf );
        if( TexDim.x <= std::numeric_limits<float>::epsilon() )
        {
            return false;
        }
        RequiredSize = TexDim;
        scale( RequiredSize.x, RequiredSize.y, Ratio );
        RequiredSize *= ( FontSize / TexFontSize );
        if( RequiredSize.x <= Dim.z && RequiredSize.y <= Dim.w )
        {
            break;
        }
        if( Buf.size() < 4 )
        {
            return false;
        }
        Buf = Buf.substr( 0, Buf.size() - 4 );
        Buf += "...";
    }
    while( true );
    RequiredSize.x /= TexDim.x;
    OutReqSize = RequiredSize;
    OutBuf = Buf;
    return true;
}

void TextUiModel::CollectVertices( Widget const& Wdg, UiVertexInserter_t& Inserter )const
{
    Text text( Wdg( Widget::PT_FontSize ), Wdg.GetDimensions(), GetColor( Wdg ), Wdg( Widget::PT_Text ), glm::vec2( 0.0, 0.0 ), false );
    CollectVertices( text, Inserter );
}

void TextUiModel::CollectVertices( Text const& text, UiVertexInserter_t& Inserter )
{
    int w, h;
    engine::Engine::Get().GetSystem<engine::WindowSystem>()->GetWindowSize( w, h );
    float Ratio = ( h != 0 ) ? ( w / h ) : 1.0f;
    glm::vec2 RequiredSize;
    std::string Buf;
    if( !CalcRequiredSize( text, RequiredSize, Buf, Ratio ) )
    {
        return;
    }
    glm::vec4 const& Col = text.mColor;
    glm::vec4 Dim = text.mDimensions;
    static Font& Fnt( Font::Get() );
    for( std::string::const_iterator i = Buf.begin(), e = Buf.end(); i != e; ++i )
    {
        Character const& Char = Fnt.GetChar( *i );
        SpritePhase const& Phase = Char.Phase;
        Dim.z = RequiredSize.x * Char.Size.x;
        Dim.w = RequiredSize.x * Ratio * Char.Size.y;
        TexturedBox( Dim, Phase, Col, Inserter );
        Dim.x += Dim.z;
    }
}

<commit_msg>B: let there be floats. floats are good.<commit_after>#include "i_render.h"
#include "text_uimodel.h"
#include "main/window.h"
#include "engine/engine.h"
#include "text.h"
#include "font.h"

namespace {
void scale( float& x, float& y, float ratio )
{
    if( ratio >= 1.0f )
    {
        x /= ratio;
    }
    else
    {
        y *= ratio;
    }
}
}

bool TextUiModel::CalcRequiredSize( Widget const& Wdg, glm::vec2& OutReqSize, std::string& OutBuf, float Ratio )
{
    Text text( Wdg( Widget::PT_FontSize ), Wdg.GetDimensions(), GetColor( Wdg ), Wdg( Widget::PT_Text ), glm::vec2( 0.0, 0.0 ), false );
    return CalcRequiredSize( text, OutReqSize, OutBuf, Ratio );
}

bool TextUiModel::CalcRequiredSize( Text const& text, glm::vec2& OutReqSize, std::string& OutBuf, float Ratio )
{
    static Font& Fnt( Font::Get() );
    double FontSize = text.mFontSize;
    double TexFontSize = Fnt.GetFontSize();
    glm::vec4 const& Dim = text.mDimensions;
    if( TexFontSize <= std::numeric_limits<float>::epsilon() )
    {
        return false;
    }
    glm::vec2 RequiredSize;
    glm::vec2 TexDim;
    std::string Buf = text.mText;
    do
    {
        if( Buf.empty() )
        {
            return false;
        }
        TexDim = Fnt.GetDim( Buf );
        if( TexDim.x <= std::numeric_limits<float>::epsilon() )
        {
            return false;
        }
        RequiredSize = TexDim;
        scale( RequiredSize.x, RequiredSize.y, Ratio );
        RequiredSize *= ( FontSize / TexFontSize );
        if( RequiredSize.x <= Dim.z && RequiredSize.y <= Dim.w )
        {
            break;
        }
        if( Buf.size() < 4 )
        {
            return false;
        }
        Buf = Buf.substr( 0, Buf.size() - 4 );
        Buf += "...";
    }
    while( true );
    RequiredSize.x /= TexDim.x;
    OutReqSize = RequiredSize;
    OutBuf = Buf;
    return true;
}

void TextUiModel::CollectVertices( Widget const& Wdg, UiVertexInserter_t& Inserter )const
{
    Text text( Wdg( Widget::PT_FontSize ), Wdg.GetDimensions(), GetColor( Wdg ), Wdg( Widget::PT_Text ), glm::vec2( 0.0, 0.0 ), false );
    CollectVertices( text, Inserter );
}

void TextUiModel::CollectVertices( Text const& text, UiVertexInserter_t& Inserter )
{
    int w, h;
    engine::Engine::Get().GetSystem<engine::WindowSystem>()->GetWindowSize( w, h );
    float Ratio = ( h != 0 ) ? ( 1.0f * w / h ) : 1.0f;
    glm::vec2 RequiredSize;
    std::string Buf;
    if( !CalcRequiredSize( text, RequiredSize, Buf, Ratio ) )
    {
        return;
    }
    glm::vec4 const& Col = text.mColor;
    glm::vec4 Dim = text.mDimensions;
    static Font& Fnt( Font::Get() );
    for( std::string::const_iterator i = Buf.begin(), e = Buf.end(); i != e; ++i )
    {
        Character const& Char = Fnt.GetChar( *i );
        SpritePhase const& Phase = Char.Phase;
        Dim.z = RequiredSize.x * Char.Size.x;
        Dim.w = RequiredSize.x * Ratio * Char.Size.y;
        TexturedBox( Dim, Phase, Col, Inserter );
        Dim.x += Dim.z;
    }
}

<|endoftext|>


<commit_before>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2015.  All rights reserved
 */
#include    "../StroikaPreComp.h"

#include    "../Execution/Thread.h"
#include    "../Execution/ThreadAbortException.h"

#include    "BlockAllocator.h"

using   namespace   Stroika;
using   namespace   Stroika::Foundation;
using   namespace   Stroika::Foundation::Memory;
using   namespace   Stroika::Foundation::Memory::Private_;
using   namespace   Stroika::Foundation::Execution;

using   namespace   Execution;

Memory::Private_::LockType_*    Memory::Private_::sLock_  =   nullptr;

/*
 ********************************************************************************
 *********************** BlockAllocator_ModuleInit_ *****************************
 ********************************************************************************
 */
BlockAllocator_ModuleInit_::BlockAllocator_ModuleInit_ ()
{
    Require (sLock_ == nullptr);
    sLock_ = new Private_::LockType_ ();
}

BlockAllocator_ModuleInit_::~BlockAllocator_ModuleInit_ ()
{
    RequireNotNull (sLock_);
    delete sLock_;
    sLock_ = nullptr;
}

/*
 ********************************************************************************
 ************** Memory::MakeModuleDependency_BlockAllocator *********************
 ********************************************************************************
 */
Execution::ModuleDependency Memory::MakeModuleDependency_BlockAllocator ()
{
    return Execution::ModuleInitializer<Private_::BlockAllocator_ModuleInit_>::GetDependency ();
}

/*
 ********************************************************************************
 *********** Memory::Private_::DoDeleteHandlingLocksExceptionsEtc_ **************
 ********************************************************************************
 */
void    Memory::Private_::DoDeleteHandlingLocksExceptionsEtc_ (void* p, void** staticNextLinkP) noexcept {
	/*
	 *	Logically this just does a lock acquire and assginemnt through pointers (swap). But
	 *	it checks for thread abort exceptions, and supresses that if needed, since this is noexcept
	 *	and can be used in DTOR. You can interupt (abort) a thread while it deletes things.
	 */
    try {
#if     qCompilerAndStdLib_make_unique_lock_IsSlow
        MACRO_LOCK_GUARD_CONTEXT (Private_::GetLock_ ());
#else
        auto    critSec  { make_unique_lock (Private_::GetLock_ ()) };
#endif
        // push p onto the head of linked free list
        (*(void**)p) = *staticNextLinkP;
        *staticNextLinkP = p;
    }
    catch (Execution::ThreadAbortException&)
    {
        Execution::Thread::SuppressAbortInContext  suppressContext;
#if     qCompilerAndStdLib_make_unique_lock_IsSlow
        MACRO_LOCK_GUARD_CONTEXT (Private_::GetLock_ ());
#else
        auto    critSec  { make_unique_lock (Private_::GetLock_ ()) };
#endif
        // push p onto the head of linked free list
        (*(void**)p) = *staticNextLinkP;
        *staticNextLinkP = p;
    }
}
<commit_msg>run astyle<commit_after>/*
 * Copyright(c) Sophist Solutions, Inc. 1990-2015.  All rights reserved
 */
#include    "../StroikaPreComp.h"

#include    "../Execution/Thread.h"
#include    "../Execution/ThreadAbortException.h"

#include    "BlockAllocator.h"

using   namespace   Stroika;
using   namespace   Stroika::Foundation;
using   namespace   Stroika::Foundation::Memory;
using   namespace   Stroika::Foundation::Memory::Private_;
using   namespace   Stroika::Foundation::Execution;

using   namespace   Execution;

Memory::Private_::LockType_*    Memory::Private_::sLock_  =   nullptr;

/*
 ********************************************************************************
 *********************** BlockAllocator_ModuleInit_ *****************************
 ********************************************************************************
 */
BlockAllocator_ModuleInit_::BlockAllocator_ModuleInit_ ()
{
    Require (sLock_ == nullptr);
    sLock_ = new Private_::LockType_ ();
}

BlockAllocator_ModuleInit_::~BlockAllocator_ModuleInit_ ()
{
    RequireNotNull (sLock_);
    delete sLock_;
    sLock_ = nullptr;
}

/*
 ********************************************************************************
 ************** Memory::MakeModuleDependency_BlockAllocator *********************
 ********************************************************************************
 */
Execution::ModuleDependency Memory::MakeModuleDependency_BlockAllocator ()
{
    return Execution::ModuleInitializer<Private_::BlockAllocator_ModuleInit_>::GetDependency ();
}

/*
 ********************************************************************************
 *********** Memory::Private_::DoDeleteHandlingLocksExceptionsEtc_ **************
 ********************************************************************************
 */
void    Memory::Private_::DoDeleteHandlingLocksExceptionsEtc_ (void* p, void** staticNextLinkP) noexcept {
    /*
     *  Logically this just does a lock acquire and assginemnt through pointers (swap). But
     *  it checks for thread abort exceptions, and supresses that if needed, since this is noexcept
     *  and can be used in DTOR. You can interupt (abort) a thread while it deletes things.
     */
    try {
#if     qCompilerAndStdLib_make_unique_lock_IsSlow
        MACRO_LOCK_GUARD_CONTEXT (Private_::GetLock_ ());
#else
        auto    critSec  { make_unique_lock (Private_::GetLock_ ()) };
#endif
        // push p onto the head of linked free list
        (*(void**)p) = *staticNextLinkP;
        * staticNextLinkP = p;
    }
    catch (Execution::ThreadAbortException&)
    {
        Execution::Thread::SuppressAbortInContext  suppressContext;
#if     qCompilerAndStdLib_make_unique_lock_IsSlow
        MACRO_LOCK_GUARD_CONTEXT (Private_::GetLock_ ());
#else
        auto    critSec  { make_unique_lock (Private_::GetLock_ ()) };
#endif
        // push p onto the head of linked free list
        (*(void**)p) = *staticNextLinkP;
        *staticNextLinkP = p;
    }
}
<|endoftext|>