<commit_before>#include "Variant.h"
#include "split.h"
#include <getopt.h>

using namespace std;
using namespace vcflib;

void printSummary(char** argv) {
    cerr << "usage: " << argv[0] << " [options] <vcf file>" << endl
         << endl
         << "options:" << endl
         << "    -f, --info-filter     specifies a filter to apply to the info fields of records," << endl
         << "                          removes alleles which do not pass the filter" << endl
         << "    -g, --genotype-filter specifies a filter to apply to the genotype fields of records" << endl
         << "    -k, --keep-info       used in conjunction with '-g', keeps variant info, but removes genotype" << endl
         << "    -s, --filter-sites    filter entire records, not just alleles" << endl
         << "    -t, --tag-pass        tag vcf records as positively filtered with this tag, print all records" << endl
         << "    -F, --tag-fail        tag vcf records as negatively filtered with this tag, print all records" << endl
         << "    -A, --append-filter   append the existing filter tag, don't just replace it" << endl
         << "    -a, --allele-tag      apply -t on a per-allele basis.  adds or sets the corresponding INFO field tag" << endl
         << "    -v, --invert          inverts the filter, e.g. grep -v" << endl
         << "    -o, --or              use logical OR instead of AND to combine filters" << endl
         << "    -r, --region          specify a region on which to target the filtering, requires a BGZF" << endl
         << "                          compressed file which has been indexed with tabix.  any number of" << endl
         << "                          regions may be specified." << endl
         << endl
         << "Filter the specified vcf file using the set of filters." << endl
         << "Filters are specified in the form \"<ID> <operator> <value>:" << endl
         << " -f \"DP > 10\"  # for info fields" << endl
         << " -g \"GT = 1|1\" # for genotype fields" << endl
         << " -f \"CpG\"  # for 'flag' fields" << endl
         << endl
         << "Operators can be any of: =, !, <, >, |, &" << endl
         << endl
         << "Any number of filters may be specified.  They are combined via logical AND" << endl
         << "unless --or is specified on the command line.  Obtain logical negation through" << endl
         << "the use of parentheses, e.g. \"! ( DP = 10 )\"" << endl
         << endl
         << "For convenience, you can specify \"QUAL\" to refer to the quality of the site, even" << endl
         << "though it does not appear in the INFO fields." << endl
         << endl;
    exit(0);
}

bool passesFilters(Variant& var, vector<VariantFilter>& filters, bool logicalOr, string alt = "") {
    for (vector<VariantFilter>::iterator f = filters.begin(); f != filters.end(); ++f) {
        string s = "";
        if (logicalOr) {
            if (alt.empty()) {
                if (f->passes(var, s)) return true;
            } else {
                if (f->passes(var, s, alt)) return true;
            }
        } else {
            if (alt.empty()) {
                if (!f->passes(var, s)) return false;
            } else {
                if (!f->passes(var, s, alt)) return false;
            }
        }
    }
    if (logicalOr)
        return false;
    else
        return true;
}

int main(int argc, char** argv) {

    int c;
    bool invert = false;
    bool logicalOr = false;
    bool filterSites = false;
    bool keepInfo = false;
    vector<string> infofilterStrs;
    vector<VariantFilter> infofilters;
    vector<string> genofilterStrs;
    vector<VariantFilter> genofilters;
    string tagPass = "";
    string tagFail = "";
    string filterSpec;
    string alleleTag;
    vector<string> regions;
    bool replaceFilter = true;

    if (argc == 1)
        printSummary(argv);

    while (true) {
        static struct option long_options[] =
            {
                /* These options set a flag. */
                //{"verbose", no_argument,       &verbose_flag, 1},
                {"help", no_argument, 0, 'h'},
                {"filter-sites", no_argument, 0, 's'},
                {"info-filter",  required_argument, 0, 'f'},
                {"genotype-filter",  required_argument, 0, 'g'},
                {"tag-pass", required_argument, 0, 't'},
                {"tag-pass", required_argument, 0, 'F'},
                {"append-filter", no_argument, 0, 'A'},
                {"allele-tag", required_argument, 0, 'a'},
                {"invert", no_argument, 0, 'v'},
                {"or", no_argument, 0, 'o'},
                {"region", required_argument, 0, 'r'},
                {"keep-info", no_argument, 0, 'k'},
                //{"length",  no_argument, &printLength, true},
                {0, 0, 0, 0}
            };
        /* getopt_long stores the option index here. */
        int option_index = 0;

        c = getopt_long (argc, argv, "hvAsof:g:kt:F:r:a:",
                         long_options, &option_index);

        /* Detect the end of the options. */
        if (c == -1)
            break;

        switch (c)
        {
        case 0:
            /* If this option set a flag, do nothing else now. */
            if (long_options[option_index].flag != 0)
                break;
            printf ("option %s", long_options[option_index].name);
            if (optarg)
                printf (" with arg %s", optarg);
            printf ("\n");
            break;

        case 'f':
            filterSpec += " " + string(optarg);
            infofilterStrs.push_back(string(optarg));
            break;

        case 's':
            filterSites = true;
            break;

        case 'a':
            alleleTag = optarg;
            break;

        case 'g':
            filterSpec += " genotypes filtered with: " + string(optarg);
            genofilterStrs.push_back(string(optarg));
            break;

        case 't':
            tagPass = optarg;
            break;

        case 'F':
            tagFail = optarg;
            break;

        case 'A':
            replaceFilter = false;
            break;

        case 'h':
            printSummary(argv);
            exit(0);
            break;

        case 'v':
            invert = true;
            break;

        case 'o':
            logicalOr = true;
            break;

        case 'r':
            regions.push_back(optarg);
            break;

        case 'k':
        	keepInfo = true;
        	break;

        case '?':
            /* getopt_long already printed an error message. */
            printSummary(argv);
            exit(1);
            break;

        default:
            abort ();
        }
    }

    if (genofilterStrs.size() == 0 && keepInfo) {
		cout << "argument '-k' (--keep-info) requires a Genotype filter: ('-g')" << endl
			<< "i.e.: -g \"GT = 1|1\" -k" << endl;
		exit(1);
	}

    filterSpec = filterSpec.substr(1); // strip leading " "

    VariantCallFile variantFile;
    string inputFilename;
    if (optind == argc - 1) {
        inputFilename = argv[optind];
        variantFile.open(inputFilename);
    } else {
        variantFile.open(std::cin);
    }

    if (!variantFile.is_open()) {
        return 1;
    }

    for (vector<string>::iterator f = infofilterStrs.begin(); f != infofilterStrs.end(); ++f) {
        infofilters.push_back(VariantFilter(*f, VariantFilter::RECORD, variantFile.infoTypes));
    }

    for (vector<string>::iterator f = genofilterStrs.begin(); f != genofilterStrs.end(); ++f) {
        genofilters.push_back(VariantFilter(*f, VariantFilter::SAMPLE, variantFile.formatTypes));
    }

    vector<string> headerlines = split(variantFile.header, "\n");
    variantFile.header.clear();
    for (vector<string>::iterator l = headerlines.begin(); l != headerlines.end(); ++l) {
        if (!filterSpec.empty() && (l->find("INFO") != string::npos || l + 1 == headerlines.end())) {
            variantFile.header += "##filter=\"" + filterSpec + "\"\n";
            filterSpec.clear();
        }
        variantFile.header += *l + ((l + 1 == headerlines.end()) ? "" : "\n");
    }

    if (!tagPass.empty()) {
        variantFile.addHeaderLine("##FILTER=<ID="+ tagPass +",Description=\"Record passes the filters: " + filterSpec + ".\">");
    }

    if (!tagFail.empty()) {
        variantFile.addHeaderLine("##FILTER=<ID="+ tagFail +",Description=\"Record fails the filters: " + filterSpec + ".\">");
    }

    if (!alleleTag.empty()) {
        if (tagFail.empty()) {
            tagFail = "";
        }
        if (tagPass.empty()) {
            tagPass = "PASS";
        }
        variantFile.addHeaderLine("##INFO=<ID="+ alleleTag +",Number=A,Type=String,Description=\"" + tagPass + " if this allele passes the filters, " + tagFail + " if not, filters are: " + filterSpec + ".\">");
    }

    cout << variantFile.header << endl;

    /*
      if (genofilters.empty()) {
      variantFile.parseSamples = false;
      }
    */

    if (filterSites) {
        variantFile.parseSamples = false;
    }

    Variant var(variantFile);

    vector<string>::iterator regionItr = regions.begin();

    do {

        if (!inputFilename.empty() && !regions.empty()) {
            string regionStr = *regionItr++;
            variantFile.setRegion(regionStr);
        }

        while (variantFile.getNextVariant(var)) {
            if (!genofilters.empty()) {
                for (vector<VariantFilter>::iterator f = genofilters.begin(); f != genofilters.end(); ++f) {
					f->removeFilteredGenotypes(var, keepInfo);
                }
            }
            if (!infofilters.empty()) {
                if (filterSites) {
                    bool passes = passesFilters(var, infofilters, logicalOr);
                    if (invert) {
                        passes = !passes;
                    }
                    if (passes) {
                        if (!tagPass.empty()) {
                            if (alleleTag.empty()) {
                                if (replaceFilter) {
                                    var.filter.clear();
                                    var.addFilter(tagPass);
                                } else {
                                    var.addFilter(tagPass);
                                }
                            } else {
                                var.info[alleleTag].clear();
                                for (vector<string>::iterator a = var.alt.begin(); a != var.alt.end(); ++a) {
                                    var.info[alleleTag].push_back(tagPass);
                                }
                            }
                        } else {
                            if (!var.originalLine.empty()) {
                                cout << var.originalLine << endl;
                            } else {
                                cout << var << endl;
                            }
                        }
                    } else {
                        if (!tagFail.empty()) {
                            if (alleleTag.empty()) {
                                if (replaceFilter) {
                                    var.filter.clear();
                                    var.addFilter(tagFail);
                                } else {
                                    var.addFilter(tagFail);
                                }
                            } else {
                                var.info[alleleTag].clear();
                                for (vector<string>::iterator a = var.alt.begin(); a != var.alt.end(); ++a) {
                                    var.info[alleleTag].push_back(tagFail);
                                }
                            }
                        }
                    }
                    if (passes && !tagPass.empty()) {
                        cout << var << endl;
                    } else if (!tagFail.empty()) {
                        cout << var << endl;
                    }
                } else { // filter out alleles which pass
                    // removes the failing alleles
                    vector<string> failingAlts;
                    vector<string> passingAlts;
                    vector<bool> passes;
                    for (vector<string>::iterator a = var.alt.begin(); a != var.alt.end(); ++a) {
                        if (!passesFilters(var, infofilters, logicalOr, *a)) {
                            failingAlts.push_back(*a);
                            passes.push_back(false);
                        } else {
                            passingAlts.push_back(*a);
                            passes.push_back(true);
                        }
                    }
                    if (tagPass.empty()) { // if there is no specified tag, just remove the failing alts
                        if (failingAlts.size() < var.alt.size()) {
                            for (vector<string>::iterator a = failingAlts.begin(); a != failingAlts.end(); ++a) {
                                var.removeAlt(*a);
                            }
                            cout << var << endl;
                        }
                    } else { // otherwise, apply the tag
                        if (alleleTag.empty()) {
                            if (!passingAlts.empty()) {
                                if (replaceFilter) {
                                    var.filter.clear();
                                    var.addFilter(tagPass);
                                } else {
                                    var.addFilter(tagPass);
                                }
                            } else {
                                if (replaceFilter) {
                                    var.filter.clear();
                                    if (!tagFail.empty()) {
                                        var.addFilter(tagFail);
                                    }
                                } else {
                                    if (!tagFail.empty()) {
                                        var.addFilter(tagFail);
                                    }
                                }
                            }
                        } else {
                            var.info[alleleTag].clear();
                            for (vector<bool>::iterator p = passes.begin(); p != passes.end(); ++p) {
                                if (*p) {
                                    var.info[alleleTag].push_back(tagPass);
                                } else {
                                    var.info[alleleTag].push_back(tagFail);
                                }
                            }
                        }
                        // TODO
                        // here, if we don't use genotype filters, we shouldn't re-print the samples
                        // we haven't done anything to this part of the input.
                        cout << var << endl;
                    }
                }
            } else {
                if (genofilters.empty()) {
                    cout << variantFile.line << endl;
                } else {
                    cout << var << endl;
                }
            }
        }

    } while (regionItr != regions.end());

    return 0;

}

<commit_msg>fix issue #86<commit_after>#include "Variant.h"
#include "split.h"
#include <getopt.h>

using namespace std;
using namespace vcflib;

void printSummary(char** argv) {
    cerr << "usage: " << argv[0] << " [options] <vcf file>" << endl
         << endl
         << "options:" << endl
         << "    -f, --info-filter     specifies a filter to apply to the info fields of records," << endl
         << "                          removes alleles which do not pass the filter" << endl
         << "    -g, --genotype-filter specifies a filter to apply to the genotype fields of records" << endl
         << "    -k, --keep-info       used in conjunction with '-g', keeps variant info, but removes genotype" << endl
         << "    -s, --filter-sites    filter entire records, not just alleles" << endl
         << "    -t, --tag-pass        tag vcf records as positively filtered with this tag, print all records" << endl
         << "    -F, --tag-fail        tag vcf records as negatively filtered with this tag, print all records" << endl
         << "    -A, --append-filter   append the existing filter tag, don't just replace it" << endl
         << "    -a, --allele-tag      apply -t on a per-allele basis.  adds or sets the corresponding INFO field tag" << endl
         << "    -v, --invert          inverts the filter, e.g. grep -v" << endl
         << "    -o, --or              use logical OR instead of AND to combine filters" << endl
         << "    -r, --region          specify a region on which to target the filtering, requires a BGZF" << endl
         << "                          compressed file which has been indexed with tabix.  any number of" << endl
         << "                          regions may be specified." << endl
         << endl
         << "Filter the specified vcf file using the set of filters." << endl
         << "Filters are specified in the form \"<ID> <operator> <value>:" << endl
         << " -f \"DP > 10\"  # for info fields" << endl
         << " -g \"GT = 1|1\" # for genotype fields" << endl
         << " -f \"CpG\"  # for 'flag' fields" << endl
         << endl
         << "Operators can be any of: =, !, <, >, |, &" << endl
         << endl
         << "Any number of filters may be specified.  They are combined via logical AND" << endl
         << "unless --or is specified on the command line.  Obtain logical negation through" << endl
         << "the use of parentheses, e.g. \"! ( DP = 10 )\"" << endl
         << endl
         << "For convenience, you can specify \"QUAL\" to refer to the quality of the site, even" << endl
         << "though it does not appear in the INFO fields." << endl
         << endl;
    exit(0);
}

bool passesFilters(Variant& var, vector<VariantFilter>& filters, bool logicalOr, string alt = "") {
    for (vector<VariantFilter>::iterator f = filters.begin(); f != filters.end(); ++f) {
        string s = "";
        if (logicalOr) {
            if (alt.empty()) {
                if (f->passes(var, s)) return true;
            } else {
                if (f->passes(var, s, alt)) return true;
            }
        } else {
            if (alt.empty()) {
                if (!f->passes(var, s)) return false;
            } else {
                if (!f->passes(var, s, alt)) return false;
            }
        }
    }
    if (logicalOr)
        return false;
    else
        return true;
}

int main(int argc, char** argv) {

    int c;
    bool invert = false;
    bool logicalOr = false;
    bool filterSites = false;
    bool keepInfo = false;
    vector<string> infofilterStrs;
    vector<VariantFilter> infofilters;
    vector<string> genofilterStrs;
    vector<VariantFilter> genofilters;
    string tagPass = "";
    string tagFail = "";
    string filterSpec;
    string alleleTag;
    vector<string> regions;
    bool replaceFilter = true;

    if (argc == 1)
        printSummary(argv);

    while (true) {
        static struct option long_options[] =
            {
                /* These options set a flag. */
                //{"verbose", no_argument,       &verbose_flag, 1},
                {"help", no_argument, 0, 'h'},
                {"filter-sites", no_argument, 0, 's'},
                {"info-filter",  required_argument, 0, 'f'},
                {"genotype-filter",  required_argument, 0, 'g'},
                {"tag-pass", required_argument, 0, 't'},
                {"tag-pass", required_argument, 0, 'F'},
                {"append-filter", no_argument, 0, 'A'},
                {"allele-tag", required_argument, 0, 'a'},
                {"invert", no_argument, 0, 'v'},
                {"or", no_argument, 0, 'o'},
                {"region", required_argument, 0, 'r'},
                {"keep-info", no_argument, 0, 'k'},
                //{"length",  no_argument, &printLength, true},
                {0, 0, 0, 0}
            };
        /* getopt_long stores the option index here. */
        int option_index = 0;

        c = getopt_long (argc, argv, "hvAsof:g:kt:F:r:a:",
                         long_options, &option_index);

        /* Detect the end of the options. */
        if (c == -1)
            break;

        switch (c)
        {
        case 0:
            /* If this option set a flag, do nothing else now. */
            if (long_options[option_index].flag != 0)
                break;
            printf ("option %s", long_options[option_index].name);
            if (optarg)
                printf (" with arg %s", optarg);
            printf ("\n");
            break;

        case 'f':
            filterSpec += " " + string(optarg);
            infofilterStrs.push_back(string(optarg));
            break;

        case 's':
            filterSites = true;
            break;

        case 'a':
            alleleTag = optarg;
            break;

        case 'g':
            filterSpec += " genotypes filtered with: " + string(optarg);
            genofilterStrs.push_back(string(optarg));
            break;

        case 't':
            tagPass = optarg;
            break;

        case 'F':
            tagFail = optarg;
            break;

        case 'A':
            replaceFilter = false;
            break;

        case 'h':
            printSummary(argv);
            exit(0);
            break;

        case 'v':
            invert = true;
            break;

        case 'o':
            logicalOr = true;
            break;

        case 'r':
            regions.push_back(optarg);
            break;

        case 'k':
        	keepInfo = true;
        	break;

        case '?':
            /* getopt_long already printed an error message. */
            printSummary(argv);
            exit(1);
            break;

        default:
            abort ();
        }
    }

    if(filterSpec.empty()){
      cout << "Argument -g or -f is required" << endl;
      exit(1);
    }

    if (genofilterStrs.size() == 0 && keepInfo) {
		cout << "argument '-k' (--keep-info) requires a Genotype filter: ('-g')" << endl
			<< "i.e.: -g \"GT = 1|1\" -k" << endl;
		exit(1);
	}

    filterSpec = filterSpec.substr(1); // strip leading " "

    VariantCallFile variantFile;
    string inputFilename;
    if (optind == argc - 1) {
        inputFilename = argv[optind];
        variantFile.open(inputFilename);
    } else {
        variantFile.open(std::cin);
    }

    if (!variantFile.is_open()) {
        return 1;
    }

    for (vector<string>::iterator f = infofilterStrs.begin(); f != infofilterStrs.end(); ++f) {
        infofilters.push_back(VariantFilter(*f, VariantFilter::RECORD, variantFile.infoTypes));
    }

    for (vector<string>::iterator f = genofilterStrs.begin(); f != genofilterStrs.end(); ++f) {
        genofilters.push_back(VariantFilter(*f, VariantFilter::SAMPLE, variantFile.formatTypes));
    }

    vector<string> headerlines = split(variantFile.header, "\n");
    variantFile.header.clear();
    for (vector<string>::iterator l = headerlines.begin(); l != headerlines.end(); ++l) {
        if (!filterSpec.empty() && (l->find("INFO") != string::npos || l + 1 == headerlines.end())) {
            variantFile.header += "##filter=\"" + filterSpec + "\"\n";
            filterSpec.clear();
        }
        variantFile.header += *l + ((l + 1 == headerlines.end()) ? "" : "\n");
    }

    if (!tagPass.empty()) {
        variantFile.addHeaderLine("##FILTER=<ID="+ tagPass +",Description=\"Record passes the filters: " + filterSpec + ".\">");
    }

    if (!tagFail.empty()) {
        variantFile.addHeaderLine("##FILTER=<ID="+ tagFail +",Description=\"Record fails the filters: " + filterSpec + ".\">");
    }

    if (!alleleTag.empty()) {
        if (tagFail.empty()) {
            tagFail = "";
        }
        if (tagPass.empty()) {
            tagPass = "PASS";
        }
        variantFile.addHeaderLine("##INFO=<ID="+ alleleTag +",Number=A,Type=String,Description=\"" + tagPass + " if this allele passes the filters, " + tagFail + " if not, filters are: " + filterSpec + ".\">");
    }

    cout << variantFile.header << endl;

    /*
      if (genofilters.empty()) {
      variantFile.parseSamples = false;
      }
    */

    if (filterSites) {
        variantFile.parseSamples = false;
    }

    Variant var(variantFile);

    vector<string>::iterator regionItr = regions.begin();

    do {

        if (!inputFilename.empty() && !regions.empty()) {
            string regionStr = *regionItr++;
            variantFile.setRegion(regionStr);
        }

        while (variantFile.getNextVariant(var)) {
            if (!genofilters.empty()) {
                for (vector<VariantFilter>::iterator f = genofilters.begin(); f != genofilters.end(); ++f) {
					f->removeFilteredGenotypes(var, keepInfo);
                }
            }
            if (!infofilters.empty()) {
                if (filterSites) {
                    bool passes = passesFilters(var, infofilters, logicalOr);
                    if (invert) {
                        passes = !passes;
                    }
                    if (passes) {
                        if (!tagPass.empty()) {
                            if (alleleTag.empty()) {
                                if (replaceFilter) {
                                    var.filter.clear();
                                    var.addFilter(tagPass);
                                } else {
                                    var.addFilter(tagPass);
                                }
                            } else {
                                var.info[alleleTag].clear();
                                for (vector<string>::iterator a = var.alt.begin(); a != var.alt.end(); ++a) {
                                    var.info[alleleTag].push_back(tagPass);
                                }
                            }
                        } else {
                            if (!var.originalLine.empty()) {
                                cout << var.originalLine << endl;
                            } else {
                                cout << var << endl;
                            }
                        }
                    } else {
                        if (!tagFail.empty()) {
                            if (alleleTag.empty()) {
                                if (replaceFilter) {
                                    var.filter.clear();
                                    var.addFilter(tagFail);
                                } else {
                                    var.addFilter(tagFail);
                                }
                            } else {
                                var.info[alleleTag].clear();
                                for (vector<string>::iterator a = var.alt.begin(); a != var.alt.end(); ++a) {
                                    var.info[alleleTag].push_back(tagFail);
                                }
                            }
                        }
                    }
                    if (passes && !tagPass.empty()) {
                        cout << var << endl;
                    } else if (!tagFail.empty()) {
                        cout << var << endl;
                    }
                } else { // filter out alleles which pass
                    // removes the failing alleles
                    vector<string> failingAlts;
                    vector<string> passingAlts;
                    vector<bool> passes;
                    for (vector<string>::iterator a = var.alt.begin(); a != var.alt.end(); ++a) {
                        if (!passesFilters(var, infofilters, logicalOr, *a)) {
                            failingAlts.push_back(*a);
                            passes.push_back(false);
                        } else {
                            passingAlts.push_back(*a);
                            passes.push_back(true);
                        }
                    }
                    if (tagPass.empty()) { // if there is no specified tag, just remove the failing alts
                        if (failingAlts.size() < var.alt.size()) {
                            for (vector<string>::iterator a = failingAlts.begin(); a != failingAlts.end(); ++a) {
                                var.removeAlt(*a);
                            }
                            cout << var << endl;
                        }
                    } else { // otherwise, apply the tag
                        if (alleleTag.empty()) {
                            if (!passingAlts.empty()) {
                                if (replaceFilter) {
                                    var.filter.clear();
                                    var.addFilter(tagPass);
                                } else {
                                    var.addFilter(tagPass);
                                }
                            } else {
                                if (replaceFilter) {
                                    var.filter.clear();
                                    if (!tagFail.empty()) {
                                        var.addFilter(tagFail);
                                    }
                                } else {
                                    if (!tagFail.empty()) {
                                        var.addFilter(tagFail);
                                    }
                                }
                            }
                        } else {
                            var.info[alleleTag].clear();
                            for (vector<bool>::iterator p = passes.begin(); p != passes.end(); ++p) {
                                if (*p) {
                                    var.info[alleleTag].push_back(tagPass);
                                } else {
                                    var.info[alleleTag].push_back(tagFail);
                                }
                            }
                        }
                        // TODO
                        // here, if we don't use genotype filters, we shouldn't re-print the samples
                        // we haven't done anything to this part of the input.
                        cout << var << endl;
                    }
                }
            } else {
                if (genofilters.empty()) {
                    cout << variantFile.line << endl;
                } else {
                    cout << var << endl;
                }
            }
        }

    } while (regionItr != regions.end());

    return 0;

}

<|endoftext|>


<commit_before>#include "model.h"
#include "modelwidget.h"
#include "figurepainter.h"
#include "recognition.h"
#include "layouting.h"
#include <QPainter>
#include <QMouseEvent>
#include <QInputDialog>
#include <QGesture>
#include <QDebug>
#include <QTimer>
#include <iostream>

Ui::ModelWidget::ModelWidget(QWidget *parent) :
    QWidget(parent), mouseAction(MouseAction::None), _gridStep(0), _showTrack(true), _showRecognitionResult(true) {
    setFocusPolicy(Qt::FocusPolicy::StrongFocus);
    grabGesture(Qt::PinchGesture);
}

void drawTrack(QPainter &painter, Scaler &scaler, const Track &track) {
    for (size_t i = 0; i + 1 < track.size(); i++) {
        painter.drawLine(scaler(track[i]), scaler(track[i + 1]));
    }
}

int Ui::ModelWidget::gridStep() {
    return _gridStep;
}

void Ui::ModelWidget::setGridStep(int newGridStep) {
    if (newGridStep < 0) {
        throw std::runtime_error("Grid step should be >= 0");
    }
    _gridStep = newGridStep;
    repaint();
}

double Ui::ModelWidget::scaleFactor() {
    return scaler.scaleFactor;
}

void Ui::ModelWidget::setScaleFactor(double newScaleFactor) {
    if (!(newScaleFactor >= 0.01)) { // >= instead of < for NaNs
        throw std::runtime_error("Scale factor should be >= 0.01");
    }
    scaler.scaleFactor = newScaleFactor;
    emit scaleFactorChanged();
    repaint();
}

bool Ui::ModelWidget::showTrack() {
    return _showTrack;
}
void Ui::ModelWidget::setShowTrack(bool newShowTrack) {
    _showTrack = newShowTrack;
}

bool Ui::ModelWidget::showRecognitionResult() {
    return _showRecognitionResult;
}
void Ui::ModelWidget::setShowRecognitionResult(bool newShowRecognitionResult) {
    _showRecognitionResult = newShowRecognitionResult;
}

void Ui::ModelWidget::setModel(Model model) {
    commitedModel = std::move(model);
    previousModels.clear();
    redoModels.clear();
    emit canUndoChanged();
    emit canRedoChanged();
}
Model &Ui::ModelWidget::getModel() {
    return commitedModel;
}

bool Ui::ModelWidget::canUndo() {
    return !previousModels.empty();
}

void Ui::ModelWidget::undo() {
    if (!canUndo()) {
        throw std::runtime_error("Cannot undo");
    }
    redoModels.push_front(std::move(commitedModel));
    commitedModel = std::move(previousModels.back());
    previousModels.pop_back();
    if (!canUndo()) {
        emit canUndoChanged();
    }
    emit canRedoChanged();
    repaint();
}

bool Ui::ModelWidget::canRedo() {
    return !redoModels.empty();
}

void Ui::ModelWidget::redo() {
    if (!canRedo()) {
        throw std::runtime_error("Cannot redo");
    }
    previousModels.push_back(std::move(commitedModel));
    commitedModel = std::move(redoModels.front());
    redoModels.pop_front();
    if (!canRedo()) {
        canRedoChanged();
    }
    canUndoChanged();
    repaint();
}

double roundDownToMultiple(double x, double multiple) {
    return floor(x / multiple) * multiple;
}

void Ui::ModelWidget::paintEvent(QPaintEvent *) {
    QPainter painter(this);
    painter.fillRect(QRect(QPoint(), size()), Qt::white);

    QFont font;
    font.setPointSizeF(10 * scaler.scaleFactor);
    painter.setFont(font);

    QPen pen(Qt::black);
    pen.setWidthF(scaler.scaleFactor);
    painter.setPen(pen);

    FigurePainter fpainter(painter, scaler);
    if (gridStep() > 0) {
        int step = gridStep();
        // Calculating visible area
        Point p1 = scaler(QPointF(0, 0));
        Point p2 = scaler(QPointF(width(), height()));
        if (p1.x > p2.x) { std::swap(p1.x, p2.x); }
        if (p1.y > p2.y) { std::swap(p1.y, p2.y); }

        // Finding starting point for the grid
        p1.x = roundDownToMultiple(p1.x, step);
        p1.y = roundDownToMultiple(p1.y, step);

        // Drawing
        QPen pen(QColor(192, 192, 192, 255));
        pen.setStyle(Qt::DashLine);
        painter.setPen(pen);
        for (int x = p1.x; x <= p2.x; x += step) {
            painter.drawLine(scaler(Point(x, p1.y)), scaler(Point(x, p2.y)));
        }
        for (int y = p1.y; y <= p2.y; y += step) {
            painter.drawLine(scaler(Point(p1.x, y)), scaler(Point(p2.x, y)));
        }
    }

    Model copiedModel;
    Model &modelToDraw = (lastTrack.empty() || !showRecognitionResult()) ? commitedModel : (copiedModel = commitedModel);
    PFigure modified = showRecognitionResult() ? recognize(lastTrack, modelToDraw) : nullptr;
    for (PFigure fig : modelToDraw) {
        if (fig == modified) {
            pen.setColor(Qt::magenta);
        } else if (fig == modelToDraw.selectedFigure) {
            pen.setColor(Qt::blue);
        } else {
            pen.setColor(Qt::black);
        }
        painter.setPen(pen);
        fig->visit(fpainter);
    }

    if (showTrack()) {
        pen.setColor(QColor(255, 0, 0, 16));
        pen.setWidth(3 * scaler.scaleFactor);
        painter.setPen(pen);
        drawTrack(painter, scaler, lastTrack);
        for (const Track &track : visibleTracks) {
            drawTrack(painter, scaler, track);
        }
    }
}

void Ui::ModelWidget::mousePressEvent(QMouseEvent *event) {
    lastTrack = Track();
    if (event->modifiers().testFlag(Qt::ShiftModifier)) {
        mouseAction = MouseAction::ViewpointMove;
        viewpointMoveStart = event->pos();
        viewpointMoveOldScaler = scaler;
        setCursor(Qt::ClosedHandCursor);
    } else {
        mouseAction = MouseAction::TrackActive;
        lastTrack.points.push_back(scaler(event->pos()));
    }
    repaint();
}
void Ui::ModelWidget::mouseMoveEvent(QMouseEvent *event) {
    if (mouseAction == MouseAction::ViewpointMove) {
        scaler = viewpointMoveOldScaler;
        scaler.zeroPoint = scaler.zeroPoint + scaler(viewpointMoveStart) - scaler(event->pos());
        repaint();
    } else if (mouseAction == MouseAction::TrackActive) {
        lastTrack.points.push_back(scaler(event->pos()));
        if (showTrack() || showRecognitionResult()) {
            repaint();
        }
    } else {
        event->ignore();
    }
}
void Ui::ModelWidget::mouseReleaseEvent(QMouseEvent *event) {
    if (mouseAction == MouseAction::None) {
        event->ignore();
        return;
    }
    if (mouseAction == MouseAction::ViewpointMove) {
        mouseAction = MouseAction::None;
        setCursor(Qt::ArrowCursor);
        scaler = viewpointMoveOldScaler;
        scaler.zeroPoint = scaler.zeroPoint + scaler(viewpointMoveStart) - scaler(event->pos());
        repaint();
        return;
    }
    assert(mouseAction == MouseAction::TrackActive);
    mouseAction = MouseAction::None;
    lastTrack.points.push_back(scaler(event->pos()));
    Model previousModel = commitedModel;
    PFigure modifiedFigure = recognize(lastTrack, commitedModel);
    if (_gridStep > 0 && modifiedFigure) {
        GridAlignLayouter layouter(_gridStep);
        layouter.updateLayout(commitedModel, modifiedFigure);
        commitedModel.recalculate();
    }

    visibleTracks.push_back(lastTrack);
    auto iterator = --visibleTracks.end();
    QTimer *timer = new QTimer(this);

    connect(timer, &QTimer::timeout, [this, iterator, timer]() {
        visibleTracks.erase(iterator);
        delete timer;
        repaint();
    });
    timer->setInterval(1500);
    timer->setSingleShot(true);
    timer->start();

    lastTrack = Track();
    if (modifiedFigure) {
        previousModels.push_back(previousModel);
        redoModels.clear();
        emit canUndoChanged();
        emit canRedoChanged();
    }
    repaint();
}
void Ui::ModelWidget::keyReleaseEvent(QKeyEvent *event) {
    event->ignore();
    if (event->key() == Qt::Key_Escape && mouseAction == MouseAction::TrackActive) {
        event->accept();
        lastTrack = Track();
        mouseAction = MouseAction::None;
        repaint();
    }
    if (event->key() == Qt::Key_Delete) {
        if (commitedModel.selectedFigure) {
            event->accept();
            previousModels.push_back(commitedModel);
            redoModels.clear();
            for (auto it = commitedModel.begin(); it != commitedModel.end(); it++) {
                if (*it == commitedModel.selectedFigure) {
                    commitedModel.removeFigure(it);
                    break;
                }
            }
            emit canUndoChanged();
            emit canRedoChanged();
            repaint();
        }
    }
}

void Ui::ModelWidget::mouseDoubleClickEvent(QMouseEvent *event) {
    event->ignore();
    auto &figure = commitedModel.selectedFigure;
    if (!figure) { return; }

    Point eventPos = scaler(event->pos());
    bool hit = false;
    hit |= figure->isInsideOrOnBorder(eventPos);
    hit |= figure->getApproximateDistanceToBorder(eventPos) <= figureSelectGap();
    if (!hit) { return; }

    event->accept();
    bool ok;
    QString newLabel = QInputDialog::getMultiLineText(this, "Figure label", "Specify new figure label",
                                             QString::fromStdString(figure->label()),
                                                      &ok);
    if (ok) {
        previousModels.push_back(commitedModel);
        redoModels.clear();

        figure->setLabel(newLabel.toStdString());

        emit canUndoChanged();
        emit canRedoChanged();
        repaint();
    }
}

bool Ui::ModelWidget::event(QEvent *event) {
    if (event->type() == QEvent::Gesture) {
        QGestureEvent *gevent = static_cast<QGestureEvent*>(event);
        QPinchGesture *gesture = static_cast<QPinchGesture*>(gevent->gesture(Qt::PinchGesture));
        if (gesture) {
            gevent->accept(gesture);

            lastTrack = Track();
            mouseAction = MouseAction::None;

            scaler.zeroPoint = scaler.zeroPoint + scaler(gesture->lastCenterPoint()) - scaler(gesture->centerPoint());
            scaler.scaleWithFixedPoint(scaler(gesture->centerPoint()), gesture->scaleFactor());
            emit scaleFactorChanged();
            repaint();

            return true;
        }
    }
    return QWidget::event(event);
}
<commit_msg>modelwidget: now update() is called instead of repaint() (#53)<commit_after>#include "model.h"
#include "modelwidget.h"
#include "figurepainter.h"
#include "recognition.h"
#include "layouting.h"
#include <QPainter>
#include <QMouseEvent>
#include <QInputDialog>
#include <QGesture>
#include <QDebug>
#include <QTimer>
#include <iostream>

Ui::ModelWidget::ModelWidget(QWidget *parent) :
    QWidget(parent), mouseAction(MouseAction::None), _gridStep(0), _showTrack(true), _showRecognitionResult(true) {
    setFocusPolicy(Qt::FocusPolicy::StrongFocus);
    grabGesture(Qt::PinchGesture);
}

void drawTrack(QPainter &painter, Scaler &scaler, const Track &track) {
    for (size_t i = 0; i + 1 < track.size(); i++) {
        painter.drawLine(scaler(track[i]), scaler(track[i + 1]));
    }
}

int Ui::ModelWidget::gridStep() {
    return _gridStep;
}

void Ui::ModelWidget::setGridStep(int newGridStep) {
    if (newGridStep < 0) {
        throw std::runtime_error("Grid step should be >= 0");
    }
    _gridStep = newGridStep;
    update();
}

double Ui::ModelWidget::scaleFactor() {
    return scaler.scaleFactor;
}

void Ui::ModelWidget::setScaleFactor(double newScaleFactor) {
    if (!(newScaleFactor >= 0.01)) { // >= instead of < for NaNs
        throw std::runtime_error("Scale factor should be >= 0.01");
    }
    scaler.scaleFactor = newScaleFactor;
    emit scaleFactorChanged();
    update();
}

bool Ui::ModelWidget::showTrack() {
    return _showTrack;
}
void Ui::ModelWidget::setShowTrack(bool newShowTrack) {
    _showTrack = newShowTrack;
}

bool Ui::ModelWidget::showRecognitionResult() {
    return _showRecognitionResult;
}
void Ui::ModelWidget::setShowRecognitionResult(bool newShowRecognitionResult) {
    _showRecognitionResult = newShowRecognitionResult;
}

void Ui::ModelWidget::setModel(Model model) {
    commitedModel = std::move(model);
    previousModels.clear();
    redoModels.clear();
    emit canUndoChanged();
    emit canRedoChanged();
}
Model &Ui::ModelWidget::getModel() {
    return commitedModel;
}

bool Ui::ModelWidget::canUndo() {
    return !previousModels.empty();
}

void Ui::ModelWidget::undo() {
    if (!canUndo()) {
        throw std::runtime_error("Cannot undo");
    }
    redoModels.push_front(std::move(commitedModel));
    commitedModel = std::move(previousModels.back());
    previousModels.pop_back();
    if (!canUndo()) {
        emit canUndoChanged();
    }
    emit canRedoChanged();
    update();
}

bool Ui::ModelWidget::canRedo() {
    return !redoModels.empty();
}

void Ui::ModelWidget::redo() {
    if (!canRedo()) {
        throw std::runtime_error("Cannot redo");
    }
    previousModels.push_back(std::move(commitedModel));
    commitedModel = std::move(redoModels.front());
    redoModels.pop_front();
    if (!canRedo()) {
        canRedoChanged();
    }
    canUndoChanged();
    update();
}

double roundDownToMultiple(double x, double multiple) {
    return floor(x / multiple) * multiple;
}

void Ui::ModelWidget::paintEvent(QPaintEvent *) {
    QPainter painter(this);
    painter.fillRect(QRect(QPoint(), size()), Qt::white);

    QFont font;
    font.setPointSizeF(10 * scaler.scaleFactor);
    painter.setFont(font);

    QPen pen(Qt::black);
    pen.setWidthF(scaler.scaleFactor);
    painter.setPen(pen);

    FigurePainter fpainter(painter, scaler);
    if (gridStep() > 0) {
        int step = gridStep();
        // Calculating visible area
        Point p1 = scaler(QPointF(0, 0));
        Point p2 = scaler(QPointF(width(), height()));
        if (p1.x > p2.x) { std::swap(p1.x, p2.x); }
        if (p1.y > p2.y) { std::swap(p1.y, p2.y); }

        // Finding starting point for the grid
        p1.x = roundDownToMultiple(p1.x, step);
        p1.y = roundDownToMultiple(p1.y, step);

        // Drawing
        QPen pen(QColor(192, 192, 192, 255));
        pen.setStyle(Qt::DashLine);
        painter.setPen(pen);
        for (int x = p1.x; x <= p2.x; x += step) {
            painter.drawLine(scaler(Point(x, p1.y)), scaler(Point(x, p2.y)));
        }
        for (int y = p1.y; y <= p2.y; y += step) {
            painter.drawLine(scaler(Point(p1.x, y)), scaler(Point(p2.x, y)));
        }
    }

    Model copiedModel;
    Model &modelToDraw = (lastTrack.empty() || !showRecognitionResult()) ? commitedModel : (copiedModel = commitedModel);
    PFigure modified = showRecognitionResult() ? recognize(lastTrack, modelToDraw) : nullptr;
    for (PFigure fig : modelToDraw) {
        if (fig == modified) {
            pen.setColor(Qt::magenta);
        } else if (fig == modelToDraw.selectedFigure) {
            pen.setColor(Qt::blue);
        } else {
            pen.setColor(Qt::black);
        }
        painter.setPen(pen);
        fig->visit(fpainter);
    }

    if (showTrack()) {
        pen.setColor(QColor(255, 0, 0, 16));
        pen.setWidth(3 * scaler.scaleFactor);
        painter.setPen(pen);
        drawTrack(painter, scaler, lastTrack);
        for (const Track &track : visibleTracks) {
            drawTrack(painter, scaler, track);
        }
    }
}

void Ui::ModelWidget::mousePressEvent(QMouseEvent *event) {
    lastTrack = Track();
    if (event->modifiers().testFlag(Qt::ShiftModifier)) {
        mouseAction = MouseAction::ViewpointMove;
        viewpointMoveStart = event->pos();
        viewpointMoveOldScaler = scaler;
        setCursor(Qt::ClosedHandCursor);
    } else {
        mouseAction = MouseAction::TrackActive;
        lastTrack.points.push_back(scaler(event->pos()));
    }
    update();
}
void Ui::ModelWidget::mouseMoveEvent(QMouseEvent *event) {
    if (mouseAction == MouseAction::ViewpointMove) {
        scaler = viewpointMoveOldScaler;
        scaler.zeroPoint = scaler.zeroPoint + scaler(viewpointMoveStart) - scaler(event->pos());
        update();
    } else if (mouseAction == MouseAction::TrackActive) {
        lastTrack.points.push_back(scaler(event->pos()));
        if (showTrack() || showRecognitionResult()) {
            update();
        }
    } else {
        event->ignore();
    }
}
void Ui::ModelWidget::mouseReleaseEvent(QMouseEvent *event) {
    if (mouseAction == MouseAction::None) {
        event->ignore();
        return;
    }
    if (mouseAction == MouseAction::ViewpointMove) {
        mouseAction = MouseAction::None;
        setCursor(Qt::ArrowCursor);
        scaler = viewpointMoveOldScaler;
        scaler.zeroPoint = scaler.zeroPoint + scaler(viewpointMoveStart) - scaler(event->pos());
        update();
        return;
    }
    assert(mouseAction == MouseAction::TrackActive);
    mouseAction = MouseAction::None;
    lastTrack.points.push_back(scaler(event->pos()));
    Model previousModel = commitedModel;
    PFigure modifiedFigure = recognize(lastTrack, commitedModel);
    if (_gridStep > 0 && modifiedFigure) {
        GridAlignLayouter layouter(_gridStep);
        layouter.updateLayout(commitedModel, modifiedFigure);
        commitedModel.recalculate();
    }

    visibleTracks.push_back(lastTrack);
    auto iterator = --visibleTracks.end();
    QTimer *timer = new QTimer(this);

    connect(timer, &QTimer::timeout, [this, iterator, timer]() {
        visibleTracks.erase(iterator);
        delete timer;
        update();
    });
    timer->setInterval(1500);
    timer->setSingleShot(true);
    timer->start();

    lastTrack = Track();
    if (modifiedFigure) {
        previousModels.push_back(previousModel);
        redoModels.clear();
        emit canUndoChanged();
        emit canRedoChanged();
    }
    update();
}
void Ui::ModelWidget::keyReleaseEvent(QKeyEvent *event) {
    event->ignore();
    if (event->key() == Qt::Key_Escape && mouseAction == MouseAction::TrackActive) {
        event->accept();
        lastTrack = Track();
        mouseAction = MouseAction::None;
        update();
    }
    if (event->key() == Qt::Key_Delete) {
        if (commitedModel.selectedFigure) {
            event->accept();
            previousModels.push_back(commitedModel);
            redoModels.clear();
            for (auto it = commitedModel.begin(); it != commitedModel.end(); it++) {
                if (*it == commitedModel.selectedFigure) {
                    commitedModel.removeFigure(it);
                    break;
                }
            }
            emit canUndoChanged();
            emit canRedoChanged();
            update();
        }
    }
}

void Ui::ModelWidget::mouseDoubleClickEvent(QMouseEvent *event) {
    event->ignore();
    auto &figure = commitedModel.selectedFigure;
    if (!figure) { return; }

    Point eventPos = scaler(event->pos());
    bool hit = false;
    hit |= figure->isInsideOrOnBorder(eventPos);
    hit |= figure->getApproximateDistanceToBorder(eventPos) <= figureSelectGap();
    if (!hit) { return; }

    event->accept();
    bool ok;
    QString newLabel = QInputDialog::getMultiLineText(this, "Figure label", "Specify new figure label",
                                             QString::fromStdString(figure->label()),
                                                      &ok);
    if (ok) {
        previousModels.push_back(commitedModel);
        redoModels.clear();

        figure->setLabel(newLabel.toStdString());

        emit canUndoChanged();
        emit canRedoChanged();
        update();
    }
}

bool Ui::ModelWidget::event(QEvent *event) {
    if (event->type() == QEvent::Gesture) {
        QGestureEvent *gevent = static_cast<QGestureEvent*>(event);
        QPinchGesture *gesture = static_cast<QPinchGesture*>(gevent->gesture(Qt::PinchGesture));
        if (gesture) {
            gevent->accept(gesture);

            lastTrack = Track();
            mouseAction = MouseAction::None;

            scaler.zeroPoint = scaler.zeroPoint + scaler(gesture->lastCenterPoint()) - scaler(gesture->centerPoint());
            scaler.scaleWithFixedPoint(scaler(gesture->centerPoint()), gesture->scaleFactor());
            emit scaleFactorChanged();
            update();

            return true;
        }
    }
    return QWidget::event(event);
}
<|endoftext|>


<commit_before>#include <cstring>

#include <VBE/dependencies/stb_image/stb_image.hpp>
#include <VBE/config.hpp>
#include <VBE/graphics/Image.hpp>
#include <VBE/graphics/OpenGL.hpp>
#include <VBE/graphics/Texture2DArray.hpp>
#include <VBE/system/Log.hpp>

// Texture arrays are not supported in GLES2
#ifndef VBE_GLES2

//static
Texture2DArray Texture2DArray::load(
        std::vector<std::unique_ptr<std::istream>>& files,
        TextureFormat::Format format) {
    unsigned int slices = files.size();
    VBE_ASSERT(slices > 0, "You must provide at least one slice (one filepath)");

    vec2ui size;
    unsigned int channels = 0;

    unsigned char* pixels = nullptr;
    for (unsigned int i = 0; i < slices; i++) {
        Image img = Image::load(std::move(files[i]));
        if (i == 0) {
            size = img.getSize();
            channels = img.getChannels();
            pixels = new unsigned char[4*size.x*size.y*slices];
        }
        VBE_ASSERT(size == img.getSize(), "Image " << i << " has a different size.");
        VBE_ASSERT(img.getChannels() == channels, "Image " << i << " has a different channel count.");

        const int sliceSize = channels*size.x*size.y*sizeof(unsigned char);
        memcpy(pixels + sliceSize*i, img.getData(), sliceSize);
    }

    TextureFormat::Format sourceFormat = TextureFormat::channelsToFormat(channels);
    if(format == TextureFormat::AUTO)
        format = sourceFormat;

    Texture2DArray res(vec3ui(size.x, size.y, slices), format);
    res.setData(pixels, sourceFormat, TextureFormat::UNSIGNED_BYTE);
    delete[] pixels;
    return res;
}

Texture2DArray::Texture2DArray() : Texture(Texture::Type2DArray) {
}

Texture2DArray::Texture2DArray(vec3ui size, TextureFormat::Format format) :
    Texture(Texture::Type2DArray, format), size(size) {
    setData(nullptr, TextureFormat::getBaseFormat(format), TextureFormat::UNSIGNED_BYTE);
}

void Texture2DArray::setData(
        const void *pixels,
        TextureFormat::Format sourceFormat,
        TextureFormat::SourceType sourceType) {
    VBE_ASSERT(TextureFormat::isBaseFormat(sourceFormat), "Only base formats are accepted as source format for pixel data on texture loads. Specify the sizing of your input through the sourceType only");

    Texture2DArray::bind(this, 0);
    GL_ASSERT(glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, getFormat(), size.x, size.y, size.z, 0, sourceFormat, sourceType, (GLvoid*) pixels));
}

vec3ui Texture2DArray::getSize() const {
    return size;
}

Texture2DArray::Texture2DArray(Texture2DArray&& rhs) : Texture2DArray() {
    using std::swap;
    swap(*this, rhs);
}

Texture2DArray& Texture2DArray::operator=(Texture2DArray&& rhs) {
    using std::swap;
    swap(*this, rhs);
    return *this;
}

void swap(Texture2DArray& a, Texture2DArray& b) {
    using std::swap;
    swap(static_cast<Texture&>(a), static_cast<Texture&>(b));
    swap(a.size, b.size);
}

#endif // VBE_GLES2
<commit_msg>Use depth as source format for glTexImage3D<commit_after>#include <cstring>

#include <VBE/dependencies/stb_image/stb_image.hpp>
#include <VBE/config.hpp>
#include <VBE/graphics/Image.hpp>
#include <VBE/graphics/OpenGL.hpp>
#include <VBE/graphics/Texture2DArray.hpp>
#include <VBE/system/Log.hpp>

// Texture arrays are not supported in GLES2
#ifndef VBE_GLES2

//static
Texture2DArray Texture2DArray::load(
        std::vector<std::unique_ptr<std::istream>>& files,
        TextureFormat::Format format) {
    unsigned int slices = files.size();
    VBE_ASSERT(slices > 0, "You must provide at least one slice (one filepath)");

    vec2ui size;
    unsigned int channels = 0;

    unsigned char* pixels = nullptr;
    for (unsigned int i = 0; i < slices; i++) {
        Image img = Image::load(std::move(files[i]));
        if (i == 0) {
            size = img.getSize();
            channels = img.getChannels();
            pixels = new unsigned char[4*size.x*size.y*slices];
        }
        VBE_ASSERT(size == img.getSize(), "Image " << i << " has a different size.");
        VBE_ASSERT(img.getChannels() == channels, "Image " << i << " has a different channel count.");

        const int sliceSize = channels*size.x*size.y*sizeof(unsigned char);
        memcpy(pixels + sliceSize*i, img.getData(), sliceSize);
    }

    TextureFormat::Format sourceFormat = TextureFormat::channelsToFormat(channels);
    if(format == TextureFormat::AUTO)
        format = sourceFormat;

    Texture2DArray res(vec3ui(size.x, size.y, slices), format);
    res.setData(pixels, sourceFormat, TextureFormat::UNSIGNED_BYTE);
    delete[] pixels;
    return res;
}

Texture2DArray::Texture2DArray() : Texture(Texture::Type2DArray) {
}

Texture2DArray::Texture2DArray(vec3ui size, TextureFormat::Format format) :
    Texture(Texture::Type2DArray, format), size(size) {
    setData(nullptr, TextureFormat::getBaseFormat(format), TextureFormat::UNSIGNED_BYTE);
}

void Texture2DArray::setData(
        const void *pixels,
        TextureFormat::Format sourceFormat,
        TextureFormat::SourceType sourceType) {
    VBE_ASSERT(TextureFormat::isBaseFormat(sourceFormat), "Only base formats are accepted as source format for pixel data on texture loads. Specify the sizing of your input through the sourceType only");

    Texture2DArray::bind(this, 0);
    if(sourceFormat == TextureFormat::DEPTH_COMPONENT || sourceFormat == TextureFormat::DEPTH_STENCIL)
        sourceFormat = TextureFormat::DEPTH_COMPONENT;
    GL_ASSERT(glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, getFormat(), size.x, size.y, size.z, 0, sourceFormat, sourceType, (GLvoid*) pixels));
}

vec3ui Texture2DArray::getSize() const {
    return size;
}

Texture2DArray::Texture2DArray(Texture2DArray&& rhs) : Texture2DArray() {
    using std::swap;
    swap(*this, rhs);
}

Texture2DArray& Texture2DArray::operator=(Texture2DArray&& rhs) {
    using std::swap;
    swap(*this, rhs);
    return *this;
}

void swap(Texture2DArray& a, Texture2DArray& b) {
    using std::swap;
    swap(static_cast<Texture&>(a), static_cast<Texture&>(b));
    swap(a.size, b.size);
}

#endif // VBE_GLES2
<|endoftext|>


<commit_before>#include "genotype.h"

const std::vector<char> Genotype::alleles = {'A','T','G','C'};

Genotype::Genotype(std::string gtstr) : gt(), ploidy(0) {
	for(auto it = gtstr.begin(); it != gtstr.end(); ++it){
		++gt[*it];
		ploidy+=1;
	}
}

Genotype::Genotype(std::map<char,int> gt) : gt(gt), ploidy(0) {
	for(auto it = gt.begin(); it!= gt.end(); ++it){
		ploidy += it->second;
	}
}

int Genotype::numbase(char n){
	return gt[n];
}

int Genotype::numnotbase(char n){
	return ploidy - gt[n];
}

int Genotype::getploidy(){
	return ploidy;
}

//check out http://genome.sph.umich.edu/wiki/Relationship_between_Ploidy,_Alleles_and_Genotypes
void Genotype::enumerate_gts(std::vector<Genotype> &v, int stopallele, unsigned int ploidy, std::string genotype){
	if (genotype.length() == ploidy){
		v.push_back(Genotype(genotype));
	}
	else{
		for (int i = 0; i < stopallele; ++i){
			std::string s(1,alleles[i]);
			s.append(genotype);
			enumerate_gts(v,i+1, ploidy, s);
		}
	}
}

double Genotype::p_finite_alleles(char ref, double ref_weight, double theta, double pi){
	double p = 0.0;
}

std::vector<Genotype> Genotype::enumerate_gts(int ploidy){
	std::vector<Genotype> v;
	enumerate_gts(v,alleles.size(),ploidy,std::string());
	return v;
}

std::string Genotype::to_string() const{
	std::string s;
	for(auto it = gt.begin(); it != gt.end(); ++it){
		s.append(it->second,it->first);
	}
	return s;
}

std::ostream& operator<<(std::ostream& os, const Genotype gt){
	return os << gt.to_string();
}

<commit_msg>start p_finite_alleles function<commit_after>#include "genotype.h"

const std::vector<char> Genotype::alleles = {'A','T','G','C'};

Genotype::Genotype(std::string gtstr) : gt(), ploidy(0) {
	for(auto it = gtstr.begin(); it != gtstr.end(); ++it){
		++gt[*it];
		ploidy+=1;
	}
}

Genotype::Genotype(std::map<char,int> gt) : gt(gt), ploidy(0) {
	for(auto it = gt.begin(); it!= gt.end(); ++it){
		ploidy += it->second;
	}
}

int Genotype::numbase(char n){
	return gt[n];
}

int Genotype::numnotbase(char n){
	return ploidy - gt[n];
}

int Genotype::getploidy(){
	return ploidy;
}

//check out http://genome.sph.umich.edu/wiki/Relationship_between_Ploidy,_Alleles_and_Genotypes
void Genotype::enumerate_gts(std::vector<Genotype> &v, int stopallele, unsigned int ploidy, std::string genotype){
	if (genotype.length() == ploidy){
		v.push_back(Genotype(genotype));
	}
	else{
		for (int i = 0; i < stopallele; ++i){
			std::string s(1,alleles[i]);
			s.append(genotype);
			enumerate_gts(v,i+1, ploidy, s);
		}
	}
}

double Genotype::p_finite_alleles(char ref, double ref_weight, double theta, std::map<char,double> pi){
	double p = 1.0;
	for (auto it = gt.begin(); it != gt.end(); ++it){
		char allele = it->first;
		int count = it->second;
		double w = (ref == allele ? ref_weight : 0);
		for (int i = 0; i < count; ++i){
			p *= (w + theta * pi[allele] + i);
		}
	}
}

std::vector<Genotype> Genotype::enumerate_gts(int ploidy){
	std::vector<Genotype> v;
	enumerate_gts(v,alleles.size(),ploidy,std::string());
	return v;
}

std::string Genotype::to_string() const{
	std::string s;
	for(auto it = gt.begin(); it != gt.end(); ++it){
		s.append(it->second,it->first);
	}
	return s;
}

std::ostream& operator<<(std::ostream& os, const Genotype gt){
	return os << gt.to_string();
}

<|endoftext|>


<commit_before>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/*
$Log$
Revision 1.1  2007/06/27 16:55:24  zampolli
Task for TOF Calibration, optimized for pp runs

Revision 1.2  2006/02/13 17:22:26  arcelli
just Fixing Log info

Revision 1.1  2006/02/13 16:10:48  arcelli
Add classes for TOF Calibration (C.Zampolli)

author: Chiara Zampolli, zampolli@bo.infn.it
*/

///////////////////////////////////////////////////////////////////////////////
//                                                                           //
// class for TOF calibration                                                 //
//                                                                           //
///////////////////////////////////////////////////////////////////////////////

#include "AliTOFChannelOffline.h"
#include "AliLog.h"

ClassImp(AliTOFChannelOffline)

//________________________________________________________________
AliTOFChannelOffline::AliTOFChannelOffline()
{
  for(Int_t i=0;i<6;i++) fSlewPar[i]=0.;
}

//________________________________________________________________
AliTOFChannelOffline::AliTOFChannelOffline(Float_t* slewingPar)
{
  for(Int_t i = 0; i<6;i++) fSlewPar[i]=slewingPar[i];
}

//________________________________________________________________
AliTOFChannelOffline::~AliTOFChannelOffline()
{
  //dtor
  AliInfo("I'm in the dtor of the channel offline");
}

//________________________________________________________________
AliTOFChannelOffline::AliTOFChannelOffline(const AliTOFChannelOffline& channel) :
  TObject(channel)
{
// copy constructor
  for(Int_t i = 0; i<6;i++) fSlewPar[i]=channel.GetSlewPar(i);
}

//________________________________________________________________
AliTOFChannelOffline &AliTOFChannelOffline::operator =(const AliTOFChannelOffline& channel)
{
// assignment operator
  for(Int_t i = 0; i<6;i++) fSlewPar[i]=channel.GetSlewPar(i);
  return *this;
}

//
//________________________________________________________________
//virtual AliTOFChannelOffline::~AliTOFChannelOffline()/
//{

//}
//*/

//________________________________________________________________
void AliTOFChannelOffline::SetSlewPar(Float_t* slewingPar)
{
  if(slewingPar) for(Int_t i = 0; i<6;i++) fSlewPar[i]=slewingPar[i];
  else for(int t=0; t<6; t++) fSlewPar[t] = 0.;
}

<commit_msg>Obsolete printing removed.<commit_after>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/*
$Log$
Revision 1.1  2007/06/27 16:55:24  zampolli
Task for TOF Calibration, optimized for pp runs

Revision 1.2  2006/02/13 17:22:26  arcelli
just Fixing Log info

Revision 1.1  2006/02/13 16:10:48  arcelli
Add classes for TOF Calibration (C.Zampolli)

author: Chiara Zampolli, zampolli@bo.infn.it
*/

///////////////////////////////////////////////////////////////////////////////
//                                                                           //
// class for TOF calibration                                                 //
//                                                                           //
///////////////////////////////////////////////////////////////////////////////

#include "AliTOFChannelOffline.h"
#include "AliLog.h"

ClassImp(AliTOFChannelOffline)

//________________________________________________________________
AliTOFChannelOffline::AliTOFChannelOffline()
{
  for(Int_t i=0;i<6;i++) fSlewPar[i]=0.;
}

//________________________________________________________________
AliTOFChannelOffline::AliTOFChannelOffline(Float_t* slewingPar)
{
  for(Int_t i = 0; i<6;i++) fSlewPar[i]=slewingPar[i];
}

//________________________________________________________________
AliTOFChannelOffline::~AliTOFChannelOffline()
{
  //dtor

}

//________________________________________________________________
AliTOFChannelOffline::AliTOFChannelOffline(const AliTOFChannelOffline& channel) :
  TObject(channel)
{
// copy constructor
  for(Int_t i = 0; i<6;i++) fSlewPar[i]=channel.GetSlewPar(i);
}

//________________________________________________________________
AliTOFChannelOffline &AliTOFChannelOffline::operator =(const AliTOFChannelOffline& channel)
{
// assignment operator
  for(Int_t i = 0; i<6;i++) fSlewPar[i]=channel.GetSlewPar(i);
  return *this;
}

//
//________________________________________________________________
//virtual AliTOFChannelOffline::~AliTOFChannelOffline()/
//{

//}
//*/

//________________________________________________________________
void AliTOFChannelOffline::SetSlewPar(Float_t* slewingPar)
{
  if(slewingPar) for(Int_t i = 0; i<6;i++) fSlewPar[i]=slewingPar[i];
  else for(int t=0; t<6; t++) fSlewPar[t] = 0.;
}

<|endoftext|>


<commit_before>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/printing/print_preview_dialog_controller.h"
#include "chrome/browser/printing/print_preview_test.h"
#include "chrome/browser/printing/print_view_manager.h"
#include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/webui/print_preview/print_preview_ui.h"
#include "content/public/browser/navigation_details.h"
#include "content/public/common/url_constants.h"

using content::WebContents;

// Test crashes on Aura due to initiator's native view having no parent.
// http://crbug.com/104284
#if defined(USE_AURA)
#define MAYBE_GetOrCreatePreviewDialog DISABLED_GetOrCreatePreviewDialog
#define MAYBE_MultiplePreviewDialogs DISABLED_MultiplePreviewDialogs
#define MAYBE_ClearInitiatorDetails DISABLED_ClearInitiatorDetails
#else
#define MAYBE_GetOrCreatePreviewDialog GetOrCreatePreviewDialog
#define MAYBE_MultiplePreviewDialogs MultiplePreviewDialogs
#define MAYBE_ClearInitiatorDetails ClearInitiatorDetails
#endif

namespace printing {

typedef PrintPreviewTest PrintPreviewDialogControllerUnitTest;

// Create/Get a preview dialog for initiator.
TEST_F(PrintPreviewDialogControllerUnitTest, MAYBE_GetOrCreatePreviewDialog) {
  // Lets start with one window with one tab.
  EXPECT_EQ(1u, chrome::GetTotalBrowserCount());
  EXPECT_EQ(0, browser()->tab_strip_model()->count());
  chrome::NewTab(browser());
  EXPECT_EQ(1, browser()->tab_strip_model()->count());

  // Create a reference to initiator contents.
  WebContents* initiator = browser()->tab_strip_model()->GetActiveWebContents();

  PrintPreviewDialogController* dialog_controller =
      PrintPreviewDialogController::GetInstance();
  ASSERT_TRUE(dialog_controller);

  // Get the preview dialog for initiator.
  PrintViewManager::FromWebContents(initiator)->PrintPreviewNow(false);
  WebContents* preview_dialog =
      dialog_controller->GetOrCreatePreviewDialog(initiator);

  // New print preview dialog is a constrained window, so the number of tabs is
  // still 1.
  EXPECT_EQ(1, browser()->tab_strip_model()->count());
  EXPECT_NE(initiator, preview_dialog);

  // Get the print preview dialog for the same initiator.
  WebContents* new_preview_dialog =
      dialog_controller->GetOrCreatePreviewDialog(initiator);

  // Preview dialog already exists. Tab count remains the same.
  EXPECT_EQ(1, browser()->tab_strip_model()->count());

  // 1:1 relationship between initiator and preview dialog.
  EXPECT_EQ(new_preview_dialog, preview_dialog);
}

// Tests multiple print preview dialogs exist in the same browser for different
// initiators. If a preview dialog already exists for an initiator, that
// initiator gets focused.
TEST_F(PrintPreviewDialogControllerUnitTest, MAYBE_MultiplePreviewDialogs) {
  // Lets start with one window and two tabs.
  EXPECT_EQ(1u, chrome::GetTotalBrowserCount());
  TabStripModel* tab_strip_model = browser()->tab_strip_model();
  ASSERT_TRUE(tab_strip_model);

  EXPECT_EQ(0, tab_strip_model->count());

  // Create some new initiators.
  chrome::NewTab(browser());
  WebContents* web_contents_1 = tab_strip_model->GetActiveWebContents();
  ASSERT_TRUE(web_contents_1);

  chrome::NewTab(browser());
  WebContents* web_contents_2 = tab_strip_model->GetActiveWebContents();
  ASSERT_TRUE(web_contents_2);
  EXPECT_EQ(2, tab_strip_model->count());

  PrintPreviewDialogController* dialog_controller =
      PrintPreviewDialogController::GetInstance();
  ASSERT_TRUE(dialog_controller);

  // Create preview dialog for |web_contents_1|
  PrintViewManager::FromWebContents(web_contents_1)->PrintPreviewNow(false);
  WebContents* preview_dialog_1 =
      dialog_controller->GetOrCreatePreviewDialog(web_contents_1);

  EXPECT_NE(web_contents_1, preview_dialog_1);
  EXPECT_EQ(2, tab_strip_model->count());

  // Create preview dialog for |web_contents_2|
  PrintViewManager::FromWebContents(web_contents_2)->PrintPreviewNow(false);
  WebContents* preview_dialog_2 =
      dialog_controller->GetOrCreatePreviewDialog(web_contents_2);

  EXPECT_NE(web_contents_2, preview_dialog_2);
  EXPECT_NE(preview_dialog_1, preview_dialog_2);
  // 2 initiators and 2 preview dialogs exist in the same browser.  The preview
  // dialogs are constrained in their respective initiators.
  EXPECT_EQ(2, tab_strip_model->count());

  int tab_1_index = tab_strip_model->GetIndexOfWebContents(web_contents_1);
  int tab_2_index = tab_strip_model->GetIndexOfWebContents(web_contents_2);
  int preview_dialog_1_index =
      tab_strip_model->GetIndexOfWebContents(preview_dialog_1);
  int preview_dialog_2_index =
      tab_strip_model->GetIndexOfWebContents(preview_dialog_2);

  // Constrained dialogs are not in the TabStripModel.
  EXPECT_EQ(-1, preview_dialog_1_index);
  EXPECT_EQ(-1, preview_dialog_2_index);

  // Since |preview_dialog_2_index| was the most recently created dialog, its
  // initiator should have focus.
  EXPECT_EQ(tab_2_index, tab_strip_model->active_index());

  // When we get the preview dialog for |web_contents_1|,
  // |preview_dialog_1| is activated and focused.
  dialog_controller->GetOrCreatePreviewDialog(web_contents_1);
  EXPECT_EQ(tab_1_index, tab_strip_model->active_index());
}

// Check clearing the initiator details associated with a print preview dialog
// allows the initiator to create another print preview dialog.
TEST_F(PrintPreviewDialogControllerUnitTest, MAYBE_ClearInitiatorDetails) {
  // Lets start with one window with one tab.
  EXPECT_EQ(1u, chrome::GetTotalBrowserCount());
  EXPECT_EQ(0, browser()->tab_strip_model()->count());
  chrome::NewTab(browser());
  EXPECT_EQ(1, browser()->tab_strip_model()->count());

  // Create a reference to initiator contents.
  WebContents* initiator = browser()->tab_strip_model()->GetActiveWebContents();

  PrintPreviewDialogController* dialog_controller =
      PrintPreviewDialogController::GetInstance();
  ASSERT_TRUE(dialog_controller);

  // Get the preview dialog for the initiator.
  PrintViewManager::FromWebContents(initiator)->PrintPreviewNow(false);
  WebContents* preview_dialog =
      dialog_controller->GetOrCreatePreviewDialog(initiator);

  // New print preview dialog is a constrained window, so the number of tabs is
  // still 1.
  EXPECT_EQ(1, browser()->tab_strip_model()->count());
  EXPECT_NE(initiator, preview_dialog);

  // Clear the initiator details associated with the preview dialog.
  dialog_controller->EraseInitiatorInfo(preview_dialog);

  // Get a new print preview dialog for the initiator.
  WebContents* new_preview_dialog =
      dialog_controller->GetOrCreatePreviewDialog(initiator);

  // New print preview dialog is a constrained window, so the number of tabs is
  // still 1.
  EXPECT_EQ(1, browser()->tab_strip_model()->count());
  // Verify a new print preview dialog has been created.
  EXPECT_NE(new_preview_dialog, preview_dialog);
}

}  // namespace printing
<commit_msg>Print Preview: Re-enable some tests on Aura.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/printing/print_preview_dialog_controller.h"
#include "chrome/browser/printing/print_preview_test.h"
#include "chrome/browser/printing/print_view_manager.h"
#include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/webui/print_preview/print_preview_ui.h"
#include "content/public/browser/navigation_details.h"
#include "content/public/common/url_constants.h"

using content::WebContents;

namespace printing {

typedef PrintPreviewTest PrintPreviewDialogControllerUnitTest;

// Create/Get a preview dialog for initiator.
TEST_F(PrintPreviewDialogControllerUnitTest, GetOrCreatePreviewDialog) {
  // Lets start with one window with one tab.
  EXPECT_EQ(1u, chrome::GetTotalBrowserCount());
  EXPECT_EQ(0, browser()->tab_strip_model()->count());
  chrome::NewTab(browser());
  EXPECT_EQ(1, browser()->tab_strip_model()->count());

  // Create a reference to initiator contents.
  WebContents* initiator = browser()->tab_strip_model()->GetActiveWebContents();

  PrintPreviewDialogController* dialog_controller =
      PrintPreviewDialogController::GetInstance();
  ASSERT_TRUE(dialog_controller);

  // Get the preview dialog for initiator.
  PrintViewManager::FromWebContents(initiator)->PrintPreviewNow(false);
  WebContents* preview_dialog =
      dialog_controller->GetOrCreatePreviewDialog(initiator);

  // New print preview dialog is a constrained window, so the number of tabs is
  // still 1.
  EXPECT_EQ(1, browser()->tab_strip_model()->count());
  EXPECT_NE(initiator, preview_dialog);

  // Get the print preview dialog for the same initiator.
  WebContents* new_preview_dialog =
      dialog_controller->GetOrCreatePreviewDialog(initiator);

  // Preview dialog already exists. Tab count remains the same.
  EXPECT_EQ(1, browser()->tab_strip_model()->count());

  // 1:1 relationship between initiator and preview dialog.
  EXPECT_EQ(new_preview_dialog, preview_dialog);
}

// Tests multiple print preview dialogs exist in the same browser for different
// initiators. If a preview dialog already exists for an initiator, that
// initiator gets focused.
TEST_F(PrintPreviewDialogControllerUnitTest, MultiplePreviewDialogs) {
  // Lets start with one window and two tabs.
  EXPECT_EQ(1u, chrome::GetTotalBrowserCount());
  TabStripModel* tab_strip_model = browser()->tab_strip_model();
  ASSERT_TRUE(tab_strip_model);

  EXPECT_EQ(0, tab_strip_model->count());

  // Create some new initiators.
  chrome::NewTab(browser());
  WebContents* web_contents_1 = tab_strip_model->GetActiveWebContents();
  ASSERT_TRUE(web_contents_1);

  chrome::NewTab(browser());
  WebContents* web_contents_2 = tab_strip_model->GetActiveWebContents();
  ASSERT_TRUE(web_contents_2);
  EXPECT_EQ(2, tab_strip_model->count());

  PrintPreviewDialogController* dialog_controller =
      PrintPreviewDialogController::GetInstance();
  ASSERT_TRUE(dialog_controller);

  // Create preview dialog for |web_contents_1|
  PrintViewManager::FromWebContents(web_contents_1)->PrintPreviewNow(false);
  WebContents* preview_dialog_1 =
      dialog_controller->GetOrCreatePreviewDialog(web_contents_1);

  EXPECT_NE(web_contents_1, preview_dialog_1);
  EXPECT_EQ(2, tab_strip_model->count());

  // Create preview dialog for |web_contents_2|
  PrintViewManager::FromWebContents(web_contents_2)->PrintPreviewNow(false);
  WebContents* preview_dialog_2 =
      dialog_controller->GetOrCreatePreviewDialog(web_contents_2);

  EXPECT_NE(web_contents_2, preview_dialog_2);
  EXPECT_NE(preview_dialog_1, preview_dialog_2);
  // 2 initiators and 2 preview dialogs exist in the same browser.  The preview
  // dialogs are constrained in their respective initiators.
  EXPECT_EQ(2, tab_strip_model->count());

  int tab_1_index = tab_strip_model->GetIndexOfWebContents(web_contents_1);
  int tab_2_index = tab_strip_model->GetIndexOfWebContents(web_contents_2);
  int preview_dialog_1_index =
      tab_strip_model->GetIndexOfWebContents(preview_dialog_1);
  int preview_dialog_2_index =
      tab_strip_model->GetIndexOfWebContents(preview_dialog_2);

  // Constrained dialogs are not in the TabStripModel.
  EXPECT_EQ(-1, preview_dialog_1_index);
  EXPECT_EQ(-1, preview_dialog_2_index);

  // Since |preview_dialog_2_index| was the most recently created dialog, its
  // initiator should have focus.
  EXPECT_EQ(tab_2_index, tab_strip_model->active_index());

  // When we get the preview dialog for |web_contents_1|,
  // |preview_dialog_1| is activated and focused.
  dialog_controller->GetOrCreatePreviewDialog(web_contents_1);
  EXPECT_EQ(tab_1_index, tab_strip_model->active_index());
}

// Check clearing the initiator details associated with a print preview dialog
// allows the initiator to create another print preview dialog.
TEST_F(PrintPreviewDialogControllerUnitTest, ClearInitiatorDetails) {
  // Lets start with one window with one tab.
  EXPECT_EQ(1u, chrome::GetTotalBrowserCount());
  EXPECT_EQ(0, browser()->tab_strip_model()->count());
  chrome::NewTab(browser());
  EXPECT_EQ(1, browser()->tab_strip_model()->count());

  // Create a reference to initiator contents.
  WebContents* initiator = browser()->tab_strip_model()->GetActiveWebContents();

  PrintPreviewDialogController* dialog_controller =
      PrintPreviewDialogController::GetInstance();
  ASSERT_TRUE(dialog_controller);

  // Get the preview dialog for the initiator.
  PrintViewManager::FromWebContents(initiator)->PrintPreviewNow(false);
  WebContents* preview_dialog =
      dialog_controller->GetOrCreatePreviewDialog(initiator);

  // New print preview dialog is a constrained window, so the number of tabs is
  // still 1.
  EXPECT_EQ(1, browser()->tab_strip_model()->count());
  EXPECT_NE(initiator, preview_dialog);

  // Clear the initiator details associated with the preview dialog.
  dialog_controller->EraseInitiatorInfo(preview_dialog);

  // Get a new print preview dialog for the initiator.
  WebContents* new_preview_dialog =
      dialog_controller->GetOrCreatePreviewDialog(initiator);

  // New print preview dialog is a constrained window, so the number of tabs is
  // still 1.
  EXPECT_EQ(1, browser()->tab_strip_model()->count());
  // Verify a new print preview dialog has been created.
  EXPECT_NE(new_preview_dialog, preview_dialog);
}

}  // namespace printing
<|endoftext|>


<commit_before><commit_msg>PWGPP-570 - Use truncation from the RecoParam (harwired before)+ Errors<commit_after><|endoftext|>


<commit_before>/*
    Copyright (c) 2014 Daniel Vrátil <dvratil@redhat.com>

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

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

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

#include "tagfetchhelper.h"
#include "handler.h"
#include "response.h"
#include "libs/imapparser_p.h"
#include "libs/protocol_p.h"
#include "storage/querybuilder.h"
#include "storage/queryhelper.h"
#include "entities.h"
#include "connection.h"

using namespace Akonadi;
using namespace Akonadi::Server;

TagFetchHelper::TagFetchHelper( Connection *connection, const ImapSet &set )
  : QObject()
  , mConnection( connection )
  , mSet( set )
{
}

QSqlQuery TagFetchHelper::buildAttributeQuery()
{
  QueryBuilder qb( TagAttribute::tableName() );
  qb.addColumn( TagAttribute::tagIdColumn() );
  qb.addColumn( TagAttribute::typeColumn() );
  qb.addColumn( TagAttribute::valueColumn() );
  qb.addSortColumn( TagAttribute::tagIdColumn(), Query::Descending );

  QueryHelper::setToQuery( mSet, TagAttribute::tagIdColumn(), qb );

  if ( !qb.exec() ) {
    throw HandlerException( "Unable to list tag attributes" );
  }

  qb.query().next();
  return qb.query();
}

QSqlQuery TagFetchHelper::buildTagQuery()
{
  QueryBuilder qb( Tag::tableName() );
  qb.addColumns( Tag::fullColumnNames() );

  qb.addJoin( QueryBuilder::InnerJoin, TagType::tableName(),
                     Tag::typeIdFullColumnName(), TagType::idFullColumnName() );
  qb.addColumn( TagType::nameFullColumnName() );

  // Expose tag's remote ID only to resources
  if ( mConnection->context()->resource().isValid() ) {
    qb.addColumn( TagRemoteIdResourceRelation::remoteIdFullColumnName() );
    qb.addJoin( QueryBuilder::LeftJoin, TagRemoteIdResourceRelation::tableName(),
                Tag::idFullColumnName(), TagRemoteIdResourceRelation::tagIdFullColumnName() );
    Query::Condition joinCondition;
    joinCondition.addColumnCondition( Resource::idFullColumnName(), Query::Equals, TagRemoteIdResourceRelation::resourceIdFullColumnName() );
    joinCondition.addValueCondition( Resource::nameFullColumnName(), Query::Equals, mConnection->context()->resource().name() );
    qb.addJoin( QueryBuilder::LeftJoin, Resource::tableName(), joinCondition );
  }

  qb.addSortColumn( Tag::idFullColumnName(), Query::Descending );
  QueryHelper::setToQuery( mSet, Tag::idFullColumnName(), qb );

  if ( !qb.exec() ) {
    throw HandlerException( "Unable to list tags" );
  }

  qb.query().next();
  return qb.query();
}

bool TagFetchHelper::fetchTags(const QByteArray& responseIdentifier)
{

  QSqlQuery tagQuery = buildTagQuery();
  QSqlQuery attributeQuery = buildAttributeQuery();

  Response response;
  response.setUntagged();
  while ( tagQuery.isValid() ) {
    const qint64 tagId = tagQuery.value( 0 ).toLongLong();
    const QByteArray gid = tagQuery.value( 1 ).toByteArray();
    const qint64 parentId = tagQuery.value( 2 ).toLongLong();
    //we're ignoring the type id
    const QByteArray type = tagQuery.value( 4 ).toByteArray();
    QByteArray remoteId;
    if ( mConnection->context()->resource().isValid() ) {
      remoteId = tagQuery.value( 5 ).toByteArray();
    }

    QList<QByteArray> attributes;
    attributes << AKONADI_PARAM_UID << QByteArray::number( tagId );
    attributes << AKONADI_PARAM_GID << ImapParser::quote( gid );
    attributes << AKONADI_PARAM_PARENT << QByteArray::number( parentId );
    attributes << AKONADI_PARAM_MIMETYPE " " + ImapParser::quote( type );
    if ( !remoteId.isEmpty() ) {
      attributes << AKONADI_PARAM_REMOTEID << remoteId;
    }

    while ( attributeQuery.isValid() ) {
      const qint64 id = attributeQuery.value( 0 ).toLongLong();
      if ( id > tagId ) {
        attributeQuery.next();
        continue;
      } else if ( id < tagId ) {
        break;
      }

      const QByteArray attrName = attributeQuery.value( 1 ).toByteArray();
      const QByteArray attrValue = attributeQuery.value( 2 ).toByteArray();

      attributes << attrName << ImapParser::quote( attrValue );
      attributeQuery.next();
    }

    QByteArray tagReply = QByteArray::number( tagId ) + ' ' + responseIdentifier + " (";
    tagReply += ImapParser::join( attributes, " " ) + ')';
    response.setUntagged();
    response.setString( tagReply );
    Q_EMIT responseAvailable( response );

    tagQuery.next();
  }

  return true;
}

<commit_msg>TagFetchHelper: Fix SQL query for fetching tag RIDs<commit_after>/*
    Copyright (c) 2014 Daniel Vrátil <dvratil@redhat.com>

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

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

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

#include "tagfetchhelper.h"
#include "handler.h"
#include "response.h"
#include "libs/imapparser_p.h"
#include "libs/protocol_p.h"
#include "storage/querybuilder.h"
#include "storage/queryhelper.h"
#include "entities.h"
#include "connection.h"

using namespace Akonadi;
using namespace Akonadi::Server;

TagFetchHelper::TagFetchHelper( Connection *connection, const ImapSet &set )
  : QObject()
  , mConnection( connection )
  , mSet( set )
{
}

QSqlQuery TagFetchHelper::buildAttributeQuery()
{
  QueryBuilder qb( TagAttribute::tableName() );
  qb.addColumn( TagAttribute::tagIdColumn() );
  qb.addColumn( TagAttribute::typeColumn() );
  qb.addColumn( TagAttribute::valueColumn() );
  qb.addSortColumn( TagAttribute::tagIdColumn(), Query::Descending );

  QueryHelper::setToQuery( mSet, TagAttribute::tagIdColumn(), qb );

  if ( !qb.exec() ) {
    throw HandlerException( "Unable to list tag attributes" );
  }

  qb.query().next();
  return qb.query();
}

QSqlQuery TagFetchHelper::buildTagQuery()
{
  QueryBuilder qb( Tag::tableName() );
  qb.addColumns( Tag::fullColumnNames() );

  qb.addJoin( QueryBuilder::InnerJoin, TagType::tableName(),
                     Tag::typeIdFullColumnName(), TagType::idFullColumnName() );
  qb.addColumn( TagType::nameFullColumnName() );

  // Expose tag's remote ID only to resources
  if ( mConnection->context()->resource().isValid() ) {
    qb.addColumn( TagRemoteIdResourceRelation::remoteIdFullColumnName() );
    Query::Condition joinCondition;
    joinCondition.addValueCondition( TagRemoteIdResourceRelation::resourceIdFullColumnName(),
                                     Query::Equals, mConnection->context()->resource().id() );
    joinCondition.addColumnCondition( TagRemoteIdResourceRelation::tagIdFullColumnName(),
                                     Query::Equals, Tag::idFullColumnName() );
    qb.addJoin( QueryBuilder::LeftJoin, TagRemoteIdResourceRelation::tableName(), joinCondition );
  }

  qb.addSortColumn( Tag::idFullColumnName(), Query::Descending );
  QueryHelper::setToQuery( mSet, Tag::idFullColumnName(), qb );
  if ( !qb.exec() ) {
    throw HandlerException( "Unable to list tags" );
  }

  qb.query().next();
  return qb.query();
}

bool TagFetchHelper::fetchTags(const QByteArray& responseIdentifier)
{

  QSqlQuery tagQuery = buildTagQuery();
  QSqlQuery attributeQuery = buildAttributeQuery();

  Response response;
  response.setUntagged();
  while ( tagQuery.isValid() ) {
    const qint64 tagId = tagQuery.value( 0 ).toLongLong();
    const QByteArray gid = tagQuery.value( 1 ).toByteArray();
    const qint64 parentId = tagQuery.value( 2 ).toLongLong();
    //we're ignoring the type id
    const QByteArray type = tagQuery.value( 4 ).toByteArray();
    QByteArray remoteId;
    if ( mConnection->context()->resource().isValid() ) {
      remoteId = tagQuery.value( 5 ).toByteArray();
    }

    QList<QByteArray> attributes;
    attributes << AKONADI_PARAM_UID << QByteArray::number( tagId );
    attributes << AKONADI_PARAM_GID << ImapParser::quote( gid );
    attributes << AKONADI_PARAM_PARENT << QByteArray::number( parentId );
    attributes << AKONADI_PARAM_MIMETYPE " " + ImapParser::quote( type );
    if ( !remoteId.isEmpty() ) {
      attributes << AKONADI_PARAM_REMOTEID << remoteId;
    }

    while ( attributeQuery.isValid() ) {
      const qint64 id = attributeQuery.value( 0 ).toLongLong();
      if ( id > tagId ) {
        attributeQuery.next();
        continue;
      } else if ( id < tagId ) {
        break;
      }

      const QByteArray attrName = attributeQuery.value( 1 ).toByteArray();
      const QByteArray attrValue = attributeQuery.value( 2 ).toByteArray();

      attributes << attrName << ImapParser::quote( attrValue );
      attributeQuery.next();
    }

    QByteArray tagReply = QByteArray::number( tagId ) + ' ' + responseIdentifier + " (";
    tagReply += ImapParser::join( attributes, " " ) + ')';
    response.setUntagged();
    response.setString( tagReply );
    Q_EMIT responseAvailable( response );

    tagQuery.next();
  }

  return true;
}

<|endoftext|>