<commit_before>/*
 * PrimeSieveGUI.cpp -- This file is part of primesieve
 *
 * Copyright (C) 2012 <NAME>, <<EMAIL>>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
 */

#include "PrimeSieveGUI.h"
#include "ui_PrimeSieveGUI.h"
#include "PrimeSieveProcess.h"
#include "../soe/ParallelPrimeSieve.h"
#include "../expr/ExpressionParser.h"

#include <QtGlobal>
#include <QCoreApplication>
#include <QByteArray>
#include <QTextStream>
#include <QFile>
#include <QSize>
#include <QMessageBox>
#include <QTextCursor>
#include <stdexcept>

PrimeSieveGUI::PrimeSieveGUI(QWidget *parent) :
  QMainWindow(parent), ui(new Ui::PrimeSieveGUI), validator_(0),
  primeSieveProcess_(0), saveAct_(0), quitAct_(0), aboutAct_(0),
  alignmentGroup_(0) {
  ui->setupUi(this);
  primeText_.push_back("Prime numbers");
  primeText_.push_back("Twin primes");
  primeText_.push_back("Prime triplets");
  primeText_.push_back("Prime quadruplets");
  primeText_.push_back("Prime quintuplets");
  primeText_.push_back("Prime sextuplets");
  primeText_.push_back("Prime septuplets");
  this->initGUI();
  this->initConnections();
}

PrimeSieveGUI::~PrimeSieveGUI() {
  this->cleanUp();
  delete validator_;
  delete saveAct_;
  delete quitAct_;
  delete aboutAct_;
  delete alignmentGroup_;
  for (; !countAct_.isEmpty(); countAct_.pop_back())
    delete countAct_.back();
  for (; !printAct_.isEmpty(); printAct_.pop_back())
    delete printAct_.back();
  // Qt code
  delete ui;
}

void PrimeSieveGUI::changeEvent(QEvent *e) {
  QMainWindow::changeEvent(e);
  switch (e->type()) {
  case QEvent::LanguageChange:
    ui->retranslateUi(this);
    break;
  default:
    break;
  }
}

void PrimeSieveGUI::initGUI() {
  this->setWindowTitle(APPLICATION_NAME + " " + APPLICATION_VERSION);
  this->createMenu(primeText_);

  // fill the sieveSizeComboBox with power of 2 values <= "4096 KB"
  for (int i = MINIMUM_SIEVE_SIZE; i <= MAXIMUM_SIEVE_SIZE; i *= 2)
    ui->sieveSizeComboBox->addItem(QString::number(i) + " KB");
  this->setTo(ui->sieveSizeComboBox, DEFAULT_SIEVE_SIZE);

  // fill the threadsComboBox with power of 2 values <= maxThreads_
  maxThreads_ = ParallelPrimeSieve::getMaxThreads();
  for (int i = 1; i < maxThreads_; i *= 2)
    ui->threadsComboBox->addItem(QString::number(i));
  ui->threadsComboBox->addItem(QString::number(maxThreads_));
  this->setTo(ui->threadsComboBox, "1");

  // set an ideal ComboBox width
  int width = ui->sieveSizeComboBox->minimumSizeHint().width();
  ui->sieveSizeComboBox->setFixedWidth(width);
  ui->threadsComboBox->setFixedWidth(width);

  // set a nice GUI size
  QSize size = this->sizeHint();
  size.setWidth(this->minimumSizeHint().width());
#if defined(Q_OS_WIN)
  size.setHeight(size.height() - size.height() / 10);
#endif
  this->resize(size);

  // limit input for arithmetic expressions
  QRegExp rx("[0-9\\+\\-\\*\\/\\%\\^\\(\\)\\e\\E]*");
  validator_ = new QRegExpValidator(rx, this);
  ui->lowerBoundLineEdit->setValidator(validator_);
  ui->upperBoundLineEdit->setValidator(validator_);
}

void PrimeSieveGUI::initConnections() {
  connect(&progressBarTimer_,     SIGNAL(timeout()),                    this, SLOT(advanceProgressBar()));
  connect(ui->lowerBoundLineEdit, SIGNAL(textChanged(const QString &)), this, SLOT(autoSetThreads()));
  connect(ui->upperBoundLineEdit, SIGNAL(textChanged(const QString &)), this, SLOT(autoSetThreads()));
  connect(ui->autoSetCheckBox,    SIGNAL(toggled(bool)),                this, SLOT(autoSetThreads()));
  connect(saveAct_,               SIGNAL(triggered()),                  this, SLOT(saveToFile()));
  connect(quitAct_,               SIGNAL(triggered()),                  qApp, SLOT(closeAllWindows()));
  connect(alignmentGroup_,        SIGNAL(triggered(QAction*)),          this, SLOT(printMenuClicked(QAction*)));
  connect(aboutAct_,              SIGNAL(triggered()),                  this, SLOT(showAboutDialog()));
}

/**
 * Get the sieve size in kilobytes from the sieveSizeComboBox.
 * @post sieveSize >= 1 && sieveSize <= 4096.
 */
int PrimeSieveGUI::getSieveSize() {
  QString sieveSize(ui->sieveSizeComboBox->currentText());
  // remove " KB"
  sieveSize.chop(3);
  return sieveSize.toInt();
}

/**
 * Get the number of threads from the threadsComboBox.
 */
int PrimeSieveGUI::getThreads() {
  return ui->threadsComboBox->currentText().toInt();
}

quint64 PrimeSieveGUI::getNumber(const QString& str) {
  if (str.isEmpty())
    throw std::invalid_argument("Please enter a lower and upper bound for prime sieving.");

  ExpressionParser<quint64> parser;
  quint64 result = 0;
  try {
    result = parser.eval(str.toAscii().data());
  }
  catch (parser_error& e) {
    throw std::invalid_argument(e.what());
  }

  int digits = str.count(QRegExp("[0-9]"));
  if (parser.getResult() >= UPPER_BOUND_LIMIT || (
      digits == str.size() && (
      digits >  UPPER_BOUND_STR.size() || (
      digits == UPPER_BOUND_STR.size() &&
      str    >= UPPER_BOUND_STR))))
    throw std::invalid_argument("Please use positive integers < 2^64 - 2^32*10.");<commit_msg>updated src/expr/ExpressionParser.h to version 2.2<commit_after>/*
 * PrimeSieveGUI.cpp -- This file is part of primesieve
 *
 * Copyright (C) 2012 <NAME>, <<EMAIL>>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.

 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
 */

#include "PrimeSieveGUI.h"
#include "ui_PrimeSieveGUI.h"
#include "PrimeSieveProcess.h"
#include "../soe/ParallelPrimeSieve.h"
#include "../expr/ExpressionParser.h"

#include <QtGlobal>
#include <QCoreApplication>
#include <QByteArray>
#include <QTextStream>
#include <QFile>
#include <QSize>
#include <QMessageBox>
#include <QTextCursor>
#include <stdexcept>

PrimeSieveGUI::PrimeSieveGUI(QWidget *parent) :
  QMainWindow(parent), ui(new Ui::PrimeSieveGUI), validator_(0),
  primeSieveProcess_(0), saveAct_(0), quitAct_(0), aboutAct_(0),
  alignmentGroup_(0) {
  ui->setupUi(this);
  primeText_.push_back("Prime numbers");
  primeText_.push_back("Twin primes");
  primeText_.push_back("Prime triplets");
  primeText_.push_back("Prime quadruplets");
  primeText_.push_back("Prime quintuplets");
  primeText_.push_back("Prime sextuplets");
  primeText_.push_back("Prime septuplets");
  this->initGUI();
  this->initConnections();
}

PrimeSieveGUI::~PrimeSieveGUI() {
  this->cleanUp();
  delete validator_;
  delete saveAct_;
  delete quitAct_;
  delete aboutAct_;
  delete alignmentGroup_;
  for (; !countAct_.isEmpty(); countAct_.pop_back())
    delete countAct_.back();
  for (; !printAct_.isEmpty(); printAct_.pop_back())
    delete printAct_.back();
  // Qt code
  delete ui;
}

void PrimeSieveGUI::changeEvent(QEvent *e) {
  QMainWindow::changeEvent(e);
  switch (e->type()) {
  case QEvent::LanguageChange:
    ui->retranslateUi(this);
    break;
  default:
    break;
  }
}

void PrimeSieveGUI::initGUI() {
  this->setWindowTitle(APPLICATION_NAME + " " + APPLICATION_VERSION);
  this->createMenu(primeText_);

  // fill the sieveSizeComboBox with power of 2 values <= "4096 KB"
  for (int i = MINIMUM_SIEVE_SIZE; i <= MAXIMUM_SIEVE_SIZE; i *= 2)
    ui->sieveSizeComboBox->addItem(QString::number(i) + " KB");
  this->setTo(ui->sieveSizeComboBox, DEFAULT_SIEVE_SIZE);

  // fill the threadsComboBox with power of 2 values <= maxThreads_
  maxThreads_ = ParallelPrimeSieve::getMaxThreads();
  for (int i = 1; i < maxThreads_; i *= 2)
    ui->threadsComboBox->addItem(QString::number(i));
  ui->threadsComboBox->addItem(QString::number(maxThreads_));
  this->setTo(ui->threadsComboBox, "1");

  // set an ideal ComboBox width
  int width = ui->sieveSizeComboBox->minimumSizeHint().width();
  ui->sieveSizeComboBox->setFixedWidth(width);
  ui->threadsComboBox->setFixedWidth(width);

  // set a nice GUI size
  QSize size = this->sizeHint();
  size.setWidth(this->minimumSizeHint().width());
#if defined(Q_OS_WIN)
  size.setHeight(size.height() - size.height() / 10);
#endif
  this->resize(size);

  // limit input for arithmetic expressions
  QRegExp rx("[0-9\\+\\-\\*\\/\\%\\^\\(\\)\\e\\E]*");
  validator_ = new QRegExpValidator(rx, this);
  ui->lowerBoundLineEdit->setValidator(validator_);
  ui->upperBoundLineEdit->setValidator(validator_);
}

void PrimeSieveGUI::initConnections() {
  connect(&progressBarTimer_,     SIGNAL(timeout()),                    this, SLOT(advanceProgressBar()));
  connect(ui->lowerBoundLineEdit, SIGNAL(textChanged(const QString &)), this, SLOT(autoSetThreads()));
  connect(ui->upperBoundLineEdit, SIGNAL(textChanged(const QString &)), this, SLOT(autoSetThreads()));
  connect(ui->autoSetCheckBox,    SIGNAL(toggled(bool)),                this, SLOT(autoSetThreads()));
  connect(saveAct_,               SIGNAL(triggered()),                  this, SLOT(saveToFile()));
  connect(quitAct_,               SIGNAL(triggered()),                  qApp, SLOT(closeAllWindows()));
  connect(alignmentGroup_,        SIGNAL(triggered(QAction*)),          this, SLOT(printMenuClicked(QAction*)));
  connect(aboutAct_,              SIGNAL(triggered()),                  this, SLOT(showAboutDialog()));
}

/**
 * Get the sieve size in kilobytes from the sieveSizeComboBox.
 * @post sieveSize >= 1 && sieveSize <= 4096.
 */
int PrimeSieveGUI::getSieveSize() {
  QString sieveSize(ui->sieveSizeComboBox->currentText());
  // remove " KB"
  sieveSize.chop(3);
  return sieveSize.toInt();
}

/**
 * Get the number of threads from the threadsComboBox.
 */
int PrimeSieveGUI::getThreads() {
  return ui->threadsComboBox->currentText().toInt();
}

quint64 PrimeSieveGUI::getNumber(const QString& str) {
  if (str.isEmpty())
    throw std::invalid_argument("Please enter a lower and upper bound for prime sieving.");

  ExpressionParser<quint64> parser;
  quint64 result = 0;
  try {
    result = parser.eval(str.toAscii().data());
  }
  catch (parser_error& e) {
    throw std::invalid_argument(e.what());
  }

  int digits = str.count(QRegExp("[0-9]"));
  if (result >= UPPER_BOUND_LIMIT || (
      digits == str.size() && (
      digits >  UPPER_BOUND_STR.size() || (
      digits == UPPER_BOUND_STR.size() &&
      str    >= UPPER_BOUND_STR))))
    throw std::invalid_argument("Please use positive integers < 2^64 - 2^32*10.");
{'fraction_non_alphanumeric': 0.14528251834821823, 'fraction_numerical': 0.008665664514988063, 'mean_word_length': 4.250696378830083, 'pattern_counts': {'":': 0, '<': 43, '<?xml version=': 0, '>': 115, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2741788', 'n_tokens_mistral': 3785, 'n_tokens_neox': 3631, 'n_words': 837}