<commit_before>/*
 *  Copyright 2007-2015 The OpenMx Project
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

#include <ctype.h>
#define R_NO_REMAP
#include <R.h>
#include <Rinternals.h>

#include "omxState.h"
#include "omxNPSOLSpecific.h"
#include "omxMatrix.h"
#include "glue.h"
#include "omxImportFrontendState.h"
#include "Compute.h"
#include "npsolswitch.h"
#include "omxBuffer.h"

template <typename T1>
void GradientOptimizerContext::allConstraintsFun(Eigen::MatrixBase<T1> &constraintOut)
{
	omxState *globalState = fc->state;
	int l=0;
	for(int j = 0; j < (int) globalState->conList.size(); j++) {
		omxConstraint &cs = *globalState->conList[j];
		cs.refreshAndGrab(fc, omxConstraint::LESS_THAN, &constraintOut(l));
		l += cs.size;
	}
}

#ifdef  __cplusplus
extern "C" {
#endif

/* NPSOL-related functions */
extern void F77_SUB(npsol)(int *n, int *nclin, int *ncnln, int *ldA, int *ldJ, int *ldR, double *A,
                            double *bl, double *bu, void* funcon, void* funobj, int *inform, int *iter,
                            int *istate, double *c, double *cJac, double *clambda, double *f, double *g, double *R,
                            double *x, int *iw, int *leniw, double *w, int *lenw);
extern void F77_SUB(npoptn)(char* string, int Rf_length);

#ifdef  __cplusplus
}
#endif

#if HAS_NPSOL

static struct GradientOptimizerContext *NPSOL_GOpt;

void F77_SUB(npsolObjectiveFunction)(int* mode, int* n, double* x,
				     double* f, double* g, int* nstate)
{
	if (x != NPSOL_GOpt->fc->est) return;  // this is strange but necessary
	double fit = NPSOL_GOpt->recordFit(x, mode);
	*f = fit;
}

/* (Non)Linear Constraint Functions */
void F77_SUB(npsolConstraintFunction)
	(	int *mode, int *ncnln, int *n,
		int *ldJ, int *needc, double *x,
		double *c, double *cJac, int *nstate)
{
	if(*mode==1) return;

	// "Note that if there are any nonlinear constraints then the
	// first call to CONFUN will precede the first call to
	// OBJFUN." Hence, we must copyParamToModel here.

	NPSOL_GOpt->fc->copyParamToModel();

	Eigen::Map< Eigen::VectorXd > cE(c, *ncnln);
	NPSOL_GOpt->allConstraintsFun(cE);
}

static void omxNPSOL1(double *est, GradientOptimizerContext &rf, int equality, int inequality)
{
	rf.optName = "NPSOL";
	rf.setupAllBounds();
	if (std::isfinite(rf.ControlTolerance)) {
		std::string opt = string_snprintf("Optimality tolerance %.8g", rf.ControlTolerance);
		F77_CALL(npoptn)((char*) opt.c_str(), opt.size());
	}
	if (rf.warmStart) {
		std::string opt = string_snprintf("Warm start");
		F77_CALL(npoptn)((char*) opt.c_str(), opt.size());
	} else {
		std::string opt = string_snprintf("Cold start");
		F77_CALL(npoptn)((char*) opt.c_str(), opt.size());
	}

	// Will fail if we re-enter after an exception
	//if (NPSOL_fitMatrix) Rf_error("NPSOL is not reentrant");
	FitContext *fc = rf.fc;
	NPSOL_GOpt = &rf;

    int nclin = 0;
    int nlinwid = std::max(1, nclin);
    int ncnln = equality + inequality;
    int nlnwid = std::max(1, ncnln);

	if (ncnln == 0) {
		// ensure we never move to a worse point
		int mode = 0;
		double fit = rf.recordFit(fc->est, &mode);
		if (!std::isfinite(fit)) {
			rf.informOut = INFORM_STARTING_VALUES_INFEASIBLE;
			NPSOL_GOpt = NULL;
			return;
		}
		if (mode == -1) {
			NPSOL_GOpt = NULL;
			return;
		}
	}

	int n = int(fc->numParam);

        int nctotl = n + nlinwid + nlnwid;

        int leniw = 3 * n + nclin + 2 * ncnln;
        int lenw = 2 * n * n + n * nclin + 2 * n * ncnln + 20 * n + 11 * nclin + 21 * ncnln;

        int ldA = nlinwid;          // NPSOL specifies this should be either 1 or nclin, whichever is greater
        int ldJ = nlnwid;           // NPSOL specifies this should be either 1 or nclin, whichever is greater
        int ldR = n;                // TODO: Test alternative versions of the size of R to see what's best.

    /* Allocate arrays */
	Eigen::ArrayXXd A(ldA, n);  // maybe transposed?
	Eigen::VectorXd c(nlnwid);
	Eigen::MatrixXd cJac(ldJ, n); // maybe transposed?
	Eigen::VectorXd clambda(nctotl);
	Eigen::VectorXd w(lenw);
	Eigen::VectorXi istate(nctotl);
	Eigen::VectorXi iw(leniw);

	if (rf.warmStart) {
		istate.setZero();
		clambda.setZero();
	}

    /*  F77_CALL(npsol)
        (   int *n,                 -- Number of variables
            int *nclin,             -- Number of linear constraints
            int *ncnln,             -- Number of nonlinear constraints
            int *ldA,               -- Row dimension of A (Linear Constraints)
            int *ldJ,               -- Row dimension of cJac (Jacobian)
            int *ldR,               -- Row dimension of R (Hessian)
            double *A,              -- Linear Constraints Array A (in Column-major order)
            double *bl,             -- Lower Bounds Array (at least n + nclin + ncnln long)
            double *bu,             -- Upper Bounds Array (at least n + nclin + ncnln long)
            function funcon,        -- Nonlinear constraint function
            function funobj,        -- Objective function
            int *inform,            -- Used to report state.  Need not be initialized.
            int *iter,              -- Used to report number of major iterations performed.  Need not be initialized.
            int *istate,            -- Initial State.  Need not be initialized unless using Warm Start.
            double *c,              -- Array of length ncnln.  Need not be initialized.  Reports nonlinear constraints at final iteration.
            double *cJac,           -- Array of Row-length ldJ.  Unused if ncnln = 0. Generally need not be initialized.
            double *clambda,        -- Array of length n+nclin+ncnln.  Need not be initialized unless using Warm Start. Reports final QP multipliers.
            double *f,              -- Used to report final objective value.  Need not be initialized.
            double *g,              -- Array of length n. Used to report final objective gradient.  Need not be initialized.
            double *R,              -- Array of length ldR.  Need not be intialized unless using Warm Start.
            double *x,              -- Array of length n.  Contains initial solution estimate.
            int *iw,                -- Array of length leniw. Need not be initialized.  Provides workspace.
            int *leniw,             -- Length of iw.  Must be at least 3n + nclin + ncnln.
            double *w,              -- Array of length lenw. Need not be initialized.  Provides workspace.
            int *lenw               -- Length of w.  Must be at least 2n^2 + n*nclin + 2*n*ncnln + 20*n + 11*nclin +21*ncnln
        )

        bl, bu, istate, and clambda are all length n+nclin+ncnln.
            First n elements refer to the vars, in order.
            Next nclin elements refer to bounds on Ax
            Last ncnln elements refer to bounds on c(x)

        All arrays must be in column-major order.
        */

	fc->grad.resize(n);
	rf.hessOut.resize(n, n);
	double fit; // do not pass in &fc->fit
	int iter_out; // ignored
	F77_CALL(npsol)(&n, &nclin, &ncnln, &ldA, &ldJ, &ldR, A.data(),
			rf.solLB.data(), rf.solUB.data(), (void*)F77_SUB(npsolConstraintFunction),
			(void*) F77_SUB(npsolObjectiveFunction), &rf.informOut, &iter_out,
			istate.data(), c.data(), cJac.data(),
			clambda.data(), &fit, fc->grad.data(), rf.hessOut.data(), fc->est, iw.data(), &leniw, w.data(), &lenw);

	// NPSOL can return the wrong fit and estimates, but hard to
	// know what to do if there are constraints.
	if (rf.bestEst.size() && ncnln == 0) {
		fc->fit = rf.bestFit;
		memcpy(fc->est, rf.bestEst.data(), sizeof(double) * fc->numParam);
	}

    NPSOL_GOpt = NULL;
}

void omxNPSOL(double *est, GradientOptimizerContext &rf)
{
	FitContext *fc = rf.fc;
	Eigen::Map< Eigen::ArrayXd > Est(est, fc->numParam);
	Eigen::ArrayXd startingPoint = Est;

	omxState *globalState = fc->state;
	int equality, inequality;
	globalState->countNonlinearConstraints(equality, inequality);

	omxNPSOL1(est, rf, equality, inequality);

	if (equality + inequality == 0) return;

	int retry = 6;
	double best = std::numeric_limits<double>::max();
	while (--retry >= 0) {
		fc->copyParamToModel();

		Eigen::VectorXd cE(equality + inequality);
		rf.allConstraintsFun(cE);

		double norm = cE.norm();
		if (rf.verbose >= 1) {
			mxLog("NPSOL: feasibility constraints at %f; retry %d",
			      norm, 1+retry);
		}
		if (norm >= best) {
			// NPSOL can jump off a cliff and get lost.
			// Try to move back toward a more feasible region.
			Est = (Est + startingPoint) / 2;
		} else {
			best = norm;
		}
		if (!(cE.array().abs() < Global->feasibilityTolerance).all()) {
			omxNPSOL1(est, rf, equality, inequality);
		} else {
			break;
		}
	}
}

void omxSetNPSOLOpts(SEXP options)
{
    omxManageProtectInsanity mpi;

    static const char *whitelist[] = {
        "Central Difference Interval",
        "Crash Tolerance",
        "Derivative level",
        "Difference interval",
        "Feasibility tolerance",
        "Function precision",
        "Hessian",
        "Infinite bound size",
        "Infinite step size",
        "Iteration limit",
        "Iters",
        "Line search tolerance",
        "Major iteration limit",
        "Major iterations",
        "Print level",
        "Print file",
        "Minor iteration limit",
        "Minor print level",
        "Nolist",
        "Optimality tolerance",
        "Step limit",
        "Summary file",
        "Verify level",
        0
    };

    const int opBufLen = 250;
    char optionCharArray[opBufLen];
    int numOptions = Rf_length(options);
    SEXP optionNames;
    Rf_protect(optionNames = Rf_getAttrib(options, R_NamesSymbol));
    for(int i = 0; i < numOptions; i++) {
        const char *nextOptionName = CHAR(STRING_ELT(optionNames, i));
        const char *nextOptionValue = CHAR(Rf_asChar(VECTOR_ELT(options, i)));
        bool ok=false;
        for (int wx=0; whitelist[wx]; ++wx) {
            if (matchCaseInsensitive(nextOptionName, whitelist[wx])) {
                ok=true;
                break;
            }
        }
        if (!ok) continue;
        snprintf(optionCharArray, opBufLen, "%s %s", nextOptionName, nextOptionValue);
        F77_CALL(npoptn)(optionCharArray, strlen(optionCharArray));
        if(OMX_DEBUG) { mxLog("Option %s ", optionCharArray);}
    }
}
#endif
<commit_msg>Feasibility tolerance seems to affect unconstrained problems<commit_after>/*
 *  Copyright 2007-2015 The OpenMx Project
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *   Unless required by applicable law or agreed to in writing, software
 *   distributed under the License is distributed on an "AS IS" BASIS,
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

#include <ctype.h>
#define R_NO_REMAP
#include <R.h>
#include <Rinternals.h>

#include "omxState.h"
#include "omxNPSOLSpecific.h"
#include "omxMatrix.h"
#include "glue.h"
#include "omxImportFrontendState.h"
#include "Compute.h"
#include "npsolswitch.h"
#include "omxBuffer.h"

template <typename T1>
void GradientOptimizerContext::allConstraintsFun(Eigen::MatrixBase<T1> &constraintOut)
{
	omxState *globalState = fc->state;
	int l=0;
	for(int j = 0; j < (int) globalState->conList.size(); j++) {
		omxConstraint &cs = *globalState->conList[j];
		cs.refreshAndGrab(fc, omxConstraint::LESS_THAN, &constraintOut(l));
		l += cs.size;
	}
}

#ifdef  __cplusplus
extern "C" {
#endif

/* NPSOL-related functions */
extern void F77_SUB(npsol)(int *n, int *nclin, int *ncnln, int *ldA, int *ldJ, int *ldR, double *A,
                            double *bl, double *bu, void* funcon, void* funobj, int *inform, int *iter,
                            int *istate, double *c, double *cJac, double *clambda, double *f, double *g, double *R,
                            double *x, int *iw, int *leniw, double *w, int *lenw);
extern void F77_SUB(npoptn)(char* string, int Rf_length);

#ifdef  __cplusplus
}
#endif

#if HAS_NPSOL

static struct GradientOptimizerContext *NPSOL_GOpt;

void F77_SUB(npsolObjectiveFunction)(int* mode, int* n, double* x,
				     double* f, double* g, int* nstate)
{
	if (x != NPSOL_GOpt->fc->est) return;  // this is strange but necessary
	double fit = NPSOL_GOpt->recordFit(x, mode);
	*f = fit;
}

/* (Non)Linear Constraint Functions */
void F77_SUB(npsolConstraintFunction)
	(	int *mode, int *ncnln, int *n,
		int *ldJ, int *needc, double *x,
		double *c, double *cJac, int *nstate)
{
	if(*mode==1) return;

	// "Note that if there are any nonlinear constraints then the
	// first call to CONFUN will precede the first call to
	// OBJFUN." Hence, we must copyParamToModel here.

	NPSOL_GOpt->fc->copyParamToModel();

	Eigen::Map< Eigen::VectorXd > cE(c, *ncnln);
	NPSOL_GOpt->allConstraintsFun(cE);
}

static void omxNPSOL1(double *est, GradientOptimizerContext &rf, int equality, int inequality)
{
	rf.optName = "NPSOL";
	rf.setupAllBounds();
	{
		double ft = (equality+inequality)? Global->feasibilityTolerance : 1e-5;
		std::string opt = string_snprintf("Feasibility tolerance %.8g", ft);
		F77_CALL(npoptn)((char*) opt.c_str(), opt.size());
	}
	if (std::isfinite(rf.ControlTolerance)) {
		std::string opt = string_snprintf("Optimality tolerance %.8g", rf.ControlTolerance);
		F77_CALL(npoptn)((char*) opt.c_str(), opt.size());
	}
	if (rf.warmStart) {
		std::string opt = string_snprintf("Warm start");
		F77_CALL(npoptn)((char*) opt.c_str(), opt.size());
	} else {
		std::string opt = string_snprintf("Cold start");
		F77_CALL(npoptn)((char*) opt.c_str(), opt.size());
	}

	// Will fail if we re-enter after an exception
	//if (NPSOL_fitMatrix) Rf_error("NPSOL is not reentrant");
	FitContext *fc = rf.fc;
	NPSOL_GOpt = &rf;

    int nclin = 0;
    int nlinwid = std::max(1, nclin);
    int ncnln = equality + inequality;
    int nlnwid = std::max(1, ncnln);

	if (ncnln == 0) {
		// ensure we never move to a worse point
		int mode = 0;
		double fit = rf.recordFit(fc->est, &mode);
		if (!std::isfinite(fit)) {
			rf.informOut = INFORM_STARTING_VALUES_INFEASIBLE;
			NPSOL_GOpt = NULL;
			return;
		}
		if (mode == -1) {
			NPSOL_GOpt = NULL;
			return;
		}
	}

	int n = int(fc->numParam);

        int nctotl = n + nlinwid + nlnwid;

        int leniw = 3 * n + nclin + 2 * ncnln;
        int lenw = 2 * n * n + n * nclin + 2 * n * ncnln + 20 * n + 11 * nclin + 21 * ncnln;

        int ldA = nlinwid;          // NPSOL specifies this should be either 1 or nclin, whichever is greater
        int ldJ = nlnwid;           // NPSOL specifies this should be either 1 or nclin, whichever is greater
        int ldR = n;                // TODO: Test alternative versions of the size of R to see what's best.

    /* Allocate arrays */
	Eigen::ArrayXXd A(ldA, n);  // maybe transposed?
	Eigen::VectorXd c(nlnwid);
	Eigen::MatrixXd cJac(ldJ, n); // maybe transposed?
	Eigen::VectorXd clambda(nctotl);
	Eigen::VectorXd w(lenw);
	Eigen::VectorXi istate(nctotl);
	Eigen::VectorXi iw(leniw);

	if (rf.warmStart) {
		istate.setZero();
		clambda.setZero();
	}

    /*  F77_CALL(npsol)
        (   int *n,                 -- Number of variables
            int *nclin,             -- Number of linear constraints
            int *ncnln,             -- Number of nonlinear constraints
            int *ldA,               -- Row dimension of A (Linear Constraints)
            int *ldJ,               -- Row dimension of cJac (Jacobian)
            int *ldR,               -- Row dimension of R (Hessian)
            double *A,              -- Linear Constraints Array A (in Column-major order)
            double *bl,             -- Lower Bounds Array (at least n + nclin + ncnln long)
            double *bu,             -- Upper Bounds Array (at least n + nclin + ncnln long)
            function funcon,        -- Nonlinear constraint function
            function funobj,        -- Objective function
            int *inform,            -- Used to report state.  Need not be initialized.
            int *iter,              -- Used to report number of major iterations performed.  Need not be initialized.
            int *istate,            -- Initial State.  Need not be initialized unless using Warm Start.
            double *c,              -- Array of length ncnln.  Need not be initialized.  Reports nonlinear constraints at final iteration.
            double *cJac,           -- Array of Row-length ldJ.  Unused if ncnln = 0. Generally need not be initialized.
            double *clambda,        -- Array of length n+nclin+ncnln.  Need not be initialized unless using Warm Start. Reports final QP multipliers.
            double *f,              -- Used to report final objective value.  Need not be initialized.
            double *g,              -- Array of length n. Used to report final objective gradient.  Need not be initialized.
            double *R,              -- Array of length ldR.  Need not be intialized unless using Warm Start.
            double *x,              -- Array of length n.  Contains initial solution estimate.
            int *iw,                -- Array of length leniw. Need not be initialized.  Provides workspace.
            int *leniw,             -- Length of iw.  Must be at least 3n + nclin + ncnln.
            double *w,              -- Array of length lenw. Need not be initialized.  Provides workspace.
            int *lenw               -- Length of w.  Must be at least 2n^2 + n*nclin + 2*n*ncnln + 20*n + 11*nclin +21*ncnln
        )

        bl, bu, istate, and clambda are all length n+nclin+ncnln.
            First n elements refer to the vars, in order.
            Next nclin elements refer to bounds on Ax
            Last ncnln elements refer to bounds on c(x)

        All arrays must be in column-major order.
        */

	fc->grad.resize(n);
	rf.hessOut.resize(n, n);
	double fit; // do not pass in &fc->fit
	int iter_out; // ignored
	F77_CALL(npsol)(&n, &nclin, &ncnln, &ldA, &ldJ, &ldR, A.data(),
			rf.solLB.data(), rf.solUB.data(), (void*)F77_SUB(npsolConstraintFunction),
			(void*) F77_SUB(npsolObjectiveFunction), &rf.informOut, &iter_out,
			istate.data(), c.data(), cJac.data(),
			clambda.data(), &fit, fc->grad.data(), rf.hessOut.data(), fc->est, iw.data(), &leniw, w.data(), &lenw);

	// NPSOL can return the wrong fit and estimates, but hard to
	// know what to do if there are constraints.
	if (rf.bestEst.size() && ncnln == 0) {
		fc->fit = rf.bestFit;
		memcpy(fc->est, rf.bestEst.data(), sizeof(double) * fc->numParam);
	}

    NPSOL_GOpt = NULL;
}

void omxNPSOL(double *est, GradientOptimizerContext &rf)
{
	FitContext *fc = rf.fc;
	Eigen::Map< Eigen::ArrayXd > Est(est, fc->numParam);
	Eigen::ArrayXd startingPoint = Est;

	omxState *globalState = fc->state;
	int equality, inequality;
	globalState->countNonlinearConstraints(equality, inequality);

	omxNPSOL1(est, rf, equality, inequality);

	if (equality + inequality == 0) return;

	int retry = 6;
	double best = std::numeric_limits<double>::max();
	while (--retry >= 0) {
		fc->copyParamToModel();

		Eigen::VectorXd cE(equality + inequality);
		rf.allConstraintsFun(cE);

		double norm = cE.norm();
		if (rf.verbose >= 1) {
			mxLog("NPSOL: feasibility constraints at %f; retry %d",
			      norm, 1+retry);
		}
		if (norm >= best) {
			// NPSOL can jump off a cliff and get lost.
			// Try to move back toward a more feasible region.
			Est = (Est + startingPoint) / 2;
		} else {
			best = norm;
		}
		if (!(cE.array().abs() < Global->feasibilityTolerance).all()) {
			omxNPSOL1(est, rf, equality, inequality);
		} else {
			break;
		}
	}
}

void omxSetNPSOLOpts(SEXP options)
{
    omxManageProtectInsanity mpi;

    static const char *whitelist[] = {
        "Central Difference Interval",
        "Crash Tolerance",
        "Derivative level",
        "Difference interval",
        "Feasibility tolerance",
        "Function precision",
        "Hessian",
        "Infinite bound size",
        "Infinite step size",
        "Iteration limit",
        "Iters",
        "Line search tolerance",
        "Major iteration limit",
        "Major iterations",
        "Print level",
        "Print file",
        "Minor iteration limit",
        "Minor print level",
        "Nolist",
        "Optimality tolerance",
        "Step limit",
        "Summary file",
        "Verify level",
        0
    };

    const int opBufLen = 250;
    char optionCharArray[opBufLen];
    int numOptions = Rf_length(options);
    SEXP optionNames;
    Rf_protect(optionNames = Rf_getAttrib(options, R_NamesSymbol));
    for(int i = 0; i < numOptions; i++) {
        const char *nextOptionName = CHAR(STRING_ELT(optionNames, i));
        const char *nextOptionValue = CHAR(Rf_asChar(VECTOR_ELT(options, i)));
        bool ok=false;
        for (int wx=0; whitelist[wx]; ++wx) {
            if (matchCaseInsensitive(nextOptionName, whitelist[wx])) {
                ok=true;
                break;
            }
        }
        if (!ok) continue;
        snprintf(optionCharArray, opBufLen, "%s %s", nextOptionName, nextOptionValue);
        F77_CALL(npoptn)(optionCharArray, strlen(optionCharArray));
        if(OMX_DEBUG) { mxLog("Option %s ", optionCharArray);}
    }
}
#endif
<|endoftext|>


<commit_before>/*
* Copyright (c) 2003-2016 Rony Shapiro <ronys@pwsafe.org>.
* All rights reserved. Use of the code is allowed under the
* Artistic License 2.0 terms, as specified in the LICENSE file
* distributed with this code, or available from
* http://www.opensource.org/licenses/artistic-license-2.0.php
*/

/**
 * \file Windows-specific implementation of logit.h
 */

#include "../logit.h"
#include "../../core/PWSLog.h"

#include <wtypes.h>

void pws_os::Logit(LPCTSTR lpszFormat, ...)
{
  va_list args;
  va_start(args, lpszFormat);

  TCHAR szBuffer[1024];
  int nBuf = _vsntprintf_s(szBuffer, sizeof(szBuffer) / sizeof(TCHAR), _TRUNCATE,
                           lpszFormat, args);
#ifdef DEBUG
  ASSERT(nBuf > 0);
#else
  UNREFERENCED_PARAMETER(nBuf); // In Release build only otherwise MS Compiler warning
#endif
  PWSLog::GetLog()->Add(stringT(szBuffer));
  va_end(args);
}
<commit_msg>Disable telemetry installed by Microsoft in VS2015<commit_after>/*
* Copyright (c) 2003-2016 Rony Shapiro <ronys@pwsafe.org>.
* All rights reserved. Use of the code is allowed under the
* Artistic License 2.0 terms, as specified in the LICENSE file
* distributed with this code, or available from
* http://www.opensource.org/licenses/artistic-license-2.0.php
*/

/**
 * \file Windows-specific implementation of logit.h
 */

#include "../logit.h"
#include "../../core/PWSLog.h"

#include <wtypes.h>

// Following disables Microsoft's telemetry code
// added in VS2015
// See https://www.reddit.com/r/cpp/comments/4ibauu/visual_studio_adding_telemetry_function_calls_to/
extern "C"
{
        void _cdecl __vcrt_initialize_telemetry_provider() {}
        void _cdecl __telemetry_main_invoke_trigger() {}
        void _cdecl __telemetry_main_return_trigger() {}
        void _cdecl __vcrt_uninitialize_telemetry_provider() {}
};

void pws_os::Logit(LPCTSTR lpszFormat, ...)
{
  va_list args;
  va_start(args, lpszFormat);

  TCHAR szBuffer[1024];
  int nBuf = _vsntprintf_s(szBuffer, sizeof(szBuffer) / sizeof(TCHAR), _TRUNCATE,
                           lpszFormat, args);
#ifdef DEBUG
  ASSERT(nBuf > 0);
#else
  UNREFERENCED_PARAMETER(nBuf); // In Release build only otherwise MS Compiler warning
#endif
  PWSLog::GetLog()->Add(stringT(szBuffer));
  va_end(args);
}
<|endoftext|>


<commit_before>#include <ximgproc.hpp>

extern "C"
struct TensorWrapper niBlackThreshold(struct TensorWrapper src, struct TensorWrapper dst, double maxValue, int type, int blockSize, double delta) {

    cv::Mat dst_mat;
    if(!dst.isNull()) dst_mat = dst.toMat();

    cv::ximgproc::niBlackThreshold(src.toMat(), dst_mat, maxValue, type, blockSize, delta);

    return TensorWrapper(dst_mat);
}

// GraphSegmentation

extern "C"
struct GraphSegmentationPtr GraphSegmentation_ctor(double sigma, float k, int min_size) {
    return rescueObjectFromPtr(cv::ximgproc::segmentation::createGraphSegmentation(sigma, k, min_size));
}

extern "C"
void GraphSegmentation_dtor(struct GraphSegmentationPtr ptr) {
    delete static_cast<cv::ximgproc::segmentation::GraphSegmentation *>(ptr.ptr);
}

extern "C"
struct TensorWrapper GraphSegmentation_processImage(struct GraphSegmentationPtr ptr, struct TensorWrapper img) {

    cv::Mat result;
    ptr->processImage(img.toMat(), result);
    return TensorWrapper(result);
}

extern "C"
void GraphSegmentation_setSigma(struct GraphSegmentationPtr ptr, double s) {
    ptr->setSigma(s);
}

extern "C"
double GraphSegmentation_getSigma(struct GraphSegmentationPtr ptr) {
    return ptr->getSigma();
}

extern "C"
void GraphSegmentation_setK(struct GraphSegmentationPtr ptr, float k) {
    ptr->setK(k);
}

extern "C"
float GraphSegmentation_getK(struct GraphSegmentationPtr ptr) {
    return ptr->getK();
}

extern "C"
void GraphSegmentation_setMinSize(struct GraphSegmentationPtr ptr, int min_size) {
    ptr->setMinSize(min_size);
}

extern "C"
int GraphSegmentation_getMinSize(struct GraphSegmentationPtr ptr) {
    return ptr->getMinSize();
}

// SelectiveSearchSegmentation

extern "C"
struct SelectiveSearchSegmentationPtr SelectiveSearchSegmentation_ctor() {
    return rescueObjectFromPtr(cv::ximgproc::segmentation::createSelectiveSearchSegmentation());
}

extern "C"
void SelectiveSearchSegmentationPtr_dtor(struct SelectiveSearchSegmentationPtr ptr) {
    delete static_cast<cv::ximgproc::segmentation::SelectiveSearchSegmentation *>(ptr.ptr);
}

extern "C"
void SelectiveSearchSegmentation_setBaseImage(struct SelectiveSearchSegmentationPtr ptr, struct TensorWrapper img) {
    ptr->setBaseImage(img.toMat());
}

extern "C"
void SelectiveSearchSegmentation_switchToSingleStrategy(struct SelectiveSearchSegmentationPtr ptr, int k, float sigma) {
    ptr->switchToSingleStrategy(k, sigma);
}

extern "C"
void SelectiveSearchSegmentation_switchToSelectiveSearchFast(struct SelectiveSearchSegmentationPtr ptr, int k, int inc_k, float sigma) {
    ptr->switchToSelectiveSearchFast(k, inc_k, sigma);
}

extern "C"
void SelectiveSearchSegmentation_switchToSelectiveSearchQuality(struct SelectiveSearchSegmentationPtr ptr, int k, int inc_k, float sigma) {
    ptr->switchToSelectiveSearchQuality(k, inc_k, sigma);
}

extern "C"
void SelectiveSearchSegmentation_addImage(struct SelectiveSearchSegmentationPtr ptr, struct TensorWrapper img) {
    ptr->setBaseImage(img.toMat());
}

extern "C"
void SelectiveSearchSegmentation_clearImages(struct SelectiveSearchSegmentationPtr ptr) {
    ptr->clearImages();
}

extern "C"
void SelectiveSearchSegmentation_addGraphSegmentation(struct SelectiveSearchSegmentationPtr ptr, struct GraphSegmentationPtr gs) {
    ptr->addGraphSegmentation(*gs);
}

extern "C"
void SelectiveSearchSegmentation_clearGraphSegmentations(struct SelectiveSearchSegmentationPtr ptr) {
    ptr->clearGraphSegmentations();
}

extern "C"
void SelectiveSearchSegmentation_addStrategy(struct SelectiveSearchSegmentationPtr ptr, struct SelectiveSearchSegmentationStrategyPtr s) {
    ptr->addStrategy(*s);
}

extern "C"
void SelectiveSearchSegmentation_clearStrategies(struct SelectiveSearchSegmentationPtr ptr) {
    ptr->clearStrategies();
}

extern "C"
struct RectArray SelectiveSearchSegmentation_process(struct SelectiveSearchSegmentationPtr ptr) {

    std::vector<cv::Rect> result;
    ptr->process(result);

    return RectArray(result);
}
<commit_msg>Try solving #103<commit_after>#include <ximgproc.hpp>

extern "C"
struct TensorWrapper niBlackThreshold(struct TensorWrapper src, struct TensorWrapper dst, double maxValue, int type, int blockSize, double delta) {

    cv::Mat dst_mat;
    if(!dst.isNull()) dst_mat = dst.toMat();

    cv::ximgproc::niBlackThreshold(src.toMat(), dst_mat, maxValue, type, blockSize, delta);

    return TensorWrapper(dst_mat);
}

// GraphSegmentation

extern "C"
struct GraphSegmentationPtr GraphSegmentation_ctor(double sigma, float k, int min_size) {
    return rescueObjectFromPtr(cv::ximgproc::segmentation::createGraphSegmentation(sigma, k, min_size));
}

extern "C"
void GraphSegmentation_dtor(struct GraphSegmentationPtr ptr) {
    delete static_cast<cv::ximgproc::segmentation::GraphSegmentation *>(ptr.ptr);
}

extern "C"
struct TensorWrapper GraphSegmentation_processImage(struct GraphSegmentationPtr ptr, struct TensorWrapper img) {

    cv::Mat result;
    ptr->processImage(img.toMat(), result);
    return TensorWrapper(result);
}

extern "C"
void GraphSegmentation_setSigma(struct GraphSegmentationPtr ptr, double s) {
    ptr->setSigma(s);
}

extern "C"
double GraphSegmentation_getSigma(struct GraphSegmentationPtr ptr) {
    return ptr->getSigma();
}

extern "C"
void GraphSegmentation_setK(struct GraphSegmentationPtr ptr, float k) {
    ptr->setK(k);
}

extern "C"
float GraphSegmentation_getK(struct GraphSegmentationPtr ptr) {
    return ptr->getK();
}

extern "C"
void GraphSegmentation_setMinSize(struct GraphSegmentationPtr ptr, int min_size) {
    ptr->setMinSize(min_size);
}

extern "C"
int GraphSegmentation_getMinSize(struct GraphSegmentationPtr ptr) {
    return ptr->getMinSize();
}

// See #103
#ifndef APPLE

// SelectiveSearchSegmentation

extern "C"
struct SelectiveSearchSegmentationPtr SelectiveSearchSegmentation_ctor() {
    return rescueObjectFromPtr(cv::ximgproc::segmentation::createSelectiveSearchSegmentation());
}

extern "C"
void SelectiveSearchSegmentationPtr_dtor(struct SelectiveSearchSegmentationPtr ptr) {
    delete static_cast<cv::ximgproc::segmentation::SelectiveSearchSegmentation *>(ptr.ptr);
}

extern "C"
void SelectiveSearchSegmentation_setBaseImage(struct SelectiveSearchSegmentationPtr ptr, struct TensorWrapper img) {
    ptr->setBaseImage(img.toMat());
}

extern "C"
void SelectiveSearchSegmentation_switchToSingleStrategy(struct SelectiveSearchSegmentationPtr ptr, int k, float sigma) {
    ptr->switchToSingleStrategy(k, sigma);
}

extern "C"
void SelectiveSearchSegmentation_switchToSelectiveSearchFast(struct SelectiveSearchSegmentationPtr ptr, int k, int inc_k, float sigma) {
    ptr->switchToSelectiveSearchFast(k, inc_k, sigma);
}

extern "C"
void SelectiveSearchSegmentation_switchToSelectiveSearchQuality(struct SelectiveSearchSegmentationPtr ptr, int k, int inc_k, float sigma) {
    ptr->switchToSelectiveSearchQuality(k, inc_k, sigma);
}

extern "C"
void SelectiveSearchSegmentation_addImage(struct SelectiveSearchSegmentationPtr ptr, struct TensorWrapper img) {
    ptr->setBaseImage(img.toMat());
}

extern "C"
void SelectiveSearchSegmentation_clearImages(struct SelectiveSearchSegmentationPtr ptr) {
    ptr->clearImages();
}

extern "C"
void SelectiveSearchSegmentation_addGraphSegmentation(struct SelectiveSearchSegmentationPtr ptr, struct GraphSegmentationPtr gs) {
    ptr->addGraphSegmentation(*gs);
}

extern "C"
void SelectiveSearchSegmentation_clearGraphSegmentations(struct SelectiveSearchSegmentationPtr ptr) {
    ptr->clearGraphSegmentations();
}

extern "C"
void SelectiveSearchSegmentation_addStrategy(struct SelectiveSearchSegmentationPtr ptr, struct SelectiveSearchSegmentationStrategyPtr s) {
    ptr->addStrategy(*s);
}

extern "C"
void SelectiveSearchSegmentation_clearStrategies(struct SelectiveSearchSegmentationPtr ptr) {
    ptr->clearStrategies();
}

extern "C"
struct RectArray SelectiveSearchSegmentation_process(struct SelectiveSearchSegmentationPtr ptr) {

    std::vector<cv::Rect> result;
    ptr->process(result);

    return RectArray(result);
}
#endif
<|endoftext|>


<commit_before>
#include "opencv2/objdetect.hpp"
#include "opencv2/videoio.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/tracking.hpp"

// best available resolution / rate: ffplay -pixel_format mjpeg -video_size 1920x1080 /dev/video1
// best recording solution: ffmpeg -framerate 30 -y -f video4linux2 -pixel_format mjpeg -video_size 1920x1080 -i /dev/video1 -f pulse -i default -acodec copy -vcodec copy /tmp/output.mkv
// alternate: mencoder tv:// -tv driver=v4l2:width=1920:height=1080:device=/dev/video1:fps=30:outfmt=mjpeg:forceaudio:alsa=1:adevice=default -ovc copy -oac copy -o /tmp/output.mkv

// an example pipe: ffmpeg -framerate 30 -f video4linux2 -pixel_format mjpeg -video_size 1280x720 -i /dev/video0 -vcodec copy -f avi pipe:1 | build/bin/yer-face --captureFile=- --frameDrop

#include "Logger.hpp"
#include "SDLDriver.hpp"
#include "FFmpegDriver.hpp"
#include "FaceTracker.hpp"
#include "FrameDerivatives.hpp"
#include "FaceMapper.hpp"
#include "Metrics.hpp"
#include "Utilities.hpp"

#include <iostream>
#include <cstdio>
#include <cstdlib>

using namespace std;
using namespace cv;
using namespace YerFace;

String captureFile;
String dlibFaceLandmarks;
String dlibFaceDetector;
String previewImgSeq;
bool frameDrop;
String window_name = "Yer Face: A Stupid Facial Performance Capture Engine";

SDLWindowRenderer sdlWindowRenderer;
SDL_Thread *workerThread;

Logger *logger;
SDLDriver *sdlDriver;
FFmpegDriver *ffmpegDriver;
FrameDerivatives *frameDerivatives;
FaceTracker *faceTracker;
FaceMapper *faceMapper;
Metrics *metrics;

unsigned long workingFrameNumber = 0;
SDL_mutex *flipWorkingCompletedMutex;

//VARIABLES PROTECTED BY frameSizeMutex
Size frameSize;
bool frameSizeValid = false;
SDL_mutex *frameSizeMutex;
//END VARIABLES PROTECTED BY frameSizeMutex

static int runCaptureLoop(void *ptr);
void doRenderPreviewFrame(void);

int main(int argc, const char** argv) {
	Logger::setLoggingFilter(SDL_LOG_PRIORITY_VERBOSE, SDL_LOG_CATEGORY_APPLICATION);
	logger = new Logger("YerFace");

	//Command line options.
	CommandLineParser parser(argc, argv,
		"{help h||Usage message.}"
		"{dlibFaceLandmarks|data/dlib-models/shape_predictor_68_face_landmarks.dat|Model for dlib's facial landmark detector.}"
		"{dlibFaceDetector|data/dlib-models/mmod_human_face_detector.dat|Model for dlib's DNN facial landmark detector or empty string (\"\") to default to the older HOG detector.}"
		"{captureFile|/dev/video0|Video file, URL, or device to open. (Or '-' for STDIN.)}"
		"{previewImgSeq||If set, is presumed to be the file name prefix of the output preview image sequence.}"
		"{frameDrop||If true, will drop frames as necessary to keep up with frames coming from the input device. (Don't use this if the input is a file!)}");

	parser.about("Yer Face: The butt of all the jokes. (A stupid facial performance capture engine for cartoon animation.)");
	if(parser.get<bool>("help")) {
		parser.printMessage();
		return 1;
	}
	if(parser.check()) {
		parser.printMessage();
		parser.printErrors();
		return 1;
	}
	captureFile = parser.get<string>("captureFile");
	if(captureFile == "-") {
		captureFile = "pipe:0";
	}
	previewImgSeq = parser.get<string>("previewImgSeq");
	dlibFaceLandmarks = parser.get<string>("dlibFaceLandmarks");
	dlibFaceDetector = parser.get<string>("dlibFaceDetector");
	frameDrop = parser.get<bool>("frameDrop");

	//Instantiate our classes.
	frameDerivatives = new FrameDerivatives();
	sdlDriver = new SDLDriver(frameDerivatives);
	ffmpegDriver = new FFmpegDriver(frameDerivatives, captureFile, frameDrop);
	faceTracker = new FaceTracker(dlibFaceLandmarks, dlibFaceDetector, sdlDriver, frameDerivatives, false);
	faceMapper = new FaceMapper(sdlDriver, frameDerivatives, faceTracker, false);
	metrics = new Metrics("YerFace", true);

	sdlWindowRenderer.window = NULL;
	sdlWindowRenderer.renderer = NULL;

	//Create locks.
	if((frameSizeMutex = SDL_CreateMutex()) == NULL) {
		throw runtime_error("Failed creating mutex!");
	}
	if((flipWorkingCompletedMutex = SDL_CreateMutex()) == NULL) {
		throw runtime_error("Failed creating mutex!");
	}

	//Create worker thread.
	if((workerThread = SDL_CreateThread(runCaptureLoop, "CaptureLoop", (void *)NULL)) == NULL) {
		throw runtime_error("Failed spawning worker thread!");
	}

	//Launch event / rendering loop.
	while(sdlDriver->getIsRunning()) {
		SDL_Delay(10);

		if(sdlWindowRenderer.window == NULL) {
			YerFace_MutexLock(frameSizeMutex);
			if(!frameSizeValid) {
				YerFace_MutexUnlock(frameSizeMutex);
				continue;
			}
			sdlWindowRenderer = sdlDriver->createPreviewWindow(frameSize.width, frameSize.height);
			YerFace_MutexUnlock(frameSizeMutex);
		}

		if(frameDerivatives->getCompletedFrameSet()) {
			doRenderPreviewFrame();
			sdlDriver->doRenderPreviewFrame();
		}

		sdlDriver->doHandleEvents();
	}

	//Join worker thread.
	SDL_WaitThread(workerThread, NULL);

	//Cleanup.
	SDL_DestroyMutex(frameSizeMutex);
	SDL_DestroyMutex(flipWorkingCompletedMutex);

	delete metrics;
	delete faceMapper;
	delete faceTracker;
	delete frameDerivatives;
	delete ffmpegDriver;
	delete sdlDriver;
	delete logger;
	return 0;
}

int runCaptureLoop(void *ptr) {
	VideoFrame videoFrame;

	bool didSetFrameSizeValid = false;
	while(sdlDriver->getIsRunning()) {
		if(!sdlDriver->getIsPaused()) {
			if(!ffmpegDriver->waitForNextVideoFrame(&videoFrame)) {
				logger->info("FFmpeg Demuxer thread finished.");
				sdlDriver->setIsRunning(false);
				continue;
			}
			workingFrameNumber++;

			if(!didSetFrameSizeValid) {
				YerFace_MutexLock(frameSizeMutex);
				if(!frameSizeValid) {
					frameSize = videoFrame.frameCV.size();
					frameSizeValid = true;
					didSetFrameSizeValid = true;
				}
				YerFace_MutexUnlock(frameSizeMutex);
			}

			// Start timer
			metrics->startClock();

			frameDerivatives->setWorkingFrame(videoFrame.frameCV);
			ffmpegDriver->releaseVideoFrame(videoFrame);

			faceTracker->processCurrentFrame();
			faceMapper->processCurrentFrame();

			metrics->endClock();

			YerFace_MutexLock(flipWorkingCompletedMutex);

			frameDerivatives->advanceWorkingFrameToCompleted();
			faceTracker->advanceWorkingToCompleted();
			faceMapper->advanceWorkingToCompleted();

			//If requested, write image sequence.
			if(previewImgSeq.length() > 0) {
				doRenderPreviewFrame();

				int filenameLength = previewImgSeq.length() + 32;
				char filename[filenameLength];
				snprintf(filename, filenameLength, "%s-%06lu.png", previewImgSeq.c_str(), workingFrameNumber);
				logger->debug("YerFace writing preview frame to %s ...", filename);
				imwrite(filename, frameDerivatives->getCompletedPreviewFrame());
			}

			YerFace_MutexUnlock(flipWorkingCompletedMutex);
		}
	}

	return 0;
}

void doRenderPreviewFrame(void) {
	YerFace_MutexLock(flipWorkingCompletedMutex);

	frameDerivatives->resetCompletedPreviewFrame();

	faceTracker->renderPreviewHUD();
	faceMapper->renderPreviewHUD();

	Mat previewFrame = frameDerivatives->getCompletedPreviewFrame();

	putText(previewFrame, metrics->getTimesString().c_str(), Point(25,50), FONT_HERSHEY_SIMPLEX, 0.75, Scalar(0,0,255), 2);
	putText(previewFrame, metrics->getFPSString().c_str(), Point(25,75), FONT_HERSHEY_SIMPLEX, 0.75, Scalar(0,0,255), 2);

	YerFace_MutexUnlock(flipWorkingCompletedMutex);
}
<commit_msg>improve example pipe command to demonstrate max potential<commit_after>
#include "opencv2/objdetect.hpp"
#include "opencv2/videoio.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/tracking.hpp"

// best available resolution / rate: ffplay -pixel_format mjpeg -video_size 1920x1080 /dev/video1
// best recording solution: ffmpeg -framerate 30 -y -f video4linux2 -pixel_format mjpeg -video_size 1920x1080 -i /dev/video1 -f pulse -i default -acodec copy -vcodec copy /tmp/output.mkv
// alternate: mencoder tv:// -tv driver=v4l2:width=1920:height=1080:device=/dev/video1:fps=30:outfmt=mjpeg:forceaudio:alsa=1:adevice=default -ovc copy -oac copy -o /tmp/output.mkv

// On a sufficiently fast system (with CUDA hardware) and which has a sufficiently well-endowed camera, you can do something like this:
// an example pipe: ffmpeg -framerate 60 -f video4linux2 -pixel_format mjpeg -video_size 1920x1080 -i /dev/video0 -vcodec copy -f avi pipe:1 | build/bin/yer-face --captureFile=-

#include "Logger.hpp"
#include "SDLDriver.hpp"
#include "FFmpegDriver.hpp"
#include "FaceTracker.hpp"
#include "FrameDerivatives.hpp"
#include "FaceMapper.hpp"
#include "Metrics.hpp"
#include "Utilities.hpp"

#include <iostream>
#include <cstdio>
#include <cstdlib>

using namespace std;
using namespace cv;
using namespace YerFace;

String captureFile;
String dlibFaceLandmarks;
String dlibFaceDetector;
String previewImgSeq;
bool frameDrop;
String window_name = "Yer Face: A Stupid Facial Performance Capture Engine";

SDLWindowRenderer sdlWindowRenderer;
SDL_Thread *workerThread;

Logger *logger;
SDLDriver *sdlDriver;
FFmpegDriver *ffmpegDriver;
FrameDerivatives *frameDerivatives;
FaceTracker *faceTracker;
FaceMapper *faceMapper;
Metrics *metrics;

unsigned long workingFrameNumber = 0;
SDL_mutex *flipWorkingCompletedMutex;

//VARIABLES PROTECTED BY frameSizeMutex
Size frameSize;
bool frameSizeValid = false;
SDL_mutex *frameSizeMutex;
//END VARIABLES PROTECTED BY frameSizeMutex

static int runCaptureLoop(void *ptr);
void doRenderPreviewFrame(void);

int main(int argc, const char** argv) {
	Logger::setLoggingFilter(SDL_LOG_PRIORITY_VERBOSE, SDL_LOG_CATEGORY_APPLICATION);
	logger = new Logger("YerFace");

	//Command line options.
	CommandLineParser parser(argc, argv,
		"{help h||Usage message.}"
		"{dlibFaceLandmarks|data/dlib-models/shape_predictor_68_face_landmarks.dat|Model for dlib's facial landmark detector.}"
		"{dlibFaceDetector|data/dlib-models/mmod_human_face_detector.dat|Model for dlib's DNN facial landmark detector or empty string (\"\") to default to the older HOG detector.}"
		"{captureFile|/dev/video0|Video file, URL, or device to open. (Or '-' for STDIN.)}"
		"{previewImgSeq||If set, is presumed to be the file name prefix of the output preview image sequence.}"
		"{frameDrop||If true, will drop frames as necessary to keep up with frames coming from the input device. (Don't use this if the input is a file!)}");

	parser.about("Yer Face: The butt of all the jokes. (A stupid facial performance capture engine for cartoon animation.)");
	if(parser.get<bool>("help")) {
		parser.printMessage();
		return 1;
	}
	if(parser.check()) {
		parser.printMessage();
		parser.printErrors();
		return 1;
	}
	captureFile = parser.get<string>("captureFile");
	if(captureFile == "-") {
		captureFile = "pipe:0";
	}
	previewImgSeq = parser.get<string>("previewImgSeq");
	dlibFaceLandmarks = parser.get<string>("dlibFaceLandmarks");
	dlibFaceDetector = parser.get<string>("dlibFaceDetector");
	frameDrop = parser.get<bool>("frameDrop");

	//Instantiate our classes.
	frameDerivatives = new FrameDerivatives();
	sdlDriver = new SDLDriver(frameDerivatives);
	ffmpegDriver = new FFmpegDriver(frameDerivatives, captureFile, frameDrop);
	faceTracker = new FaceTracker(dlibFaceLandmarks, dlibFaceDetector, sdlDriver, frameDerivatives, false);
	faceMapper = new FaceMapper(sdlDriver, frameDerivatives, faceTracker, false);
	metrics = new Metrics("YerFace", true);

	sdlWindowRenderer.window = NULL;
	sdlWindowRenderer.renderer = NULL;

	//Create locks.
	if((frameSizeMutex = SDL_CreateMutex()) == NULL) {
		throw runtime_error("Failed creating mutex!");
	}
	if((flipWorkingCompletedMutex = SDL_CreateMutex()) == NULL) {
		throw runtime_error("Failed creating mutex!");
	}

	//Create worker thread.
	if((workerThread = SDL_CreateThread(runCaptureLoop, "CaptureLoop", (void *)NULL)) == NULL) {
		throw runtime_error("Failed spawning worker thread!");
	}

	//Launch event / rendering loop.
	while(sdlDriver->getIsRunning()) {
		SDL_Delay(10);

		if(sdlWindowRenderer.window == NULL) {
			YerFace_MutexLock(frameSizeMutex);
			if(!frameSizeValid) {
				YerFace_MutexUnlock(frameSizeMutex);
				continue;
			}
			sdlWindowRenderer = sdlDriver->createPreviewWindow(frameSize.width, frameSize.height);
			YerFace_MutexUnlock(frameSizeMutex);
		}

		if(frameDerivatives->getCompletedFrameSet()) {
			doRenderPreviewFrame();
			sdlDriver->doRenderPreviewFrame();
		}

		sdlDriver->doHandleEvents();
	}

	//Join worker thread.
	SDL_WaitThread(workerThread, NULL);

	//Cleanup.
	SDL_DestroyMutex(frameSizeMutex);
	SDL_DestroyMutex(flipWorkingCompletedMutex);

	delete metrics;
	delete faceMapper;
	delete faceTracker;
	delete frameDerivatives;
	delete ffmpegDriver;
	delete sdlDriver;
	delete logger;
	return 0;
}

int runCaptureLoop(void *ptr) {
	VideoFrame videoFrame;

	bool didSetFrameSizeValid = false;
	while(sdlDriver->getIsRunning()) {
		if(!sdlDriver->getIsPaused()) {
			if(!ffmpegDriver->waitForNextVideoFrame(&videoFrame)) {
				logger->info("FFmpeg Demuxer thread finished.");
				sdlDriver->setIsRunning(false);
				continue;
			}
			workingFrameNumber++;

			if(!didSetFrameSizeValid) {
				YerFace_MutexLock(frameSizeMutex);
				if(!frameSizeValid) {
					frameSize = videoFrame.frameCV.size();
					frameSizeValid = true;
					didSetFrameSizeValid = true;
				}
				YerFace_MutexUnlock(frameSizeMutex);
			}

			// Start timer
			metrics->startClock();

			frameDerivatives->setWorkingFrame(videoFrame.frameCV);
			ffmpegDriver->releaseVideoFrame(videoFrame);

			faceTracker->processCurrentFrame();
			faceMapper->processCurrentFrame();

			metrics->endClock();

			YerFace_MutexLock(flipWorkingCompletedMutex);

			frameDerivatives->advanceWorkingFrameToCompleted();
			faceTracker->advanceWorkingToCompleted();
			faceMapper->advanceWorkingToCompleted();

			//If requested, write image sequence.
			if(previewImgSeq.length() > 0) {
				doRenderPreviewFrame();

				int filenameLength = previewImgSeq.length() + 32;
				char filename[filenameLength];
				snprintf(filename, filenameLength, "%s-%06lu.png", previewImgSeq.c_str(), workingFrameNumber);
				logger->debug("YerFace writing preview frame to %s ...", filename);
				imwrite(filename, frameDerivatives->getCompletedPreviewFrame());
			}

			YerFace_MutexUnlock(flipWorkingCompletedMutex);
		}
	}

	return 0;
}

void doRenderPreviewFrame(void) {
	YerFace_MutexLock(flipWorkingCompletedMutex);

	frameDerivatives->resetCompletedPreviewFrame();

	faceTracker->renderPreviewHUD();
	faceMapper->renderPreviewHUD();

	Mat previewFrame = frameDerivatives->getCompletedPreviewFrame();

	putText(previewFrame, metrics->getTimesString().c_str(), Point(25,50), FONT_HERSHEY_SIMPLEX, 0.75, Scalar(0,0,255), 2);
	putText(previewFrame, metrics->getFPSString().c_str(), Point(25,75), FONT_HERSHEY_SIMPLEX, 0.75, Scalar(0,0,255), 2);

	YerFace_MutexUnlock(flipWorkingCompletedMutex);
}
<|endoftext|>


<commit_before>#include "optionsdialog.h"
#include "optionsmodel.h"
#include "bitcoinamountfield.h"
#include "monitoreddatamapper.h"
#include "guiutil.h"
#include "bitcoinunits.h"
#include "qvaluecombobox.h"

#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QPushButton>
#include <QListWidget>
#include <QStackedWidget>

#include <QCheckBox>
#include <QLabel>
#include <QLineEdit>
#include <QIntValidator>
#include <QDoubleValidator>
#include <QRegExpValidator>
#include <QDialogButtonBox>
#include <QDir>
#include <QMessageBox>

class OptionsPage: public QWidget
{
    Q_OBJECT
public:
    explicit OptionsPage(QWidget *parent=0): QWidget(parent) {}

    virtual void setMapper(MonitoredDataMapper *mapper) = 0;
};

class MainOptionsPage: public OptionsPage
{
    Q_OBJECT
public:
    explicit MainOptionsPage(QWidget *parent=0);

    virtual void setMapper(MonitoredDataMapper *mapper);
private:
    QCheckBox *detach_database;
    BitcoinAmountField *fee_edit;
};

class WindowOptionsPage: public OptionsPage
{
    Q_OBJECT
public:
    explicit WindowOptionsPage(QWidget *parent=0);

    virtual void setMapper(MonitoredDataMapper *mapper);
private:
    QCheckBox *bitcoin_at_startup;
#ifndef Q_WS_MAC
    QCheckBox *minimize_to_tray;
#endif
#ifndef Q_WS_MAC
    QCheckBox *minimize_on_close;
#endif
};

class DisplayOptionsPage: public OptionsPage
{
    Q_OBJECT
public:
    explicit DisplayOptionsPage(QWidget *parent=0);

    virtual void setMapper(MonitoredDataMapper *mapper);
private:
    QValueComboBox *lang;
    QValueComboBox *unit;
    QCheckBox *display_addresses;
    bool restart_warning_displayed;
private slots:
    void showRestartWarning();
};

class NetworkOptionsPage: public OptionsPage
{
    Q_OBJECT
public:
    explicit NetworkOptionsPage(QWidget *parent=0);

    virtual void setMapper(MonitoredDataMapper *mapper);
private:
    QCheckBox *map_port_upnp;
    QCheckBox *connect_socks4;
    QLineEdit *proxy_ip;
    QLineEdit *proxy_port;
    BitcoinAmountField *fee_edit;
};

#include "optionsdialog.moc"

OptionsDialog::OptionsDialog(QWidget *parent):
    QDialog(parent), contents_widget(0), pages_widget(0),
    model(0)
{
    contents_widget = new QListWidget();
    contents_widget->setMaximumWidth(128);

    pages_widget = new QStackedWidget();
    pages_widget->setMinimumWidth(500);
    pages_widget->setMinimumHeight(300);

    pages.append(new MainOptionsPage(this));
    pages.append(new NetworkOptionsPage(this));
    pages.append(new WindowOptionsPage(this));
    pages.append(new DisplayOptionsPage(this));

    foreach(OptionsPage *page, pages)
    {
        QListWidgetItem *item = new QListWidgetItem(page->windowTitle());
        contents_widget->addItem(item);
        pages_widget->addWidget(page);
    }

    contents_widget->setCurrentRow(0);

    QHBoxLayout *main_layout = new QHBoxLayout();
    main_layout->addWidget(contents_widget);
    main_layout->addWidget(pages_widget, 1);

    QVBoxLayout *layout = new QVBoxLayout();
    layout->addLayout(main_layout);

    QDialogButtonBox *buttonbox = new QDialogButtonBox();
    buttonbox->setStandardButtons(QDialogButtonBox::Apply|QDialogButtonBox::Ok|QDialogButtonBox::Cancel);
    apply_button = buttonbox->button(QDialogButtonBox::Apply);
    layout->addWidget(buttonbox);

    setLayout(layout);
    setWindowTitle(tr("Options"));

    /* Widget-to-option mapper */
    mapper = new MonitoredDataMapper(this);
    mapper->setSubmitPolicy(QDataWidgetMapper::ManualSubmit);
    mapper->setOrientation(Qt::Vertical);
    /* enable apply button when data modified */
    connect(mapper, SIGNAL(viewModified()), this, SLOT(enableApply()));
    /* disable apply button when new data loaded */
    connect(mapper, SIGNAL(currentIndexChanged(int)), this, SLOT(disableApply()));

    /* Event bindings */
    connect(contents_widget, SIGNAL(currentRowChanged(int)), this, SLOT(changePage(int)));
    connect(buttonbox->button(QDialogButtonBox::Ok), SIGNAL(clicked()), this, SLOT(okClicked()));
    connect(buttonbox->button(QDialogButtonBox::Cancel), SIGNAL(clicked()), this, SLOT(cancelClicked()));
    connect(buttonbox->button(QDialogButtonBox::Apply), SIGNAL(clicked()), this, SLOT(applyClicked()));
}

void OptionsDialog::setModel(OptionsModel *model)
{
    this->model = model;

    mapper->setModel(model);

    foreach(OptionsPage *page, pages)
    {
        page->setMapper(mapper);
    }

    mapper->toFirst();
}

void OptionsDialog::changePage(int index)
{
    pages_widget->setCurrentIndex(index);
}

void OptionsDialog::okClicked()
{
    mapper->submit();
    accept();
}

void OptionsDialog::cancelClicked()
{
    reject();
}

void OptionsDialog::applyClicked()
{
    mapper->submit();
    apply_button->setEnabled(false);
}

void OptionsDialog::enableApply()
{
    apply_button->setEnabled(true);
}

void OptionsDialog::disableApply()
{
    apply_button->setEnabled(false);
}

/* Main options */
MainOptionsPage::MainOptionsPage(QWidget *parent):
        OptionsPage(parent)
{
    QVBoxLayout *layout = new QVBoxLayout();
    setWindowTitle(tr("Main"));

    QLabel *fee_help = new QLabel(tr("Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended."));
    fee_help->setWordWrap(true);
    layout->addWidget(fee_help);

    QHBoxLayout *fee_hbox = new QHBoxLayout();
    fee_hbox->addSpacing(18);
    QLabel *fee_label = new QLabel(tr("Pay transaction &fee"));
    fee_hbox->addWidget(fee_label);
    fee_edit = new BitcoinAmountField();

    fee_label->setBuddy(fee_edit);
    fee_hbox->addWidget(fee_edit);
    fee_hbox->addStretch(1);

    layout->addLayout(fee_hbox);

    detach_database = new QCheckBox(tr("Detach databases at shutdown"));
    detach_database->setToolTip(tr("Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached."));
    layout->addWidget(detach_database);

    layout->addStretch(1); // Extra space at bottom
    setLayout(layout);
}

void MainOptionsPage::setMapper(MonitoredDataMapper *mapper)
{
    // Map model to widgets
    mapper->addMapping(fee_edit, OptionsModel::Fee);
    mapper->addMapping(detach_database, OptionsModel::DetachDatabases);
}

/* Display options */
DisplayOptionsPage::DisplayOptionsPage(QWidget *parent):
    OptionsPage(parent), restart_warning_displayed(false)
{
    setWindowTitle(tr("Display"));

    QVBoxLayout *layout = new QVBoxLayout();

    QHBoxLayout *lang_hbox = new QHBoxLayout();
    lang_hbox->addSpacing(18);
    QLabel *lang_label = new QLabel(tr("User Interface &Language: "));
    lang_hbox->addWidget(lang_label);
    lang = new QValueComboBox(this);
    // Make list of languages
    QDir translations(":translations");
    lang->addItem("(default)", QVariant(""));
    foreach(const QString &langStr, translations.entryList())
    {
        lang->addItem(langStr, QVariant(langStr));
    }

    lang->setToolTip(tr("The user interface language can be set here. This setting will only take effect after restarting Bitcoin."));
    connect(lang, SIGNAL(activated(int)), this, SLOT(showRestartWarning()));

    lang_label->setBuddy(lang);
    lang_hbox->addWidget(lang);

    layout->addLayout(lang_hbox);

    QHBoxLayout *unit_hbox = new QHBoxLayout();
    unit_hbox->addSpacing(18);
    QLabel *unit_label = new QLabel(tr("&Unit to show amounts in: "));
    unit_hbox->addWidget(unit_label);
    unit = new QValueComboBox(this);
    unit->setModel(new BitcoinUnits(this));
    unit->setToolTip(tr("Choose the default subdivision unit to show in the interface, and when sending coins"));

    unit_label->setBuddy(unit);
    unit_hbox->addWidget(unit);

    layout->addLayout(unit_hbox);

    display_addresses = new QCheckBox(tr("&Display addresses in transaction list"), this);
    display_addresses->setToolTip(tr("Whether to show Bitcoin addresses in the transaction list"));
    layout->addWidget(display_addresses);

    layout->addStretch();
    setLayout(layout);
}

void DisplayOptionsPage::setMapper(MonitoredDataMapper *mapper)
{
    mapper->addMapping(lang, OptionsModel::Language);
    mapper->addMapping(unit, OptionsModel::DisplayUnit);
    mapper->addMapping(display_addresses, OptionsModel::DisplayAddresses);
}

void DisplayOptionsPage::showRestartWarning()
{
    if(!restart_warning_displayed)
    {
        QMessageBox::warning(this, tr("Warning"), tr("This setting will take effect after restarting Bitcoin."), QMessageBox::Ok);
        restart_warning_displayed = true;
    }
}

/* Window options */
WindowOptionsPage::WindowOptionsPage(QWidget *parent):
        OptionsPage(parent)
{
    QVBoxLayout *layout = new QVBoxLayout();
    setWindowTitle(tr("Window"));

    bitcoin_at_startup = new QCheckBox(tr("&Start Bitcoin on window system startup"));
    bitcoin_at_startup->setToolTip(tr("Automatically start Bitcoin after the computer is turned on"));
    layout->addWidget(bitcoin_at_startup);

#ifndef Q_WS_MAC
    minimize_to_tray = new QCheckBox(tr("&Minimize to the tray instead of the taskbar"));
    minimize_to_tray->setToolTip(tr("Show only a tray icon after minimizing the window"));
    layout->addWidget(minimize_to_tray);

    minimize_on_close = new QCheckBox(tr("M&inimize on close"));
    minimize_on_close->setToolTip(tr("Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu."));
    layout->addWidget(minimize_on_close);
#endif

    layout->addStretch(1); // Extra space at bottom
    setLayout(layout);
}

void WindowOptionsPage::setMapper(MonitoredDataMapper *mapper)
{
    // Map model to widgets
    mapper->addMapping(bitcoin_at_startup, OptionsModel::StartAtStartup);
#ifndef Q_WS_MAC
    mapper->addMapping(minimize_to_tray, OptionsModel::MinimizeToTray);
#endif
#ifndef Q_WS_MAC
    mapper->addMapping(minimize_on_close, OptionsModel::MinimizeOnClose);
#endif
}

/* Network options */
NetworkOptionsPage::NetworkOptionsPage(QWidget *parent):
        OptionsPage(parent)
{
    QVBoxLayout *layout = new QVBoxLayout();
    setWindowTitle(tr("Network"));

    map_port_upnp = new QCheckBox(tr("Map port using &UPnP"));
    map_port_upnp->setToolTip(tr("Automatically open the Bitcoin client port on the router. This only works when your router supports UPnP and it is enabled."));
    layout->addWidget(map_port_upnp);

    connect_socks4 = new QCheckBox(tr("&Connect through SOCKS4 proxy:"));
    connect_socks4->setToolTip(tr("Connect to the Bitcon network through a SOCKS4 proxy (e.g. when connecting through Tor)"));
    layout->addWidget(connect_socks4);

    QHBoxLayout *proxy_hbox = new QHBoxLayout();
    proxy_hbox->addSpacing(18);
    QLabel *proxy_ip_label = new QLabel(tr("Proxy &IP: "));
    proxy_hbox->addWidget(proxy_ip_label);
    proxy_ip = new QLineEdit();
    proxy_ip->setMaximumWidth(140);
    proxy_ip->setEnabled(false);
    proxy_ip->setValidator(new QRegExpValidator(QRegExp("[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}"), this));
    proxy_ip->setToolTip(tr("IP address of the proxy (e.g. 127.0.0.1)"));
    proxy_ip_label->setBuddy(proxy_ip);
    proxy_hbox->addWidget(proxy_ip);
    QLabel *proxy_port_label = new QLabel(tr("&Port: "));
    proxy_hbox->addWidget(proxy_port_label);
    proxy_port = new QLineEdit();
    proxy_port->setMaximumWidth(55);
    proxy_port->setValidator(new QIntValidator(0, 65535, this));
    proxy_port->setEnabled(false);
    proxy_port->setToolTip(tr("Port of the proxy (e.g. 1234)"));
    proxy_port_label->setBuddy(proxy_port);
    proxy_hbox->addWidget(proxy_port);
    proxy_hbox->addStretch(1);
    layout->addLayout(proxy_hbox);

    layout->addStretch(1); // Extra space at bottom
    setLayout(layout);

    connect(connect_socks4, SIGNAL(toggled(bool)), proxy_ip, SLOT(setEnabled(bool)));
    connect(connect_socks4, SIGNAL(toggled(bool)), proxy_port, SLOT(setEnabled(bool)));

#ifndef USE_UPNP
    map_port_upnp->setDisabled(true);
#endif
}

void NetworkOptionsPage::setMapper(MonitoredDataMapper *mapper)
{
    // Map model to widgets
    mapper->addMapping(map_port_upnp, OptionsModel::MapPortUPnP);
    mapper->addMapping(connect_socks4, OptionsModel::ConnectSOCKS4);
    mapper->addMapping(proxy_ip, OptionsModel::ProxyIP);
    mapper->addMapping(proxy_port, OptionsModel::ProxyPort);
}
<commit_msg>optionsdialog.cpp: rename "Start Bitcoin on window system startup" to "Start Bitcoin on system login" and move it to Main / hide "Window" Options on Mac as there are currently none available / remove an unused variable / add Alt-Shortcuts where they were missing / allow translation of "default"<commit_after>#include "optionsdialog.h"
#include "optionsmodel.h"
#include "bitcoinamountfield.h"
#include "monitoreddatamapper.h"
#include "guiutil.h"
#include "bitcoinunits.h"
#include "qvaluecombobox.h"

#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QPushButton>
#include <QListWidget>
#include <QStackedWidget>

#include <QCheckBox>
#include <QLabel>
#include <QLineEdit>
#include <QIntValidator>
#include <QDoubleValidator>
#include <QRegExpValidator>
#include <QDialogButtonBox>
#include <QDir>
#include <QMessageBox>

class OptionsPage: public QWidget
{
    Q_OBJECT
public:
    explicit OptionsPage(QWidget *parent=0): QWidget(parent) {}

    virtual void setMapper(MonitoredDataMapper *mapper) = 0;
};

class MainOptionsPage: public OptionsPage
{
    Q_OBJECT
public:
    explicit MainOptionsPage(QWidget *parent=0);

    virtual void setMapper(MonitoredDataMapper *mapper);
private:
    BitcoinAmountField *fee_edit;
    QCheckBox *bitcoin_at_startup;
    QCheckBox *detach_database;
};

class WindowOptionsPage: public OptionsPage
{
    Q_OBJECT
public:
    explicit WindowOptionsPage(QWidget *parent=0);

    virtual void setMapper(MonitoredDataMapper *mapper);
private:
#ifndef Q_WS_MAC
    QCheckBox *minimize_to_tray;
    QCheckBox *minimize_on_close;
#endif
};

class DisplayOptionsPage: public OptionsPage
{
    Q_OBJECT
public:
    explicit DisplayOptionsPage(QWidget *parent=0);

    virtual void setMapper(MonitoredDataMapper *mapper);
private:
    QValueComboBox *lang;
    QValueComboBox *unit;
    QCheckBox *display_addresses;
    bool restart_warning_displayed;
private slots:
    void showRestartWarning();
};

class NetworkOptionsPage: public OptionsPage
{
    Q_OBJECT
public:
    explicit NetworkOptionsPage(QWidget *parent=0);

    virtual void setMapper(MonitoredDataMapper *mapper);
private:
    QCheckBox *map_port_upnp;
    QCheckBox *connect_socks4;
    QLineEdit *proxy_ip;
    QLineEdit *proxy_port;
};

#include "optionsdialog.moc"

OptionsDialog::OptionsDialog(QWidget *parent):
    QDialog(parent), contents_widget(0), pages_widget(0),
    model(0)
{
    contents_widget = new QListWidget();
    contents_widget->setMaximumWidth(128);

    pages_widget = new QStackedWidget();
    pages_widget->setMinimumWidth(500);
    pages_widget->setMinimumHeight(300);

    pages.append(new MainOptionsPage(this));
    pages.append(new NetworkOptionsPage(this));
#ifndef Q_WS_MAC
    /* Hide Window options on Mac as there are currently none available */
    pages.append(new WindowOptionsPage(this));
#endif
    pages.append(new DisplayOptionsPage(this));

    foreach(OptionsPage *page, pages)
    {
        QListWidgetItem *item = new QListWidgetItem(page->windowTitle());
        contents_widget->addItem(item);
        pages_widget->addWidget(page);
    }

    contents_widget->setCurrentRow(0);

    QHBoxLayout *main_layout = new QHBoxLayout();
    main_layout->addWidget(contents_widget);
    main_layout->addWidget(pages_widget, 1);

    QVBoxLayout *layout = new QVBoxLayout();
    layout->addLayout(main_layout);

    QDialogButtonBox *buttonbox = new QDialogButtonBox();
    buttonbox->setStandardButtons(QDialogButtonBox::Apply|QDialogButtonBox::Ok|QDialogButtonBox::Cancel);
    apply_button = buttonbox->button(QDialogButtonBox::Apply);
    layout->addWidget(buttonbox);

    setLayout(layout);
    setWindowTitle(tr("Options"));

    /* Widget-to-option mapper */
    mapper = new MonitoredDataMapper(this);
    mapper->setSubmitPolicy(QDataWidgetMapper::ManualSubmit);
    mapper->setOrientation(Qt::Vertical);
    /* enable apply button when data modified */
    connect(mapper, SIGNAL(viewModified()), this, SLOT(enableApply()));
    /* disable apply button when new data loaded */
    connect(mapper, SIGNAL(currentIndexChanged(int)), this, SLOT(disableApply()));

    /* Event bindings */
    connect(contents_widget, SIGNAL(currentRowChanged(int)), this, SLOT(changePage(int)));
    connect(buttonbox->button(QDialogButtonBox::Ok), SIGNAL(clicked()), this, SLOT(okClicked()));
    connect(buttonbox->button(QDialogButtonBox::Cancel), SIGNAL(clicked()), this, SLOT(cancelClicked()));
    connect(buttonbox->button(QDialogButtonBox::Apply), SIGNAL(clicked()), this, SLOT(applyClicked()));
}

void OptionsDialog::setModel(OptionsModel *model)
{
    this->model = model;

    mapper->setModel(model);

    foreach(OptionsPage *page, pages)
    {
        page->setMapper(mapper);
    }

    mapper->toFirst();
}

void OptionsDialog::changePage(int index)
{
    pages_widget->setCurrentIndex(index);
}

void OptionsDialog::okClicked()
{
    mapper->submit();
    accept();
}

void OptionsDialog::cancelClicked()
{
    reject();
}

void OptionsDialog::applyClicked()
{
    mapper->submit();
    apply_button->setEnabled(false);
}

void OptionsDialog::enableApply()
{
    apply_button->setEnabled(true);
}

void OptionsDialog::disableApply()
{
    apply_button->setEnabled(false);
}

/* Main options */
MainOptionsPage::MainOptionsPage(QWidget *parent):
        OptionsPage(parent)
{
    QVBoxLayout *layout = new QVBoxLayout();
    setWindowTitle(tr("Main"));

    QLabel *fee_help = new QLabel(tr("Optional transaction fee per kB that helps make sure your transactions are processed quickly. Most transactions are 1 kB. Fee 0.01 recommended."));
    fee_help->setWordWrap(true);
    layout->addWidget(fee_help);

    QHBoxLayout *fee_hbox = new QHBoxLayout();
    fee_hbox->addSpacing(18);
    QLabel *fee_label = new QLabel(tr("Pay transaction &fee"));
    fee_hbox->addWidget(fee_label);
    fee_edit = new BitcoinAmountField();

    fee_label->setBuddy(fee_edit);
    fee_hbox->addWidget(fee_edit);
    fee_hbox->addStretch(1);

    layout->addLayout(fee_hbox);

    bitcoin_at_startup = new QCheckBox(tr("&Start Bitcoin on system login"));
    bitcoin_at_startup->setToolTip(tr("Automatically start Bitcoin after logging in to the system"));
    layout->addWidget(bitcoin_at_startup);

    detach_database = new QCheckBox(tr("&Detach databases at shutdown"));
    detach_database->setToolTip(tr("Detach block and address databases at shutdown. This means they can be moved to another data directory, but it slows down shutdown. The wallet is always detached."));
    layout->addWidget(detach_database);

    layout->addStretch(1); // Extra space at bottom
    setLayout(layout);
}

void MainOptionsPage::setMapper(MonitoredDataMapper *mapper)
{
    // Map model to widgets
    mapper->addMapping(fee_edit, OptionsModel::Fee);
    mapper->addMapping(bitcoin_at_startup, OptionsModel::StartAtStartup);
    mapper->addMapping(detach_database, OptionsModel::DetachDatabases);
}

/* Display options */
DisplayOptionsPage::DisplayOptionsPage(QWidget *parent):
    OptionsPage(parent), restart_warning_displayed(false)
{
    setWindowTitle(tr("Display"));

    QVBoxLayout *layout = new QVBoxLayout();

    QHBoxLayout *lang_hbox = new QHBoxLayout();
    lang_hbox->addSpacing(18);
    QLabel *lang_label = new QLabel(tr("User Interface &Language: "));
    lang_hbox->addWidget(lang_label);
    lang = new QValueComboBox(this);
    // Make list of languages
    QDir translations(":translations");
    lang->addItem(QString("(") + tr("default") + QString(")"), QVariant(""));
    foreach(const QString &langStr, translations.entryList())
    {
        lang->addItem(langStr, QVariant(langStr));
    }

    lang->setToolTip(tr("The user interface language can be set here. This setting will only take effect after restarting Bitcoin."));
    connect(lang, SIGNAL(activated(int)), this, SLOT(showRestartWarning()));

    lang_label->setBuddy(lang);
    lang_hbox->addWidget(lang);

    layout->addLayout(lang_hbox);

    QHBoxLayout *unit_hbox = new QHBoxLayout();
    unit_hbox->addSpacing(18);
    QLabel *unit_label = new QLabel(tr("&Unit to show amounts in: "));
    unit_hbox->addWidget(unit_label);
    unit = new QValueComboBox(this);
    unit->setModel(new BitcoinUnits(this));
    unit->setToolTip(tr("Choose the default subdivision unit to show in the interface, and when sending coins"));

    unit_label->setBuddy(unit);
    unit_hbox->addWidget(unit);

    layout->addLayout(unit_hbox);

    display_addresses = new QCheckBox(tr("&Display addresses in transaction list"), this);
    display_addresses->setToolTip(tr("Whether to show Bitcoin addresses in the transaction list"));
    layout->addWidget(display_addresses);

    layout->addStretch();
    setLayout(layout);
}

void DisplayOptionsPage::setMapper(MonitoredDataMapper *mapper)
{
    mapper->addMapping(lang, OptionsModel::Language);
    mapper->addMapping(unit, OptionsModel::DisplayUnit);
    mapper->addMapping(display_addresses, OptionsModel::DisplayAddresses);
}

void DisplayOptionsPage::showRestartWarning()
{
    if(!restart_warning_displayed)
    {
        QMessageBox::warning(this, tr("Warning"), tr("This setting will take effect after restarting Bitcoin."), QMessageBox::Ok);
        restart_warning_displayed = true;
    }
}

/* Window options */
WindowOptionsPage::WindowOptionsPage(QWidget *parent):
        OptionsPage(parent)
{
    QVBoxLayout *layout = new QVBoxLayout();
    setWindowTitle(tr("Window"));

#ifndef Q_WS_MAC
    minimize_to_tray = new QCheckBox(tr("&Minimize to the tray instead of the taskbar"));
    minimize_to_tray->setToolTip(tr("Show only a tray icon after minimizing the window"));
    layout->addWidget(minimize_to_tray);

    minimize_on_close = new QCheckBox(tr("M&inimize on close"));
    minimize_on_close->setToolTip(tr("Minimize instead of exit the application when the window is closed. When this option is enabled, the application will be closed only after selecting Quit in the menu."));
    layout->addWidget(minimize_on_close);
#endif

    layout->addStretch(1); // Extra space at bottom
    setLayout(layout);
}

void WindowOptionsPage::setMapper(MonitoredDataMapper *mapper)
{
    // Map model to widgets
#ifndef Q_WS_MAC
    mapper->addMapping(minimize_to_tray, OptionsModel::MinimizeToTray);
#endif
#ifndef Q_WS_MAC
    mapper->addMapping(minimize_on_close, OptionsModel::MinimizeOnClose);
#endif
}

/* Network options */
NetworkOptionsPage::NetworkOptionsPage(QWidget *parent):
        OptionsPage(parent)
{
    QVBoxLayout *layout = new QVBoxLayout();
    setWindowTitle(tr("Network"));

    map_port_upnp = new QCheckBox(tr("Map port using &UPnP"));
    map_port_upnp->setToolTip(tr("Automatically open the Bitcoin client port on the router. This only works when your router supports UPnP and it is enabled."));
    layout->addWidget(map_port_upnp);

    connect_socks4 = new QCheckBox(tr("&Connect through SOCKS4 proxy:"));
    connect_socks4->setToolTip(tr("Connect to the Bitcon network through a SOCKS4 proxy (e.g. when connecting through Tor)"));
    layout->addWidget(connect_socks4);

    QHBoxLayout *proxy_hbox = new QHBoxLayout();
    proxy_hbox->addSpacing(18);
    QLabel *proxy_ip_label = new QLabel(tr("Proxy &IP: "));
    proxy_hbox->addWidget(proxy_ip_label);
    proxy_ip = new QLineEdit();
    proxy_ip->setMaximumWidth(140);
    proxy_ip->setEnabled(false);
    proxy_ip->setValidator(new QRegExpValidator(QRegExp("[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}"), this));
    proxy_ip->setToolTip(tr("IP address of the proxy (e.g. 127.0.0.1)"));
    proxy_ip_label->setBuddy(proxy_ip);
    proxy_hbox->addWidget(proxy_ip);
    QLabel *proxy_port_label = new QLabel(tr("&Port: "));
    proxy_hbox->addWidget(proxy_port_label);
    proxy_port = new QLineEdit();
    proxy_port->setMaximumWidth(55);
    proxy_port->setValidator(new QIntValidator(0, 65535, this));
    proxy_port->setEnabled(false);
    proxy_port->setToolTip(tr("Port of the proxy (e.g. 1234)"));
    proxy_port_label->setBuddy(proxy_port);
    proxy_hbox->addWidget(proxy_port);
    proxy_hbox->addStretch(1);
    layout->addLayout(proxy_hbox);

    layout->addStretch(1); // Extra space at bottom
    setLayout(layout);

    connect(connect_socks4, SIGNAL(toggled(bool)), proxy_ip, SLOT(setEnabled(bool)));
    connect(connect_socks4, SIGNAL(toggled(bool)), proxy_port, SLOT(setEnabled(bool)));

#ifndef USE_UPNP
    map_port_upnp->setDisabled(true);
#endif
}

void NetworkOptionsPage::setMapper(MonitoredDataMapper *mapper)
{
    // Map model to widgets
    mapper->addMapping(map_port_upnp, OptionsModel::MapPortUPnP);
    mapper->addMapping(connect_socks4, OptionsModel::ConnectSOCKS4);
    mapper->addMapping(proxy_ip, OptionsModel::ProxyIP);
    mapper->addMapping(proxy_port, OptionsModel::ProxyPort);
}
<|endoftext|>


<commit_before>// Copyright (c) 2009-2014 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "uritests.h"

#include "guiutil.h"
#include "walletmodel.h"

#include <QUrl>

void URITests::uriTests()
{
    SendCoinsRecipient rv;
    QUrl uri;
    uri.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?req-dontexist="));
    QVERIFY(!GUIUtil::parseBitcoinURI(uri, &rv));

    uri.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?dontexist="));
    QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv));
    QVERIFY(rv.address == QString("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W"));
    QVERIFY(rv.label == QString());
    QVERIFY(rv.amount == 0);

    uri.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?label=Wikipedia Example Address"));
    QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv));
    QVERIFY(rv.address == QString("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W"));
    QVERIFY(rv.label == QString("Wikipedia Example Address"));
    QVERIFY(rv.amount == 0);

    uri.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=0.001"));
    QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv));
    QVERIFY(rv.address == QString("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W"));
    QVERIFY(rv.label == QString());
    QVERIFY(rv.amount == 100000);

    uri.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=1.001"));
    QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv));
    QVERIFY(rv.address == QString("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W"));
    QVERIFY(rv.label == QString());
    QVERIFY(rv.amount == 100100000);

    uri.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=100&label=Wikipedia Example"));
    QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv));
    QVERIFY(rv.address == QString("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W"));
    QVERIFY(rv.amount == 10000000000LL);
    QVERIFY(rv.label == QString("Wikipedia Example"));

    uri.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?message=Wikipedia Example Address"));
    QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv));
    QVERIFY(rv.address == QString("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W"));
    QVERIFY(rv.label == QString());

    QVERIFY(GUIUtil::parseBitcoinURI("bitcoin://175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?message=Wikipedia Example Address", &rv));
    QVERIFY(rv.address == QString("175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W"));
    QVERIFY(rv.label == QString());

    uri.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?req-message=Wikipedia Example Address"));
    QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv));

    uri.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=1,000&label=Wikipedia Example"));
    QVERIFY(!GUIUtil::parseBitcoinURI(uri, &rv));

    uri.setUrl(QString("bitcoin:175tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=1,000.0&label=Wikipedia Example"));
    QVERIFY(!GUIUtil::parseBitcoinURI(uri, &rv));
}
<commit_msg>Update URI tests for Dogecoin<commit_after>// Copyright (c) 2009-2014 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "uritests.h"

#include "guiutil.h"
#include "walletmodel.h"

#include <QUrl>

void URITests::uriTests()
{
    SendCoinsRecipient rv;
    QUrl uri;
    uri.setUrl(QString("dogecoin:D75tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?req-dontexist="));
    QVERIFY(!GUIUtil::parseBitcoinURI(uri, &rv));

    uri.setUrl(QString("dogecoin:D75tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?dontexist="));
    QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv));
    QVERIFY(rv.address == QString("D75tWpb8K1S7NmH4Zx6rewF9WQrcZv245W"));
    QVERIFY(rv.label == QString());
    QVERIFY(rv.amount == 0);

    uri.setUrl(QString("dogecoin:D75tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?label=Wikipedia Example Address"));
    QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv));
    QVERIFY(rv.address == QString("D75tWpb8K1S7NmH4Zx6rewF9WQrcZv245W"));
    QVERIFY(rv.label == QString("Wikipedia Example Address"));
    QVERIFY(rv.amount == 0);

    uri.setUrl(QString("dogecoin:D75tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=0.001"));
    QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv));
    QVERIFY(rv.address == QString("D75tWpb8K1S7NmH4Zx6rewF9WQrcZv245W"));
    QVERIFY(rv.label == QString());
    QVERIFY(rv.amount == 100000);

    uri.setUrl(QString("dogecoin:D75tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=1.001"));
    QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv));
    QVERIFY(rv.address == QString("D75tWpb8K1S7NmH4Zx6rewF9WQrcZv245W"));
    QVERIFY(rv.label == QString());
    QVERIFY(rv.amount == 100100000);

    uri.setUrl(QString("dogecoin:D75tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=100&label=Wikipedia Example"));
    QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv));
    QVERIFY(rv.address == QString("D75tWpb8K1S7NmH4Zx6rewF9WQrcZv245W"));
    QVERIFY(rv.amount == 10000000000LL);
    QVERIFY(rv.label == QString("Wikipedia Example"));

    uri.setUrl(QString("dogecoin:D75tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?message=Wikipedia Example Address"));
    QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv));
    QVERIFY(rv.address == QString("D75tWpb8K1S7NmH4Zx6rewF9WQrcZv245W"));
    QVERIFY(rv.label == QString());

    QVERIFY(GUIUtil::parseBitcoinURI("dogecoin://D75tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?message=Wikipedia Example Address", &rv));
    QVERIFY(rv.address == QString("D75tWpb8K1S7NmH4Zx6rewF9WQrcZv245W"));
    QVERIFY(rv.label == QString());

    uri.setUrl(QString("dogecoin:D75tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?req-message=Wikipedia Example Address"));
    QVERIFY(GUIUtil::parseBitcoinURI(uri, &rv));

    uri.setUrl(QString("dogecoin:D75tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=1,000&label=Wikipedia Example"));
    QVERIFY(!GUIUtil::parseBitcoinURI(uri, &rv));

    uri.setUrl(QString("dogecoin:D75tWpb8K1S7NmH4Zx6rewF9WQrcZv245W?amount=1,000.0&label=Wikipedia Example"));
    QVERIFY(!GUIUtil::parseBitcoinURI(uri, &rv));
}
<|endoftext|>


<commit_before>// Copyright (c) 2011-2014 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "utilitydialog.h"

#include "ui_aboutdialog.h"
#include "ui_helpmessagedialog.h"

#include "bitcoingui.h"
#include "clientmodel.h"
#include "guiutil.h"

#include "clientversion.h"
#include "init.h"
#include "util.h"

#include <QLabel>
#include <QVBoxLayout>

/** "About" dialog box */
AboutDialog::AboutDialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::AboutDialog)
{
    ui->setupUi(this);

    // Set current copyright year
    ui->copyrightLabel->setText(tr("Copyright") + QString(" © 2009-%1 ").arg(COPYRIGHT_YEAR) + tr("The Bitcoin Core developers"));
}

void AboutDialog::setModel(ClientModel *model)
{
    if(model)
    {
        QString version = model->formatFullVersion();
        /* On x86 add a bit specifier to the version so that users can distinguish between
         * 32 and 64 bit builds. On other architectures, 32/64 bit may be more ambigious.
         */
#if defined(__x86_64__)
        version += " (64-bit)";
#elif defined(__i386__ )
        version += " (32-bit)";
#endif
        ui->versionLabel->setText(version);
    }
}

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

void AboutDialog::on_buttonBox_accepted()
{
    close();
}

/** "Help message" dialog box */
HelpMessageDialog::HelpMessageDialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::HelpMessageDialog)
{
    ui->setupUi(this);
    GUIUtil::restoreWindowGeometry("nHelpMessageDialogWindow", this->size(), this);

    header = tr("Bitcoin Core") + " " + tr("version") + " " +
        QString::fromStdString(FormatFullVersion()) + "\n\n" +
        tr("Usage:") + "\n" +
        "  bitcoin-qt [" + tr("command-line options") + "]                     " + "\n";

    coreOptions = QString::fromStdString(HelpMessage(HMM_BITCOIN_QT));

    uiOptions = tr("UI options") + ":\n" +
        "  -lang=<lang>           " + tr("Set language, for example \"de_DE\" (default: system locale)") + "\n" +
        "  -min                   " + tr("Start minimized") + "\n" +
        "  -splash                " + tr("Show splash screen on startup (default: 1)") + "\n" +
        "  -choosedatadir         " + tr("Choose data directory on startup (default: 0)");

    ui->helpMessageLabel->setFont(GUIUtil::bitcoinAddressFont());

    // Set help message text
    ui->helpMessageLabel->setText(header + "\n" + coreOptions + "\n" + uiOptions);
}

HelpMessageDialog::~HelpMessageDialog()
{
    GUIUtil::saveWindowGeometry("nHelpMessageDialogWindow", this);
    delete ui;
}

void HelpMessageDialog::printToConsole()
{
    // On other operating systems, the expected action is to print the message to the console.
    QString strUsage = header + "\n" + coreOptions + "\n" + uiOptions;
    fprintf(stdout, "%s", strUsage.toStdString().c_str());
}

void HelpMessageDialog::showOrPrint()
{
#if defined(WIN32)
        // On Windows, show a message box, as there is no stderr/stdout in windowed applications
        exec();
#else
        // On other operating systems, print help text to console
        printToConsole();
#endif
}

void HelpMessageDialog::on_okButton_accepted()
{
    close();
}

/** "Shutdown" window */
void ShutdownWindow::showShutdownWindow(BitcoinGUI *window)
{
    if (!window)
        return;

    // Show a simple window indicating shutdown status
    QWidget *shutdownWindow = new QWidget();
    QVBoxLayout *layout = new QVBoxLayout();
    layout->addWidget(new QLabel(
        tr("Bitcoin Core is shutting down...") + "

" +
        tr("Do not shut down the computer until this window disappears.")));
    shutdownWindow->setLayout(layout);

    // Center shutdown window at where main window was
    const QPoint global = window->mapToGlobal(window->rect().center());
    shutdownWindow->move(global.x() - shutdownWindow->width() / 2, global.y() - shutdownWindow->height() / 2);
    shutdownWindow->show();
}
<commit_msg>qt: Add closing newline to help message<commit_after>// Copyright (c) 2011-2014 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "utilitydialog.h"

#include "ui_aboutdialog.h"
#include "ui_helpmessagedialog.h"

#include "bitcoingui.h"
#include "clientmodel.h"
#include "guiutil.h"

#include "clientversion.h"
#include "init.h"
#include "util.h"

#include <QLabel>
#include <QVBoxLayout>

/** "About" dialog box */
AboutDialog::AboutDialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::AboutDialog)
{
    ui->setupUi(this);

    // Set current copyright year
    ui->copyrightLabel->setText(tr("Copyright") + QString(" © 2009-%1 ").arg(COPYRIGHT_YEAR) + tr("The Bitcoin Core developers"));
}

void AboutDialog::setModel(ClientModel *model)
{
    if(model)
    {
        QString version = model->formatFullVersion();
        /* On x86 add a bit specifier to the version so that users can distinguish between
         * 32 and 64 bit builds. On other architectures, 32/64 bit may be more ambigious.
         */
#if defined(__x86_64__)
        version += " (64-bit)";
#elif defined(__i386__ )
        version += " (32-bit)";
#endif
        ui->versionLabel->setText(version);
    }
}

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

void AboutDialog::on_buttonBox_accepted()
{
    close();
}

/** "Help message" dialog box */
HelpMessageDialog::HelpMessageDialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::HelpMessageDialog)
{
    ui->setupUi(this);
    GUIUtil::restoreWindowGeometry("nHelpMessageDialogWindow", this->size(), this);

    header = tr("Bitcoin Core") + " " + tr("version") + " " +
        QString::fromStdString(FormatFullVersion()) + "\n\n" +
        tr("Usage:") + "\n" +
        "  bitcoin-qt [" + tr("command-line options") + "]                     " + "\n";

    coreOptions = QString::fromStdString(HelpMessage(HMM_BITCOIN_QT));

    uiOptions = tr("UI options") + ":\n" +
        "  -lang=<lang>           " + tr("Set language, for example \"de_DE\" (default: system locale)") + "\n" +
        "  -min                   " + tr("Start minimized") + "\n" +
        "  -splash                " + tr("Show splash screen on startup (default: 1)") + "\n" +
        "  -choosedatadir         " + tr("Choose data directory on startup (default: 0)");

    ui->helpMessageLabel->setFont(GUIUtil::bitcoinAddressFont());

    // Set help message text
    ui->helpMessageLabel->setText(header + "\n" + coreOptions + "\n" + uiOptions);
}

HelpMessageDialog::~HelpMessageDialog()
{
    GUIUtil::saveWindowGeometry("nHelpMessageDialogWindow", this);
    delete ui;
}

void HelpMessageDialog::printToConsole()
{
    // On other operating systems, the expected action is to print the message to the console.
    QString strUsage = header + "\n" + coreOptions + "\n" + uiOptions + "\n";
    fprintf(stdout, "%s", strUsage.toStdString().c_str());
}

void HelpMessageDialog::showOrPrint()
{
#if defined(WIN32)
        // On Windows, show a message box, as there is no stderr/stdout in windowed applications
        exec();
#else
        // On other operating systems, print help text to console
        printToConsole();
#endif
}

void HelpMessageDialog::on_okButton_accepted()
{
    close();
}

/** "Shutdown" window */
void ShutdownWindow::showShutdownWindow(BitcoinGUI *window)
{
    if (!window)
        return;

    // Show a simple window indicating shutdown status
    QWidget *shutdownWindow = new QWidget();
    QVBoxLayout *layout = new QVBoxLayout();
    layout->addWidget(new QLabel(
        tr("Bitcoin Core is shutting down...") + "

" +
        tr("Do not shut down the computer until this window disappears.")));
    shutdownWindow->setLayout(layout);

    // Center shutdown window at where main window was
    const QPoint global = window->mapToGlobal(window->rect().center());
    shutdownWindow->move(global.x() - shutdownWindow->width() / 2, global.y() - shutdownWindow->height() / 2);
    shutdownWindow->show();
}
<|endoftext|>


<commit_before>#ifndef RDB_PROTOCOL_VAL_HPP_
#define RDB_PROTOCOL_VAL_HPP_

#include <string>
#include <utility>

#include "rdb_protocol/datum.hpp"
#include "rdb_protocol/datum_stream.hpp"
#include "rdb_protocol/func.hpp"
#include "rdb_protocol/ql2.pb.h"
#include "rdb_protocol/stream.hpp"

namespace ql {
class env_t;
class val_t;
class term_t;
class stream_cache2_t;
}

namespace ql {

class table_t : public ptr_baggable_t, public pb_rcheckable_t {
public:
    table_t(env_t *_env, uuid_u db_id, const std::string &name,
            bool use_outdated, const pb_rcheckable_t *src);
    datum_stream_t *as_datum_stream();
    const std::string &get_pkey();
    const datum_t *get_row(const datum_t *pval);
    datum_t *env_add_ptr(datum_t *d);

    const datum_t *make_error_datum(const any_ql_exc_t &exception);

    const datum_t *replace(const datum_t *orig, func_t *f, bool nondet_ok);
    const datum_t *replace(const datum_t *orig, const datum_t *d, bool upsert);

    std::vector<const datum_t *> batch_replace(const std::vector<const datum_t *> &original_values,
                                               func_t *replacement_generator,
                                               bool nondeterministic_replacements_ok);

    std::vector<const datum_t *> batch_replace(const std::vector<const datum_t *> &original_values,
                                               const std::vector<const datum_t *> &replacement_values,
                                               bool upsert);

private:
    struct datum_func_pair_t {
        datum_func_pair_t() : original_value(NULL), replacer(NULL), error_value(NULL) { }
        datum_func_pair_t(const datum_t *_original_value, const map_wire_func_t *_replacer)
            : original_value(_original_value), replacer(_replacer), error_value(NULL) { }

        explicit datum_func_pair_t(const datum_t *_error_value)
            : original_value(NULL), replacer(NULL), error_value(_error_value) { }

        // One of these datum_t *'s is NULL.
        const datum_t *original_value;
        const map_wire_func_t *replacer;
        const datum_t *error_value;
    };

    std::vector<const datum_t *> batch_replace(const std::vector<datum_func_pair_t> &replacements);

    struct datum_datum_pair_t {
        const datum_t *original_value;
        const datum_t *replacement_value;
    };

    const datum_t *do_replace(const datum_t *orig, const map_wire_func_t &mwf);
    const datum_t *do_replace(const datum_t *orig, func_t *f, bool nondet_ok);
    const datum_t *do_replace(const datum_t *orig, const datum_t *d, bool upsert);

    env_t *env;
    bool use_outdated;
    std::string pkey;
    scoped_ptr_t<namespace_repo_t<rdb_protocol_t>::access_t> access;
};

enum function_shortcut_t {
    NO_SHORTCUT = 0,
    IDENTITY_SHORTCUT = 1,
};

// A value is anything RQL can pass around -- a datum, a sequence, a function, a
// selection, whatever.
class val_t : public ptr_baggable_t, public pb_rcheckable_t {
public:
    // This type is intentionally opaque.  It is almost always an error to
    // compare two `val_t` types rather than testing whether one is convertible
    // to another.
    class type_t {
        friend class val_t;
        friend void run(Query *q, scoped_ptr_t<env_t> *env_ptr,
                        Response *res, stream_cache2_t *stream_cache2);
    public:
        enum raw_type_t {
            DB               = 1, // db
            TABLE            = 2, // table
            SELECTION        = 3, // table, sequence
            SEQUENCE         = 4, // sequence
            SINGLE_SELECTION = 5, // table, datum (object)
            DATUM            = 6, // datum
            FUNC             = 7  // func
        };
        type_t(raw_type_t _raw_type); // NOLINT
        bool is_convertible(type_t rhs) const;
    private:
        friend class coerce_term_t;
        friend class typeof_term_t;
        const char *name() const;
        raw_type_t raw_type;
    };
    type_t get_type() const;
    const char *get_type_name() const;

    val_t(const datum_t *_datum, const term_t *_parent, env_t *_env);
    val_t(const datum_t *_datum, table_t *_table, const term_t *_parent, env_t *_env);
    val_t(datum_stream_t *_sequence, const term_t *_parent, env_t *_env);
    val_t(table_t *_table, const term_t *_parent, env_t *_env);
    val_t(table_t *_table, datum_stream_t *_sequence,
          const term_t *_parent, env_t *_env);
    val_t(uuid_u _db, const term_t *_parent, env_t *_env);
    val_t(func_t *_func, const term_t *_parent, env_t *_env);

    uuid_u as_db();
    table_t *as_table();
    std::pair<table_t *, datum_stream_t *> as_selection();
    datum_stream_t *as_seq();
    std::pair<table_t *, const datum_t *> as_single_selection();
    // See func.hpp for an explanation of shortcut functions.
    func_t *as_func(function_shortcut_t shortcut = NO_SHORTCUT);

    const datum_t *as_datum(); // prefer the 4 below
    bool as_bool();
    double as_num();
    template<class T>
    T as_int() {
        int64_t i = as_int();
        T t = static_cast<T>(i);
        rcheck(static_cast<int64_t>(t) == i,
               strprintf("Integer too large: %" PRIi64, i));
        return t;
    }
    int64_t as_int();
    const std::string &as_str();

    std::string print() {
        if (get_type().is_convertible(type_t::DATUM)) {
            return as_datum()->print();
        } else {
            // TODO: Do something smarter here?
            return strprintf("OPAQUE VALUE %s", get_type().name());
        }
    }

private:
    void rcheck_literal_type(type_t::raw_type_t expected_raw_type);

    const term_t *parent;
    env_t *env;

    type_t type;
    uuid_u db;
    table_t *table;
    datum_stream_t *sequence;
    const datum_t *datum;
    func_t *func;

    DISABLE_COPYING(val_t);
};

}  //namespace ql

#endif // RDB_PROTOCOL_VAL_HPP_
<commit_msg>Removed the type datum_datum_pair_t.<commit_after>#ifndef RDB_PROTOCOL_VAL_HPP_
#define RDB_PROTOCOL_VAL_HPP_

#include <string>
#include <utility>

#include "rdb_protocol/datum.hpp"
#include "rdb_protocol/datum_stream.hpp"
#include "rdb_protocol/func.hpp"
#include "rdb_protocol/ql2.pb.h"
#include "rdb_protocol/stream.hpp"

namespace ql {
class env_t;
class val_t;
class term_t;
class stream_cache2_t;
}

namespace ql {

class table_t : public ptr_baggable_t, public pb_rcheckable_t {
public:
    table_t(env_t *_env, uuid_u db_id, const std::string &name,
            bool use_outdated, const pb_rcheckable_t *src);
    datum_stream_t *as_datum_stream();
    const std::string &get_pkey();
    const datum_t *get_row(const datum_t *pval);
    datum_t *env_add_ptr(datum_t *d);

    const datum_t *make_error_datum(const any_ql_exc_t &exception);

    const datum_t *replace(const datum_t *orig, func_t *f, bool nondet_ok);
    const datum_t *replace(const datum_t *orig, const datum_t *d, bool upsert);

    std::vector<const datum_t *> batch_replace(const std::vector<const datum_t *> &original_values,
                                               func_t *replacement_generator,
                                               bool nondeterministic_replacements_ok);

    std::vector<const datum_t *> batch_replace(const std::vector<const datum_t *> &original_values,
                                               const std::vector<const datum_t *> &replacement_values,
                                               bool upsert);

private:
    struct datum_func_pair_t {
        datum_func_pair_t() : original_value(NULL), replacer(NULL), error_value(NULL) { }
        datum_func_pair_t(const datum_t *_original_value, const map_wire_func_t *_replacer)
            : original_value(_original_value), replacer(_replacer), error_value(NULL) { }

        explicit datum_func_pair_t(const datum_t *_error_value)
            : original_value(NULL), replacer(NULL), error_value(_error_value) { }

        // One of these datum_t *'s is NULL.
        const datum_t *original_value;
        const map_wire_func_t *replacer;
        const datum_t *error_value;
    };

    std::vector<const datum_t *> batch_replace(const std::vector<datum_func_pair_t> &replacements);

    const datum_t *do_replace(const datum_t *orig, const map_wire_func_t &mwf);
    const datum_t *do_replace(const datum_t *orig, func_t *f, bool nondet_ok);
    const datum_t *do_replace(const datum_t *orig, const datum_t *d, bool upsert);

    env_t *env;
    bool use_outdated;
    std::string pkey;
    scoped_ptr_t<namespace_repo_t<rdb_protocol_t>::access_t> access;
};

enum function_shortcut_t {
    NO_SHORTCUT = 0,
    IDENTITY_SHORTCUT = 1,
};

// A value is anything RQL can pass around -- a datum, a sequence, a function, a
// selection, whatever.
class val_t : public ptr_baggable_t, public pb_rcheckable_t {
public:
    // This type is intentionally opaque.  It is almost always an error to
    // compare two `val_t` types rather than testing whether one is convertible
    // to another.
    class type_t {
        friend class val_t;
        friend void run(Query *q, scoped_ptr_t<env_t> *env_ptr,
                        Response *res, stream_cache2_t *stream_cache2);
    public:
        enum raw_type_t {
            DB               = 1, // db
            TABLE            = 2, // table
            SELECTION        = 3, // table, sequence
            SEQUENCE         = 4, // sequence
            SINGLE_SELECTION = 5, // table, datum (object)
            DATUM            = 6, // datum
            FUNC             = 7  // func
        };
        type_t(raw_type_t _raw_type); // NOLINT
        bool is_convertible(type_t rhs) const;
    private:
        friend class coerce_term_t;
        friend class typeof_term_t;
        const char *name() const;
        raw_type_t raw_type;
    };
    type_t get_type() const;
    const char *get_type_name() const;

    val_t(const datum_t *_datum, const term_t *_parent, env_t *_env);
    val_t(const datum_t *_datum, table_t *_table, const term_t *_parent, env_t *_env);
    val_t(datum_stream_t *_sequence, const term_t *_parent, env_t *_env);
    val_t(table_t *_table, const term_t *_parent, env_t *_env);
    val_t(table_t *_table, datum_stream_t *_sequence,
          const term_t *_parent, env_t *_env);
    val_t(uuid_u _db, const term_t *_parent, env_t *_env);
    val_t(func_t *_func, const term_t *_parent, env_t *_env);

    uuid_u as_db();
    table_t *as_table();
    std::pair<table_t *, datum_stream_t *> as_selection();
    datum_stream_t *as_seq();
    std::pair<table_t *, const datum_t *> as_single_selection();
    // See func.hpp for an explanation of shortcut functions.
    func_t *as_func(function_shortcut_t shortcut = NO_SHORTCUT);

    const datum_t *as_datum(); // prefer the 4 below
    bool as_bool();
    double as_num();
    template<class T>
    T as_int() {
        int64_t i = as_int();
        T t = static_cast<T>(i);
        rcheck(static_cast<int64_t>(t) == i,
               strprintf("Integer too large: %" PRIi64, i));
        return t;
    }
    int64_t as_int();
    const std::string &as_str();

    std::string print() {
        if (get_type().is_convertible(type_t::DATUM)) {
            return as_datum()->print();
        } else {
            // TODO: Do something smarter here?
            return strprintf("OPAQUE VALUE %s", get_type().name());
        }
    }

private:
    void rcheck_literal_type(type_t::raw_type_t expected_raw_type);

    const term_t *parent;
    env_t *env;

    type_t type;
    uuid_u db;
    table_t *table;
    datum_stream_t *sequence;
    const datum_t *datum;
    func_t *func;

    DISABLE_COPYING(val_t);
};

}  //namespace ql

#endif // RDB_PROTOCOL_VAL_HPP_
<|endoftext|>