<commit_before>#include "tabla_posiciones.h"
#include "ui_tabla_posiciones.h"

bool comparePtrParticipante(Participante* a, Participante* b) { return (*a < *b); }

tabla_posiciones::tabla_posiciones(GUI *guiP, Competencia* compP, QWidget *parent, GeneradorExcel *genExcelP, generadorReporte *genRepP) :
    QDialog(parent),
    ui(new Ui::tabla_posiciones), gui(guiP), genExcel(genExcelP), comp(compP), genRep(genRepP)
{
    ui->setupUi(this);
    QPixmap pix(":/images/Heros64.png");
    ui->label_logo->setPixmap(pix);
    this->setWindowTitle("Tabla de posiciones");
    ui->tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);

    ui->label_2->setText(comp->getNombre());
    ui->label_4->setText(comp->getModalidad()->getTipoMod()->getNombre());
    ui->label_6->setText(QString::number(comp->getFechaActual()));

    QVector<Participante*> participantesP = comp->getParticipantes();

    qSort(participantesP.begin(),participantesP.end(),comparePtrParticipante);
    comp->setParticipantes(participantesP);
    for (int i = 0; i < participantesP.size(); ++i) {

       ui->tableWidget->insertRow(i);
       int j =0;
       ui->tableWidget->setItem(i,j++,new QTableWidgetItem(participantesP[i]->getNombre()));
       ui->tableWidget->setItem(i,j++,new QTableWidgetItem(QString::number(participantesP[i]->getPuntaje()->getPuntos())));
       ui->tableWidget->setItem(i,j++,new QTableWidgetItem(QString::number(participantesP[i]->getPuntaje()->getPG())));
       ui->tableWidget->setItem(i,j++,new QTableWidgetItem(QString::number(participantesP[i]->getPuntaje()->getPP())));
       if(comp->getModalidad()->getEmpate()){
           ui->tableWidget->setItem(i,j++,new QTableWidgetItem(QString::number(participantesP[i]->getPuntaje()->getPE())));
       }
       else{
           for (int i2 = 0; i2 < ui->tableWidget->columnCount(); ++i2) {
                if(ui->tableWidget->horizontalHeaderItem(i2)->text().toLower() == "pe"){
                    ui->tableWidget->removeColumn(i2);
                }
           }
       }
       if(comp->getModalidad()->getTipoRes()->getNombre().toLower() == "por puntos"){
           ui->tableWidget->setItem(i,j++,new QTableWidgetItem(QString::number(participantesP[i]->getPuntaje()->getTF())));
           ui->tableWidget->setItem(i,j++,new QTableWidgetItem(QString::number(participantesP[i]->getPuntaje()->getTC())));
           ui->tableWidget->setItem(i,j++,new QTableWidgetItem(QString::number(participantesP[i]->getPuntaje()->getDif())));
       }
       else{
           for (int i2 = 0; i2 < ui->tableWidget->columnCount(); ++i2) {
                if(ui->tableWidget->horizontalHeaderItem(i2)->text().toLower() == "dt" ||
                   ui->tableWidget->horizontalHeaderItem(i2)->text().toLower() == "tf" ||
                   ui->tableWidget->horizontalHeaderItem(i2)->text().toLower() == "tc"  )
                {
                    ui->tableWidget->removeColumn(i2);
                }
           }
       }

    }

    ui->tableWidget->resizeColumnsToContents();
    int ancho = ui->tableWidget->geometry().width()*3.5;
    qDebug()<<ancho;
    this->resize(ancho ,500);

}

tabla_posiciones::~tabla_posiciones()
{
    delete ui;
}

void tabla_posiciones::on_pushButton_3_clicked()
{
    this->close();
}

void tabla_posiciones::on_pushButton_clicked()
{
    genExcel->generarExcel(comp);
    QMessageBox* msg = new QMessageBox(this);
    msg->setText("Se ha generado una planilla de cálculo con las posiciones");
    QPixmap icono(":/images/Heros-verde-64.png");
    msg->setIconPixmap(icono);
    msg->setModal(true);
    msg->exec();
}

void tabla_posiciones::on_pushButton_2_clicked()
{
    genRep->generar(comp);
}
<commit_msg>Mejorado ajuste de la ventana en tabla_posiciones<commit_after>#include "tabla_posiciones.h"
#include "ui_tabla_posiciones.h"

bool comparePtrParticipante(Participante* a, Participante* b) { return (*a < *b); }

tabla_posiciones::tabla_posiciones(GUI *guiP, Competencia* compP, QWidget *parent, GeneradorExcel *genExcelP, generadorReporte *genRepP) :
    QDialog(parent),
    ui(new Ui::tabla_posiciones), gui(guiP), genExcel(genExcelP), comp(compP), genRep(genRepP)
{
    ui->setupUi(this);
    QPixmap pix(":/images/Heros64.png");
    ui->label_logo->setPixmap(pix);
    this->setWindowTitle("Tabla de posiciones");
    ui->tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);

    ui->label_2->setText(comp->getNombre());
    ui->label_4->setText(comp->getModalidad()->getTipoMod()->getNombre());
    ui->label_6->setText(QString::number(comp->getFechaActual()));

    QVector<Participante*> participantesP = comp->getParticipantes();

    qSort(participantesP.begin(),participantesP.end(),comparePtrParticipante);
    comp->setParticipantes(participantesP);
    for (int i = 0; i < participantesP.size(); ++i) {

       ui->tableWidget->insertRow(i);
       int j =0;
       ui->tableWidget->setItem(i,j++,new QTableWidgetItem(participantesP[i]->getNombre()));
       ui->tableWidget->setItem(i,j++,new QTableWidgetItem(QString::number(participantesP[i]->getPuntaje()->getPuntos())));
       ui->tableWidget->setItem(i,j++,new QTableWidgetItem(QString::number(participantesP[i]->getPuntaje()->getPG())));
       ui->tableWidget->setItem(i,j++,new QTableWidgetItem(QString::number(participantesP[i]->getPuntaje()->getPP())));
       if(comp->getModalidad()->getEmpate()){
           ui->tableWidget->setItem(i,j++,new QTableWidgetItem(QString::number(participantesP[i]->getPuntaje()->getPE())));
       }
       else{
           for (int i2 = 0; i2 < ui->tableWidget->columnCount(); ++i2) {
                if(ui->tableWidget->horizontalHeaderItem(i2)->text().toLower() == "pe"){
                    ui->tableWidget->removeColumn(i2);
                }
           }
       }
       if(comp->getModalidad()->getTipoRes()->getNombre().toLower() == "por puntos"){
           ui->tableWidget->setItem(i,j++,new QTableWidgetItem(QString::number(participantesP[i]->getPuntaje()->getTF())));
           ui->tableWidget->setItem(i,j++,new QTableWidgetItem(QString::number(participantesP[i]->getPuntaje()->getTC())));
           ui->tableWidget->setItem(i,j++,new QTableWidgetItem(QString::number(participantesP[i]->getPuntaje()->getDif())));
       }
       else{
           for (int i2 = 0; i2 < ui->tableWidget->columnCount(); ++i2) {
                if(ui->tableWidget->horizontalHeaderItem(i2)->text().toLower() == "dt" ||
                   ui->tableWidget->horizontalHeaderItem(i2)->text().toLower() == "tf" ||
                   ui->tableWidget->horizontalHeaderItem(i2)->text().toLower() == "tc"  )
                {
                    ui->tableWidget->removeColumn(i2);
                }
           }
       }

    }

    ui->tableWidget->resizeColumnsToContents();
//    int ancho = ui->tableWidget->geometry().width()*3.5;
//    qDebug()<<ancho;
//    this->resize(ancho ,500);
    int width = (ui->tableWidget->columnCount() - 1) + ui->tableWidget->verticalHeader()->width();
    for(int column = 0; column < ui->tableWidget->columnCount(); column++)
    width = width + ui->tableWidget->columnWidth(column);
    ui->tableWidget->setMinimumWidth(width);
    width+=10;
    this->resize(sizeHint().width(),500);
}

tabla_posiciones::~tabla_posiciones()
{
    delete ui;
}

void tabla_posiciones::on_pushButton_3_clicked()
{
    this->close();
}

void tabla_posiciones::on_pushButton_clicked()
{
    genExcel->generarExcel(comp);
    QMessageBox* msg = new QMessageBox(this);
    msg->setText("Se ha generado una planilla de cálculo con las posiciones");
    QPixmap icono(":/images/Heros-verde-64.png");
    msg->setIconPixmap(icono);
    msg->setModal(true);
    msg->exec();
}

void tabla_posiciones::on_pushButton_2_clicked()
{
    genRep->generar(comp);
}
<|endoftext|>


<commit_before>// $Id$

//**************************************************************************
//* This file is property of and copyright by the ALICE HLT Project        *
//* ALICE Experiment at CERN, All rights reserved.                         *
//*                                                                        *
//* Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no>        *
//*                  for The ALICE HLT Project.                            *
//*                                                                        *
//* Permission to use, copy, modify and distribute this software and its   *
//* documentation strictly for non-commercial purposes is hereby granted   *
//* without fee, provided that the above copyright notice appears in all   *
//* copies and that both the copyright notice and this permission notice   *
//* appear in the supporting documentation. The authors make no claims     *
//* about the suitability of this software for any purpose. It is          *
//* provided "as is" without express or implied warranty.                  *
//**************************************************************************

/** @file   AliHLTEsdManager.cxx
    @author Matthias Richter
    @date
    @brief  Manager for merging and writing of HLT ESDs
*/

#include "AliHLTEsdManager.h"
#include "TSystem.h"
#include "TClass.h"
#include "TROOT.h"

/** ROOT macro for the implementation of ROOT specific class methods */
ClassImp(AliHLTEsdManager)

AliHLTEsdManager::AliHLTEsdManager()
  :
  AliHLTLogging()
{
  // see header file for class documentation
  // or
  // refer to README to build package
  // or
  // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
}

AliHLTEsdManager::~AliHLTEsdManager()
{
  // see header file for class documentation
}

const char* AliHLTEsdManager::fgkImplName="AliHLTEsdManagerImplementation";
const char* AliHLTEsdManager::fgkImplLibrary="libHLTrec.so";

AliHLTEsdManager* AliHLTEsdManager::New()
{
  // see header file for class documentation
  int iLibResult=0;
  AliHLTEsdManager* instance=NULL;
  AliHLTLogging log;
  TClass* pCl=NULL;
  ROOT::NewFunc_t pNewFunc=NULL;
  do {
    pCl=TClass::GetClass(fgkImplName);
  } while (!pCl && (iLibResult=gSystem->Load(fgkImplLibrary))==0);
  if (iLibResult>=0) {
    if (pCl && (pNewFunc=pCl->GetNew())!=NULL) {
      void* p=(*pNewFunc)(NULL);
      if (p) {
	instance=reinterpret_cast<AliHLTEsdManager*>(p);
	if (!instance) {
	  log.Logging(kHLTLogError, "AliHLTEsdManager::New", "ESD handling", "type cast to AliHLTEsdManager instance failed");
	}
      } else {
	log.Logging(kHLTLogError, "AliHLTEsdManager::New", "ESD handling", "can not create AliHLTEsdManager instance from class descriptor");
      }
      delete pCl;
    } else {
      log.Logging(kHLTLogError, "AliHLTEsdManager::New", "ESD handling", "can not find AliHLTEsdManager class descriptor");
    }
  } else {
    log.Logging(kHLTLogError, "AliHLTEsdManager::New", "ESD handling", "can not load libHLTrec library");
  }
  return instance;
}

void AliHLTEsdManager::Delete(AliHLTEsdManager* instance)
{
  // see header file for class documentation
  if (!instance) return;

  // check if the library is still there in order to have the
  // destructor available
  TClass* pCl=TClass::GetClass("AliHLTEsdManagerImlementation");
  if (!pCl) return;
  delete pCl;

  delete instance;
}
<commit_msg>bugfix: do not delete TClass objects in the dynamic handling of instances<commit_after>// $Id$

//**************************************************************************
//* This file is property of and copyright by the ALICE HLT Project        *
//* ALICE Experiment at CERN, All rights reserved.                         *
//*                                                                        *
//* Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no>        *
//*                  for The ALICE HLT Project.                            *
//*                                                                        *
//* Permission to use, copy, modify and distribute this software and its   *
//* documentation strictly for non-commercial purposes is hereby granted   *
//* without fee, provided that the above copyright notice appears in all   *
//* copies and that both the copyright notice and this permission notice   *
//* appear in the supporting documentation. The authors make no claims     *
//* about the suitability of this software for any purpose. It is          *
//* provided "as is" without express or implied warranty.                  *
//**************************************************************************

/** @file   AliHLTEsdManager.cxx
    @author Matthias Richter
    @date
    @brief  Manager for merging and writing of HLT ESDs
*/

#include "AliHLTEsdManager.h"
#include "TSystem.h"
#include "TClass.h"
#include "TROOT.h"

/** ROOT macro for the implementation of ROOT specific class methods */
ClassImp(AliHLTEsdManager)

AliHLTEsdManager::AliHLTEsdManager()
  :
  AliHLTLogging()
{
  // see header file for class documentation
  // or
  // refer to README to build package
  // or
  // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
}

AliHLTEsdManager::~AliHLTEsdManager()
{
  // see header file for class documentation
}

const char* AliHLTEsdManager::fgkImplName="AliHLTEsdManagerImplementation";
const char* AliHLTEsdManager::fgkImplLibrary="libHLTrec.so";

AliHLTEsdManager* AliHLTEsdManager::New()
{
  // see header file for class documentation
  int iLibResult=0;
  AliHLTEsdManager* instance=NULL;
  AliHLTLogging log;
  TClass* pCl=NULL;
  ROOT::NewFunc_t pNewFunc=NULL;
  do {
    pCl=TClass::GetClass(fgkImplName);
  } while (!pCl && (iLibResult=gSystem->Load(fgkImplLibrary))==0);
  if (iLibResult>=0) {
    if (pCl && (pNewFunc=pCl->GetNew())!=NULL) {
      void* p=(*pNewFunc)(NULL);
      if (p) {
	instance=reinterpret_cast<AliHLTEsdManager*>(p);
	if (!instance) {
	  log.Logging(kHLTLogError, "AliHLTEsdManager::New", "ESD handling", "type cast to AliHLTEsdManager instance failed");
	}
      } else {
	log.Logging(kHLTLogError, "AliHLTEsdManager::New", "ESD handling", "can not create AliHLTEsdManager instance from class descriptor");
      }
    } else {
      log.Logging(kHLTLogError, "AliHLTEsdManager::New", "ESD handling", "can not find AliHLTEsdManager class descriptor");
    }
  } else {
    log.Logging(kHLTLogError, "AliHLTEsdManager::New", "ESD handling", "can not load libHLTrec library");
  }
  return instance;
}

void AliHLTEsdManager::Delete(AliHLTEsdManager* instance)
{
  // see header file for class documentation
  if (!instance) return;

  // check if the library is still there in order to have the
  // destructor available
  TClass* pCl=TClass::GetClass(fgkImplName);
  if (!pCl) {
    AliHLTLogging log;
    log.Logging(kHLTLogError, "AliHLTEsdManager::Delete", "ESD handling", "potential memory leak: libHLTrec library not available, skipping destruction %p", instance);
    return;
  }

  delete instance;
}
<|endoftext|>


<commit_before>/*
  Sample unit tests for BasicServer
 */

#include <exception>
#include <iostream>
#include <string>
#include <utility>
#include <vector>

#include <cpprest/http_client.h>
#include <cpprest/json.h>

#include <pplx/pplxtasks.h>

#include <UnitTest++/UnitTest++.h>

using std::cerr;
using std::cout;
using std::endl;
using std::make_pair;
using std::pair;
using std::string;
using std::vector;

using web::http::http_headers;
using web::http::http_request;
using web::http::http_response;
using web::http::method;
using web::http::methods;
using web::http::status_code;
using web::http::status_codes;
using web::http::uri_builder;

using web::http::client::http_client;

using web::json::value;

/*
  Make an HTTP request, returning the status code and any JSON value in the body

  method: member of web::http::methods
  uri_string: uri of the request
  req_body: [optional] a json::value to be passed as the message body

  If the response has a body with Content-Type: application/json,
  the second part of the result is the json::value of the body.
  If the response does not have that Content-Type, the second part
  of the result is simply json::value {}.

  You're welcome to read this code but bear in mind: It's the single
  trickiest part of the sample code. You can just call it without
  attending to its internals, if you prefer.
 */

// Version with explicit third argument
pair<status_code,value> do_request (const method& http_method, const string& uri_string, const value& req_body) {
  http_request request {http_method};
  if (req_body != value {}) {
    http_headers& headers (request.headers());
    headers.add("Content-Type", "application/json");
    request.set_body(req_body);
  }

  status_code code;
  value resp_body;
  http_client client {uri_string};
  client.request (request)
    .then([&code](http_response response)
	  {
	    code = response.status_code();
	    const http_headers& headers {response.headers()};
	    auto content_type (headers.find("Content-Type"));
	    if (content_type == headers.end() ||
		content_type->second != "application/json")
	      return pplx::task<value> ([] { return value {};});
	    else
	      return response.extract_json();
	  })
    .then([&resp_body](value v) -> void
	  {
	    resp_body = v;
	    return;
	  })
    .wait();
  return make_pair(code, resp_body);
}

// Version that defaults third argument
pair<status_code,value> do_request (const method& http_method, const string& uri_string) {
  return do_request (http_method, uri_string, value {});
}

/*
  Utility to create a table

  addr: Prefix of the URI (protocol, address, and port)
  table: Table in which to insert the entity
 */
int create_table (const string& addr, const string& table) {
  pair<status_code,value> result {do_request (methods::POST, addr + "CreateTable/" + table)};
  return result.first;
}

/*
  Utility to delete a table

  addr: Prefix of the URI (protocol, address, and port)
  table: Table in which to insert the entity
 */
int delete_table (const string& addr, const string& table) {
  // SIGH--Note that REST SDK uses "methods::DEL", not "methods::DELETE"
  pair<status_code,value> result {
    do_request (methods::DEL,
		addr + "DeleteTable/" + table)};
  return result.first;
}

/*
  Utility to put an entity with a single property

  addr: Prefix of the URI (protocol, address, and port)
  table: Table in which to insert the entity
  partition: Partition of the entity
  row: Row of the entity
  prop: Name of the property
  pstring: Value of the property, as a string
 */
int put_entity(const string& addr, const string& table, const string& partition, const string& row, const string& prop, const string& pstring) {
  pair<status_code,value> result {
    do_request (methods::PUT,
		addr + "UpdateEntity/" + table + "/" + partition + "/" + row,
		value::object (vector<pair<string,value>>
			       {make_pair(prop, value::string(pstring))}))};
  return result.first;
}

/*
  Utility to delete an entity

  addr: Prefix of the URI (protocol, address, and port)
  table: Table in which to insert the entity
  partition: Partition of the entity
  row: Row of the entity
 */
int delete_entity (const string& addr, const string& table, const string& partition, const string& row)  {
  // SIGH--Note that REST SDK uses "methods::DEL", not "methods::DELETE"
  pair<status_code,value> result {
    do_request (methods::DEL,
		addr + "DeleteEntity/" + table + "/" + partition + "/" + row)};
  return result.first;
}

/*
  A sample fixture that ensures TestTable exists, and
  at least has the entity Franklin,Aretha/USA
  with the property "Song": "RESPECT".

  The entity is deleted when the fixture shuts down
  but the table is left. See the comments in the code
  for the reason for this design.
 */
SUITE(GET) {
  class GetFixture {
  public:
    static constexpr const char* addr {"http://127.0.0.1:34568/"};
    static constexpr const char* table {"TestTable"};
    static constexpr const char* partition {"Franklin,Aretha"};
    static constexpr const char* row {"USA"};
    static constexpr const char* property {"Song"};
    static constexpr const char* prop_val {"RESPECT"};

  public:
    GetFixture() {
      int make_result {create_table(addr, table)};
      cerr << "create result " << make_result << endl;
      if (make_result != status_codes::Created && make_result != status_codes::Accepted) {
	throw std::exception();
      }
      int put_result {put_entity (addr, table, partition, row, property, prop_val)};
      cerr << "put result " << put_result << endl;
      if (put_result != status_codes::OK) {
	throw std::exception();
      }
    }
    ~GetFixture() {
      int del_ent_result {delete_entity (addr, table, partition, row)};
      if (del_ent_result != status_codes::OK) {
	throw std::exception();
      }

      /*
	In traditional unit testing, we might delete the table after every test.

	However, in cloud NoSQL environments (Azure Tables, Amazon DynamoDB)
	creating and deleting tables are rate-limited operations. So we
	leave the table after each test but delete all its entities.
       */
      cout << "Skipping table delete" << endl;
      /*
      int del_result {delete_table(addr, table)};
      cerr << "delete result " << del_result << endl;
      if (del_result != status_codes::OK) {
	throw std::exception();
      }
      */
    }
  };

  /*
    A test of GET of a single entity
    addr/table/partition/row/property

   */
  TEST_FIXTURE(GetFixture, GetSingle) {
    pair<status_code,value> result {
      do_request (methods::GET,
		  string(GetFixture::addr)
		  + GetFixture::table + "/"
		  + GetFixture::partition + "/"
		  + GetFixture::row)};

      CHECK_EQUAL(string("{\"")
		  + GetFixture::property
		  + "\":\""
		  + GetFixture::prop_val
		  + "\"}",
		  result.second.serialize());
      CHECK_EQUAL(status_codes::OK, result.first);
    }

  /*
    A test of GET all table entries
   */
  TEST_FIXTURE(GetFixture, GetAll) {
    string partition {"Katherines,The"};
    string row {"Canada"};
    string property {"Home"};
    string prop_val {"Vancouver"};
    int put_result {put_entity (GetFixture::addr, GetFixture::table, partition, row, property, prop_val)};
    cerr << "put result " << put_result << endl;
    assert (put_result == status_codes::OK);

    pair<status_code,value> result {
      do_request (methods::GET,
		  string(GetFixture::addr)
		  + string(GetFixture::table))};
    CHECK(result.second.is_array());
    CHECK_EQUAL(2, result.second.as_array().size());
    /*
      Checking the body is not well-supported by UnitTest++, as we have to test
      independent of the order of returned values.
     */
    //CHECK_EQUAL(body.serialize(), string("{\"")+string(GetFixture::property)+ "\":\""+string(GetFixture::prop_val)+"\"}");
    CHECK_EQUAL(status_codes::OK, result.first);

    //GET all tests

    //table name does not exist
    result = do_request( methods::GET, string(GetFixture::addr) + "NonexistentTable" );
    CHECK_EQUAL(status_codes::NotFound, result.first);

    // addr/table/ <- add "/" at end
    result = do_request( methods::GET, string(GetFixture::addr) + string(GetFixture::table) + "/" );
    CHECK_EQUAL(status_codes::OK, result.first);

    //just addr, no table name
    result = do_request( methods::GET, string(GetFixture::addr) );
    CHECK_EQUAL( status_codes::BadRequest, result.first);

/*
    //no addr doesn't work
    result = do_request( methods::GET, string(GetFixture::table) );
    CHECK_EQUAL( status_codes::BadRequest, result.first);
*/

/*
    //table/table name as partition
    result = do_request( methods::GET, string(GetFixture::addr) + string(GetFixture::table) + "/" + string(GetFixture::table) );
    CHECK_EQUAL( status_codes::BadRequest, result.first);
*/

    CHECK_EQUAL(status_codes::OK, delete_entity (GetFixture::addr, GetFixture::table, partition, row));
  }
}

/*
  Locate and run all tests
 */
int main(int argc, const char* argv[]) {
  return UnitTest::RunAllTests();
}
<commit_msg>Add more tests for GET all<commit_after>/*
  Sample unit tests for BasicServer
 */

#include <exception>
#include <iostream>
#include <string>
#include <utility>
#include <vector>

#include <cpprest/http_client.h>
#include <cpprest/json.h>

#include <pplx/pplxtasks.h>

#include <UnitTest++/UnitTest++.h>

using std::cerr;
using std::cout;
using std::endl;
using std::make_pair;
using std::pair;
using std::string;
using std::vector;

using web::http::http_headers;
using web::http::http_request;
using web::http::http_response;
using web::http::method;
using web::http::methods;
using web::http::status_code;
using web::http::status_codes;
using web::http::uri_builder;

using web::http::client::http_client;

using web::json::value;

/*
  Make an HTTP request, returning the status code and any JSON value in the body

  method: member of web::http::methods
  uri_string: uri of the request
  req_body: [optional] a json::value to be passed as the message body

  If the response has a body with Content-Type: application/json,
  the second part of the result is the json::value of the body.
  If the response does not have that Content-Type, the second part
  of the result is simply json::value {}.

  You're welcome to read this code but bear in mind: It's the single
  trickiest part of the sample code. You can just call it without
  attending to its internals, if you prefer.
 */

// Version with explicit third argument
pair<status_code,value> do_request (const method& http_method, const string& uri_string, const value& req_body) {
  http_request request {http_method};
  if (req_body != value {}) {
    http_headers& headers (request.headers());
    headers.add("Content-Type", "application/json");
    request.set_body(req_body);
  }

  status_code code;
  value resp_body;
  http_client client {uri_string};
  client.request (request)
    .then([&code](http_response response)
	  {
	    code = response.status_code();
	    const http_headers& headers {response.headers()};
	    auto content_type (headers.find("Content-Type"));
	    if (content_type == headers.end() ||
		content_type->second != "application/json")
	      return pplx::task<value> ([] { return value {};});
	    else
	      return response.extract_json();
	  })
    .then([&resp_body](value v) -> void
	  {
	    resp_body = v;
	    return;
	  })
    .wait();
  return make_pair(code, resp_body);
}

// Version that defaults third argument
pair<status_code,value> do_request (const method& http_method, const string& uri_string) {
  return do_request (http_method, uri_string, value {});
}

/*
  Utility to create a table

  addr: Prefix of the URI (protocol, address, and port)
  table: Table in which to insert the entity
 */
int create_table (const string& addr, const string& table) {
  pair<status_code,value> result {do_request (methods::POST, addr + "CreateTable/" + table)};
  return result.first;
}

/*
  Utility to delete a table

  addr: Prefix of the URI (protocol, address, and port)
  table: Table in which to insert the entity
 */
int delete_table (const string& addr, const string& table) {
  // SIGH--Note that REST SDK uses "methods::DEL", not "methods::DELETE"
  pair<status_code,value> result {
    do_request (methods::DEL,
		addr + "DeleteTable/" + table)};
  return result.first;
}

/*
  Utility to put an entity with a single property

  addr: Prefix of the URI (protocol, address, and port)
  table: Table in which to insert the entity
  partition: Partition of the entity
  row: Row of the entity
  prop: Name of the property
  pstring: Value of the property, as a string
 */
int put_entity(const string& addr, const string& table, const string& partition, const string& row, const string& prop, const string& pstring) {
  pair<status_code,value> result {
    do_request (methods::PUT,
		addr + "UpdateEntity/" + table + "/" + partition + "/" + row,
		value::object (vector<pair<string,value>>
			       {make_pair(prop, value::string(pstring))}))};
  return result.first;
}

/*
  Utility to delete an entity

  addr: Prefix of the URI (protocol, address, and port)
  table: Table in which to insert the entity
  partition: Partition of the entity
  row: Row of the entity
 */
int delete_entity (const string& addr, const string& table, const string& partition, const string& row)  {
  // SIGH--Note that REST SDK uses "methods::DEL", not "methods::DELETE"
  pair<status_code,value> result {
    do_request (methods::DEL,
		addr + "DeleteEntity/" + table + "/" + partition + "/" + row)};
  return result.first;
}

/*
  A sample fixture that ensures TestTable exists, and
  at least has the entity Franklin,Aretha/USA
  with the property "Song": "RESPECT".

  The entity is deleted when the fixture shuts down
  but the table is left. See the comments in the code
  for the reason for this design.
 */
SUITE(GET) {
  class GetFixture {
  public:
    static constexpr const char* addr {"http://127.0.0.1:34568/"};
    static constexpr const char* table {"TestTable"};
    static constexpr const char* partition {"Franklin,Aretha"};
    static constexpr const char* row {"USA"};
    static constexpr const char* property {"Song"};
    static constexpr const char* prop_val {"RESPECT"};

  public:
    GetFixture() {
      int make_result {create_table(addr, table)};
      cerr << "create result " << make_result << endl;
      if (make_result != status_codes::Created && make_result != status_codes::Accepted) {
	throw std::exception();
      }
      int put_result {put_entity (addr, table, partition, row, property, prop_val)};
      cerr << "put result " << put_result << endl;
      if (put_result != status_codes::OK) {
	throw std::exception();
      }
    }
    ~GetFixture() {
      int del_ent_result {delete_entity (addr, table, partition, row)};
      if (del_ent_result != status_codes::OK) {
	throw std::exception();
      }

      /*
	In traditional unit testing, we might delete the table after every test.

	However, in cloud NoSQL environments (Azure Tables, Amazon DynamoDB)
	creating and deleting tables are rate-limited operations. So we
	leave the table after each test but delete all its entities.
       */
      cout << "Skipping table delete" << endl;
      /*
      int del_result {delete_table(addr, table)};
      cerr << "delete result " << del_result << endl;
      if (del_result != status_codes::OK) {
	throw std::exception();
      }
      */
    }
  };

  /*
    A test of GET of a single entity
    addr/table/partition/row/property

   */
  TEST_FIXTURE(GetFixture, GetSingle) {
    pair<status_code,value> result {
      do_request (methods::GET,
		  string(GetFixture::addr)
		  + GetFixture::table + "/"
		  + GetFixture::partition + "/"
		  + GetFixture::row)};

      CHECK_EQUAL(string("{\"")
		  + GetFixture::property
		  + "\":\""
		  + GetFixture::prop_val
		  + "\"}",
		  result.second.serialize());
      CHECK_EQUAL(status_codes::OK, result.first);
    }

  /*
    A test of GET all table entries
   */
  TEST_FIXTURE(GetFixture, GetAll) {
    string partition {"Katherines,The"};
    string row {"Canada"};
    string property {"Home"};
    string prop_val {"Vancouver"};
    int put_result {put_entity (GetFixture::addr, GetFixture::table, partition, row, property, prop_val)};
    cerr << "put result " << put_result << endl;
    assert (put_result == status_codes::OK);

    pair<status_code,value> result {
      do_request (methods::GET,
		  string(GetFixture::addr)
		  + string(GetFixture::table))};
    CHECK(result.second.is_array());
    CHECK_EQUAL(2, result.second.as_array().size());
    /*
      Checking the body is not well-supported by UnitTest++, as we have to test
      independent of the order of returned values.
     */
    //CHECK_EQUAL(body.serialize(), string("{\"")+string(GetFixture::property)+ "\":\""+string(GetFixture::prop_val)+"\"}");
    CHECK_EQUAL(status_codes::OK, result.first);
/*
    //GET all tests

    // table name does not exist
    result = do_request( methods::GET, string(GetFixture::addr) + "NonexistentTable" );
    CHECK_EQUAL(status_codes::NotFound, result.first);

    // addr/table/ <- add "/" at end
    result = do_request( methods::GET, string(GetFixture::addr) + string(GetFixture::table) + "/" );
    CHECK_EQUAL(status_codes::OK, result.first);

    // just addr, no table name
    result = do_request( methods::GET, string(GetFixture::addr) );
    CHECK_EQUAL( status_codes::BadRequest, result.first);

    // no addr doesn't work
    result = do_request( methods::GET, string(GetFixture::table) );
    CHECK_EQUAL( status_codes::BadRequest, result.first);

    // table/table, second table name as partition
    result = do_request( methods::GET, string(GetFixture::addr) + string(GetFixture::table) + "/" + string(GetFixture::table) );
    CHECK_EQUAL( status_codes::BadRequest, result.first);
*/

    CHECK_EQUAL(status_codes::OK, delete_entity (GetFixture::addr, GetFixture::table, partition, row));
  }

  /*
    A test of GET all entities from a specific partition
  */
  TEST_FIXTURE(GetFixture, GetPartition) {
    string partition {"Katherines,The"};
    string row {"Canada"};
    string property {"Home"};
    string prop_val {"Vancouver"};
    int put_result {put_entity (GetFixture::addr, GetFixture::table, partition, row, property, prop_val)};
    cerr << "put result " << put_result << endl;
    assert (put_result == status_codes::OK);

    pair<status_code,value> result {
      do_request (methods::GET, string(GetFixture::addr) + string(GetFixture::table))
    };

    CHECK(result.second.is_array());
    CHECK_EQUAL(2, result.second.as_array().size());
    /*
      Checking the body is not well-supported by UnitTest++, as we have to test
      independent of the order of returned values.
     */
    //CHECK_EQUAL(body.serialize(), string("{\"")+string(GetFixture::property)+ "\":\""+string(GetFixture::prop_val)+"\"}");
    CHECK_EQUAL(status_codes::OK, result.first);

    //TESTS

    //basic tests
    // table does not exist
    result = do_request( methods::GET, string(GetFixture::addr) + "NonexistentTable" );
    CHECK_EQUAL(status_codes::NotFound, result.first);

    // addr/table/partition/row
    // addr//partition/row -- missing table name
    result = do_request( methods::GET, string(GetFixture::addr) + "/" + string(GetFixture::partition) + "/*" );
    CHECK_EQUAL( status_codes::NotFound, result.first);

    // missing partition name
    result = do_request( methods::GET, string(GetFixture::addr) + string(GetFixture::table) + "//*" );
    CHECK_EQUAL(status_codes::BadRequest, result.first);

    //missing * for row
    result = do_request( methods::GET, string(GetFixture::addr) + string(GetFixture::table) + "/" + string(GetFixture::partition) + "/" );
    CHECK_EQUAL(status_codes::BadRequest, result.first);

    //testing for Katherines,The because partitions seems to default to Franklin,Aretha
    //give correct Katherines,The
    result = do_request( methods::GET, string(GetFixture::addr) + string(GetFixture::table) + "/Katherines,The/*" );
    CHECK_EQUAL(status_codes::OK, result.first);

    //give correct row with Katherines,The
    result = do_request( methods::GET, string(GetFixture::addr) + string(GetFixture::table) + "/Katherines,The/Canada" );
    CHECK_EQUAL(status_codes::OK, result.first);

    //give Katherines,The with wrong row
    result = do_request( methods::GET, string(GetFixture::addr) + string(GetFixture::table) + "/Katherines,The/Germany" );
    CHECK_EQUAL(status_codes::NotFound, result.first);

    //give Katherines,The with no * for row
    result = do_request( methods::GET, string(GetFixture::addr) + string(GetFixture::table) + "/Katherines,The/" );
    CHECK_EQUAL(status_codes::BadRequest, result.first);

    //deletes Katherines,The
    CHECK_EQUAL(status_codes::OK, delete_entity (GetFixture::addr, GetFixture::table, partition, row) );

    //to show it really is gone: give correct Katherines,The which worked earlier
    result = do_request( methods::GET, string(GetFixture::addr) + string(GetFixture::table) + "/Katherines,The/*" );
    CHECK_EQUAL(status_codes::OK, result.first);

    //give a row name
    result = do_request( methods::GET, string(GetFixture::addr) + string(GetFixture::table) + "/" + string(GetFixture::partition) + "/USA" );
    CHECK_EQUAL(status_codes::OK, result.first);

    //give a row name that doesn't match
    result = do_request( methods::GET, string(GetFixture::addr) + string(GetFixture::table) + "/" + string(GetFixture::partition) + "/Korea" );
    CHECK_EQUAL(status_codes::NotFound, result.first);

    //table found and ok
    result = do_request( methods::GET, string(GetFixture::addr) + string(GetFixture::table) + "/" + string(GetFixture::partition) + "/*" );
    CHECK_EQUAL(status_codes::OK, result.first);

    //don't need this anymore because Katherins,The is deleted already
    //CHECK_EQUAL(status_codes::OK, delete_entity (GetFixture::addr, GetFixture::table, partition, row) );
  }
}

/*
  Locate and run all tests
 */
int main(int argc, const char* argv[]) {
  return UnitTest::RunAllTests();
}
<|endoftext|>


<commit_before>/*
    Copyright (c) 2006 - 2007 Volker Krause <vkrause@kde.org>
    Copyright (c) 2010 Michael Jansen <kde@michael-jansen>

    This library is free software; you can redistribute it and/or modify it
    under the terms of the GNU Library General Public License as published by
    the Free Software Foundation; either version 2 of the License, or (at your
    option) any later version.

    This library is distributed in the hope that it will be useful, but WITHOUT
    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
    License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to the
    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
*/

#include "notificationmanager.h"
#include "notificationmanageradaptor.h"
#include "messagesource.h"
#include "tracer.h"
#include "storage/datastore.h"
#include "../../libs/xdgbasedirs_p.h"

#include <QtCore/QDebug>
#include <QDBusConnection>
#include <QSettings>

using namespace Akonadi;

NotificationManager* NotificationManager::mSelf = 0;

NotificationManager::NotificationManager()
  : QObject( 0 )
{
  NotificationMessage::registerDBusTypes();

  new NotificationManagerAdaptor( this );
  QDBusConnection::sessionBus().registerObject( QLatin1String("/notifications"),
    this, QDBusConnection::ExportAdaptors );
  QDBusConnection::sessionBus().registerObject( QLatin1String("/notifications/debug"),
    this, QDBusConnection::ExportScriptableSlots );

  const QString serverConfigFile = XdgBaseDirs::akonadiServerConfigFile( XdgBaseDirs::ReadWrite );
  QSettings settings( serverConfigFile, QSettings::IniFormat );

  mTimer.setInterval( settings.value( QLatin1String("NotificationManager/Interval"), 50 ).toInt() );
  mTimer.setSingleShot( true );
  connect( &mTimer, SIGNAL(timeout()), SLOT(emitPendingNotifications()) );
}

NotificationManager::~NotificationManager()
{
}

NotificationManager* NotificationManager::self()
{
  if ( !mSelf )
    mSelf = new NotificationManager();

  return mSelf;
}

void NotificationManager::connectNotificationCollector(NotificationCollector* collector)
{
  connect( collector, SIGNAL(notify(Akonadi::NotificationMessage::List)),
           SLOT(slotNotify(Akonadi::NotificationMessage::List)) );
}

void NotificationManager::slotNotify(const Akonadi::NotificationMessage::List &msgs)
{
  foreach ( const NotificationMessage &msg, msgs )
    NotificationMessage::appendAndCompress( mNotifications, msg );
  if ( !mTimer.isActive() )
    mTimer.start();
}

void NotificationManager::emitPendingNotifications()
{
  if ( mNotifications.isEmpty() )
    return;
  foreach ( const NotificationMessage &msg, mNotifications ) {
    Tracer::self()->signal( "NotificationManager::notify", msg.toString() );
  }

  Q_FOREACH( MessageSource *src, mMessageSources ) {
    src->emitNotification( mNotifications );
  }

  mNotifications.clear();
}

QDBusObjectPath NotificationManager::subscribe( const QString &identifier )
{
  MessageSource *source = mMessageSources.value( identifier );
  if ( source ) {
    // :TODO: Should this really be a warning?
    qDebug() << "Known subscriber" << identifier << "subscribes again";
  } else {
    source = new MessageSource( identifier, this );
    mMessageSources.insert( identifier, source );
  }
  return source->dbusPath();
}

void NotificationManager::unsubscribe( const QString &identifier )
{
  delete mMessageSources.take( identifier );
}

#include "notificationmanager.moc"
<commit_msg>Do not delete the message source immediately in unsubscribe. Use deleteLater()<commit_after>/*
    Copyright (c) 2006 - 2007 Volker Krause <vkrause@kde.org>
    Copyright (c) 2010 Michael Jansen <kde@michael-jansen>

    This library is free software; you can redistribute it and/or modify it
    under the terms of the GNU Library General Public License as published by
    the Free Software Foundation; either version 2 of the License, or (at your
    option) any later version.

    This library is distributed in the hope that it will be useful, but WITHOUT
    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
    License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to the
    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
*/

#include "notificationmanager.h"
#include "notificationmanageradaptor.h"
#include "messagesource.h"
#include "tracer.h"
#include "storage/datastore.h"
#include "../../libs/xdgbasedirs_p.h"

#include <QtCore/QDebug>
#include <QDBusConnection>
#include <QSettings>

using namespace Akonadi;

NotificationManager* NotificationManager::mSelf = 0;

NotificationManager::NotificationManager()
  : QObject( 0 )
{
  NotificationMessage::registerDBusTypes();

  new NotificationManagerAdaptor( this );
  QDBusConnection::sessionBus().registerObject( QLatin1String("/notifications"),
    this, QDBusConnection::ExportAdaptors );
  QDBusConnection::sessionBus().registerObject( QLatin1String("/notifications/debug"),
    this, QDBusConnection::ExportScriptableSlots );

  const QString serverConfigFile = XdgBaseDirs::akonadiServerConfigFile( XdgBaseDirs::ReadWrite );
  QSettings settings( serverConfigFile, QSettings::IniFormat );

  mTimer.setInterval( settings.value( QLatin1String("NotificationManager/Interval"), 50 ).toInt() );
  mTimer.setSingleShot( true );
  connect( &mTimer, SIGNAL(timeout()), SLOT(emitPendingNotifications()) );
}

NotificationManager::~NotificationManager()
{
}

NotificationManager* NotificationManager::self()
{
  if ( !mSelf )
    mSelf = new NotificationManager();

  return mSelf;
}

void NotificationManager::connectNotificationCollector(NotificationCollector* collector)
{
  connect( collector, SIGNAL(notify(Akonadi::NotificationMessage::List)),
           SLOT(slotNotify(Akonadi::NotificationMessage::List)) );
}

void NotificationManager::slotNotify(const Akonadi::NotificationMessage::List &msgs)
{
  foreach ( const NotificationMessage &msg, msgs )
    NotificationMessage::appendAndCompress( mNotifications, msg );
  if ( !mTimer.isActive() )
    mTimer.start();
}

void NotificationManager::emitPendingNotifications()
{
  if ( mNotifications.isEmpty() )
    return;
  foreach ( const NotificationMessage &msg, mNotifications ) {
    Tracer::self()->signal( "NotificationManager::notify", msg.toString() );
  }

  Q_FOREACH( MessageSource *src, mMessageSources ) {
    src->emitNotification( mNotifications );
  }

  mNotifications.clear();
}

QDBusObjectPath NotificationManager::subscribe( const QString &identifier )
{
  MessageSource *source = mMessageSources.value( identifier );
  if ( source ) {
    // :TODO: Should this really be a warning?
    qDebug() << "Known subscriber" << identifier << "subscribes again";
  } else {
    source = new MessageSource( identifier, this );
    mMessageSources.insert( identifier, source );
  }
  return source->dbusPath();
}

void NotificationManager::unsubscribe( const QString &identifier )
{
  MessageSource *source = mMessageSources.take( identifier );
  if ( source ) {
    source->deleteLater();
  } else {
    qDebug() << "Attempt to unsubscribe unknown subscriber" << identifier;
  }
}

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


<commit_before>//------------------------------ cpProjectSettingsExtension.h ------------------------------

#include <qtIgnoreCompilerWarnings.h>

// TinyXml:
#include <tinyxml.h>

// QT:
#include <QtWidgets>

// Infra:
#include <AMDTBaseTools/Include/gtAssert.h>
#include <AMDTApplicationComponents/Include/acFunctions.h>

// AMDTApplicationFramework:
#include <AMDTApplicationFramework/Include/afAppStringConstants.h>
#include <AMDTApplicationFramework/Include/afCSSSettings.h>
#include <AMDTApplicationFramework/src/afUtils.h>

// Local:
#include <AMDTGpuProfiling/gpProjectSettingsExtension.h>
#include <AMDTGpuProfiling/ProfileManager.h>
#include <AMDTGpuProfiling/gpExecutionMode.h>

#define GP_LINE_EDIT_MARGIN 15
#define GP_MAX_FRAME_CAPTURE_WIDTH 30

gpProjectSettingsExtension::gpProjectSettingsExtension() :
    m_pAutomaticCheckBox(nullptr),
    m_pOptionsComboBox(nullptr),
    m_pOptionsEdit(nullptr),
    m_pPortLineEdit(nullptr),
    m_bUpdateSettings(false),
    m_processName(""),
    m_processNumber("1"),
    m_validator(1, 100, this),
    m_pNumberFramesCombo(nullptr),
    m_numFramesToCapture("1")
{
}

gpProjectSettingsExtension::~gpProjectSettingsExtension()
{
}

void gpProjectSettingsExtension::Initialize()
{
    QVBoxLayout* pMainLayout = new QVBoxLayout;

    QLabel* pCaptionAPI = new QLabel(GPU_STR_projectSettingsAPISelection);
    pCaptionAPI->setStyleSheet(AF_STR_captionLabelStyleSheetMain);

    // Add H layout for the sampling interval widgets:
    QHBoxLayout* pHLayout1 = new QHBoxLayout;
    QHBoxLayout* pHLayout2 = new QHBoxLayout;
    QHBoxLayout* pHLayout3 = new QHBoxLayout;

    m_pAutomaticCheckBox = new QCheckBox(GPU_STR_projectSettingsAutomaticConnect);

    m_pOptionsComboBox = new QComboBox();
    m_pOptionsComboBox->addItem(GPU_STR_projectSettingsComboProcessNumberOption);
    m_pOptionsComboBox->addItem(GPU_STR_projectSettingsComboAPIInProcessOption);
    m_pOptionsComboBox->addItem(GPU_STR_projectSettingsComboAPIOption);

    m_pOptionsEdit = new QLineEdit();

    pHLayout1->addWidget(m_pAutomaticCheckBox);
    pHLayout1->addWidget(m_pOptionsComboBox);
    pHLayout1->addWidget(m_pOptionsEdit);

    pHLayout1->addStretch();

    m_pPortLineEdit = new QLineEdit();
    QIntValidator* pValidator = new QIntValidator;
    pValidator->setRange(0, GP_MAX_PORT_NUMBER);
    m_pPortLineEdit->setValidator(pValidator);
    int maxWidth = QFontMetrics(m_pPortLineEdit->font()).boundingRect(QString::number(GP_MAX_PORT_NUMBER)).width() + GP_LINE_EDIT_MARGIN;
    m_pPortLineEdit->setMaximumWidth(maxWidth);
    pHLayout2->addWidget(new QLabel(GPU_STR_projectSettingsServerConnectionPort), 0);
    pHLayout2->addWidget(m_pPortLineEdit, 0);
    pHLayout2->addStretch();

    // Add the number of frames to capture options
    m_pNumberFramesCombo = new QComboBox();
    m_pNumberFramesCombo->addItems(QString("1,2,3").split(","));
    m_pNumberFramesCombo->setMaximumWidth(GP_MAX_FRAME_CAPTURE_WIDTH);
    pHLayout3->addWidget(new QLabel(GPU_STR_projectSettingNumberOfFramesToCapture), 0);
    pHLayout3->addWidget(m_pNumberFramesCombo, 0);
    pHLayout3->addStretch();

    pMainLayout->addWidget(pCaptionAPI);
    pMainLayout->addLayout(pHLayout1);
    pMainLayout->addLayout(pHLayout2);
    pMainLayout->addLayout(pHLayout3);

    pMainLayout->addStretch();

    setLayout(pMainLayout);

    // connecting to the controls events
    bool rc = connect(m_pAutomaticCheckBox, SIGNAL(clicked(bool)), this, SLOT(OnAutomaticClicked(bool)));
    GT_ASSERT(rc);

    rc = connect(m_pOptionsComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(OnConnectionSelected(int)));
    GT_ASSERT(rc);

    rc = connect(m_pOptionsEdit, SIGNAL(textEdited(const QString&)), this, SLOT(OnTextEdited(const QString&)));
    GT_ASSERT(rc);

    rc = connect(m_pNumberFramesCombo, SIGNAL(currentIndexChanged(const QString&)), this, SLOT(OnNumFramesEdited(const QString&)));
    GT_ASSERT(rc);
}

gtString gpProjectSettingsExtension::ExtensionXMLString()
{
    gtString retVal = GPU_STR_projectSettingExtensionName;
    return retVal;
}

gtString gpProjectSettingsExtension::ExtensionTreePathAsString()
{
    gtString retVal = GPU_STR_projectSettingExtensionDisplayName;
    return retVal;
}

bool gpProjectSettingsExtension::GetXMLSettingsString(gtString& projectAsXMLString)
{
    bool retVal = false;

    projectAsXMLString.appendFormattedString(L"<%ls>", ExtensionXMLString().asCharArray());

    gpExecutionMode* pFrameAnalysisManager = ProfileManager::Instance()->GetFrameAnalysisModeManager();
    GT_IF_WITH_ASSERT(pFrameAnalysisManager != nullptr)
    {
        gpProjectSettings& settings = pFrameAnalysisManager->ProjectSettings();
        // Add the flag as a bool flag, the combo selection and the string text to the xml
        afUtils::addFieldToXML(projectAsXMLString, GPU_STR_projectSettingsAutomaticXMLField, settings.m_shouldConnectAutomatically);
        afUtils::addFieldToXML(projectAsXMLString, GPU_STR_projectSettingsConnectionXMLField, settings.m_connection);
        afUtils::addFieldToXML(projectAsXMLString, GPU_STR_projectSettingsPortNumberXMLField, settings.m_serverConnectionPort);
        afUtils::addFieldToXML(projectAsXMLString, GPU_STR_projectSettingsProcessNumberXMLField, acQStringToGTString(settings.m_processNumber));
        afUtils::addFieldToXML(projectAsXMLString, GPU_STR_projectSettingsProcessNameXMLField, acQStringToGTString(settings.m_processName));
        afUtils::addFieldToXML(projectAsXMLString, GPU_STR_projectSettingsNumberFramesToCaptureXMLField, acQStringToGTString(settings.m_numFramesToCapture));
    }
    projectAsXMLString.appendFormattedString(L"</%ls>", ExtensionXMLString().asCharArray());

    retVal = true;

    return retVal;
}

bool gpProjectSettingsExtension::SetSettingsFromXMLString(const gtString& projectAsXMLString)
{
    bool retVal = false;

    gtString enabledCountersStr, samplingIntervalStr;

    TiXmlNode* pTPNode = new TiXmlElement(ExtensionXMLString().asASCIICharArray());
    QString projectAsQtXML = acGTStringToQString(projectAsXMLString);
    QByteArray projectAsQtXMLAsUTF8 = projectAsQtXML.toUtf8();

    pTPNode->Parse(projectAsQtXMLAsUTF8.data(), 0, TIXML_DEFAULT_ENCODING);
    gtString tpNodeTitle;
    tpNodeTitle.fromASCIIString(pTPNode->Value());

    if (ExtensionXMLString() == tpNodeTitle.asCharArray())
    {
        gpExecutionMode* pFrameAnalysisManager = ProfileManager::Instance()->GetFrameAnalysisModeManager();
        GT_IF_WITH_ASSERT(pFrameAnalysisManager != nullptr)
        {
            gpProjectSettings& settings = pFrameAnalysisManager->ProjectSettings();
            int connectionType = 0, portNumber = GP_DEFAULT_PORT;
            gtString connectionNumber;
            gtString connectionName;
            gtString numFramesToCapture;

            afUtils::getFieldFromXML(*pTPNode, GPU_STR_projectSettingsAutomaticXMLField, settings.m_shouldConnectAutomatically);
            afUtils::getFieldFromXML(*pTPNode, GPU_STR_projectSettingsConnectionXMLField, connectionType);
            afUtils::getFieldFromXML(*pTPNode, GPU_STR_projectSettingsPortNumberXMLField, portNumber);
            settings.m_connection = (gpProjectSettings::eConnectionType)connectionType;
            afUtils::getFieldFromXML(*pTPNode, GPU_STR_projectSettingsProcessNumberXMLField, connectionNumber);
            afUtils::getFieldFromXML(*pTPNode, GPU_STR_projectSettingsProcessNameXMLField, connectionName);
            afUtils::getFieldFromXML(*pTPNode, GPU_STR_projectSettingsNumberFramesToCaptureXMLField, numFramesToCapture);

            settings.m_processNumber = acGTStringToQString(connectionNumber);
            settings.m_processName = acGTStringToQString(connectionName);

            settings.m_serverConnectionPort = portNumber;

            settings.m_numFramesToCapture = acGTStringToQString(numFramesToCapture);

            retVal = true;
        }
    }

    // Load settings to the controls:
    retVal = RestoreCurrentSettings() && retVal;

    return retVal;
}

bool gpProjectSettingsExtension::SaveCurrentSettings()
{
    bool retVal = true;

    // Sanity check:
    GT_IF_WITH_ASSERT(m_pAutomaticCheckBox != nullptr && m_pOptionsComboBox != nullptr && m_pOptionsEdit != nullptr && m_pPortLineEdit != nullptr)
    {
        gpExecutionMode* pFrameAnalysisManager = ProfileManager::Instance()->GetFrameAnalysisModeManager();
        GT_IF_WITH_ASSERT(pFrameAnalysisManager != nullptr)
        {
            if (m_bUpdateSettings)
            {
                gpProjectSettings& settings = pFrameAnalysisManager->ProjectSettings();
                settings.m_shouldConnectAutomatically = m_pAutomaticCheckBox->isChecked() ? 1 : 0;
                settings.m_connection = (gpProjectSettings::eConnectionType)m_pOptionsComboBox->currentIndex();
                bool rc = false;
                settings.m_serverConnectionPort = m_pPortLineEdit->text().toInt(&rc);
                GT_ASSERT(rc);
                settings.m_processName = m_processName;
                settings.m_processNumber = m_processNumber;

                settings.m_numFramesToCapture = m_numFramesToCapture;

                m_bUpdateSettings = false;
            }

            retVal = true;
        }
    }

    return retVal;
}

void gpProjectSettingsExtension::RestoreDefaultProjectSettings()
{
    GT_IF_WITH_ASSERT(m_pAutomaticCheckBox != nullptr && m_pOptionsComboBox != nullptr && m_pOptionsEdit != nullptr && m_pNumberFramesCombo != nullptr)
    {
        m_pAutomaticCheckBox->setChecked(true);
        m_pOptionsComboBox->setCurrentIndex(2);
        m_pOptionsEdit->setVisible(false);
        m_pPortLineEdit->setText(QString::number(GP_DEFAULT_PORT));
        m_processName = "";
        m_processNumber = "1";
        m_numFramesToCapture = "1";
        m_pNumberFramesCombo->setCurrentText("1");
        // Set the value in the line edit:
        m_bUpdateSettings = true;
    }
}

bool gpProjectSettingsExtension::AreSettingsValid(gtString& invalidMessageStr)
{
    GT_UNREFERENCED_PARAMETER(invalidMessageStr);

    // No project setting page at this stage for this extension
    bool retVal = true;

    return retVal;
}

bool gpProjectSettingsExtension::RestoreCurrentSettings()
{
    bool retVal = true;

    GT_IF_WITH_ASSERT(m_pAutomaticCheckBox != nullptr && m_pOptionsComboBox != nullptr && m_pOptionsEdit != nullptr)
    {
        gpExecutionMode* pFrameAnalysisManager = ProfileManager::Instance()->GetFrameAnalysisModeManager();
        GT_IF_WITH_ASSERT(pFrameAnalysisManager != nullptr)
        {
            gpProjectSettings& settings = pFrameAnalysisManager->ProjectSettings();
            m_pAutomaticCheckBox->setChecked(settings.m_shouldConnectAutomatically != 0);
            m_pOptionsComboBox->setCurrentIndex(settings.m_connection);
            m_pOptionsEdit->setVisible(true);
            m_processName = settings.m_processName;
            m_processNumber = settings.m_processNumber;

            switch (settings.m_connection)
            {
                case gpProjectSettings::egpProcessConnection:
                    m_pOptionsEdit->setText(settings.m_processNumber);
                    break;

                case gpProjectSettings::egpFirstApiInProcessConnection:
                    m_pOptionsEdit->setText(settings.m_processName);
                    break;

                case gpProjectSettings::egpFirstApiConnection:
                    m_pOptionsEdit->setVisible(false);
                    m_pOptionsEdit->setText("");
                    break;

                default:
                    GT_ASSERT(false);
                    break;
            }

            m_pPortLineEdit->setText(QString::number(settings.m_serverConnectionPort));

            m_numFramesToCapture = settings.m_numFramesToCapture;
            m_pNumberFramesCombo->setCurrentText(m_numFramesToCapture);
        }
    }
    return retVal;
}

void gpProjectSettingsExtension::OnAutomaticClicked(bool)
{
    m_bUpdateSettings = true;
}

void gpProjectSettingsExtension::OnConnectionSelected(int index)
{
    m_bUpdateSettings = true;
    m_pOptionsEdit->setHidden((gpProjectSettings::eConnectionType)index == gpProjectSettings::egpFirstApiConnection);

    if ((gpProjectSettings::eConnectionType)index == gpProjectSettings::egpProcessConnection)
    {
        m_pOptionsEdit->setValidator(&m_validator);
        m_pOptionsEdit->setText(m_processNumber);
    }
    else if ((gpProjectSettings::eConnectionType)index == gpProjectSettings::egpFirstApiInProcessConnection)
    {
        m_pOptionsEdit->setValidator(nullptr);
        m_pOptionsEdit->setText(m_processName);
    }
}

void gpProjectSettingsExtension::OnTextEdited(const QString& text)
{
    m_bUpdateSettings = true;
    GT_IF_WITH_ASSERT(m_pAutomaticCheckBox != nullptr && m_pOptionsComboBox != nullptr && m_pOptionsEdit != nullptr)
    {
        if (m_pOptionsComboBox->currentIndex() == gpProjectSettings::egpProcessConnection)
        {
            m_processNumber = text;
        }
        else if (m_pOptionsComboBox->currentIndex() == gpProjectSettings::egpFirstApiInProcessConnection)
        {
            m_processName = text;
        }
    }
}

void gpProjectSettingsExtension::OnNumFramesEdited(const QString& text)
{
    m_bUpdateSettings = true;
    GT_IF_WITH_ASSERT(m_pNumberFramesCombo != nullptr)
    {
        m_numFramesToCapture = text;
    }
}
<commit_msg>fix width of frame settings<commit_after>//------------------------------ cpProjectSettingsExtension.h ------------------------------

#include <qtIgnoreCompilerWarnings.h>

// TinyXml:
#include <tinyxml.h>

// QT:
#include <QtWidgets>

// Infra:
#include <AMDTBaseTools/Include/gtAssert.h>
#include <AMDTApplicationComponents/Include/acFunctions.h>

// AMDTApplicationFramework:
#include <AMDTApplicationFramework/Include/afAppStringConstants.h>
#include <AMDTApplicationFramework/Include/afCSSSettings.h>
#include <AMDTApplicationFramework/src/afUtils.h>

// Local:
#include <AMDTGpuProfiling/gpProjectSettingsExtension.h>
#include <AMDTGpuProfiling/ProfileManager.h>
#include <AMDTGpuProfiling/gpExecutionMode.h>

#define GP_LINE_EDIT_MARGIN 15
#define GP_MAX_FRAME_CAPTURE_WIDTH 60

gpProjectSettingsExtension::gpProjectSettingsExtension() :
    m_pAutomaticCheckBox(nullptr),
    m_pOptionsComboBox(nullptr),
    m_pOptionsEdit(nullptr),
    m_pPortLineEdit(nullptr),
    m_bUpdateSettings(false),
    m_processName(""),
    m_processNumber("1"),
    m_validator(1, 100, this),
    m_pNumberFramesCombo(nullptr),
    m_numFramesToCapture("1")
{
}

gpProjectSettingsExtension::~gpProjectSettingsExtension()
{
}

void gpProjectSettingsExtension::Initialize()
{
    QVBoxLayout* pMainLayout = new QVBoxLayout;

    QLabel* pCaptionAPI = new QLabel(GPU_STR_projectSettingsAPISelection);
    pCaptionAPI->setStyleSheet(AF_STR_captionLabelStyleSheetMain);

    // Add H layout for the sampling interval widgets:
    QHBoxLayout* pHLayout1 = new QHBoxLayout;
    QHBoxLayout* pHLayout2 = new QHBoxLayout;
    QHBoxLayout* pHLayout3 = new QHBoxLayout;

    m_pAutomaticCheckBox = new QCheckBox(GPU_STR_projectSettingsAutomaticConnect);

    m_pOptionsComboBox = new QComboBox();
    m_pOptionsComboBox->addItem(GPU_STR_projectSettingsComboProcessNumberOption);
    m_pOptionsComboBox->addItem(GPU_STR_projectSettingsComboAPIInProcessOption);
    m_pOptionsComboBox->addItem(GPU_STR_projectSettingsComboAPIOption);

    m_pOptionsEdit = new QLineEdit();

    pHLayout1->addWidget(m_pAutomaticCheckBox);
    pHLayout1->addWidget(m_pOptionsComboBox);
    pHLayout1->addWidget(m_pOptionsEdit);

    pHLayout1->addStretch();

    m_pPortLineEdit = new QLineEdit();
    QIntValidator* pValidator = new QIntValidator;
    pValidator->setRange(0, GP_MAX_PORT_NUMBER);
    m_pPortLineEdit->setValidator(pValidator);
    int maxWidth = QFontMetrics(m_pPortLineEdit->font()).boundingRect(QString::number(GP_MAX_PORT_NUMBER)).width() + GP_LINE_EDIT_MARGIN;
    m_pPortLineEdit->setMaximumWidth(maxWidth);
    pHLayout2->addWidget(new QLabel(GPU_STR_projectSettingsServerConnectionPort), 0);
    pHLayout2->addWidget(m_pPortLineEdit, 0);
    pHLayout2->addStretch();

    // Add the number of frames to capture options
    m_pNumberFramesCombo = new QComboBox();
    m_pNumberFramesCombo->addItems(QString("1,2,3").split(","));
    m_pNumberFramesCombo->setMaximumWidth(GP_MAX_FRAME_CAPTURE_WIDTH);
    pHLayout3->addWidget(new QLabel(GPU_STR_projectSettingNumberOfFramesToCapture), 0);
    pHLayout3->addWidget(m_pNumberFramesCombo, 0);
    pHLayout3->addStretch();

    pMainLayout->addWidget(pCaptionAPI);
    pMainLayout->addLayout(pHLayout1);
    pMainLayout->addLayout(pHLayout2);
    pMainLayout->addLayout(pHLayout3);

    pMainLayout->addStretch();

    setLayout(pMainLayout);

    // connecting to the controls events
    bool rc = connect(m_pAutomaticCheckBox, SIGNAL(clicked(bool)), this, SLOT(OnAutomaticClicked(bool)));
    GT_ASSERT(rc);

    rc = connect(m_pOptionsComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(OnConnectionSelected(int)));
    GT_ASSERT(rc);

    rc = connect(m_pOptionsEdit, SIGNAL(textEdited(const QString&)), this, SLOT(OnTextEdited(const QString&)));
    GT_ASSERT(rc);

    rc = connect(m_pNumberFramesCombo, SIGNAL(currentIndexChanged(const QString&)), this, SLOT(OnNumFramesEdited(const QString&)));
    GT_ASSERT(rc);
}

gtString gpProjectSettingsExtension::ExtensionXMLString()
{
    gtString retVal = GPU_STR_projectSettingExtensionName;
    return retVal;
}

gtString gpProjectSettingsExtension::ExtensionTreePathAsString()
{
    gtString retVal = GPU_STR_projectSettingExtensionDisplayName;
    return retVal;
}

bool gpProjectSettingsExtension::GetXMLSettingsString(gtString& projectAsXMLString)
{
    bool retVal = false;

    projectAsXMLString.appendFormattedString(L"<%ls>", ExtensionXMLString().asCharArray());

    gpExecutionMode* pFrameAnalysisManager = ProfileManager::Instance()->GetFrameAnalysisModeManager();
    GT_IF_WITH_ASSERT(pFrameAnalysisManager != nullptr)
    {
        gpProjectSettings& settings = pFrameAnalysisManager->ProjectSettings();
        // Add the flag as a bool flag, the combo selection and the string text to the xml
        afUtils::addFieldToXML(projectAsXMLString, GPU_STR_projectSettingsAutomaticXMLField, settings.m_shouldConnectAutomatically);
        afUtils::addFieldToXML(projectAsXMLString, GPU_STR_projectSettingsConnectionXMLField, settings.m_connection);
        afUtils::addFieldToXML(projectAsXMLString, GPU_STR_projectSettingsPortNumberXMLField, settings.m_serverConnectionPort);
        afUtils::addFieldToXML(projectAsXMLString, GPU_STR_projectSettingsProcessNumberXMLField, acQStringToGTString(settings.m_processNumber));
        afUtils::addFieldToXML(projectAsXMLString, GPU_STR_projectSettingsProcessNameXMLField, acQStringToGTString(settings.m_processName));
        afUtils::addFieldToXML(projectAsXMLString, GPU_STR_projectSettingsNumberFramesToCaptureXMLField, acQStringToGTString(settings.m_numFramesToCapture));
    }
    projectAsXMLString.appendFormattedString(L"</%ls>", ExtensionXMLString().asCharArray());

    retVal = true;

    return retVal;
}

bool gpProjectSettingsExtension::SetSettingsFromXMLString(const gtString& projectAsXMLString)
{
    bool retVal = false;

    gtString enabledCountersStr, samplingIntervalStr;

    TiXmlNode* pTPNode = new TiXmlElement(ExtensionXMLString().asASCIICharArray());
    QString projectAsQtXML = acGTStringToQString(projectAsXMLString);
    QByteArray projectAsQtXMLAsUTF8 = projectAsQtXML.toUtf8();

    pTPNode->Parse(projectAsQtXMLAsUTF8.data(), 0, TIXML_DEFAULT_ENCODING);
    gtString tpNodeTitle;
    tpNodeTitle.fromASCIIString(pTPNode->Value());

    if (ExtensionXMLString() == tpNodeTitle.asCharArray())
    {
        gpExecutionMode* pFrameAnalysisManager = ProfileManager::Instance()->GetFrameAnalysisModeManager();
        GT_IF_WITH_ASSERT(pFrameAnalysisManager != nullptr)
        {
            gpProjectSettings& settings = pFrameAnalysisManager->ProjectSettings();
            int connectionType = 0, portNumber = GP_DEFAULT_PORT;
            gtString connectionNumber;
            gtString connectionName;
            gtString numFramesToCapture;

            afUtils::getFieldFromXML(*pTPNode, GPU_STR_projectSettingsAutomaticXMLField, settings.m_shouldConnectAutomatically);
            afUtils::getFieldFromXML(*pTPNode, GPU_STR_projectSettingsConnectionXMLField, connectionType);
            afUtils::getFieldFromXML(*pTPNode, GPU_STR_projectSettingsPortNumberXMLField, portNumber);
            settings.m_connection = (gpProjectSettings::eConnectionType)connectionType;
            afUtils::getFieldFromXML(*pTPNode, GPU_STR_projectSettingsProcessNumberXMLField, connectionNumber);
            afUtils::getFieldFromXML(*pTPNode, GPU_STR_projectSettingsProcessNameXMLField, connectionName);
            afUtils::getFieldFromXML(*pTPNode, GPU_STR_projectSettingsNumberFramesToCaptureXMLField, numFramesToCapture);

            settings.m_processNumber = acGTStringToQString(connectionNumber);
            settings.m_processName = acGTStringToQString(connectionName);

            settings.m_serverConnectionPort = portNumber;

            settings.m_numFramesToCapture = acGTStringToQString(numFramesToCapture);

            retVal = true;
        }
    }

    // Load settings to the controls:
    retVal = RestoreCurrentSettings() && retVal;

    return retVal;
}

bool gpProjectSettingsExtension::SaveCurrentSettings()
{
    bool retVal = true;

    // Sanity check:
    GT_IF_WITH_ASSERT(m_pAutomaticCheckBox != nullptr && m_pOptionsComboBox != nullptr && m_pOptionsEdit != nullptr && m_pPortLineEdit != nullptr)
    {
        gpExecutionMode* pFrameAnalysisManager = ProfileManager::Instance()->GetFrameAnalysisModeManager();
        GT_IF_WITH_ASSERT(pFrameAnalysisManager != nullptr)
        {
            if (m_bUpdateSettings)
            {
                gpProjectSettings& settings = pFrameAnalysisManager->ProjectSettings();
                settings.m_shouldConnectAutomatically = m_pAutomaticCheckBox->isChecked() ? 1 : 0;
                settings.m_connection = (gpProjectSettings::eConnectionType)m_pOptionsComboBox->currentIndex();
                bool rc = false;
                settings.m_serverConnectionPort = m_pPortLineEdit->text().toInt(&rc);
                GT_ASSERT(rc);
                settings.m_processName = m_processName;
                settings.m_processNumber = m_processNumber;

                settings.m_numFramesToCapture = m_numFramesToCapture;

                m_bUpdateSettings = false;
            }

            retVal = true;
        }
    }

    return retVal;
}

void gpProjectSettingsExtension::RestoreDefaultProjectSettings()
{
    GT_IF_WITH_ASSERT(m_pAutomaticCheckBox != nullptr && m_pOptionsComboBox != nullptr && m_pOptionsEdit != nullptr && m_pNumberFramesCombo != nullptr)
    {
        m_pAutomaticCheckBox->setChecked(true);
        m_pOptionsComboBox->setCurrentIndex(2);
        m_pOptionsEdit->setVisible(false);
        m_pPortLineEdit->setText(QString::number(GP_DEFAULT_PORT));
        m_processName = "";
        m_processNumber = "1";
        m_numFramesToCapture = "1";
        m_pNumberFramesCombo->setCurrentText("1");
        // Set the value in the line edit:
        m_bUpdateSettings = true;
    }
}

bool gpProjectSettingsExtension::AreSettingsValid(gtString& invalidMessageStr)
{
    GT_UNREFERENCED_PARAMETER(invalidMessageStr);

    // No project setting page at this stage for this extension
    bool retVal = true;

    return retVal;
}

bool gpProjectSettingsExtension::RestoreCurrentSettings()
{
    bool retVal = true;

    GT_IF_WITH_ASSERT(m_pAutomaticCheckBox != nullptr && m_pOptionsComboBox != nullptr && m_pOptionsEdit != nullptr)
    {
        gpExecutionMode* pFrameAnalysisManager = ProfileManager::Instance()->GetFrameAnalysisModeManager();
        GT_IF_WITH_ASSERT(pFrameAnalysisManager != nullptr)
        {
            gpProjectSettings& settings = pFrameAnalysisManager->ProjectSettings();
            m_pAutomaticCheckBox->setChecked(settings.m_shouldConnectAutomatically != 0);
            m_pOptionsComboBox->setCurrentIndex(settings.m_connection);
            m_pOptionsEdit->setVisible(true);
            m_processName = settings.m_processName;
            m_processNumber = settings.m_processNumber;

            switch (settings.m_connection)
            {
                case gpProjectSettings::egpProcessConnection:
                    m_pOptionsEdit->setText(settings.m_processNumber);
                    break;

                case gpProjectSettings::egpFirstApiInProcessConnection:
                    m_pOptionsEdit->setText(settings.m_processName);
                    break;

                case gpProjectSettings::egpFirstApiConnection:
                    m_pOptionsEdit->setVisible(false);
                    m_pOptionsEdit->setText("");
                    break;

                default:
                    GT_ASSERT(false);
                    break;
            }

            m_pPortLineEdit->setText(QString::number(settings.m_serverConnectionPort));

            m_numFramesToCapture = settings.m_numFramesToCapture;
            m_pNumberFramesCombo->setCurrentText(m_numFramesToCapture);
        }
    }
    return retVal;
}

void gpProjectSettingsExtension::OnAutomaticClicked(bool)
{
    m_bUpdateSettings = true;
}

void gpProjectSettingsExtension::OnConnectionSelected(int index)
{
    m_bUpdateSettings = true;
    m_pOptionsEdit->setHidden((gpProjectSettings::eConnectionType)index == gpProjectSettings::egpFirstApiConnection);

    if ((gpProjectSettings::eConnectionType)index == gpProjectSettings::egpProcessConnection)
    {
        m_pOptionsEdit->setValidator(&m_validator);
        m_pOptionsEdit->setText(m_processNumber);
    }
    else if ((gpProjectSettings::eConnectionType)index == gpProjectSettings::egpFirstApiInProcessConnection)
    {
        m_pOptionsEdit->setValidator(nullptr);
        m_pOptionsEdit->setText(m_processName);
    }
}

void gpProjectSettingsExtension::OnTextEdited(const QString& text)
{
    m_bUpdateSettings = true;
    GT_IF_WITH_ASSERT(m_pAutomaticCheckBox != nullptr && m_pOptionsComboBox != nullptr && m_pOptionsEdit != nullptr)
    {
        if (m_pOptionsComboBox->currentIndex() == gpProjectSettings::egpProcessConnection)
        {
            m_processNumber = text;
        }
        else if (m_pOptionsComboBox->currentIndex() == gpProjectSettings::egpFirstApiInProcessConnection)
        {
            m_processName = text;
        }
    }
}

void gpProjectSettingsExtension::OnNumFramesEdited(const QString& text)
{
    m_bUpdateSettings = true;
    GT_IF_WITH_ASSERT(m_pNumberFramesCombo != nullptr)
    {
        m_numFramesToCapture = text;
    }
}
<|endoftext|>


<commit_before>#include "base/logging.h"
#include "input/input_state.h"
#include "ui/screen.h"
#include "ui/ui.h"

Screen::Screen(bool isUiScreen) : screenManager_(0), isUiScreen_(isUiScreen) { }
Screen::~Screen() { }

ScreenManager::ScreenManager() {
	nextScreen_ = 0;
	uiContext_ = 0;
	dialogFinished_ = 0;
}

ScreenManager::~ScreenManager() {
	shutdown();
}

void ScreenManager::switchScreen(Screen *screen) {
	// Note that if a dialog is found, this will be a silent background switch that
	// will only become apparent if the dialog is closed. The previous screen will stick around
	// until that switch.
	// TODO: is this still true?
	if (nextScreen_ != 0) {
		FLOG("WTF? Already had a nextScreen_");
	}
	if (stack_.empty() || screen != stack_.back().screen) {
		nextScreen_ = screen;
		nextScreen_->setScreenManager(this);
	}
}

void ScreenManager::update(InputState &input) {
	if (nextScreen_) {
		ILOG("Screen switch! Top of the stack switches.");
		switchToNext();
	}

	if (stack_.size()) {
		stack_.back().screen->update(input);
	}
}

void ScreenManager::switchToNext()
{
	Layer temp = {0, 0};
	if (!stack_.empty())
	{
		temp = stack_.back();
		stack_.pop_back();
	}
	Layer newLayer = {nextScreen_, 0};
	stack_.push_back(newLayer);
	delete temp.screen;
	nextScreen_ = 0;
}

void ScreenManager::touch(int pointer, float x, float y, double time, TouchEvent event)
{
	if (stack_.size()) {
		stack_.back().screen->touch(pointer, x, y, time, event);
		return;
	}
}

void ScreenManager::render() {
	if (stack_.size()) {
		switch (stack_.back().flags)
		{
		case LAYER_SIDEMENU:
			if (stack_.size() == 1)
			{
				ELOG("Can't have sidemenu over nothing");
				break;
			}
			else
			{
				auto iter = stack_.end();
				iter--;
				iter--;
				Layer backback = *iter;
				UIDisableBegin();
				// Also shift to the right somehow...
				backback.screen->render();
				UIDisableEnd();
				stack_.back().screen->render();
				break;
			}
		default:
			stack_.back().screen->render();
			break;
		}
	} else {
		ELOG("No current screen!");
	}

	processFinishDialog();
}

void ScreenManager::sendMessage(const char *msg, const char *value)
{
	if (stack_.size())
		stack_.back().screen->sendMessage(msg, value);
}

void ScreenManager::deviceLost()
{
	if (stack_.size())
		stack_.back().screen->deviceLost();
	// Dialogs too? Nah, they should only use the standard UI texture anyway.
	// TODO: Change this when it becomes necessary.
}

Screen *ScreenManager::topScreen() {
	if (stack_.size())
		return stack_.back().screen;
	else
		return 0;
}

void ScreenManager::shutdown() {
	for (auto x = stack_.begin(); x != stack_.end(); x++)
	{
		delete x->screen;
	}
	stack_.clear();
	delete nextScreen_;
}

void ScreenManager::push(Screen *screen, int layerFlags) {
	if (nextScreen_ && stack_.empty()) {
		// we're during init, this is OK
		switchToNext();
	}
	screen->setScreenManager(this);
	Layer layer = {screen, layerFlags};
	stack_.push_back(layer);
}

void ScreenManager::pop() {
	if (stack_.size()) {
		delete stack_.back().screen;
		stack_.pop_back();
	} else {
		ELOG("Can't pop when stack empty");
	}
}

void ScreenManager::finishDialog(const Screen *dialog, DialogResult result)
{
	if (dialog != stack_.back().screen)
	{
		ELOG("Wrong dialog being finished!");
		return;
	}
	if (!stack_.size()) {
		ELOG("Must be in a dialog to finishDialog");
		return;
	}
	dialogFinished_ = dialog;
	dialogResult_ = result;
}

void ScreenManager::processFinishDialog()
{
	if (dialogFinished_)
	{
		if (stack_.size()) {
			stack_.pop_back();
		}

		Screen *caller = topScreen();
		caller->dialogFinished(dialogFinished_, dialogResult_);
		delete dialogFinished_;
		dialogFinished_ = 0;
	}
}<commit_msg>Zero nextScreen_ on screenmanager shutdown.<commit_after>#include "base/logging.h"
#include "input/input_state.h"
#include "ui/screen.h"
#include "ui/ui.h"

Screen::Screen(bool isUiScreen) : screenManager_(0), isUiScreen_(isUiScreen) { }
Screen::~Screen() { }

ScreenManager::ScreenManager() {
	nextScreen_ = 0;
	uiContext_ = 0;
	dialogFinished_ = 0;
}

ScreenManager::~ScreenManager() {
	shutdown();
}

void ScreenManager::switchScreen(Screen *screen) {
	// Note that if a dialog is found, this will be a silent background switch that
	// will only become apparent if the dialog is closed. The previous screen will stick around
	// until that switch.
	// TODO: is this still true?
	if (nextScreen_ != 0) {
		FLOG("WTF? Already had a nextScreen_");
	}
	if (stack_.empty() || screen != stack_.back().screen) {
		nextScreen_ = screen;
		nextScreen_->setScreenManager(this);
	}
}

void ScreenManager::update(InputState &input) {
	if (nextScreen_) {
		ILOG("Screen switch! Top of the stack switches.");
		switchToNext();
	}

	if (stack_.size()) {
		stack_.back().screen->update(input);
	}
}

void ScreenManager::switchToNext()
{
	Layer temp = {0, 0};
	if (!stack_.empty())
	{
		temp = stack_.back();
		stack_.pop_back();
	}
	Layer newLayer = {nextScreen_, 0};
	stack_.push_back(newLayer);
	delete temp.screen;
	nextScreen_ = 0;
}

void ScreenManager::touch(int pointer, float x, float y, double time, TouchEvent event)
{
	if (stack_.size()) {
		stack_.back().screen->touch(pointer, x, y, time, event);
		return;
	}
}

void ScreenManager::render() {
	if (stack_.size()) {
		switch (stack_.back().flags)
		{
		case LAYER_SIDEMENU:
			if (stack_.size() == 1)
			{
				ELOG("Can't have sidemenu over nothing");
				break;
			}
			else
			{
				auto iter = stack_.end();
				iter--;
				iter--;
				Layer backback = *iter;
				UIDisableBegin();
				// Also shift to the right somehow...
				backback.screen->render();
				UIDisableEnd();
				stack_.back().screen->render();
				break;
			}
		default:
			stack_.back().screen->render();
			break;
		}
	} else {
		ELOG("No current screen!");
	}

	processFinishDialog();
}

void ScreenManager::sendMessage(const char *msg, const char *value)
{
	if (stack_.size())
		stack_.back().screen->sendMessage(msg, value);
}

void ScreenManager::deviceLost()
{
	if (stack_.size())
		stack_.back().screen->deviceLost();
	// Dialogs too? Nah, they should only use the standard UI texture anyway.
	// TODO: Change this when it becomes necessary.
}

Screen *ScreenManager::topScreen() {
	if (stack_.size())
		return stack_.back().screen;
	else
		return 0;
}

void ScreenManager::shutdown() {
	for (auto x = stack_.begin(); x != stack_.end(); x++)
	{
		delete x->screen;
	}
	stack_.clear();
	delete nextScreen_;
	nextScreen_ = 0;
}

void ScreenManager::push(Screen *screen, int layerFlags) {
	if (nextScreen_ && stack_.empty()) {
		// we're during init, this is OK
		switchToNext();
	}
	screen->setScreenManager(this);
	Layer layer = {screen, layerFlags};
	stack_.push_back(layer);
}

void ScreenManager::pop() {
	if (stack_.size()) {
		delete stack_.back().screen;
		stack_.pop_back();
	} else {
		ELOG("Can't pop when stack empty");
	}
}

void ScreenManager::finishDialog(const Screen *dialog, DialogResult result)
{
	if (dialog != stack_.back().screen)
	{
		ELOG("Wrong dialog being finished!");
		return;
	}
	if (!stack_.size()) {
		ELOG("Must be in a dialog to finishDialog");
		return;
	}
	dialogFinished_ = dialog;
	dialogResult_ = result;
}

void ScreenManager::processFinishDialog()
{
	if (dialogFinished_)
	{
		if (stack_.size()) {
			stack_.pop_back();
		}

		Screen *caller = topScreen();
		caller->dialogFinished(dialogFinished_, dialogResult_);
		delete dialogFinished_;
		dialogFinished_ = 0;
	}
}
<|endoftext|>


<commit_before>#include <node.h>
#include <nan.h>
#include <v8.h>
#include <vector>
#include "mouse.h"
#include "deadbeef_rand.h"
#include "keypress.h"
#include "screen.h"
#include "screengrab.h"
#include "MMBitmap.h"
#include "snprintf.h"
#include "microsleep.h"

using namespace v8;

/*
 __  __
|  \/  | ___  _   _ ___  ___
| |\/| |/ _ \| | | / __|/ _ \
| |  | | (_) | |_| \__ \  __/
|_|  |_|\___/ \__,_|___/\___|

*/

NAN_METHOD(moveMouse)
{
	NanScope();
	if (args.Length() < 2)
	{
		return NanThrowError("Invalid number of arguments.");
	}
	size_t x = args[0]->Int32Value();
	size_t y = args[1]->Int32Value();

	MMPoint point;
	point = MMPointMake(x, y);
	moveMouse(point);
	NanReturnValue(NanNew("1"));
}

NAN_METHOD(moveMouseSmooth)
{
	NanScope();
	if (args.Length() < 2)
	{
		return NanThrowError("Invalid number of arguments.");
	}
	size_t x = args[0]->Int32Value();
	size_t y = args[1]->Int32Value();

	MMPoint point;
	point = MMPointMake(x, y);
	smoothlyMoveMouse(point);
	NanReturnValue(NanNew("1"));
}

NAN_METHOD(getMousePos)
{
	NanScope();

	MMPoint pos = getMousePos();

 	//Return object with .x and .y.
	Local<Object> obj = NanNew<Object>();
	obj->Set(NanNew<String>("x"), NanNew<Number>(pos.x));
	obj->Set(NanNew<String>("y"), NanNew<Number>(pos.y));
	NanReturnValue(obj);
}

NAN_METHOD(mouseClick)
{
	NanScope();

	MMMouseButton button = LEFT_BUTTON;

	if (args.Length() == 1)
	{
		char *b = (*v8::String::Utf8Value(args[0]->ToString()));

		if (strcmp(b, "left") == 0)
		{
			button = LEFT_BUTTON;
		}
		else if (strcmp(b, "right") == 0)
		{
			button = RIGHT_BUTTON;
		}
		else if (strcmp(b, "middle") == 0)
		{
			button = CENTER_BUTTON;
		}
		else
		{
			return NanThrowError("Invalid mouse button specified.");
		}
	}
	else if (args.Length() > 1)
	{
		return NanThrowError("Invalid number of arguments.");
	}

	clickMouse(button);

	NanReturnValue(NanNew("1"));
}

NAN_METHOD(mouseToggle)
{
	NanScope();

	MMMouseButton button = LEFT_BUTTON;
	bool down;

	if (args.Length() > 0)
	{
		const char *d = (*v8::String::Utf8Value(args[0]->ToString()));

		if (strcmp(d, "down") == 0)
		{
			down = true;;
		}
		else if (strcmp(d, "up") == 0)
		{
			down = false;
		}
		else
		{
			return NanThrowError("Invalid mouse button state specified.");
		}
	}

	if (args.Length() == 2)
	{
		char *b = (*v8::String::Utf8Value(args[1]->ToString()));

		if (strcmp(b, "left") == 0)
		{
			button = LEFT_BUTTON;
		}
		else if (strcmp(b, "right") == 0)
		{
			button = RIGHT_BUTTON;
		}
		else if (strcmp(b, "middle") == 0)
		{
			button = CENTER_BUTTON;
		}
		else
		{
			return NanThrowError("Invalid mouse button specified.");
		}
	}
	else if (args.Length() > 2)
	{
		return NanThrowError("Invalid number of arguments.");
	}

	toggleMouse(down, button);

	NanReturnValue(NanNew("1"));
}

/*
 _  __          _                         _
| |/ /___ _   _| |__   ___   __ _ _ __ __| |
| ' // _ \ | | | '_ \ / _ \ / _` | '__/ _` |
| . \  __/ |_| | |_) | (_) | (_| | | | (_| |
|_|\_\___|\__, |_.__/ \___/ \__,_|_|  \__,_|
          |___/
*/

int CheckKeyCodes(char* k, MMKeyCode *key)
{
	if (!key) return -1;

	if (strcmp(k, "alt") == 0)
	{
		*key = K_ALT;
	}
  	else if (strcmp(k, "command") == 0)
	{
		*key = K_META;
	}
  	else if (strcmp(k, "control") == 0)
	{
		*key = K_CONTROL;
	}
  	else if (strcmp(k, "shift") == 0)
	{
		*key = K_SHIFT;
	}
	else if (strcmp(k, "backspace") == 0)
	{
		*key = K_BACKSPACE;
	}
	else if (strcmp(k, "enter") == 0)
	{
		*key = K_RETURN;
	}
	else if (strcmp(k, "tab") == 0)
	{
		*key = K_TAB;
	}
	else if (strcmp(k, "up") == 0)
	{
		*key = K_UP;
	}
	else if (strcmp(k, "down") == 0)
	{
		*key = K_DOWN;
	}
	else if (strcmp(k, "left") == 0)
	{
		*key = K_LEFT;
	}
	else if (strcmp(k, "right") == 0)
	{
		*key = K_RIGHT;
	}
	else if (strcmp(k, "escape") == 0)
	{
		*key = K_ESCAPE;
	}
	else if (strcmp(k, "delete") == 0)
	{
		*key = K_DELETE;
	}
	else if (strcmp(k, "home") == 0)
	{
		*key = K_HOME;
	}
	else if (strcmp(k, "end") == 0)
	{
		*key = K_END;
	}
	else if (strcmp(k, "pageup") == 0)
	{
		*key = K_PAGEUP;
	}
	else if (strcmp(k, "pagedown") == 0)
	{
		*key = K_PAGEDOWN;
	}
	else if (strcmp(k, "space") == 0)
	{
		*key = K_SPACE;
	}
	else if (strlen(k) == 1)
	{
		*key = keyCodeForChar(*k);
	}
	else
	{
		return -2;
	}

	return 0;
}

int CheckKeyFlags(char* f, MMKeyFlags* flags)
{
	if (!flags) return -1;

	if (strcmp(f, "alt") == 0)
	{
    	*flags = MOD_ALT;
  	}
  	else if(strcmp(f, "command") == 0)
	{
    	*flags = MOD_META;
  	}
  	else if(strcmp(f, "control") == 0)
	{
    	*flags = MOD_CONTROL;
  	}
  	else if(strcmp(f, "shift") == 0)
	{
    	*flags = MOD_SHIFT;
	}
	else if(strcmp(f, "none") == 0)
	{
    	*flags = MOD_NONE;
  	}
 	else
	{
    	return -2;
  	}

	return 0;
}

NAN_METHOD(keyTap)
{
	NanScope();

	MMKeyFlags flags = MOD_NONE;
	MMKeyCode key;

  	char *k;
  	char *f;

  	v8::String::Utf8Value fstr(args[1]->ToString());
  	v8::String::Utf8Value kstr(args[0]->ToString());
  	k = *kstr;
  	f = *fstr;

	switch (args.Length())
	{
		case 2:
			break;
		case 1:
			f = NULL;
			break;
		default:
			return NanThrowError("Invalid number of arguments.");
	}

  	if (f)
	{
		switch(CheckKeyFlags(f, &flags))
    	{
			case -1:
				return NanThrowError("Null pointer in key flag.");
        		break;
			case -2:
				return NanThrowError("Invalid key flag specified.");
        		break;
    	}
	}

	switch(CheckKeyCodes(k, &key))
	{
		case -1:
			return NanThrowError("Null pointer in key code.");
			break;
		case -2:
			return NanThrowError("Invalid key code specified.");
			break;
		default:
			tapKeyCode(key, flags);
			microsleep(10);
	}

	NanReturnValue(NanNew("1"));
}

NAN_METHOD(keyToggle)
{
	NanScope();

	MMKeyFlags flags = MOD_NONE;
	MMKeyCode key;

	char *k;
	bool down;
	char *f;

	v8::String::Utf8Value kstr(args[0]->ToString());
	v8::String::Utf8Value fstr(args[2]->ToString());
	down = args[1]->BooleanValue();
	k = *kstr;
	f = *fstr;

	switch (args.Length())
	{
    	case 3:
      		break;
    	case 2:
      		f = NULL;
      		break;
    	default:
      		return NanThrowError("Invalid number of arguments.");
	}

	if (f)
	{
		switch(CheckKeyFlags(f, &flags))
		{
			case -1:
        		return NanThrowError("Null pointer in key flag.");
        		break;
			case -2:
        		return NanThrowError("Invalid key flag specified.");
        		break;
		}
	}

	switch(CheckKeyCodes(k, &key))
	{
		case -1:
    		return NanThrowError("Null pointer in key code.");
			break;
		case -2:
			return NanThrowError("Invalid key code specified.");
			break;
		default:
			toggleKeyCode(key, down, flags);
      		microsleep(10);
	}

	NanReturnValue(NanNew("1"));
}

NAN_METHOD(typeString)
{
	NanScope();

	char *str;
	NanUtf8String string(args[0]);

	str = *string;

	typeString(str);

	NanReturnValue(NanNew("1"));
}

/*
  ____
 / ___|  ___ _ __ ___  ___ _ __
 \___ \ / __| '__/ _ \/ _ \ '_ \
  ___) | (__| | |  __/  __/ | | |
 |____/ \___|_|  \___|\___|_| |_|

*/

NAN_METHOD(getPixelColor)
{
	NanScope();

	MMBitmapRef bitmap;
	MMRGBHex color;

	size_t x = args[0]->Int32Value();
	size_t y = args[1]->Int32Value();

	bitmap = copyMMBitmapFromDisplayInRect(MMRectMake(x, y, 1, 1));

	color = MMRGBHexAtPoint(bitmap, 0, 0);

	char hex [7];

	//Length needs to be 7 because snprintf includes a terminating null.
	//Use %06x to pad hex value with leading 0s.
	snprintf(hex, 7, "%06x", color);

	destroyMMBitmap(bitmap);

	NanReturnValue(NanNew(hex));
}

NAN_METHOD(getScreenSize)
{
	NanScope();

	//Get display size.
	MMSize displaySize = getMainDisplaySize();

	//Create our return object.
	Local<Object> obj = NanNew<Object>();
	obj->Set(NanNew<String>("width"), NanNew<Number>(displaySize.width));
	obj->Set(NanNew<String>("height"), NanNew<Number>(displaySize.height));

	//Return our object with .width and .height.
	NanReturnValue(obj);
}

void init(Handle<Object> target)
{

	target->Set(NanNew<String>("moveMouse"),
		NanNew<FunctionTemplate>(moveMouse)->GetFunction());

	target->Set(NanNew<String>("moveMouseSmooth"),
		NanNew<FunctionTemplate>(moveMouseSmooth)->GetFunction());

	target->Set(NanNew<String>("getMousePos"),
		NanNew<FunctionTemplate>(getMousePos)->GetFunction());

	target->Set(NanNew<String>("mouseClick"),
		NanNew<FunctionTemplate>(mouseClick)->GetFunction());

	target->Set(NanNew<String>("mouseToggle"),
		NanNew<FunctionTemplate>(mouseToggle)->GetFunction());

	target->Set(NanNew<String>("keyTap"),
		NanNew<FunctionTemplate>(keyTap)->GetFunction());

	target->Set(NanNew<String>("keyToggle"),
		NanNew<FunctionTemplate>(keyToggle)->GetFunction());

	target->Set(NanNew<String>("typeString"),
		NanNew<FunctionTemplate>(typeString)->GetFunction());

	target->Set(NanNew<String>("getPixelColor"),
		NanNew<FunctionTemplate>(getPixelColor)->GetFunction());

	target->Set(NanNew<String>("getScreenSize"),
		NanNew<FunctionTemplate>(getScreenSize)->GetFunction());

}

NODE_MODULE(robotjs, init)
<commit_msg>Sleep after mouse events. #14<commit_after>#include <node.h>
#include <nan.h>
#include <v8.h>
#include <vector>
#include "mouse.h"
#include "deadbeef_rand.h"
#include "keypress.h"
#include "screen.h"
#include "screengrab.h"
#include "MMBitmap.h"
#include "snprintf.h"
#include "microsleep.h"

using namespace v8;

/*
 __  __
|  \/  | ___  _   _ ___  ___
| |\/| |/ _ \| | | / __|/ _ \
| |  | | (_) | |_| \__ \  __/
|_|  |_|\___/ \__,_|___/\___|

*/

NAN_METHOD(moveMouse)
{
	NanScope();
	if (args.Length() < 2)
	{
		return NanThrowError("Invalid number of arguments.");
	}
	size_t x = args[0]->Int32Value();
	size_t y = args[1]->Int32Value();

	MMPoint point;
	point = MMPointMake(x, y);
	moveMouse(point);
	microsleep(10);

	NanReturnValue(NanNew("1"));
}

NAN_METHOD(moveMouseSmooth)
{
	NanScope();
	if (args.Length() < 2)
	{
		return NanThrowError("Invalid number of arguments.");
	}
	size_t x = args[0]->Int32Value();
	size_t y = args[1]->Int32Value();

	MMPoint point;
	point = MMPointMake(x, y);
	smoothlyMoveMouse(point);
	microsleep(10);

	NanReturnValue(NanNew("1"));
}

NAN_METHOD(getMousePos)
{
	NanScope();

	MMPoint pos = getMousePos();

 	//Return object with .x and .y.
	Local<Object> obj = NanNew<Object>();
	obj->Set(NanNew<String>("x"), NanNew<Number>(pos.x));
	obj->Set(NanNew<String>("y"), NanNew<Number>(pos.y));
	NanReturnValue(obj);
}

NAN_METHOD(mouseClick)
{
	NanScope();

	MMMouseButton button = LEFT_BUTTON;

	if (args.Length() == 1)
	{
		char *b = (*v8::String::Utf8Value(args[0]->ToString()));

		if (strcmp(b, "left") == 0)
		{
			button = LEFT_BUTTON;
		}
		else if (strcmp(b, "right") == 0)
		{
			button = RIGHT_BUTTON;
		}
		else if (strcmp(b, "middle") == 0)
		{
			button = CENTER_BUTTON;
		}
		else
		{
			return NanThrowError("Invalid mouse button specified.");
		}
	}
	else if (args.Length() > 1)
	{
		return NanThrowError("Invalid number of arguments.");
	}

	clickMouse(button);
	microsleep(10);

	NanReturnValue(NanNew("1"));
}

NAN_METHOD(mouseToggle)
{
	NanScope();

	MMMouseButton button = LEFT_BUTTON;
	bool down;

	if (args.Length() > 0)
	{
		const char *d = (*v8::String::Utf8Value(args[0]->ToString()));

		if (strcmp(d, "down") == 0)
		{
			down = true;;
		}
		else if (strcmp(d, "up") == 0)
		{
			down = false;
		}
		else
		{
			return NanThrowError("Invalid mouse button state specified.");
		}
	}

	if (args.Length() == 2)
	{
		char *b = (*v8::String::Utf8Value(args[1]->ToString()));

		if (strcmp(b, "left") == 0)
		{
			button = LEFT_BUTTON;
		}
		else if (strcmp(b, "right") == 0)
		{
			button = RIGHT_BUTTON;
		}
		else if (strcmp(b, "middle") == 0)
		{
			button = CENTER_BUTTON;
		}
		else
		{
			return NanThrowError("Invalid mouse button specified.");
		}
	}
	else if (args.Length() > 2)
	{
		return NanThrowError("Invalid number of arguments.");
	}

	toggleMouse(down, button);
	microsleep(10);

	NanReturnValue(NanNew("1"));
}

/*
 _  __          _                         _
| |/ /___ _   _| |__   ___   __ _ _ __ __| |
| ' // _ \ | | | '_ \ / _ \ / _` | '__/ _` |
| . \  __/ |_| | |_) | (_) | (_| | | | (_| |
|_|\_\___|\__, |_.__/ \___/ \__,_|_|  \__,_|
          |___/
*/

int CheckKeyCodes(char* k, MMKeyCode *key)
{
	if (!key) return -1;

	if (strcmp(k, "alt") == 0)
	{
		*key = K_ALT;
	}
  	else if (strcmp(k, "command") == 0)
	{
		*key = K_META;
	}
  	else if (strcmp(k, "control") == 0)
	{
		*key = K_CONTROL;
	}
  	else if (strcmp(k, "shift") == 0)
	{
		*key = K_SHIFT;
	}
	else if (strcmp(k, "backspace") == 0)
	{
		*key = K_BACKSPACE;
	}
	else if (strcmp(k, "enter") == 0)
	{
		*key = K_RETURN;
	}
	else if (strcmp(k, "tab") == 0)
	{
		*key = K_TAB;
	}
	else if (strcmp(k, "up") == 0)
	{
		*key = K_UP;
	}
	else if (strcmp(k, "down") == 0)
	{
		*key = K_DOWN;
	}
	else if (strcmp(k, "left") == 0)
	{
		*key = K_LEFT;
	}
	else if (strcmp(k, "right") == 0)
	{
		*key = K_RIGHT;
	}
	else if (strcmp(k, "escape") == 0)
	{
		*key = K_ESCAPE;
	}
	else if (strcmp(k, "delete") == 0)
	{
		*key = K_DELETE;
	}
	else if (strcmp(k, "home") == 0)
	{
		*key = K_HOME;
	}
	else if (strcmp(k, "end") == 0)
	{
		*key = K_END;
	}
	else if (strcmp(k, "pageup") == 0)
	{
		*key = K_PAGEUP;
	}
	else if (strcmp(k, "pagedown") == 0)
	{
		*key = K_PAGEDOWN;
	}
	else if (strcmp(k, "space") == 0)
	{
		*key = K_SPACE;
	}
	else if (strlen(k) == 1)
	{
		*key = keyCodeForChar(*k);
	}
	else
	{
		return -2;
	}

	return 0;
}

int CheckKeyFlags(char* f, MMKeyFlags* flags)
{
	if (!flags) return -1;

	if (strcmp(f, "alt") == 0)
	{
    	*flags = MOD_ALT;
  	}
  	else if(strcmp(f, "command") == 0)
	{
    	*flags = MOD_META;
  	}
  	else if(strcmp(f, "control") == 0)
	{
    	*flags = MOD_CONTROL;
  	}
  	else if(strcmp(f, "shift") == 0)
	{
    	*flags = MOD_SHIFT;
	}
	else if(strcmp(f, "none") == 0)
	{
    	*flags = MOD_NONE;
  	}
 	else
	{
    	return -2;
  	}

	return 0;
}

NAN_METHOD(keyTap)
{
	NanScope();

	MMKeyFlags flags = MOD_NONE;
	MMKeyCode key;

  	char *k;
  	char *f;

  	v8::String::Utf8Value fstr(args[1]->ToString());
  	v8::String::Utf8Value kstr(args[0]->ToString());
  	k = *kstr;
  	f = *fstr;

	switch (args.Length())
	{
		case 2:
			break;
		case 1:
			f = NULL;
			break;
		default:
			return NanThrowError("Invalid number of arguments.");
	}

  	if (f)
	{
		switch(CheckKeyFlags(f, &flags))
    	{
			case -1:
				return NanThrowError("Null pointer in key flag.");
        		break;
			case -2:
				return NanThrowError("Invalid key flag specified.");
        		break;
    	}
	}

	switch(CheckKeyCodes(k, &key))
	{
		case -1:
			return NanThrowError("Null pointer in key code.");
			break;
		case -2:
			return NanThrowError("Invalid key code specified.");
			break;
		default:
			tapKeyCode(key, flags);
			microsleep(10);
	}

	NanReturnValue(NanNew("1"));
}

NAN_METHOD(keyToggle)
{
	NanScope();

	MMKeyFlags flags = MOD_NONE;
	MMKeyCode key;

	char *k;
	bool down;
	char *f;

	v8::String::Utf8Value kstr(args[0]->ToString());
	v8::String::Utf8Value fstr(args[2]->ToString());
	down = args[1]->BooleanValue();
	k = *kstr;
	f = *fstr;

	switch (args.Length())
	{
    	case 3:
      		break;
    	case 2:
      		f = NULL;
      		break;
    	default:
      		return NanThrowError("Invalid number of arguments.");
	}

	if (f)
	{
		switch(CheckKeyFlags(f, &flags))
		{
			case -1:
        		return NanThrowError("Null pointer in key flag.");
        		break;
			case -2:
        		return NanThrowError("Invalid key flag specified.");
        		break;
		}
	}

	switch(CheckKeyCodes(k, &key))
	{
		case -1:
    		return NanThrowError("Null pointer in key code.");
			break;
		case -2:
			return NanThrowError("Invalid key code specified.");
			break;
		default:
			toggleKeyCode(key, down, flags);
      		microsleep(10);
	}

	NanReturnValue(NanNew("1"));
}

NAN_METHOD(typeString)
{
	NanScope();

	char *str;
	NanUtf8String string(args[0]);

	str = *string;

	typeString(str);

	NanReturnValue(NanNew("1"));
}

/*
  ____
 / ___|  ___ _ __ ___  ___ _ __
 \___ \ / __| '__/ _ \/ _ \ '_ \
  ___) | (__| | |  __/  __/ | | |
 |____/ \___|_|  \___|\___|_| |_|

*/

NAN_METHOD(getPixelColor)
{
	NanScope();

	MMBitmapRef bitmap;
	MMRGBHex color;

	size_t x = args[0]->Int32Value();
	size_t y = args[1]->Int32Value();

	bitmap = copyMMBitmapFromDisplayInRect(MMRectMake(x, y, 1, 1));

	color = MMRGBHexAtPoint(bitmap, 0, 0);

	char hex [7];

	//Length needs to be 7 because snprintf includes a terminating null.
	//Use %06x to pad hex value with leading 0s.
	snprintf(hex, 7, "%06x", color);

	destroyMMBitmap(bitmap);

	NanReturnValue(NanNew(hex));
}

NAN_METHOD(getScreenSize)
{
	NanScope();

	//Get display size.
	MMSize displaySize = getMainDisplaySize();

	//Create our return object.
	Local<Object> obj = NanNew<Object>();
	obj->Set(NanNew<String>("width"), NanNew<Number>(displaySize.width));
	obj->Set(NanNew<String>("height"), NanNew<Number>(displaySize.height));

	//Return our object with .width and .height.
	NanReturnValue(obj);
}

void init(Handle<Object> target)
{

	target->Set(NanNew<String>("moveMouse"),
		NanNew<FunctionTemplate>(moveMouse)->GetFunction());

	target->Set(NanNew<String>("moveMouseSmooth"),
		NanNew<FunctionTemplate>(moveMouseSmooth)->GetFunction());

	target->Set(NanNew<String>("getMousePos"),
		NanNew<FunctionTemplate>(getMousePos)->GetFunction());

	target->Set(NanNew<String>("mouseClick"),
		NanNew<FunctionTemplate>(mouseClick)->GetFunction());

	target->Set(NanNew<String>("mouseToggle"),
		NanNew<FunctionTemplate>(mouseToggle)->GetFunction());

	target->Set(NanNew<String>("keyTap"),
		NanNew<FunctionTemplate>(keyTap)->GetFunction());

	target->Set(NanNew<String>("keyToggle"),
		NanNew<FunctionTemplate>(keyToggle)->GetFunction());

	target->Set(NanNew<String>("typeString"),
		NanNew<FunctionTemplate>(typeString)->GetFunction());

	target->Set(NanNew<String>("getPixelColor"),
		NanNew<FunctionTemplate>(getPixelColor)->GetFunction());

	target->Set(NanNew<String>("getScreenSize"),
		NanNew<FunctionTemplate>(getScreenSize)->GetFunction());

}

NODE_MODULE(robotjs, init)
<|endoftext|>