<commit_before>//  Author Amoriello Hutti - 2015

#include <token/commands.h>

#include <Arduino.h>

#ifndef TEST_NO_KEYBOARD
  //#include <Keyboard.h>
  //#include <HID.h>
  #include <HID-Project.h>
#endif  // TEST_NO_KEYBOARD

#include <token/token.h>
#include <token/password.h>
#include <token/crypto.h>
#include <token/communication/channel.h>
#include <token/log.h>

CmdProcessor g_cmd_registrer[cmdid::kNbCmd];

void Pair(const Command&) {
  Response resp;

  g_token.Pair();

  TLOG2("Pair");

  const SymKey& pass_key = g_token.PassKey();
  const SymKey& cr_key = g_token.CRKey();
  const SymKey& req_key = g_token.ReqKey();

  resp.hdr.id = respid::kOk;
  uint8_t key_size = sizeof(pass_key.data);
  resp.hdr.arg_size = 3 * key_size;

  for (int i = 0; i < key_size; ++i) {
    resp.arg[i] = pass_key.data[i];
    resp.arg[16 + i] = cr_key.data[i];
    resp.arg[32 + i] = req_key.data[i];
  }

  g_chan.WriteResponse(resp);
}

void CreateChallenge(const Command&) {
  Response resp;

  TLOG2("Challenge");

  resp.hdr.id = respid::kOk;
  resp.hdr.arg_size = sizeof(Challenge);

  Challenge* p_challenge = (Challenge*)(&resp.arg);
  CreateChallenge(p_challenge);

  g_chan.WriteResponse(resp);
}

void CreatePassword(const Command& cmd) {
  Response resp;
  Password pass;

  TLOG2("CreatePassword");

  uint8_t size = cmd.arg[0];
  if (size > Password::kMaxCharacters) {
    resp.hdr.id = respid::kInvalidArgument;
    resp.hdr.arg_size = 0;
    g_chan.WriteResponse(resp);
    return;
  }

  CreatePassword(&pass, size);

  uint8_t arg_size = EncryptPassword(pass, g_token.PassKey(), &resp.arg[0]);

  resp.hdr.id = respid::kOk;
  resp.hdr.arg_size = arg_size;

  g_chan.WriteResponse(resp);
}

void TypePassword(const Command& cmd) {
  Response resp;

  TLOG2("TypePassword");

  if (cmd.hdr.arg_size < 80 || cmd.hdr.arg_size > 81) {
    resp.hdr.id = respid::kInvalidArgument;
    resp.hdr.arg_size = 0;
    g_chan.WriteResponse(resp);
    return;
  }

  // This is valid has long has Password has 1 data member aligned
  // and packed(1)
  Password* p_pass = (Password*)resp.arg;

  DecryptPassword(cmd.arg, g_token.PassKey(), p_pass);

  char* p_password = (char*)&resp.arg;

#ifndef TEST_NO_KEYBOARD
  Keyboard.print(p_password);

  if (cmd.hdr.arg_size == 81) {  // Need to press enter?
    Keyboard.press(KEY_ENTER);
    Keyboard.releaseAll();
  }
#endif  // TEST_NO_KEYBOARD

  resp.hdr.id = respid::kOk;
  resp.hdr.arg_size = 0;
  g_chan.WriteResponse(resp);
}

void LockComputer(const Command&) {
  Response resp;

  Keyboard.press(KEY_LEFT_GUI);
  Keyboard.release('l');

  resp.hdr.id = respid::kOk;
  resp.hdr.arg_size = 0;
  g_chan.WriteResponse(resp);
}

void TypeString(const Command& cmd) {
  Response resp;

  if (cmd.hdr.arg_size >= 100) {
    resp.hdr.id = respid::kInvalidArgument;
    resp.hdr.arg_size = 0;
    g_chan.WriteResponse(resp);
    return;
  }

  char* string = (char*)cmd.arg;

#ifndef TEST_NO_KEYBOARD
  Keyboard.print(string);

  //length will contains string length + 1
  uint8_t length = 0;
  while (string[length++]);

  // Check for additional key
  if (cmd.hdr.arg_size > length) {
    uint8_t nbAdditionnalKeyPress = cmd.hdr.arg_size - length;
    uint8_t beginKeyIndex = cmd.hdr.arg_size - nbAdditionnalKeyPress;
    for (uint8_t i = 0; i < nbAdditionnalKeyPress; ++i) {
      Keyboard.press(cmd.arg[beginKeyIndex + i]);
      Keyboard.releaseAll();
    }
  }
#endif  // TEST_NO_KEYBOARD

  resp.hdr.id = respid::kOk;
  resp.hdr.arg_size = 0;
  g_chan.WriteResponse(resp);
}

void ReturnPassword(const Command& cmd) {
  Response resp;
  Password pass;

  TLOG2("ReturnPassword");

  if (cmd.hdr.arg_size != 80) {
    resp.hdr.id = respid::kInvalidArgument;
    resp.hdr.arg_size = 0;
    g_chan.WriteResponse(resp);
    return;
  }

  /*** This works ***/
  //DecipherPassword(cmd.arg, g_token.PassKey(), (Password*)&resp2.arg);

  //CipherPassword(*(Password*)&resp2.arg, g_token.ReqKey(), resp.arg);
  /*** This works ***/

  DecryptPassword(cmd.arg, g_token.PassKey(), &pass);

  auto arg_size = EncryptPassword(pass, g_token.ReqKey(), resp.arg);

  resp.hdr.id = respid::kOk;
  resp.hdr.arg_size = arg_size;

  g_chan.WriteResponse(resp);
}

void ResetKeys(const Command& cmd) {
  Response resp;
  // Version (1 byte) + 3 * 16 byte key
  if (cmd.hdr.arg_size != 49) {
    resp.hdr.id = respid::kInvalidArgument;
    resp.hdr.arg_size = 0;
    g_chan.WriteResponse(resp);
    return;
  }

  //uint8_t version = cmd.arg[0];

  SymKey* p_pass_key = (SymKey*)&cmd.arg[1];
  SymKey* p_cr_key = (SymKey*)&cmd.arg[17];
  SymKey* p_req_key = (SymKey*)&cmd.arg[33];

  g_token.StoreKeys(*p_pass_key, *p_cr_key, *p_req_key);

  // The token is now paired
  g_token.Pair();

  resp.hdr.id = respid::kOk;
  resp.hdr.arg_size = 0;

  g_chan.WriteResponse(resp);
}

void Reset(const Command&) {
  Response resp;

  g_token.Reset();

  resp.hdr.id = respid::kOk;
  resp.hdr.arg_size = 0;

  g_chan.WriteResponse(resp);
}

namespace /* anonymous */ {

void RegistrerCommands() {
  g_cmd_registrer[cmdid::kPair] = &Pair;
  g_cmd_registrer[cmdid::kCreateChallenge] = &CreateChallenge;
  g_cmd_registrer[cmdid::kReset] = &Reset;

  g_cmd_registrer[cmdid::kCreatePassword] = &CreatePassword;
  g_cmd_registrer[cmdid::kTypePassword] = &TypePassword;
  g_cmd_registrer[cmdid::kReturnPassword] = &ReturnPassword;
  g_cmd_registrer[cmdid::kLockComputer] = &LockComputer;
  g_cmd_registrer[cmdid::kTypeString] = &TypeString;
  g_cmd_registrer[cmdid::kResetKeys] = &ResetKeys;
}

struct AutoCmdRegistrer {
  AutoCmdRegistrer() {
    RegistrerCommands();
  }
};

static AutoCmdRegistrer registrer2;

}  // namespace anonymous<commit_msg>removing useless comments<commit_after>//  Author Amoriello Hutti - 2015

#include <token/commands.h>

#include <Arduino.h>

#ifndef TEST_NO_KEYBOARD
  //#include <Keyboard.h>
  //#include <HID.h>
  #include <HID-Project.h>
#endif  // TEST_NO_KEYBOARD

#include <token/token.h>
#include <token/password.h>
#include <token/crypto.h>
#include <token/communication/channel.h>
#include <token/log.h>

CmdProcessor g_cmd_registrer[cmdid::kNbCmd];

void Pair(const Command&) {
  Response resp;

  g_token.Pair();

  TLOG2("Pair");

  const SymKey& pass_key = g_token.PassKey();
  const SymKey& cr_key = g_token.CRKey();
  const SymKey& req_key = g_token.ReqKey();

  resp.hdr.id = respid::kOk;
  uint8_t key_size = sizeof(pass_key.data);
  resp.hdr.arg_size = 3 * key_size;

  for (int i = 0; i < key_size; ++i) {
    resp.arg[i] = pass_key.data[i];
    resp.arg[16 + i] = cr_key.data[i];
    resp.arg[32 + i] = req_key.data[i];
  }

  g_chan.WriteResponse(resp);
}

void CreateChallenge(const Command&) {
  Response resp;

  TLOG2("Challenge");

  resp.hdr.id = respid::kOk;
  resp.hdr.arg_size = sizeof(Challenge);

  Challenge* p_challenge = (Challenge*)(&resp.arg);
  CreateChallenge(p_challenge);

  g_chan.WriteResponse(resp);
}

void CreatePassword(const Command& cmd) {
  Response resp;
  Password pass;

  TLOG2("CreatePassword");

  uint8_t size = cmd.arg[0];
  if (size > Password::kMaxCharacters) {
    resp.hdr.id = respid::kInvalidArgument;
    resp.hdr.arg_size = 0;
    g_chan.WriteResponse(resp);
    return;
  }

  CreatePassword(&pass, size);

  uint8_t arg_size = EncryptPassword(pass, g_token.PassKey(), &resp.arg[0]);

  resp.hdr.id = respid::kOk;
  resp.hdr.arg_size = arg_size;

  g_chan.WriteResponse(resp);
}

void TypePassword(const Command& cmd) {
  Response resp;

  TLOG2("TypePassword");

  if (cmd.hdr.arg_size < 80 || cmd.hdr.arg_size > 81) {
    resp.hdr.id = respid::kInvalidArgument;
    resp.hdr.arg_size = 0;
    g_chan.WriteResponse(resp);
    return;
  }

  // This is valid has long has Password has 1 data member aligned
  // and packed(1)
  Password* p_pass = (Password*)resp.arg;

  DecryptPassword(cmd.arg, g_token.PassKey(), p_pass);

  char* p_password = (char*)&resp.arg;

#ifndef TEST_NO_KEYBOARD
  Keyboard.print(p_password);

  if (cmd.hdr.arg_size == 81) {  // Need to press enter?
    Keyboard.press(KEY_ENTER);
    Keyboard.releaseAll();
  }
#endif  // TEST_NO_KEYBOARD

  resp.hdr.id = respid::kOk;
  resp.hdr.arg_size = 0;
  g_chan.WriteResponse(resp);
}

void LockComputer(const Command&) {
  Response resp;

  Keyboard.press(KEY_LEFT_GUI);
  Keyboard.release('l');

  resp.hdr.id = respid::kOk;
  resp.hdr.arg_size = 0;
  g_chan.WriteResponse(resp);
}

void TypeString(const Command& cmd) {
  Response resp;

  if (cmd.hdr.arg_size >= 100) {
    resp.hdr.id = respid::kInvalidArgument;
    resp.hdr.arg_size = 0;
    g_chan.WriteResponse(resp);
    return;
  }

  char* string = (char*)cmd.arg;

#ifndef TEST_NO_KEYBOARD
  Keyboard.print(string);

  //length will contains string length + 1
  uint8_t length = 0;
  while (string[length++]);

  // Check for additional key
  if (cmd.hdr.arg_size > length) {
    uint8_t nbAdditionnalKeyPress = cmd.hdr.arg_size - length;
    uint8_t beginKeyIndex = cmd.hdr.arg_size - nbAdditionnalKeyPress;
    for (uint8_t i = 0; i < nbAdditionnalKeyPress; ++i) {
      Keyboard.press(cmd.arg[beginKeyIndex + i]);
      Keyboard.releaseAll();
    }
  }
#endif  // TEST_NO_KEYBOARD

  resp.hdr.id = respid::kOk;
  resp.hdr.arg_size = 0;
  g_chan.WriteResponse(resp);
}

void ReturnPassword(const Command& cmd) {
  Response resp;
  Password pass;

  TLOG2("ReturnPassword");

  if (cmd.hdr.arg_size != 80) {
    resp.hdr.id = respid::kInvalidArgument;
    resp.hdr.arg_size = 0;
    g_chan.WriteResponse(resp);
    return;
  }

  DecryptPassword(cmd.arg, g_token.PassKey(), &pass);

  auto arg_size = EncryptPassword(pass, g_token.ReqKey(), resp.arg);

  resp.hdr.id = respid::kOk;
  resp.hdr.arg_size = arg_size;

  g_chan.WriteResponse(resp);
}

void ResetKeys(const Command& cmd) {
  Response resp;
  // Version (1 byte) + 3 * 16 byte key
  if (cmd.hdr.arg_size != 49) {
    resp.hdr.id = respid::kInvalidArgument;
    resp.hdr.arg_size = 0;
    g_chan.WriteResponse(resp);
    return;
  }

  //uint8_t version = cmd.arg[0];

  SymKey* p_pass_key = (SymKey*)&cmd.arg[1];
  SymKey* p_cr_key = (SymKey*)&cmd.arg[17];
  SymKey* p_req_key = (SymKey*)&cmd.arg[33];

  g_token.StoreKeys(*p_pass_key, *p_cr_key, *p_req_key);

  // The token is now paired
  g_token.Pair();

  resp.hdr.id = respid::kOk;
  resp.hdr.arg_size = 0;

  g_chan.WriteResponse(resp);
}

void Reset(const Command&) {
  Response resp;

  g_token.Reset();

  resp.hdr.id = respid::kOk;
  resp.hdr.arg_size = 0;

  g_chan.WriteResponse(resp);
}

namespace /* anonymous */ {

void RegistrerCommands() {
  g_cmd_registrer[cmdid::kPair] = &Pair;
  g_cmd_registrer[cmdid::kCreateChallenge] = &CreateChallenge;
  g_cmd_registrer[cmdid::kReset] = &Reset;

  g_cmd_registrer[cmdid::kCreatePassword] = &CreatePassword;
  g_cmd_registrer[cmdid::kTypePassword] = &TypePassword;
  g_cmd_registrer[cmdid::kReturnPassword] = &ReturnPassword;
  g_cmd_registrer[cmdid::kLockComputer] = &LockComputer;
  g_cmd_registrer[cmdid::kTypeString] = &TypeString;
  g_cmd_registrer[cmdid::kResetKeys] = &ResetKeys;
}

struct AutoCmdRegistrer {
  AutoCmdRegistrer() {
    RegistrerCommands();
  }
};

static AutoCmdRegistrer registrer2;

}  // namespace anonymous<|endoftext|>


<commit_before>/*  Copyright (C) 2006 Imperial College London and others.

    Please see the AUTHORS file in the main source directory for a full list
    of copyright holders.

    Prof. C Pain
    Applied Modelling and Computation Group
    Department of Earth Science and Engineering
    Imperial College London

    amcgsoftware@imperial.ac.uk

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation,
    version 2.1 of the License.

    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
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
    USA
*/

#include "Usage.h"
#include "spud"

using namespace std;

using namespace Spud;

map<string, string> fl_command_line_options;

void print_version(ostream& stream){
  stream<<"Revision: "<<__FLUIDITY_VERSION__
#ifdef DDEBUG
      <<" (debugging)"
#endif
      <<endl
      <<"Compile date: "<<__DATE__<<" "<<__TIME__<<endl
      <<"OpenMP Support\t\t\t"
#ifdef _OPENMP
      <<"yes\n"
#else
      <<"no\n"
#endif
      <<"Adaptivity support\t\t"
#ifdef HAVE_ADAPTIVITY
      <<"yes\n"
#else
      <<"no\n"
#endif
      <<"2D adaptivity support\t\t"
#ifdef HAVE_MBA_2D
      <<"yes\n"
#else
      <<"no\n"
#endif
      <<"3D MBA support\t\t\t"
#ifdef HAVE_MBA_3D
      <<"yes\n"
#else
      <<"no\n"
#endif
      <<"CGAL support\t\t\t"
#ifdef HAVE_CGAL
      <<"yes\n"
#else
      <<"no\n"
#endif
      <<"MPI support\t\t\t"
#ifdef HAVE_MPI
      <<"yes\n"
#else
      <<"no\n"
#endif
      <<"Double precision\t\t"
#ifdef DOUBLEP
      <<"yes\n"
#else
      <<"no\n"
#endif
      <<"CGNS support\t\t\t"
#ifdef HAVE_CGNS
      <<"yes\n"
#else
      <<"no\n"
#endif
      <<"NetCDF support\t\t\t"
#ifdef HAVE_NETCDF
      <<"yes\n"
#else
      <<"no\n"
#endif
      <<"Signal handling support\t\t"
#ifdef NSIGNAL
      <<"no\n"
#else
      <<"yes\n"
#endif
      <<"Stream I/O support\t\t"
#ifdef STREAM_IO
      <<"yes\n"
#else
      <<"no\n"
#endif
      <<"PETSc support\t\t\t"
#ifdef HAVE_PETSC
      <<"yes\n"
#else
      <<"no\n"
#endif
      <<"Hypre support\t\t\t"
#ifdef HAVE_HYPRE
      <<"yes\n"
#else
      <<"no\n"
#endif
      <<"ARPACK support\t\t\t"
#ifdef HAVE_LIBARPACK
      <<"yes\n"
#else
      <<"no\n"
#endif
      <<"Python support\t\t\t"
#ifdef HAVE_PYTHON
      <<"yes\n"
#else
      <<"no\n"
#endif
      <<"Numpy support\t\t\t"
#ifdef HAVE_NUMPY
      <<"yes\n"
#else
      <<"no\n"
#endif
      <<"VTK support\t\t\t"
#ifdef HAVE_VTK
      <<"yes\n"
#else
      <<"no\n"
#endif
      <<"Zoltan support\t\t\t"
#ifdef HAVE_ZOLTAN
      <<"yes\n"
#else
      <<"no\n"
#endif
      <<"Memory diagnostics\t\t"
#ifdef HAVE_MEMORY_STATS
      <<"yes\n"
#else
      <<"no\n"
#endif
      <<"FEMDEM support\t\t\t"
#ifdef USING_FEMDEM
      <<"yes\n"
#else
      <<"no\n"
#endif
      <<"Hyperlight support\t\t"
#ifdef HAVE_HYPERLIGHT
      <<"yes\n"
#else
      <<"no\n"
#endif
      ;
  stream.flush();
  return;
}

void print_environment(){

  const char *relevant_variables[]={"PETSC_OPTIONS"};

  int no_relevant_variables=1;

  cout<<"Environment variables relevant for fluidity:\n";
  for(int i=0; i<1; i++) {
    char *env=getenv(relevant_variables[i]);
    if(env!=NULL) {
      cout<<relevant_variables[i]<<" = "<<env<<endl;
      no_relevant_variables=0;
    }
  };
  if (no_relevant_variables)
    cout<<" none\n";

}

void usage(char *cmd){
  print_version();
  cerr<<"\n\nUsage: "<<cmd<<" [options ...] [simulation-file]\n"
      <<"\nOptions:\n"
      <<" -h, --help\n\tHelp! Prints this message.\n"
      <<" -l, --log\n\tCreate log file for each process (useful for non-interactive testing).\n"
      <<" -v <level>, --verbose\n\tVerbose output to stdout, default level 0\n"
      <<" -p, --profile\n"
      <<"\tPrint profiling data at end of run\n"
      <<"\tThis provides aggregated elapsed time for coarse-level computation\n"
      <<"\t(Turned on automatically if verbosity is at level 2 or above)\n"
      <<" -V, --version\n\tVersion\n";
  return;
}

void ParseArguments(int argc, char** argv){

#ifndef _AIX
  struct option longOptions[] = {
    {"help", 0, 0, 'h'},
    {"log", 0, 0, 'l'},
    {"profile", 0, 0, 'p'},
    {"verbose", optional_argument, 0, 'v'},
    {"version", 0, 0, 'V'},
    {0, 0, 0, 0}
  };
#endif
  int optionIndex = 0;
  int verbosity = 0;
  int c;

  // set opterr to nonzero to make getopt print error messages
  opterr=1;

  while (true){
#ifndef _AIX
    c = getopt_long(argc, argv, "hlpv::V", longOptions, &optionIndex);
#else
    c = getopt(argc, argv, "hlpv::V");
#endif
    if (c == -1) break;

    switch (c){
    case 'h':
      fl_command_line_options["help"] = "";
      break;

    case 'l':
      fl_command_line_options["log"] = "";
      break;
    case 'p':
      fl_command_line_options["profile"] = "yes";
      break;
    case 'v':
      fl_command_line_options["verbose"] = (optarg == NULL) ? "1" : optarg;
      break;

    case 'V':
      fl_command_line_options["version"] = "";
      break;

    case '?':
      // missing argument only returns ':' if the option string starts with ':'
      // but this seems to stop the printing of error messages by getopt?
      cerr<<"ERROR: unknown option or missing argument\n";
      usage(argv[0]);
      exit(-1);
    case ':':
      cerr<<"ERROR: missing argument\n";
      usage(argv[0]);
      exit(-1);
    default:
      // unexpected:
      cerr<<"ERROR: getopt returned unrecognized character code\n";
      exit(-1);
    }
  }

  // Help?
  if(fl_command_line_options.count("help")){
    usage(argv[0]);
    exit(-1);
  }

  // Version?
  if(fl_command_line_options.count("version")){
    print_version();
    exit(-1);
  }

  // Verbose?
  {
    int MyRank = 0;
#ifdef HAVE_MPI
    if(MPI::Is_initialized()){
      MyRank = MPI::COMM_WORLD.Get_rank();
    }
#endif

    if(fl_command_line_options.count("verbose") == 0){
      verbosity = 0;
    }else{
      verbosity = atoi(fl_command_line_options["verbose"].c_str());
    }
    set_global_debug_level_fc(&verbosity);
    if(verbosity >= 2){
      fl_command_line_options["profile"] = "yes";
    }
  }

  // Pseudo2d?
  if(fl_command_line_options.count("pseudo2d")){
  int val;
  val = atoi(fl_command_line_options["pseudo2d"].c_str());
  set_pseudo2d_domain_fc(&val);
  }

  // What to do with stdout/stderr?
  if(fl_command_line_options.count("log")){
    ostringstream debug_file, err_file;
    debug_file << "fluidity.log";
    err_file << "fluidity.err";
#ifdef HAVE_MPI
    if(MPI::Is_initialized()){
      int MyRank = MPI::COMM_WORLD.Get_rank();
      debug_file << "-" << MyRank;
      err_file << "-" << MyRank;
    }
#endif

    if(freopen(debug_file.str().c_str(), "w", stdout) == NULL)
      perror("failed to redirect stdio for debugging");

    if(freopen(err_file.str().c_str(), "w", stderr) == NULL)
      perror("failed to redirect stderr for debugging");
  }

  // Find the filename if one is specified. Assuming that final
  // argument is simulation filename if it does not correspond to a
  // known option.
  if (fl_command_line_options.count("xml") == 0)
  {
    if(argc > optind + 1)
    {
      fl_command_line_options["xml"] = argv[optind + 1];
    }
    else if(argc == optind + 1)
    {
      fl_command_line_options["xml"] = argv[optind];
    }
    else if(fl_command_line_options.count("xml") == 0)
    {
      usage(argv[0]);
      exit(-1);
    }
  }

  load_options(fl_command_line_options["xml"]);
  if(!have_option("/simulation_name")){
    cerr<<"ERROR: failed to find simulation name after loading options file\n";
    cerr<<"  or specified options file not found\n";
    exit(-1);
  }
  OptionError stat = get_option("/simulation_name", fl_command_line_options["simulation_name"]);
  assert(stat == SPUD_NO_ERROR);

  // now that we know the verbosity, and possibly redirected stdout,
  // we may print the given command line
  if(verbosity >= 2){
    cout<<"Fluidity command line:\n ";
    for(int i=0;i<argc; i++)
      cout<<argv[i]<<" ";
    cout<<endl;
    print_environment();

    // Useful for debugging options
    print_options();
  }

  // Environmental stuff -- this needs to me moved out of here and
  // into populate state.
  if(have_option("/timestepping/current_time/time_units")){
    string option;
    get_option("/timestepping/current_time/time_units/date", option);

    FluxesReader_global.SetSimulationTimeUnits(option.c_str());
    ClimateReader_global.SetSimulationTimeUnits(option.c_str());
    NEMOReader_v2_global.SetSimulationTimeUnits(option.c_str());
  }
  if(have_option("/environmental_data/climatology/file_name")){
    string option;
    get_option("/environmental_data/climatology/file_name", option);

    ClimateReader_global.SetClimatology(option);
  }
  if(have_option("/ocean_forcing/bulk_formulae/input_file")) {
    string option;
    get_option("/ocean_forcing/bulk_formulae/input_file/file_name", option);
    string dataset = "ERA40"; //default
    if(have_option("/ocean_forcing/bulk_formulae/file_type")) {
        get_option("/ocean_forcing/bulk_formulae/file_type/filetype/name", dataset);
    }
    if (dataset == "ERA40") {
        FluxesReader_global.RegisterDataFile(option);
        // field from NetCDF file                         Index |   Physical meaning
        FluxesReader_global.AddFieldOfInterest("u10");  //  0   | 10 metre U wind component
        FluxesReader_global.AddFieldOfInterest("v10");  //  1   | 10 metre V wind component
        FluxesReader_global.AddFieldOfInterest("ssrd"); //  2   | Surface solar radiation
        FluxesReader_global.AddFieldOfInterest("strd"); //  3   | Surface thermal radiation
        FluxesReader_global.AddFieldOfInterest("ro");   //  4   | Runoff
        FluxesReader_global.AddFieldOfInterest("tp");   //  5   | Total precipitation
        FluxesReader_global.AddFieldOfInterest("d2m");  //  6   | Dew point temp at 2m
        FluxesReader_global.AddFieldOfInterest("t2m");  //  7   | Air temp at 2m
        FluxesReader_global.AddFieldOfInterest("msl");  //  8   | Mean sea level pressure
    } else {
        cerr<<"ERROR: unsupported bulk formula input file type. Choose ERA40\n";
        exit(-1);
    }

  }

  if(have_option("/ocean_biology/lagrangian_ensemble/hyperlight")) {
    FluxesReader_global.AddFieldOfInterest("tcc");  // Total cloud cover
  }

  if(have_option("/ocean_forcing/external_data_boundary_conditions")) {
    string option;
    get_option("/ocean_forcing/external_data_boundary_conditions/input_file/file_name", option);

    if(verbosity >= 3)
      cout << "Registering external data forcing file: " << option << endl;

    NEMOReader_v2_global.RegisterDataFile(option);

    NEMOReader_v2_global.AddFieldOfInterest("temperature");  //  0   | Sea temperature
    NEMOReader_v2_global.AddFieldOfInterest("salinity");     //  1   | Salinity
    NEMOReader_v2_global.AddFieldOfInterest("u");            //  2   | Azimuthal velocity
    NEMOReader_v2_global.AddFieldOfInterest("v");            //  3   | Meridional velocity
    NEMOReader_v2_global.AddFieldOfInterest("ssh");          //  4   | Sea surface height
  }

  return;
}

void PetscInit(int argc, char** argv){
#ifdef HAVE_PETSC
  int petscargc;
  char** petscargv;
  petscargc = 1;
  petscargv = new char*[1];
  petscargv[0] = new char[strlen(argv[0]) + 1];
  strncpy(petscargv[0], argv[0], strlen(argv[0]) + 1);

  static char help[] = "Use --help to see the help.\n\n";
  PetscErrorCode ierr = PetscInitialize(&petscargc, &petscargv, NULL, help);
  // PetscInitializeFortran needs to be called when initialising PETSc from C, but calling it from Fortran
  // This sets all kinds of objects such as PETSC_NULL_OBJECT, PETSC_COMM_WORLD, etc., etc.
  ierr = PetscInitializeFortran();
  // CHKERRQ(ierr);
  signal(SIGSEGV, SIG_DFL);
  signal(SIGTRAP, SIG_DFL);

  for(int i = 0; i < petscargc; i++)
    delete [] petscargv[i];
  delete [] petscargv;
#endif
}

<commit_msg>This addresses bug lp:919315, such that a version check and help call to Fluidity does not complete with a non-zero error.<commit_after>/*  Copyright (C) 2006 Imperial College London and others.

    Please see the AUTHORS file in the main source directory for a full list
    of copyright holders.

    Prof. C Pain
    Applied Modelling and Computation Group
    Department of Earth Science and Engineering
    Imperial College London

    amcgsoftware@imperial.ac.uk

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation,
    version 2.1 of the License.

    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
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
    USA
*/

#include "Usage.h"
#include "spud"

using namespace std;

using namespace Spud;

map<string, string> fl_command_line_options;

void print_version(ostream& stream){
  stream<<"Revision: "<<__FLUIDITY_VERSION__
#ifdef DDEBUG
      <<" (debugging)"
#endif
      <<endl
      <<"Compile date: "<<__DATE__<<" "<<__TIME__<<endl
      <<"OpenMP Support\t\t\t"
#ifdef _OPENMP
      <<"yes\n"
#else
      <<"no\n"
#endif
      <<"Adaptivity support\t\t"
#ifdef HAVE_ADAPTIVITY
      <<"yes\n"
#else
      <<"no\n"
#endif
      <<"2D adaptivity support\t\t"
#ifdef HAVE_MBA_2D
      <<"yes\n"
#else
      <<"no\n"
#endif
      <<"3D MBA support\t\t\t"
#ifdef HAVE_MBA_3D
      <<"yes\n"
#else
      <<"no\n"
#endif
      <<"CGAL support\t\t\t"
#ifdef HAVE_CGAL
      <<"yes\n"
#else
      <<"no\n"
#endif
      <<"MPI support\t\t\t"
#ifdef HAVE_MPI
      <<"yes\n"
#else
      <<"no\n"
#endif
      <<"Double precision\t\t"
#ifdef DOUBLEP
      <<"yes\n"
#else
      <<"no\n"
#endif
      <<"CGNS support\t\t\t"
#ifdef HAVE_CGNS
      <<"yes\n"
#else
      <<"no\n"
#endif
      <<"NetCDF support\t\t\t"
#ifdef HAVE_NETCDF
      <<"yes\n"
#else
      <<"no\n"
#endif
      <<"Signal handling support\t\t"
#ifdef NSIGNAL
      <<"no\n"
#else
      <<"yes\n"
#endif
      <<"Stream I/O support\t\t"
#ifdef STREAM_IO
      <<"yes\n"
#else
      <<"no\n"
#endif
      <<"PETSc support\t\t\t"
#ifdef HAVE_PETSC
      <<"yes\n"
#else
      <<"no\n"
#endif
      <<"Hypre support\t\t\t"
#ifdef HAVE_HYPRE
      <<"yes\n"
#else
      <<"no\n"
#endif
      <<"ARPACK support\t\t\t"
#ifdef HAVE_LIBARPACK
      <<"yes\n"
#else
      <<"no\n"
#endif
      <<"Python support\t\t\t"
#ifdef HAVE_PYTHON
      <<"yes\n"
#else
      <<"no\n"
#endif
      <<"Numpy support\t\t\t"
#ifdef HAVE_NUMPY
      <<"yes\n"
#else
      <<"no\n"
#endif
      <<"VTK support\t\t\t"
#ifdef HAVE_VTK
      <<"yes\n"
#else
      <<"no\n"
#endif
      <<"Zoltan support\t\t\t"
#ifdef HAVE_ZOLTAN
      <<"yes\n"
#else
      <<"no\n"
#endif
      <<"Memory diagnostics\t\t"
#ifdef HAVE_MEMORY_STATS
      <<"yes\n"
#else
      <<"no\n"
#endif
      <<"FEMDEM support\t\t\t"
#ifdef USING_FEMDEM
      <<"yes\n"
#else
      <<"no\n"
#endif
      <<"Hyperlight support\t\t"
#ifdef HAVE_HYPERLIGHT
      <<"yes\n"
#else
      <<"no\n"
#endif
      ;
  stream.flush();
  return;
}

void print_environment(){

  const char *relevant_variables[]={"PETSC_OPTIONS"};

  int no_relevant_variables=1;

  cout<<"Environment variables relevant for fluidity:\n";
  for(int i=0; i<1; i++) {
    char *env=getenv(relevant_variables[i]);
    if(env!=NULL) {
      cout<<relevant_variables[i]<<" = "<<env<<endl;
      no_relevant_variables=0;
    }
  };
  if (no_relevant_variables)
    cout<<" none\n";

}

void usage(char *cmd){
  print_version();
  cerr<<"\n\nUsage: "<<cmd<<" [options ...] [simulation-file]\n"
      <<"\nOptions:\n"
      <<" -h, --help\n\tHelp! Prints this message.\n"
      <<" -l, --log\n\tCreate log file for each process (useful for non-interactive testing).\n"
      <<" -v <level>, --verbose\n\tVerbose output to stdout, default level 0\n"
      <<" -p, --profile\n"
      <<"\tPrint profiling data at end of run\n"
      <<"\tThis provides aggregated elapsed time for coarse-level computation\n"
      <<"\t(Turned on automatically if verbosity is at level 2 or above)\n"
      <<" -V, --version\n\tVersion\n";
  return;
}

void ParseArguments(int argc, char** argv){

#ifndef _AIX
  struct option longOptions[] = {
    {"help", 0, 0, 'h'},
    {"log", 0, 0, 'l'},
    {"profile", 0, 0, 'p'},
    {"verbose", optional_argument, 0, 'v'},
    {"version", 0, 0, 'V'},
    {0, 0, 0, 0}
  };
#endif
  int optionIndex = 0;
  int verbosity = 0;
  int c;

  // set opterr to nonzero to make getopt print error messages
  opterr=1;

  while (true){
#ifndef _AIX
    c = getopt_long(argc, argv, "hlpv::V", longOptions, &optionIndex);
#else
    c = getopt(argc, argv, "hlpv::V");
#endif
    if (c == -1) break;

    switch (c){
    case 'h':
      fl_command_line_options["help"] = "";
      break;

    case 'l':
      fl_command_line_options["log"] = "";
      break;
    case 'p':
      fl_command_line_options["profile"] = "yes";
      break;
    case 'v':
      fl_command_line_options["verbose"] = (optarg == NULL) ? "1" : optarg;
      break;

    case 'V':
      fl_command_line_options["version"] = "";
      break;

    case '?':
      // missing argument only returns ':' if the option string starts with ':'
      // but this seems to stop the printing of error messages by getopt?
      cerr<<"ERROR: unknown option or missing argument\n";
      usage(argv[0]);
      exit(-1);
    case ':':
      cerr<<"ERROR: missing argument\n";
      usage(argv[0]);
      exit(-1);
    default:
      // unexpected:
      cerr<<"ERROR: getopt returned unrecognized character code\n";
      exit(-1);
    }
  }

  // Help?
  if(fl_command_line_options.count("help")){
    usage(argv[0]);
    exit(0);
  }

  // Version?
  if(fl_command_line_options.count("version")){
    print_version();
    exit(0);
  }

  // Verbose?
  {
    int MyRank = 0;
#ifdef HAVE_MPI
    if(MPI::Is_initialized()){
      MyRank = MPI::COMM_WORLD.Get_rank();
    }
#endif

    if(fl_command_line_options.count("verbose") == 0){
      verbosity = 0;
    }else{
      verbosity = atoi(fl_command_line_options["verbose"].c_str());
    }
    set_global_debug_level_fc(&verbosity);
    if(verbosity >= 2){
      fl_command_line_options["profile"] = "yes";
    }
  }

  // Pseudo2d?
  if(fl_command_line_options.count("pseudo2d")){
  int val;
  val = atoi(fl_command_line_options["pseudo2d"].c_str());
  set_pseudo2d_domain_fc(&val);
  }

  // What to do with stdout/stderr?
  if(fl_command_line_options.count("log")){
    ostringstream debug_file, err_file;
    debug_file << "fluidity.log";
    err_file << "fluidity.err";
#ifdef HAVE_MPI
    if(MPI::Is_initialized()){
      int MyRank = MPI::COMM_WORLD.Get_rank();
      debug_file << "-" << MyRank;
      err_file << "-" << MyRank;
    }
#endif

    if(freopen(debug_file.str().c_str(), "w", stdout) == NULL)
      perror("failed to redirect stdio for debugging");

    if(freopen(err_file.str().c_str(), "w", stderr) == NULL)
      perror("failed to redirect stderr for debugging");
  }

  // Find the filename if one is specified. Assuming that final
  // argument is simulation filename if it does not correspond to a
  // known option.
  if (fl_command_line_options.count("xml") == 0)
  {
    if(argc > optind + 1)
    {
      fl_command_line_options["xml"] = argv[optind + 1];
    }
    else if(argc == optind + 1)
    {
      fl_command_line_options["xml"] = argv[optind];
    }
    else if(fl_command_line_options.count("xml") == 0)
    {
      usage(argv[0]);
      exit(-1);
    }
  }

  load_options(fl_command_line_options["xml"]);
  if(!have_option("/simulation_name")){
    cerr<<"ERROR: failed to find simulation name after loading options file\n";
    cerr<<"  or specified options file not found\n";
    exit(-1);
  }
  OptionError stat = get_option("/simulation_name", fl_command_line_options["simulation_name"]);
  assert(stat == SPUD_NO_ERROR);

  // now that we know the verbosity, and possibly redirected stdout,
  // we may print the given command line
  if(verbosity >= 2){
    cout<<"Fluidity command line:\n ";
    for(int i=0;i<argc; i++)
      cout<<argv[i]<<" ";
    cout<<endl;
    print_environment();

    // Useful for debugging options
    print_options();
  }

  // Environmental stuff -- this needs to me moved out of here and
  // into populate state.
  if(have_option("/timestepping/current_time/time_units")){
    string option;
    get_option("/timestepping/current_time/time_units/date", option);

    FluxesReader_global.SetSimulationTimeUnits(option.c_str());
    ClimateReader_global.SetSimulationTimeUnits(option.c_str());
    NEMOReader_v2_global.SetSimulationTimeUnits(option.c_str());
  }
  if(have_option("/environmental_data/climatology/file_name")){
    string option;
    get_option("/environmental_data/climatology/file_name", option);

    ClimateReader_global.SetClimatology(option);
  }
  if(have_option("/ocean_forcing/bulk_formulae/input_file")) {
    string option;
    get_option("/ocean_forcing/bulk_formulae/input_file/file_name", option);
    string dataset = "ERA40"; //default
    if(have_option("/ocean_forcing/bulk_formulae/file_type")) {
        get_option("/ocean_forcing/bulk_formulae/file_type/filetype/name", dataset);
    }
    if (dataset == "ERA40") {
        FluxesReader_global.RegisterDataFile(option);
        // field from NetCDF file                         Index |   Physical meaning
        FluxesReader_global.AddFieldOfInterest("u10");  //  0   | 10 metre U wind component
        FluxesReader_global.AddFieldOfInterest("v10");  //  1   | 10 metre V wind component
        FluxesReader_global.AddFieldOfInterest("ssrd"); //  2   | Surface solar radiation
        FluxesReader_global.AddFieldOfInterest("strd"); //  3   | Surface thermal radiation
        FluxesReader_global.AddFieldOfInterest("ro");   //  4   | Runoff
        FluxesReader_global.AddFieldOfInterest("tp");   //  5   | Total precipitation
        FluxesReader_global.AddFieldOfInterest("d2m");  //  6   | Dew point temp at 2m
        FluxesReader_global.AddFieldOfInterest("t2m");  //  7   | Air temp at 2m
        FluxesReader_global.AddFieldOfInterest("msl");  //  8   | Mean sea level pressure
    } else {
        cerr<<"ERROR: unsupported bulk formula input file type. Choose ERA40\n";
        exit(-1);
    }

  }

  if(have_option("/ocean_biology/lagrangian_ensemble/hyperlight")) {
    FluxesReader_global.AddFieldOfInterest("tcc");  // Total cloud cover
  }

  if(have_option("/ocean_forcing/external_data_boundary_conditions")) {
    string option;
    get_option("/ocean_forcing/external_data_boundary_conditions/input_file/file_name", option);

    if(verbosity >= 3)
      cout << "Registering external data forcing file: " << option << endl;

    NEMOReader_v2_global.RegisterDataFile(option);

    NEMOReader_v2_global.AddFieldOfInterest("temperature");  //  0   | Sea temperature
    NEMOReader_v2_global.AddFieldOfInterest("salinity");     //  1   | Salinity
    NEMOReader_v2_global.AddFieldOfInterest("u");            //  2   | Azimuthal velocity
    NEMOReader_v2_global.AddFieldOfInterest("v");            //  3   | Meridional velocity
    NEMOReader_v2_global.AddFieldOfInterest("ssh");          //  4   | Sea surface height
  }

  return;
}

void PetscInit(int argc, char** argv){
#ifdef HAVE_PETSC
  int petscargc;
  char** petscargv;
  petscargc = 1;
  petscargv = new char*[1];
  petscargv[0] = new char[strlen(argv[0]) + 1];
  strncpy(petscargv[0], argv[0], strlen(argv[0]) + 1);

  static char help[] = "Use --help to see the help.\n\n";
  PetscErrorCode ierr = PetscInitialize(&petscargc, &petscargv, NULL, help);
  // PetscInitializeFortran needs to be called when initialising PETSc from C, but calling it from Fortran
  // This sets all kinds of objects such as PETSC_NULL_OBJECT, PETSC_COMM_WORLD, etc., etc.
  ierr = PetscInitializeFortran();
  // CHKERRQ(ierr);
  signal(SIGSEGV, SIG_DFL);
  signal(SIGTRAP, SIG_DFL);

  for(int i = 0; i < petscargc; i++)
    delete [] petscargv[i];
  delete [] petscargv;
#endif
}

<|endoftext|>


<commit_before>#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "model.h"
#include "model_io.h"
#include "figurepainter.h"
#include "build_info.h"
#include <fstream>
#include <QFileDialog>
#include <QInputDialog>
#include <QMessageBox>
#include <QShortcut>
#include <QScreen>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow),
    modelWidget(nullptr),
    redoExtraShortcut(QKeySequence("Ctrl+Shift+Z"), this),
    zoomInExtraShortcut(QKeySequence("Ctrl+="), this)
{
    ui->setupUi(this);
    connect(&redoExtraShortcut  , &QShortcut::activated, ui->actionRedo  , &QAction::trigger);
    connect(&zoomInExtraShortcut, &QShortcut::activated, ui->actionZoomIn, &QAction::trigger);
    setModelWidget(new Ui::ModelWidget());
    setWindowIcon(QIcon(":/icon.ico"));
}

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

void MainWindow::on_actionNew_triggered() {
    setModelWidget(new Ui::ModelWidget());
    currentFileName = QString();
}

void MainWindow::setModelWidget(Ui::ModelWidget *newWidget) {
    if (this->modelWidget) {
        ui->wrapperFrame->layout()->removeWidget(this->modelWidget);
        delete this->modelWidget;
    }

    this->modelWidget = newWidget;
    ui->wrapperFrame->layout()->addWidget(this->modelWidget);
    ui->actionSaveAs->setEnabled(true);
    ui->actionUndo->setEnabled(modelWidget->canUndo());
    connect(modelWidget, &Ui::ModelWidget::canUndoChanged, [this]() {
        ui->actionUndo->setEnabled(modelWidget->canUndo());
    });
    ui->actionRedo->setEnabled(modelWidget->canRedo());
    connect(modelWidget, &Ui::ModelWidget::canRedoChanged, [this]() {
        ui->actionRedo->setEnabled(modelWidget->canRedo());
    });
    connect(modelWidget, &Ui::ModelWidget::scaleFactorChanged, [this]() {
        ui->actionZoomOut->setEnabled(modelWidget->scaleFactor() > SCALE_FACTOR_STEP + 1e-8);
    });
    modelWidget->setGridStep(ui->actionShowGrid->isChecked() ? defaultGridStep : 0);

    QScreen *screen = QApplication::screens().at(0);
    modelWidget->setScaleFactor(screen->logicalDotsPerInch() / 96.0);
}

void MainWindow::on_actionOpen_triggered() {
    QString filename = QFileDialog::getOpenFileName(
                           this,
                           "Select file with a model",
                           QDir::currentPath(),
                           "Models (*.model)"
                       );
    if (filename == "") {
        return;
    }

    std::unique_ptr<Ui::ModelWidget> modelWidget(new Ui::ModelWidget());
    std::ifstream file(filename.toStdString());
    try {
        Model model;
        file >> model;
        modelWidget->setModel(std::move(model));
    } catch (model_format_error &e) {
        QMessageBox::critical(this, "Error while opening model", e.what());
        return;
    }

    setModelWidget(modelWidget.release());
    currentFileName = filename;
}

void MainWindow::on_actionSave_triggered() {
    if (currentFileName == QString()) {
        ui->actionSaveAs->trigger();
        return;
    }
    Model &model = this->modelWidget->getModel();
    std::ofstream file(currentFileName.toStdString());
    file << model;
}

QString forceFileExtension(QString filename, QString selectedFilter) {
    QString extension = selectedFilter.mid(selectedFilter.indexOf("(*.") + 3);
    extension.chop(1); // chop trailing )
    extension = ("." + extension).toLower();
    if (!filename.endsWith(extension)) {
        filename += extension;
    }
    return filename;
}

void MainWindow::on_actionSaveAs_triggered() {
    QString selectedFilter;
    QString filename = QFileDialog::getSaveFileName(
                           this,
                           "Select file to save in",
                           QDir::currentPath(),
                           "Models (*.model);;SVG (*.svg);;PNG (*.png)",
                           &selectedFilter
                       );
    if (filename == "") {
        return;
    }
    filename = forceFileExtension(filename, selectedFilter);
    Model &model = this->modelWidget->getModel();
    std::ofstream file(filename.toStdString());
    if (filename.toLower().endsWith(".svg")) {
        exportModelToSvg(model, file);
    } else if (filename.toLower().endsWith(".png")) {
        file.close();
        exportModelToImageFile(model, filename);
    } else {
        file << model;
        currentFileName = filename;
    }
}

void MainWindow::on_actionUndo_triggered() {
    // Extra check is added for symmetry with actionRedo
    if (!modelWidget->canUndo()) { return; }
    modelWidget->undo();
}

void MainWindow::on_actionRedo_triggered() {
    // Extra check is added because there is extra shortcut
    if (!modelWidget->canRedo()) { return; }
    modelWidget->redo();
}

void MainWindow::on_actionShowGrid_triggered() {
    if (ui->actionShowGrid->isChecked()) {
        defaultGridStep = QInputDialog::getInt(this, "Grid step", "Specify grid step in pixels", defaultGridStep, 1, int(1e9));
    }
    modelWidget->setGridStep(ui->actionShowGrid->isChecked() ? defaultGridStep : 0);
}

void MainWindow::on_actionZoomIn_triggered() {
    modelWidget->setScaleFactor(modelWidget->scaleFactor() + SCALE_FACTOR_STEP);
}

void MainWindow::on_actionZoomOut_triggered() {
    modelWidget->setScaleFactor(modelWidget->scaleFactor() - SCALE_FACTOR_STEP);
}

void MainWindow::on_actionExit_triggered() {
    QApplication::exit();
}

void MainWindow::on_actionAbout_triggered() {
    QMessageBox::about(this, "About Manugram",
                       QString()
                       + "Git commit hash: " + GIT_LAST_SHA1 + "\n"
                       + "Git commit date: " + GIT_LAST_TIME + "\n"
                       + "Build time: " + BUILD_TIME
                       );
}
<commit_msg>mainwindow: now opened files are fully read to stringstream and processed afterwards (#45)<commit_after>#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "model.h"
#include "model_io.h"
#include "figurepainter.h"
#include "build_info.h"
#include <sstream>
#include <fstream>
#include <QFileDialog>
#include <QInputDialog>
#include <QMessageBox>
#include <QShortcut>
#include <QScreen>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow),
    modelWidget(nullptr),
    redoExtraShortcut(QKeySequence("Ctrl+Shift+Z"), this),
    zoomInExtraShortcut(QKeySequence("Ctrl+="), this)
{
    ui->setupUi(this);
    connect(&redoExtraShortcut  , &QShortcut::activated, ui->actionRedo  , &QAction::trigger);
    connect(&zoomInExtraShortcut, &QShortcut::activated, ui->actionZoomIn, &QAction::trigger);
    setModelWidget(new Ui::ModelWidget());
    setWindowIcon(QIcon(":/icon.ico"));
}

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

void MainWindow::on_actionNew_triggered() {
    setModelWidget(new Ui::ModelWidget());
    currentFileName = QString();
}

void MainWindow::setModelWidget(Ui::ModelWidget *newWidget) {
    if (this->modelWidget) {
        ui->wrapperFrame->layout()->removeWidget(this->modelWidget);
        delete this->modelWidget;
    }

    this->modelWidget = newWidget;
    ui->wrapperFrame->layout()->addWidget(this->modelWidget);
    ui->actionSaveAs->setEnabled(true);
    ui->actionUndo->setEnabled(modelWidget->canUndo());
    connect(modelWidget, &Ui::ModelWidget::canUndoChanged, [this]() {
        ui->actionUndo->setEnabled(modelWidget->canUndo());
    });
    ui->actionRedo->setEnabled(modelWidget->canRedo());
    connect(modelWidget, &Ui::ModelWidget::canRedoChanged, [this]() {
        ui->actionRedo->setEnabled(modelWidget->canRedo());
    });
    connect(modelWidget, &Ui::ModelWidget::scaleFactorChanged, [this]() {
        ui->actionZoomOut->setEnabled(modelWidget->scaleFactor() > SCALE_FACTOR_STEP + 1e-8);
    });
    modelWidget->setGridStep(ui->actionShowGrid->isChecked() ? defaultGridStep : 0);

    QScreen *screen = QApplication::screens().at(0);
    modelWidget->setScaleFactor(screen->logicalDotsPerInch() / 96.0);
}

void MainWindow::on_actionOpen_triggered() {
    QString filename = QFileDialog::getOpenFileName(
                           this,
                           "Select file with a model",
                           QDir::currentPath(),
                           "Models (*.model)"
                       );
    if (filename == "") {
        return;
    }

    std::unique_ptr<Ui::ModelWidget> modelWidget(new Ui::ModelWidget());
    QFile file(filename);
    if (!file.open(QFile::ReadOnly)) {
        QMessageBox::critical(this, "Error while opening model", "Unable to open file for reading");
        return;
    }
    std::stringstream data;
    data << file.readAll().toStdString();
    file.close();
    try {
        Model model;
        data >> model;
        modelWidget->setModel(std::move(model));
    } catch (model_format_error &e) {
        QMessageBox::critical(this, "Error while opening model", e.what());
        return;
    }

    setModelWidget(modelWidget.release());
    currentFileName = filename;
}

void MainWindow::on_actionSave_triggered() {
    if (currentFileName == QString()) {
        ui->actionSaveAs->trigger();
        return;
    }
    Model &model = this->modelWidget->getModel();
    std::ofstream file(currentFileName.toStdString());
    file << model;
}

QString forceFileExtension(QString filename, QString selectedFilter) {
    QString extension = selectedFilter.mid(selectedFilter.indexOf("(*.") + 3);
    extension.chop(1); // chop trailing )
    extension = ("." + extension).toLower();
    if (!filename.endsWith(extension)) {
        filename += extension;
    }
    return filename;
}

void MainWindow::on_actionSaveAs_triggered() {
    QString selectedFilter;
    QString filename = QFileDialog::getSaveFileName(
                           this,
                           "Select file to save in",
                           QDir::currentPath(),
                           "Models (*.model);;SVG (*.svg);;PNG (*.png)",
                           &selectedFilter
                       );
    if (filename == "") {
        return;
    }
    filename = forceFileExtension(filename, selectedFilter);
    Model &model = this->modelWidget->getModel();
    std::ofstream file(filename.toStdString());
    if (filename.toLower().endsWith(".svg")) {
        exportModelToSvg(model, file);
    } else if (filename.toLower().endsWith(".png")) {
        file.close();
        exportModelToImageFile(model, filename);
    } else {
        file << model;
        currentFileName = filename;
    }
}

void MainWindow::on_actionUndo_triggered() {
    // Extra check is added for symmetry with actionRedo
    if (!modelWidget->canUndo()) { return; }
    modelWidget->undo();
}

void MainWindow::on_actionRedo_triggered() {
    // Extra check is added because there is extra shortcut
    if (!modelWidget->canRedo()) { return; }
    modelWidget->redo();
}

void MainWindow::on_actionShowGrid_triggered() {
    if (ui->actionShowGrid->isChecked()) {
        defaultGridStep = QInputDialog::getInt(this, "Grid step", "Specify grid step in pixels", defaultGridStep, 1, int(1e9));
    }
    modelWidget->setGridStep(ui->actionShowGrid->isChecked() ? defaultGridStep : 0);
}

void MainWindow::on_actionZoomIn_triggered() {
    modelWidget->setScaleFactor(modelWidget->scaleFactor() + SCALE_FACTOR_STEP);
}

void MainWindow::on_actionZoomOut_triggered() {
    modelWidget->setScaleFactor(modelWidget->scaleFactor() - SCALE_FACTOR_STEP);
}

void MainWindow::on_actionExit_triggered() {
    QApplication::exit();
}

void MainWindow::on_actionAbout_triggered() {
    QMessageBox::about(this, "About Manugram",
                       QString()
                       + "Git commit hash: " + GIT_LAST_SHA1 + "\n"
                       + "Git commit date: " + GIT_LAST_TIME + "\n"
                       + "Build time: " + BUILD_TIME
                       );
}
<|endoftext|>


<commit_before>//
// TODO:
// - printview - lepiej generowane szerokosci do tabelki
// - usunąć duplikat execSQL() - zrobic jakos globalnie?
// - prawdziwe validateDate
// - menu do sterowania num.uproszczona, # kopii, EOL, wybór pliku szablonu
// - numeracja uproszczona - uzywac? (wtedy bez miesiaca)
// - liczba kopii - uzywac? (ale to u mnie, czy w print/page setup?)
// - pole 'uwagi' w towar/faktura nie reaguje na zmiany
// - dialog kalendarza
// - DECROUND zaimplementować jako hook i userfunction, nie jako patch na sqlite
// - dummy menu ze statystykami
//		np. sprzedaży netto: select nazwa, decround(sum(decround(decround(netto*(100-rabat)/100.0)*ilosc))) as suma from pozycjafakt group by nazwa order by suma desc;
// - trzymanie stanu magazynu, info i podsumowania magazynowe
// - na koniec - usunac printfy z debugiem
// zmiana curtab i przełączanie jest brzydkie, może cały beFakTab powinien
// dziedziczyć z btab?

#include "mainwindow.h"
#include "dialfirma.h"
#include "dialvat.h"
#include "sqlschema.h"
#include "tabfirma.h"
#include "tabtowar.h"
#include "tabfaktura.h"

#include <Alert.h>
#include <Application.h>
#include <File.h>
#include <View.h>
#include <Menu.h>
#include <MenuBar.h>
#include <MenuItem.h>
#include <TabView.h>

#include <stdio.h>

const uint32 MENU_PRINTO	= 'MPOR';
const uint32 MENU_PRINTC	= 'MPKO';
const uint32 MENU_PRINTD	= 'MPKD';
const uint32 MENU_CONFFIRMA	= 'MKOF';
const uint32 MENU_CONFVAT	= 'MKOV';
const uint32 MENU_PRINTPS	= 'MPPS';
const uint32 MENU_PRINTT80	= 'MPT8';
const uint32 MENU_PRINTT136 = 'MPT1';
const uint32 MENU_PRINTHTML = 'MPHT';
const uint32 MENU_ABOUT		= 'MABO';

enum { FAKTURATAB = 0, TOWARTAB, FIRMATAB };

BeFAKMainWindow::BeFAKMainWindow(const char *windowTitle) : BWindow(
	BRect(100, 100, 900, 700), windowTitle, B_DOCUMENT_WINDOW, B_OUTLINE_RESIZE, B_CURRENT_WORKSPACE ) {

	BView *mainView = new BView(this->Bounds(), "mainView", B_FOLLOW_ALL_SIDES, 0);

	if (mainView == NULL) {
		AppReturnValue = B_NO_MEMORY;
		be_app->PostMessage(B_QUIT_REQUESTED);
		return;
	}

	mainView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
	this->AddChild(mainView);

	BRect r;
	r = mainView->Bounds();
	r.bottom = 20;
	menuBar = new BMenuBar(r, "menuBar");
	mainView->AddChild(menuBar);

	menu = new BMenu("Plik", B_ITEMS_IN_COLUMN);
	menu->AddItem(new BMenuItem("O programie", new BMessage(MENU_ABOUT)));
	menu->AddSeparatorItem();
	menu->AddItem(new BMenuItem("Ustawienia strony", new BMessage(MENU_PAGESETUP)));
	menu->AddItem(new BMenuItem("Zamknij", new BMessage(B_QUIT_REQUESTED), 'Q'));
	menuBar->AddItem(menu);

	menu = new BMenu("Dokument", B_ITEMS_IN_COLUMN);
	menu->AddItem(pmenuo = new BMenuItem("Oryginał", new BMessage(MENU_PRINTO)));
	menu->AddItem(pmenuc = new BMenuItem("Kopia", new BMessage(MENU_PRINTC)));
	menu->AddItem(pmenud = new BMenuItem("Duplikat", new BMessage(MENU_PRINTD)));
	menuBar->AddItem(menu);

	menu = new BMenu("Opcje", B_ITEMS_IN_COLUMN);
	menu->AddItem(new BMenuItem("Dane firmy", new BMessage(MENU_CONFFIRMA)));
	BMenu *printmenu = new BMenu("Rodzaj wydruku", B_ITEMS_IN_COLUMN);
	menu->AddItem(printmenu);
	menu->AddItem(new BMenuItem("Stawki VAT", new BMessage(MENU_CONFVAT)));
	menuBar->AddItem(menu);

	printmenu->AddItem(pmenups   = new BMenuItem("Drukarka", new BMessage(MENU_PRINTPS)));
	printmenu->AddItem(pmenut80  = new BMenuItem("Tekst (80 kol.)", new BMessage(MENU_PRINTT80)));
	printmenu->AddItem(pmenut136 = new BMenuItem("Tekst (136 kol.)", new BMessage(MENU_PRINTT136)));
	printmenu->AddItem(pmenuhtml = new BMenuItem("HTML", new BMessage(MENU_PRINTHTML)));

	// tabview
	r = mainView->Bounds();
	r.top = 20;
	tabView = new BTabView(r, "tabView");
	mainView->AddChild(tabView);

	// initialize database
	int ret = OpenDatabase();
	if (ret < 0)
		exit(1);

	// check if configuration is there
	DoCheckConfig();
	// initialize datawidgets
	initTabs(tabView);
	curTab = tabs[FAKTURATAB];
	tabView->Select(FAKTURATAB);
	updateMenus();
}

BeFAKMainWindow::~BeFAKMainWindow() {
	CloseDatabase();
}

void BeFAKMainWindow::initTabs(BTabView *tv) {
	tabs[FAKTURATAB] = new tabFaktura(tv, dbData, this);
	tabs[TOWARTAB] = new tabTowar(tv, dbData, this);
	tabs[FIRMATAB] = new tabFirma(tv, dbData, this);
}

void BeFAKMainWindow::DoConfigFirma(bool cancancel) {
	firmaDialog = new dialFirma(APP_NAME, dbData, cancancel);
}

void BeFAKMainWindow::DoConfigVAT(void) {
	vatDialog = new dialVat(dbData, this);
}

void BeFAKMainWindow::DoCheckConfig(void) {
	int nRows, nCols;
	char **result;
	BString sql;
	// select NAZWA and all config data
	sql = "SELECT nazwa, wersja, p_mode, p_typ, p_textcols, p_texteol, p_lkopii, f_numprosta FROM konfiguracja WHERE zrobiona = 1";
//printf("sql:%s\n",sql.String());
	sqlite_get_table(dbData, sql.String(), &result, &nRows, &nCols, &dbErrMsg);
//printf ("got:%ix%i\n", nRows, nCols);
	if (nRows < 1) {
		DoConfigFirma(false);	// should never happen
	} else {
		int i = nCols;
		sql = result[i++];	// test for 'nazwa' not ""
		if (sql.Length() == 0)
			DoConfigFirma(false);
		// read other config data from result
		if (strcmp(result[i++], APP_DBVERSION)) {
			sql = "Plik:\n"; sql += DATABASE_PATHNAME;
			sql += "\nzawiera nieprawidłową (starszą) wersję bazy danych,\n";
			sql += "proszę go usunąć i wprowadzić dane ponownie.\n";
			sql += "Do czasu rozstrzygnięcia konkursu format bazy\n";
			sql += "może jeszcze ulec zmianie!\n";
			BAlert *error = new BAlert(APP_NAME, sql.String(), "OK", NULL, NULL, B_WIDTH_AS_USUAL, B_STOP_ALERT);
			error->Go();
			exit(2);
		}
		p_mode = toint(result[i++]);
		p_typ = toint(result[i++]);
		p_textcols = toint(result[i++]);
		p_texteol = toint(result[i++]);
		p_lkopii = toint(result[i++]);
		f_numprosta = toint(result[i++]);
	}
}

void BeFAKMainWindow::updateMenus(void) {
	pmenuo->SetMarked(p_typ == 0);
	pmenuc->SetMarked(p_typ == 1);
	pmenud->SetMarked(p_typ == 2);
	pmenups->SetMarked(p_mode == 0);
	pmenut80->SetMarked( (p_mode==1) && (p_textcols==80) );
	pmenut136->SetMarked( (p_mode==1) && (p_textcols==136) );
	pmenuhtml->SetMarked(p_mode == 2);
	BString sql = "UPDATE konfiguracja SET p_mode = %i, p_typ = %i, p_textcols = %i, "
		"p_texteol = %i, p_lkopii = %i, f_numprosta = %i "
		"WHERE zrobiona = 1";
	sqlite_exec_printf(dbData, sql.String(), 0, 0, &dbErrMsg,
		p_mode, p_typ, p_textcols, p_texteol, p_lkopii, f_numprosta);
//printf("result:%s\n",dbErrMsg);
}

void BeFAKMainWindow::MessageReceived(BMessage *Message) {
	BString title;
	const char *tmp;

	this->DisableUpdates();
	switch (Message->what) {
		case MENU_PRINTO:
			p_typ = 0;
			updateMenus();
			break;
		case MENU_PRINTC:
			p_typ = 1;
			updateMenus();
			break;
		case MENU_PRINTD:
			p_typ = 2;
			updateMenus();
			break;
		case MENU_PRINTPS:
			p_mode = 0;
			updateMenus();
			break;
		case MENU_PRINTT80:
			p_mode = 1;
			p_textcols = 80;
			updateMenus();
			break;
		case MENU_PRINTT136:
			p_mode = 1;
			p_textcols = 136;
			updateMenus();
			break;
		case MENU_PRINTHTML:
			p_mode = 2;
			updateMenus();
			break;
		case MENU_ABOUT:
			// really should go with B_ABOUT_REQUESTED, but it doesn't work...
			be_app->AboutRequested();
			break;
		case MENU_CONFFIRMA:
			DoConfigFirma();
			break;
		case MENU_CONFVAT:
			DoConfigVAT();
			break;
		case MSG_NAMECHANGE:
			if (Message->FindString("_newtitle", &tmp) == B_OK) {
				title = APP_NAME; title += " : "; title += tmp;
				this->SetTitle(title.String());
			}
			break;
		case MENU_PAGESETUP:
		case MSG_REQFIRMAUP:
		case MSG_REQTOWARUP:
			tabs[FAKTURATAB]->MessageReceived(Message);
			break;
		case MSG_REQTOWARLIST:
			tabs[TOWARTAB]->MessageReceived(Message);
			break;
		case MSG_REQFIRMALIST:
			tabs[FIRMATAB]->MessageReceived(Message);
			break;
		case MSG_REQVATUP:
			tabs[FAKTURATAB]->MessageReceived(Message);
			tabs[TOWARTAB]->MessageReceived(Message);
			break;
		default:
			curTab = tabs[tabView->Selection()];
			curTab->MessageReceived(Message);
			break;
	}
	BWindow::MessageReceived(Message);
	this->EnableUpdates();
}

bool BeFAKMainWindow::QuitRequested() {
//	config->position = this->Frame();
//	config->save();
	curTab->CommitCurdata(false);
	be_app->PostMessage(B_QUIT_REQUESTED);
	return BWindow::QuitRequested();
}

//--------------------
// database stuff, abstract it?

int BeFAKMainWindow::OpenDatabase(void) {
	// BFile test wouldn't be necessary if sqlite_open retured file not found
	// error as advertised
	BFile fData;
	int fResult = fData.SetTo(DATABASE_PATHNAME, B_READ_ONLY);
	// open database anyway - new or existing
	dbData = sqlite_open(DATABASE_PATHNAME, 0666, &dbErrMsg);
	if ((dbData==0)||(dbErrMsg!=0)) {
		// due to sqlite problems - this code is never reached; pity
//		printf("database not found\n");
		return -1;
	}
	if (fResult != B_OK) {
		// file wasn't there - new database has been created
		// populate it with schema and default configuration
		InitDatabase();
	}
	// if VACUUM fails on DB there is another error, we can't handle it
	return sqlite_exec(dbData, "VACUUM", 0, 0, &dbErrMsg);
}

void BeFAKMainWindow::CloseDatabase(void) {
	sqlite_exec(dbData, "VACUUM", 0, 0, &dbErrMsg);
	sqlite_close(dbData);
}

void BeFAKMainWindow::InitDatabase(void) {
//	printf("new database, fill with schema\n");
	sqlite_exec(dbData, sql_schema, 0, 0, &dbErrMsg);
//printf("init result:[%s]\n", dbErrMsg);
}
<commit_msg>- extended todo list<commit_after>//
// TODO:
// - prawdziwe validateDate
//		- akceptuj yyyy/mm/dd, yyyy-mm-dd, dd-mm-yyyy, dd/mm/yyyy
//			- zamiana '/' na '-' i dalej
//		- uzupełniaj yyyy-mm do pierwszego dnia miesiąca
//		- uzupełniaj yyyy do pierwszego dnia roku
//		- na wyjściu standard: yyyy-mm-dd
//		- jeśli nic nie pasuje, to dać datę dzisiejszą
// - nowy dialog do konfiguracji wydruku:
//		- rodzaj wydruku: kopia/oryginał/duplikat/oryignał+kopia
//		- liczba kopii
//		- system wydruku: print_server/txt/html
//		- txt: liczba kolumn
//		- txt: znak końca linii
// - parametry wydruku przetwarzać w tabfaktura, każdy obiekt print używać raz
//		- przy zapisie do pliku dołączać typ dokumentu i numer kopii do nazwy
// - menu do sterowania num.uproszczona
//	 - numeracja uproszczona - uzywac? (wtedy bez miesiaca)
// - pole 'uwagi' w towar/faktura nie reaguje na zmiany
// - dialog kalendarza
// - dummy menu ze statystykami
//		np. sprzedaży netto: select nazwa, decround(sum(decround(decround(netto*(100-rabat)/100.0)*ilosc))) as suma from pozycjafakt group by nazwa order by suma desc;
// - trzymanie stanu magazynu, info i podsumowania magazynowe
//		- info o stanie magazynowym z dnia XXXX do ustawienia w towary
//		- podsumowanie zliczać dynamicznie (nie trzeba wtedy uaktualniać stanu
//		  przy zmianie faktury)
// - usunąć duplikat execSQL() - zrobic jakos globalnie?
// - na koniec - usunac printfy z debugiem
//
// zmiana curtab i przełączanie jest brzydkie, może cały beFakTab powinien
// dziedziczyć z btab?

#include "mainwindow.h"
#include "dialfirma.h"
#include "dialvat.h"
#include "sqlschema.h"
#include "tabfirma.h"
#include "tabtowar.h"
#include "tabfaktura.h"

#include <Alert.h>
#include <Application.h>
#include <File.h>
#include <View.h>
#include <Menu.h>
#include <MenuBar.h>
#include <MenuItem.h>
#include <TabView.h>

#include <stdio.h>

const uint32 MENU_PRINTO	= 'MPOR';
const uint32 MENU_PRINTC	= 'MPKO';
const uint32 MENU_PRINTD	= 'MPKD';
const uint32 MENU_CONFFIRMA	= 'MKOF';
const uint32 MENU_CONFVAT	= 'MKOV';
const uint32 MENU_PRINTPS	= 'MPPS';
const uint32 MENU_PRINTT80	= 'MPT8';
const uint32 MENU_PRINTT136 = 'MPT1';
const uint32 MENU_PRINTHTML = 'MPHT';
const uint32 MENU_ABOUT		= 'MABO';

enum { FAKTURATAB = 0, TOWARTAB, FIRMATAB };

BeFAKMainWindow::BeFAKMainWindow(const char *windowTitle) : BWindow(
	BRect(100, 100, 900, 700), windowTitle, B_DOCUMENT_WINDOW, B_OUTLINE_RESIZE, B_CURRENT_WORKSPACE ) {

	BView *mainView = new BView(this->Bounds(), "mainView", B_FOLLOW_ALL_SIDES, 0);

	if (mainView == NULL) {
		AppReturnValue = B_NO_MEMORY;
		be_app->PostMessage(B_QUIT_REQUESTED);
		return;
	}

	mainView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
	this->AddChild(mainView);

	BRect r;
	r = mainView->Bounds();
	r.bottom = 20;
	menuBar = new BMenuBar(r, "menuBar");
	mainView->AddChild(menuBar);

	menu = new BMenu("Plik", B_ITEMS_IN_COLUMN);
	menu->AddItem(new BMenuItem("O programie", new BMessage(MENU_ABOUT)));
	menu->AddSeparatorItem();
	menu->AddItem(new BMenuItem("Ustawienia strony", new BMessage(MENU_PAGESETUP)));
	menu->AddItem(new BMenuItem("Zamknij", new BMessage(B_QUIT_REQUESTED), 'Q'));
	menuBar->AddItem(menu);

	menu = new BMenu("Dokument", B_ITEMS_IN_COLUMN);
	menu->AddItem(pmenuo = new BMenuItem("Oryginał", new BMessage(MENU_PRINTO)));
	menu->AddItem(pmenuc = new BMenuItem("Kopia", new BMessage(MENU_PRINTC)));
	menu->AddItem(pmenud = new BMenuItem("Duplikat", new BMessage(MENU_PRINTD)));
	menuBar->AddItem(menu);

	menu = new BMenu("Opcje", B_ITEMS_IN_COLUMN);
	menu->AddItem(new BMenuItem("Dane firmy", new BMessage(MENU_CONFFIRMA)));
	BMenu *printmenu = new BMenu("Rodzaj wydruku", B_ITEMS_IN_COLUMN);
	menu->AddItem(printmenu);
	menu->AddItem(new BMenuItem("Stawki VAT", new BMessage(MENU_CONFVAT)));
	menuBar->AddItem(menu);

	printmenu->AddItem(pmenups   = new BMenuItem("Drukarka", new BMessage(MENU_PRINTPS)));
	printmenu->AddItem(pmenut80  = new BMenuItem("Tekst (80 kol.)", new BMessage(MENU_PRINTT80)));
	printmenu->AddItem(pmenut136 = new BMenuItem("Tekst (136 kol.)", new BMessage(MENU_PRINTT136)));
	printmenu->AddItem(pmenuhtml = new BMenuItem("HTML", new BMessage(MENU_PRINTHTML)));

	// tabview
	r = mainView->Bounds();
	r.top = 20;
	tabView = new BTabView(r, "tabView");
	mainView->AddChild(tabView);

	// initialize database
	int ret = OpenDatabase();
	if (ret < 0)
		exit(1);

	// check if configuration is there
	DoCheckConfig();
	// initialize datawidgets
	initTabs(tabView);
	curTab = tabs[FAKTURATAB];
	tabView->Select(FAKTURATAB);
	updateMenus();
}

BeFAKMainWindow::~BeFAKMainWindow() {
	CloseDatabase();
}

void BeFAKMainWindow::initTabs(BTabView *tv) {
	tabs[FAKTURATAB] = new tabFaktura(tv, dbData, this);
	tabs[TOWARTAB] = new tabTowar(tv, dbData, this);
	tabs[FIRMATAB] = new tabFirma(tv, dbData, this);
}

void BeFAKMainWindow::DoConfigFirma(bool cancancel) {
	firmaDialog = new dialFirma(APP_NAME, dbData, cancancel);
}

void BeFAKMainWindow::DoConfigVAT(void) {
	vatDialog = new dialVat(dbData, this);
}

void BeFAKMainWindow::DoCheckConfig(void) {
	int nRows, nCols;
	char **result;
	BString sql;
	// select NAZWA and all config data
	sql = "SELECT nazwa, wersja, p_mode, p_typ, p_textcols, p_texteol, p_lkopii, f_numprosta FROM konfiguracja WHERE zrobiona = 1";
//printf("sql:%s\n",sql.String());
	sqlite_get_table(dbData, sql.String(), &result, &nRows, &nCols, &dbErrMsg);
//printf ("got:%ix%i\n", nRows, nCols);
	if (nRows < 1) {
		DoConfigFirma(false);	// should never happen
	} else {
		int i = nCols;
		sql = result[i++];	// test for 'nazwa' not ""
		if (sql.Length() == 0)
			DoConfigFirma(false);
		// read other config data from result
		if (strcmp(result[i++], APP_DBVERSION)) {
			sql = "Plik:\n"; sql += DATABASE_PATHNAME;
			sql += "\nzawiera nieprawidłową (starszą) wersję bazy danych,\n";
			sql += "proszę go usunąć i wprowadzić dane ponownie.\n";
			sql += "Do czasu rozstrzygnięcia konkursu format bazy\n";
			sql += "może jeszcze ulec zmianie!\n";
			BAlert *error = new BAlert(APP_NAME, sql.String(), "OK", NULL, NULL, B_WIDTH_AS_USUAL, B_STOP_ALERT);
			error->Go();
			exit(2);
		}
		p_mode = toint(result[i++]);
		p_typ = toint(result[i++]);
		p_textcols = toint(result[i++]);
		p_texteol = toint(result[i++]);
		p_lkopii = toint(result[i++]);
		f_numprosta = toint(result[i++]);
	}
}

void BeFAKMainWindow::updateMenus(void) {
	pmenuo->SetMarked(p_typ == 0);
	pmenuc->SetMarked(p_typ == 1);
	pmenud->SetMarked(p_typ == 2);
	pmenups->SetMarked(p_mode == 0);
	pmenut80->SetMarked( (p_mode==1) && (p_textcols==80) );
	pmenut136->SetMarked( (p_mode==1) && (p_textcols==136) );
	pmenuhtml->SetMarked(p_mode == 2);
	BString sql = "UPDATE konfiguracja SET p_mode = %i, p_typ = %i, p_textcols = %i, "
		"p_texteol = %i, p_lkopii = %i, f_numprosta = %i "
		"WHERE zrobiona = 1";
	sqlite_exec_printf(dbData, sql.String(), 0, 0, &dbErrMsg,
		p_mode, p_typ, p_textcols, p_texteol, p_lkopii, f_numprosta);
//printf("result:%s\n",dbErrMsg);
}

void BeFAKMainWindow::MessageReceived(BMessage *Message) {
	BString title;
	const char *tmp;

	this->DisableUpdates();
	switch (Message->what) {
		case MENU_PRINTO:
			p_typ = 0;
			updateMenus();
			break;
		case MENU_PRINTC:
			p_typ = 1;
			updateMenus();
			break;
		case MENU_PRINTD:
			p_typ = 2;
			updateMenus();
			break;
		case MENU_PRINTPS:
			p_mode = 0;
			updateMenus();
			break;
		case MENU_PRINTT80:
			p_mode = 1;
			p_textcols = 80;
			updateMenus();
			break;
		case MENU_PRINTT136:
			p_mode = 1;
			p_textcols = 136;
			updateMenus();
			break;
		case MENU_PRINTHTML:
			p_mode = 2;
			updateMenus();
			break;
		case MENU_ABOUT:
			// really should go with B_ABOUT_REQUESTED, but it doesn't work...
			be_app->AboutRequested();
			break;
		case MENU_CONFFIRMA:
			DoConfigFirma();
			break;
		case MENU_CONFVAT:
			DoConfigVAT();
			break;
		case MSG_NAMECHANGE:
			if (Message->FindString("_newtitle", &tmp) == B_OK) {
				title = APP_NAME; title += " : "; title += tmp;
				this->SetTitle(title.String());
			}
			break;
		case MENU_PAGESETUP:
		case MSG_REQFIRMAUP:
		case MSG_REQTOWARUP:
			tabs[FAKTURATAB]->MessageReceived(Message);
			break;
		case MSG_REQTOWARLIST:
			tabs[TOWARTAB]->MessageReceived(Message);
			break;
		case MSG_REQFIRMALIST:
			tabs[FIRMATAB]->MessageReceived(Message);
			break;
		case MSG_REQVATUP:
			tabs[FAKTURATAB]->MessageReceived(Message);
			tabs[TOWARTAB]->MessageReceived(Message);
			break;
		default:
			curTab = tabs[tabView->Selection()];
			curTab->MessageReceived(Message);
			break;
	}
	BWindow::MessageReceived(Message);
	this->EnableUpdates();
}

bool BeFAKMainWindow::QuitRequested() {
//	config->position = this->Frame();
//	config->save();
	curTab->CommitCurdata(false);
	be_app->PostMessage(B_QUIT_REQUESTED);
	return BWindow::QuitRequested();
}

//--------------------
// database stuff, abstract it?

int BeFAKMainWindow::OpenDatabase(void) {
	// BFile test wouldn't be necessary if sqlite_open retured file not found
	// error as advertised
	BFile fData;
	int fResult = fData.SetTo(DATABASE_PATHNAME, B_READ_ONLY);
	// open database anyway - new or existing
	dbData = sqlite_open(DATABASE_PATHNAME, 0666, &dbErrMsg);
	if ((dbData==0)||(dbErrMsg!=0)) {
		// due to sqlite problems - this code is never reached; pity
//		printf("database not found\n");
		return -1;
	}
	if (fResult != B_OK) {
		// file wasn't there - new database has been created
		// populate it with schema and default configuration
		InitDatabase();
	}
	// if VACUUM fails on DB there is another error, we can't handle it
	return sqlite_exec(dbData, "VACUUM", 0, 0, &dbErrMsg);
}

void BeFAKMainWindow::CloseDatabase(void) {
	sqlite_exec(dbData, "VACUUM", 0, 0, &dbErrMsg);
	sqlite_close(dbData);
}

void BeFAKMainWindow::InitDatabase(void) {
//	printf("new database, fill with schema\n");
	sqlite_exec(dbData, sql_schema, 0, 0, &dbErrMsg);
//printf("init result:[%s]\n", dbErrMsg);
}
<|endoftext|>


<commit_before>/*
 * KDots
 * Copyright (c) 2011-2012 Minh Ngo <nlminhtl@gmail.com>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
#include "mainwindow.hpp"
#include <QDir>
#include <KMenuBar>
#include <KStatusBar>
#include <KConfigDialog>
#include <KToolBar>
#include <KAction>
#include <KStandardAction>
#include <KActionCollection>
#include <interface/iplugin.hpp>
#include <interface/irival.hpp>
#include "ui_mainwindow.h"
#include "ui_boardconfigwidget.h"
#include "newgamedialog.hpp"
#include "tablewidget.hpp"
#include "plugincontainer.hpp"
#include "kdots.h"

namespace KDots
{
	MainWindow::MainWindow (QWidget *parent)
		: KXmlGuiWindow (parent)
		, m_ui (new Ui::MainWindow)
		, m_destroyTable (false)
		, m_table (NULL)
	{
		m_ui->setupUi (this);

#ifdef NEW_LIBKDEGAMES
		Kg::difficulty ()->addStandardLevel (KgDifficultyLevel::Easy);
		Kg::difficulty ()->addStandardLevel (KgDifficultyLevel::Medium);
		Kg::difficulty ()->addStandardLevel (KgDifficultyLevel::Hard);

		connect (Kg::difficulty (),
				SIGNAL (currentLevelChanged (const KgDifficultyLevel*)),
				this,
				SLOT (difficultyHandler (const KgDifficultyLevel*)));

		KgDifficultyGUI::init (this, Kg::difficulty ());

		Kg::difficulty ()->setEditable (false);
#else
		KGameDifficulty::init (this, this, SLOT (difficultyHandler (KGameDifficulty::standardLevel)));
		KGameDifficulty::addStandardLevel (KGameDifficulty::Easy);
		KGameDifficulty::addStandardLevel (KGameDifficulty::Medium);
		KGameDifficulty::addStandardLevel (KGameDifficulty::Hard);

		KGameDifficulty::setEnabled (false);
#endif
		statusBar ()->show ();
		setCentralWidget (new QWidget (this));
		initMenu ();
		setupGUI (Default, "kdotsui.rc");
	}

	MainWindow::~MainWindow ()
	{
		m_rival.reset ();
	}

#ifdef NEW_LIBKDEGAMES
	void MainWindow::difficultyHandler (const KgDifficultyLevel *level)
#else
	void MainWindow::difficultyHandler (KGameDifficulty::standardLevel level)
#endif
	{
		int diff;

#ifdef NEW_LIBKDEGAMES
		switch (level->standardLevel ())
		{
		case KgDifficultyLevel::Easy:
			diff = 1;
		case KgDifficultyLevel::Medium:
			diff = 2;
		default:
			diff = 3;
		}
#else
		switch (level)
		{
		case KGameDifficulty::Easy:
			diff = 1;
		case KGameDifficulty::Medium:
			diff = 2;
		default:
			diff = 3;
		}
#endif

		if (m_rival)
			m_rival->setDifficulty (diff);
	}

	void MainWindow::initMenu ()
	{
		KStandardAction::preferences (this, SLOT (onPreferences ()), actionCollection ());

		KAction *newAction = new KAction (KIcon ("file_new"), i18n ("&New game"), this);
		newAction->setShortcut (Qt::CTRL + Qt::Key_N);

		connect (newAction,
				SIGNAL (triggered (bool)),
				this,
				SLOT (onNewGame ()));

		actionCollection ()->addAction ("NewGame", newAction);

		KAction *endAction = actionCollection ()->addAction ("EndGame", this, SLOT (endGame ()));
		endAction->setIcon (KIcon ("window-close"));
		endAction->setText (i18n ("&End game"));
		endAction->setShortcut (Qt::CTRL + Qt::Key_E);
		endAction->setEnabled (false);

		KAction *undoAction = actionCollection ()->addAction ("UndoGame", this, SLOT (undo ()));
		undoAction->setIcon (KIcon ("undo"));
		undoAction->setText (i18n ("&Undo"));
		undoAction->setEnabled (false);
		undoAction->setShortcut (Qt::CTRL + Qt::Key_Z);

		actionCollection ()->addAction ("UndoGame", undoAction);

		connect (this,
				SIGNAL (endActionEnable (bool)),
				endAction,
				SLOT (setEnabled (bool)));

		connect (this,
				SIGNAL (undoActionEnable (bool)),
				undoAction,
				SLOT (setEnabled (bool)));
	}

	void MainWindow::endGame ()
	{
		m_table->deleteLater ();
		m_table = NULL;
		m_rival.reset ();

		emit endActionEnable (false);

		statusBar ()->clearMessage ();
	}

	void MainWindow::undo ()
	{
		if (m_table && m_rival && m_rival->canUndo ())
			m_table->undo ();
	}

	void MainWindow::onPreferences ()
	{
		KConfigDialog dialog (this, i18n ("Preferences"), Settings::self ());

		QWidget *board = new QWidget;

		Ui::BoardConfigWidget *boardUi = new Ui::BoardConfigWidget;
		boardUi->setupUi (board);

		dialog.addPage (board, i18n ("Board"), QLatin1String ("games-config-options"));

		if (m_table)
		{
			connect (&dialog,
					SIGNAL (accepted ()),
					m_table,
					SLOT (update ()));
		}

		dialog.exec ();
	}

	void MainWindow::onNewGame ()
	{
		NewGameDialog dialog;
		if (dialog.exec () != QDialog::Accepted)
			return;

		m_rival = dialog.rival ();
		m_rival->setStatusBar (statusBar ());
#ifdef NEW_LIBKDEGAMES
		difficultyHandler (Kg::difficulty ()->currentLevel ());
#else
		difficultyHandler (KGameDifficulty::level ());
#endif
		emit undoActionEnable (m_rival->canUndo ());

		connect (m_rival.get (),
				SIGNAL (needDestroy ()),
				this,
				SLOT (destroyGame ()));

		const GameConfig& config = dialog.gameConfig ();

		if (!config.isInititialized ())
			return;

		m_table = new TableWidget (config, m_rival, this);

		if (m_destroyTable)
		{
			endGame ();
			return;
		}

		connect (m_table,
				SIGNAL (updateStatusBar (const QString&)),
				statusBar (),
				SLOT (clearMessage ()));
		connect (m_table,
				SIGNAL (updateStatusBar (const QString&)),
				statusBar (),
				SLOT (showMessage (const QString&)));

		setCentralWidget (m_table);
		m_table->show ();

		emit endActionEnable (true);
	}

	void MainWindow::destroyGame ()
	{
		m_destroyTable = true;
		emit undoActionEnable (false);
	}
}

#include "include/mainwindow.moc"
<commit_msg>Fixing segfault<commit_after>/*
 * KDots
 * Copyright (c) 2011-2012 Minh Ngo <nlminhtl@gmail.com>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
#include "mainwindow.hpp"
#include <QDir>
#include <KMenuBar>
#include <KStatusBar>
#include <KConfigDialog>
#include <KToolBar>
#include <KAction>
#include <KStandardAction>
#include <KActionCollection>
#include <interface/iplugin.hpp>
#include <interface/irival.hpp>
#include "ui_mainwindow.h"
#include "ui_boardconfigwidget.h"
#include "newgamedialog.hpp"
#include "tablewidget.hpp"
#include "plugincontainer.hpp"
#include "kdots.h"

namespace KDots
{
	MainWindow::MainWindow (QWidget *parent)
		: KXmlGuiWindow (parent)
		, m_ui (new Ui::MainWindow)
		, m_destroyTable (false)
		, m_table (NULL)
	{
		m_ui->setupUi (this);

#ifdef NEW_LIBKDEGAMES
		Kg::difficulty ()->addStandardLevel (KgDifficultyLevel::Easy);
		Kg::difficulty ()->addStandardLevel (KgDifficultyLevel::Medium);
		Kg::difficulty ()->addStandardLevel (KgDifficultyLevel::Hard);

		connect (Kg::difficulty (),
				SIGNAL (currentLevelChanged (const KgDifficultyLevel*)),
				this,
				SLOT (difficultyHandler (const KgDifficultyLevel*)));

		KgDifficultyGUI::init (this);

		Kg::difficulty ()->setEditable (false);
#else
		KGameDifficulty::init (this, this, SLOT (difficultyHandler (KGameDifficulty::standardLevel)));
		KGameDifficulty::addStandardLevel (KGameDifficulty::Easy);
		KGameDifficulty::addStandardLevel (KGameDifficulty::Medium);
		KGameDifficulty::addStandardLevel (KGameDifficulty::Hard);

		KGameDifficulty::setEnabled (false);
#endif
		statusBar ()->show ();
		setCentralWidget (new QWidget (this));
		initMenu ();
		setupGUI (Default, "kdotsui.rc");
	}

	MainWindow::~MainWindow ()
	{
		m_rival.reset ();
	}

#ifdef NEW_LIBKDEGAMES
	void MainWindow::difficultyHandler (const KgDifficultyLevel *level)
#else
	void MainWindow::difficultyHandler (KGameDifficulty::standardLevel level)
#endif
	{
		int diff;

#ifdef NEW_LIBKDEGAMES
		switch (level->standardLevel ())
		{
		case KgDifficultyLevel::Easy:
			diff = 1;
		case KgDifficultyLevel::Medium:
			diff = 2;
		default:
			diff = 3;
		}
#else
		switch (level)
		{
		case KGameDifficulty::Easy:
			diff = 1;
		case KGameDifficulty::Medium:
			diff = 2;
		default:
			diff = 3;
		}
#endif

		if (m_rival)
			m_rival->setDifficulty (diff);
	}

	void MainWindow::initMenu ()
	{
		KStandardAction::preferences (this, SLOT (onPreferences ()), actionCollection ());

		KAction *newAction = new KAction (KIcon ("file_new"), i18n ("&New game"), this);
		newAction->setShortcut (Qt::CTRL + Qt::Key_N);

		connect (newAction,
				SIGNAL (triggered (bool)),
				this,
				SLOT (onNewGame ()));

		actionCollection ()->addAction ("NewGame", newAction);

		KAction *endAction = actionCollection ()->addAction ("EndGame", this, SLOT (endGame ()));
		endAction->setIcon (KIcon ("window-close"));
		endAction->setText (i18n ("&End game"));
		endAction->setShortcut (Qt::CTRL + Qt::Key_E);
		endAction->setEnabled (false);

		KAction *undoAction = actionCollection ()->addAction ("UndoGame", this, SLOT (undo ()));
		undoAction->setIcon (KIcon ("undo"));
		undoAction->setText (i18n ("&Undo"));
		undoAction->setEnabled (false);
		undoAction->setShortcut (Qt::CTRL + Qt::Key_Z);

		actionCollection ()->addAction ("UndoGame", undoAction);

		connect (this,
				SIGNAL (endActionEnable (bool)),
				endAction,
				SLOT (setEnabled (bool)));

		connect (this,
				SIGNAL (undoActionEnable (bool)),
				undoAction,
				SLOT (setEnabled (bool)));
	}

	void MainWindow::endGame ()
	{
		m_table->deleteLater ();
		m_table = NULL;
		m_rival.reset ();

		emit endActionEnable (false);

		statusBar ()->clearMessage ();
	}

	void MainWindow::undo ()
	{
		if (m_table && m_rival && m_rival->canUndo ())
			m_table->undo ();
	}

	void MainWindow::onPreferences ()
	{
		KConfigDialog dialog (this, i18n ("Preferences"), Settings::self ());

		QWidget *board = new QWidget;

		Ui::BoardConfigWidget *boardUi = new Ui::BoardConfigWidget;
		boardUi->setupUi (board);

		dialog.addPage (board, i18n ("Board"), QLatin1String ("games-config-options"));

		if (m_table)
		{
			connect (&dialog,
					SIGNAL (accepted ()),
					m_table,
					SLOT (update ()));
		}

		dialog.exec ();
	}

	void MainWindow::onNewGame ()
	{
		NewGameDialog dialog;
		if (dialog.exec () != QDialog::Accepted)
			return;

		m_rival = dialog.rival ();
		m_rival->setStatusBar (statusBar ());
#ifdef NEW_LIBKDEGAMES
		difficultyHandler (Kg::difficulty ()->currentLevel ());
#else
		difficultyHandler (KGameDifficulty::level ());
#endif
		emit undoActionEnable (m_rival->canUndo ());

		connect (m_rival.get (),
				SIGNAL (needDestroy ()),
				this,
				SLOT (destroyGame ()));

		const GameConfig& config = dialog.gameConfig ();

		if (!config.isInititialized ())
			return;

		m_table = new TableWidget (config, m_rival, this);

		if (m_destroyTable)
		{
			endGame ();
			return;
		}

		connect (m_table,
				SIGNAL (updateStatusBar (const QString&)),
				statusBar (),
				SLOT (clearMessage ()));
		connect (m_table,
				SIGNAL (updateStatusBar (const QString&)),
				statusBar (),
				SLOT (showMessage (const QString&)));

		setCentralWidget (m_table);
		m_table->show ();

		emit endActionEnable (true);
	}

	void MainWindow::destroyGame ()
	{
		m_destroyTable = true;
		emit undoActionEnable (false);
	}
}

#include "include/mainwindow.moc"
<|endoftext|>