<commit_before>#include <ctime>
#include <regex>
#include "crypto/crypto.h"
#include "logging/logging.h"

#include "director_repo.h"
#include "image_repo.h"
#include "repo.h"

Repo::Repo(Uptane::RepositoryType repo_type, boost::filesystem::path path, const std::string &expires,
           std::string correlation_id)
    : repo_type_(repo_type), path_(std::move(path)), correlation_id_(std::move(correlation_id)) {
  expiration_time_ = getExpirationTime(expires);
  if (boost::filesystem::exists(path_)) {
    if (boost::filesystem::directory_iterator(path_) != boost::filesystem::directory_iterator()) {
      readKeys();
    }
  }

  if (repo_type == Uptane::RepositoryType("director")) {
    repo_dir_ = path_ / DirectorRepo::dir;
  } else if (repo_type == Uptane::RepositoryType("image")) {
    repo_dir_ = path_ / ImageRepo::dir;
  }
}

void Repo::addDelegationToSnapshot(Json::Value *snapshot, const Uptane::Role &role) {
  boost::filesystem::path repo_dir = repo_dir_;
  if (role.IsDelegation()) {
    repo_dir = repo_dir / "delegations";
  }
  std::string role_file_name = role.ToString() + ".json";

  Json::Value role_json = Utils::parseJSONFile(repo_dir / role_file_name)["signed"];
  std::string signed_role = Utils::readFile(repo_dir / role_file_name);

  (*snapshot)["meta"][role_file_name]["version"] = role_json["version"].asUInt();

  if (role_json["delegations"].isObject()) {
    auto delegations_list = role_json["delegations"]["roles"];

    for (Json::ValueIterator it = delegations_list.begin(); it != delegations_list.end(); it++) {
      addDelegationToSnapshot(snapshot, Uptane::Role((*it)["name"].asString(), true));
    }
  }
}

void Repo::updateRepo() {
  boost::filesystem::path repo_dir = repo_dir_;
  Json::Value old_snapshot = Utils::parseJSONFile(repo_dir / "snapshot.json")["signed"];

  Json::Value snapshot;
  snapshot["_type"] = "Snapshot";
  snapshot["expires"] = old_snapshot["expires"];
  snapshot["version"] = (old_snapshot["version"].asUInt()) + 1;

  Json::Value root = Utils::parseJSONFile(repo_dir / "root.json")["signed"];
  std::string signed_root = Utils::readFile(repo_dir / "root.json");

  snapshot["meta"]["root.json"]["version"] = root["version"].asUInt();

  addDelegationToSnapshot(&snapshot, Uptane::Role::Targets());

  std::string signed_snapshot = Utils::jsonToCanonicalStr(signTuf(Uptane::Role::Snapshot(), snapshot));
  Utils::writeFile(repo_dir / "snapshot.json", signed_snapshot);

  Json::Value timestamp = Utils::parseJSONFile(repo_dir / "timestamp.json")["signed"];
  timestamp["version"] = (timestamp["version"].asUInt()) + 1;
  timestamp["meta"]["snapshot.json"]["hashes"]["sha256"] =
      boost::algorithm::to_lower_copy(boost::algorithm::hex(Crypto::sha256digest(signed_snapshot)));
  timestamp["meta"]["snapshot.json"]["hashes"]["sha512"] =
      boost::algorithm::to_lower_copy(boost::algorithm::hex(Crypto::sha512digest(signed_snapshot)));
  timestamp["meta"]["snapshot.json"]["length"] = static_cast<Json::UInt>(signed_snapshot.length());
  timestamp["meta"]["snapshot.json"]["version"] = snapshot["version"].asUInt();
  Utils::writeFile(repo_dir / "timestamp.json",
                   Utils::jsonToCanonicalStr(signTuf(Uptane::Role::Timestamp(), timestamp)));
}

Json::Value Repo::signTuf(const Uptane::Role &role, const Json::Value &json) {
  auto key = keys_[role];
  std::string b64sig =
      Utils::toBase64(Crypto::Sign(key.public_key.Type(), nullptr, key.private_key, Json::FastWriter().write(json)));
  Json::Value signature;
  switch (key.public_key.Type()) {
    case KeyType::kRSA2048:
    case KeyType::kRSA3072:
    case KeyType::kRSA4096:
      signature["method"] = "rsassa-pss";
      break;
    case KeyType::kED25519:
      signature["method"] = "ed25519";
      break;
    default:
      throw std::runtime_error("Unknown key type");
  }
  signature["sig"] = b64sig;

  Json::Value signed_data;
  signature["keyid"] = key.public_key.KeyId();

  signed_data["signed"] = json;
  signed_data["signatures"].append(signature);
  return signed_data;
}

std::string Repo::getExpirationTime(const std::string &expires) {
  if (expires.size() != 0) {
    std::smatch match;
    std::regex time_pattern("\\d{4}\\-\\d{2}\\-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z");  // NOLINT(modernize-raw-string-literal)
    if (!std::regex_match(expires, time_pattern)) {
      throw std::runtime_error("Expiration date has wrong format\n date should be in ISO 8601 UTC format");
    }
    return expires;
  } else {
    time_t raw_time;
    struct tm time_struct {};
    time(&raw_time);
    gmtime_r(&raw_time, &time_struct);
    time_struct.tm_year += 3;
    char formatted[22];
    strftime(formatted, 22, "%Y-%m-%dT%H:%M:%SZ", &time_struct);
    return formatted;
  }
}
void Repo::generateKeyPair(KeyType key_type, const Uptane::Role &key_name) {
  boost::filesystem::path keys_dir = path_ / ("keys/" + repo_type_.toString() + "/" + key_name.ToString());
  boost::filesystem::create_directories(keys_dir);

  std::string public_key_string, private_key;
  Crypto::generateKeyPair(key_type, &public_key_string, &private_key);
  PublicKey public_key(public_key_string, key_type);

  std::stringstream key_str;
  key_str << key_type;

  Utils::writeFile(keys_dir / "private.key", private_key);
  Utils::writeFile(keys_dir / "public.key", public_key_string);
  Utils::writeFile(keys_dir / "key_type", key_str.str());

  keys_[key_name] = KeyPair(public_key, private_key);
}

void Repo::generateRepoKeys(KeyType key_type) {
  generateKeyPair(key_type, Uptane::Role::Root());
  generateKeyPair(key_type, Uptane::Role::Snapshot());
  generateKeyPair(key_type, Uptane::Role::Targets());
  generateKeyPair(key_type, Uptane::Role::Timestamp());
}

void Repo::generateRepo(KeyType key_type) {
  generateRepoKeys(key_type);

  boost::filesystem::create_directories(repo_dir_);
  Json::Value root;
  root["_type"] = "Root";
  root["expires"] = expiration_time_;
  root["version"] = 1;
  for (auto const &keypair : keys_) {
    root["keys"][keypair.second.public_key.KeyId()] = keypair.second.public_key.ToUptane();
  }

  Json::Value role;
  role["threshold"] = 1;

  role["keyids"].append(keys_[Uptane::Role::Root()].public_key.KeyId());
  root["roles"]["root"] = role;

  role["keyids"].clear();
  role["keyids"].append(keys_[Uptane::Role::Snapshot()].public_key.KeyId());
  root["roles"]["snapshot"] = role;

  role["keyids"].clear();
  role["keyids"].append(keys_[Uptane::Role::Targets()].public_key.KeyId());
  root["roles"]["targets"] = role;

  role["keyids"].clear();
  role["keyids"].append(keys_[Uptane::Role::Timestamp()].public_key.KeyId());
  root["roles"]["timestamp"] = role;

  std::string signed_root = Utils::jsonToCanonicalStr(signTuf(Uptane::Role::Root(), root));
  Utils::writeFile(repo_dir_ / "root.json", signed_root);
  Utils::writeFile(repo_dir_ / "1.root.json", signed_root);

  Json::Value targets;
  targets["_type"] = "Targets";
  targets["expires"] = expiration_time_;
  targets["version"] = 1;
  targets["targets"] = Json::objectValue;
  if (repo_type_ == Uptane::RepositoryType::Director() && correlation_id_ != "") {
    targets["custom"]["correlationId"] = correlation_id_;
  }
  std::string signed_targets = Utils::jsonToCanonicalStr(signTuf(Uptane::Role::Targets(), targets));
  Utils::writeFile(repo_dir_ / "targets.json", signed_targets);

  Json::Value snapshot;
  snapshot["_type"] = "Snapshot";
  snapshot["expires"] = expiration_time_;
  snapshot["version"] = 1;
  snapshot["meta"]["root.json"]["hashes"]["sha256"] =
      boost::algorithm::to_lower_copy(boost::algorithm::hex(Crypto::sha256digest(signed_root)));
  snapshot["meta"]["root.json"]["hashes"]["sha512"] =
      boost::algorithm::to_lower_copy(boost::algorithm::hex(Crypto::sha512digest(signed_root)));
  snapshot["meta"]["root.json"]["length"] = static_cast<Json::UInt>(signed_root.length());
  snapshot["meta"]["root.json"]["version"] = 1;
  snapshot["meta"]["targets.json"]["version"] = 1;
  std::string signed_snapshot = Utils::jsonToCanonicalStr(signTuf(Uptane::Role::Snapshot(), snapshot));
  Utils::writeFile(repo_dir_ / "snapshot.json", signed_snapshot);

  Json::Value timestamp;
  timestamp["_type"] = "Timestamp";
  timestamp["expires"] = expiration_time_;
  timestamp["version"] = 1;
  timestamp["meta"]["snapshot.json"]["hashes"]["sha256"] =
      boost::algorithm::to_lower_copy(boost::algorithm::hex(Crypto::sha256digest(signed_snapshot)));
  timestamp["meta"]["snapshot.json"]["hashes"]["sha512"] =
      boost::algorithm::to_lower_copy(boost::algorithm::hex(Crypto::sha512digest(signed_snapshot)));
  timestamp["meta"]["snapshot.json"]["length"] = static_cast<Json::UInt>(signed_snapshot.length());
  timestamp["meta"]["snapshot.json"]["version"] = 1;
  Utils::writeFile(repo_dir_ / "timestamp.json",
                   Utils::jsonToCanonicalStr(signTuf(Uptane::Role::Timestamp(), timestamp)));
  if (repo_type_ == Uptane::RepositoryType::Director()) {
    Utils::writeFile(path_ / DirectorRepo::dir / "manifest", std::string());  // just empty file to work with put method
  }
}

Json::Value Repo::getTarget(const std::string &target_name) {
  const Json::Value image_targets = Utils::parseJSONFile(repo_dir_ / "targets.json")["signed"];
  if (image_targets["targets"].isMember(target_name)) {
    return image_targets["targets"][target_name];
  } else if (repo_type_ == Uptane::RepositoryType::Image()) {
    for (auto &p : boost::filesystem::directory_iterator(repo_dir_ / "delegations")) {
      if (Uptane::Role::IsReserved(p.path().stem().string())) {
        continue;
      }
      auto targets = Utils::parseJSONFile(p)["signed"];
      if (targets["targets"].isMember(target_name)) {
        return targets["targets"][target_name];
      }
    }
    throw std::runtime_error(std::string("No target with name: ") + target_name);
  }
  return {};
}

void Repo::readKeys() {
  auto keys_path = path_ / "keys" / repo_type_.toString();
  for (auto &p : boost::filesystem::directory_iterator(keys_path)) {
    std::string public_key_string = Utils::readFile(p / "public.key");
    std::istringstream key_type_str(Utils::readFile(p / "key_type"));
    KeyType key_type;
    key_type_str >> key_type;
    std::string private_key_string(Utils::readFile(p / "private.key"));
    auto name = p.path().filename().string();
    keys_[Uptane::Role(name, !Uptane::Role::IsReserved(name))] =
        KeyPair(PublicKey(public_key_string, key_type), private_key_string);
  }
}

Delegation::Delegation(const boost::filesystem::path &repo_path, std::string delegation_name)
    : name(std::move(delegation_name)) {
  if (Uptane::Role::IsReserved(name)) {
    throw std::runtime_error("Delegation name " + name + " is reserved.");
  }
  boost::filesystem::path delegation_path(((repo_path / ImageRepo::dir / "delegations") / name).string() + ".json");
  boost::filesystem::path targets_path(repo_path / ImageRepo::dir / "targets.json");
  if (!boost::filesystem::exists(delegation_path) || !boost::filesystem::exists(targets_path)) {
    throw std::runtime_error(std::string("delegation ") + delegation_path.string() + " does not exist");
  }

  pattern = findPatternInTree(repo_path, name, Utils::parseJSONFile(targets_path)["signed"]);

  if (pattern.empty()) {
    throw std::runtime_error("Could not find delegation role in the delegation tree");
  }
}

std::string Delegation::findPatternInTree(const boost::filesystem::path &repo_path, const std::string &name,
                                          const Json::Value &targets_json) {
  Json::Value delegations = targets_json["delegations"];
  for (const auto &role : delegations["roles"]) {
    auto role_name = role["name"].asString();
    if (role_name == name) {
      auto pattern = role["paths"][0].asString();
      if (pattern.back() == '/') {
        pattern.append("**");
      }
      return pattern;
    } else {
      auto pattern = findPatternInTree(
          repo_path, name,
          Utils::parseJSONFile((repo_path / ImageRepo::dir / "delegations") / (role_name + ".json"))["signed"]);
      if (!pattern.empty()) {
        return pattern;
      }
    }
  }

  return "";
}
<commit_msg>Remove some zealous throws in uptane-generator<commit_after>#include <ctime>
#include <regex>
#include "crypto/crypto.h"
#include "logging/logging.h"

#include "director_repo.h"
#include "image_repo.h"
#include "repo.h"

Repo::Repo(Uptane::RepositoryType repo_type, boost::filesystem::path path, const std::string &expires,
           std::string correlation_id)
    : repo_type_(repo_type), path_(std::move(path)), correlation_id_(std::move(correlation_id)) {
  expiration_time_ = getExpirationTime(expires);
  if (boost::filesystem::exists(path_)) {
    if (boost::filesystem::directory_iterator(path_) != boost::filesystem::directory_iterator()) {
      readKeys();
    }
  }

  if (repo_type == Uptane::RepositoryType("director")) {
    repo_dir_ = path_ / DirectorRepo::dir;
  } else if (repo_type == Uptane::RepositoryType("image")) {
    repo_dir_ = path_ / ImageRepo::dir;
  }
}

void Repo::addDelegationToSnapshot(Json::Value *snapshot, const Uptane::Role &role) {
  boost::filesystem::path repo_dir = repo_dir_;
  if (role.IsDelegation()) {
    repo_dir = repo_dir / "delegations";
  }
  std::string role_file_name = role.ToString() + ".json";

  Json::Value role_json = Utils::parseJSONFile(repo_dir / role_file_name)["signed"];
  std::string signed_role = Utils::readFile(repo_dir / role_file_name);

  (*snapshot)["meta"][role_file_name]["version"] = role_json["version"].asUInt();

  if (role_json["delegations"].isObject()) {
    auto delegations_list = role_json["delegations"]["roles"];

    for (Json::ValueIterator it = delegations_list.begin(); it != delegations_list.end(); it++) {
      addDelegationToSnapshot(snapshot, Uptane::Role((*it)["name"].asString(), true));
    }
  }
}

void Repo::updateRepo() {
  boost::filesystem::path repo_dir = repo_dir_;
  Json::Value old_snapshot = Utils::parseJSONFile(repo_dir / "snapshot.json")["signed"];

  Json::Value snapshot;
  snapshot["_type"] = "Snapshot";
  snapshot["expires"] = old_snapshot["expires"];
  snapshot["version"] = (old_snapshot["version"].asUInt()) + 1;

  Json::Value root = Utils::parseJSONFile(repo_dir / "root.json")["signed"];
  std::string signed_root = Utils::readFile(repo_dir / "root.json");

  snapshot["meta"]["root.json"]["version"] = root["version"].asUInt();

  addDelegationToSnapshot(&snapshot, Uptane::Role::Targets());

  std::string signed_snapshot = Utils::jsonToCanonicalStr(signTuf(Uptane::Role::Snapshot(), snapshot));
  Utils::writeFile(repo_dir / "snapshot.json", signed_snapshot);

  Json::Value timestamp = Utils::parseJSONFile(repo_dir / "timestamp.json")["signed"];
  timestamp["version"] = (timestamp["version"].asUInt()) + 1;
  timestamp["meta"]["snapshot.json"]["hashes"]["sha256"] =
      boost::algorithm::to_lower_copy(boost::algorithm::hex(Crypto::sha256digest(signed_snapshot)));
  timestamp["meta"]["snapshot.json"]["hashes"]["sha512"] =
      boost::algorithm::to_lower_copy(boost::algorithm::hex(Crypto::sha512digest(signed_snapshot)));
  timestamp["meta"]["snapshot.json"]["length"] = static_cast<Json::UInt>(signed_snapshot.length());
  timestamp["meta"]["snapshot.json"]["version"] = snapshot["version"].asUInt();
  Utils::writeFile(repo_dir / "timestamp.json",
                   Utils::jsonToCanonicalStr(signTuf(Uptane::Role::Timestamp(), timestamp)));
}

Json::Value Repo::signTuf(const Uptane::Role &role, const Json::Value &json) {
  auto key = keys_[role];
  std::string b64sig =
      Utils::toBase64(Crypto::Sign(key.public_key.Type(), nullptr, key.private_key, Json::FastWriter().write(json)));
  Json::Value signature;
  switch (key.public_key.Type()) {
    case KeyType::kRSA2048:
    case KeyType::kRSA3072:
    case KeyType::kRSA4096:
      signature["method"] = "rsassa-pss";
      break;
    case KeyType::kED25519:
      signature["method"] = "ed25519";
      break;
    default:
      throw std::runtime_error("Unknown key type");
  }
  signature["sig"] = b64sig;

  Json::Value signed_data;
  signature["keyid"] = key.public_key.KeyId();

  signed_data["signed"] = json;
  signed_data["signatures"].append(signature);
  return signed_data;
}

std::string Repo::getExpirationTime(const std::string &expires) {
  if (expires.size() != 0) {
    std::smatch match;
    std::regex time_pattern("\\d{4}\\-\\d{2}\\-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z");  // NOLINT(modernize-raw-string-literal)
    if (!std::regex_match(expires, time_pattern)) {
      throw std::runtime_error("Expiration date has wrong format\n date should be in ISO 8601 UTC format");
    }
    return expires;
  } else {
    time_t raw_time;
    struct tm time_struct {};
    time(&raw_time);
    gmtime_r(&raw_time, &time_struct);
    time_struct.tm_year += 3;
    char formatted[22];
    strftime(formatted, 22, "%Y-%m-%dT%H:%M:%SZ", &time_struct);
    return formatted;
  }
}
void Repo::generateKeyPair(KeyType key_type, const Uptane::Role &key_name) {
  boost::filesystem::path keys_dir = path_ / ("keys/" + repo_type_.toString() + "/" + key_name.ToString());
  boost::filesystem::create_directories(keys_dir);

  std::string public_key_string, private_key;
  Crypto::generateKeyPair(key_type, &public_key_string, &private_key);
  PublicKey public_key(public_key_string, key_type);

  std::stringstream key_str;
  key_str << key_type;

  Utils::writeFile(keys_dir / "private.key", private_key);
  Utils::writeFile(keys_dir / "public.key", public_key_string);
  Utils::writeFile(keys_dir / "key_type", key_str.str());

  keys_[key_name] = KeyPair(public_key, private_key);
}

void Repo::generateRepoKeys(KeyType key_type) {
  generateKeyPair(key_type, Uptane::Role::Root());
  generateKeyPair(key_type, Uptane::Role::Snapshot());
  generateKeyPair(key_type, Uptane::Role::Targets());
  generateKeyPair(key_type, Uptane::Role::Timestamp());
}

void Repo::generateRepo(KeyType key_type) {
  generateRepoKeys(key_type);

  boost::filesystem::create_directories(repo_dir_);
  Json::Value root;
  root["_type"] = "Root";
  root["expires"] = expiration_time_;
  root["version"] = 1;
  for (auto const &keypair : keys_) {
    root["keys"][keypair.second.public_key.KeyId()] = keypair.second.public_key.ToUptane();
  }

  Json::Value role;
  role["threshold"] = 1;

  role["keyids"].append(keys_[Uptane::Role::Root()].public_key.KeyId());
  root["roles"]["root"] = role;

  role["keyids"].clear();
  role["keyids"].append(keys_[Uptane::Role::Snapshot()].public_key.KeyId());
  root["roles"]["snapshot"] = role;

  role["keyids"].clear();
  role["keyids"].append(keys_[Uptane::Role::Targets()].public_key.KeyId());
  root["roles"]["targets"] = role;

  role["keyids"].clear();
  role["keyids"].append(keys_[Uptane::Role::Timestamp()].public_key.KeyId());
  root["roles"]["timestamp"] = role;

  std::string signed_root = Utils::jsonToCanonicalStr(signTuf(Uptane::Role::Root(), root));
  Utils::writeFile(repo_dir_ / "root.json", signed_root);
  Utils::writeFile(repo_dir_ / "1.root.json", signed_root);

  Json::Value targets;
  targets["_type"] = "Targets";
  targets["expires"] = expiration_time_;
  targets["version"] = 1;
  targets["targets"] = Json::objectValue;
  if (repo_type_ == Uptane::RepositoryType::Director() && correlation_id_ != "") {
    targets["custom"]["correlationId"] = correlation_id_;
  }
  std::string signed_targets = Utils::jsonToCanonicalStr(signTuf(Uptane::Role::Targets(), targets));
  Utils::writeFile(repo_dir_ / "targets.json", signed_targets);

  Json::Value snapshot;
  snapshot["_type"] = "Snapshot";
  snapshot["expires"] = expiration_time_;
  snapshot["version"] = 1;
  snapshot["meta"]["root.json"]["hashes"]["sha256"] =
      boost::algorithm::to_lower_copy(boost::algorithm::hex(Crypto::sha256digest(signed_root)));
  snapshot["meta"]["root.json"]["hashes"]["sha512"] =
      boost::algorithm::to_lower_copy(boost::algorithm::hex(Crypto::sha512digest(signed_root)));
  snapshot["meta"]["root.json"]["length"] = static_cast<Json::UInt>(signed_root.length());
  snapshot["meta"]["root.json"]["version"] = 1;
  snapshot["meta"]["targets.json"]["version"] = 1;
  std::string signed_snapshot = Utils::jsonToCanonicalStr(signTuf(Uptane::Role::Snapshot(), snapshot));
  Utils::writeFile(repo_dir_ / "snapshot.json", signed_snapshot);

  Json::Value timestamp;
  timestamp["_type"] = "Timestamp";
  timestamp["expires"] = expiration_time_;
  timestamp["version"] = 1;
  timestamp["meta"]["snapshot.json"]["hashes"]["sha256"] =
      boost::algorithm::to_lower_copy(boost::algorithm::hex(Crypto::sha256digest(signed_snapshot)));
  timestamp["meta"]["snapshot.json"]["hashes"]["sha512"] =
      boost::algorithm::to_lower_copy(boost::algorithm::hex(Crypto::sha512digest(signed_snapshot)));
  timestamp["meta"]["snapshot.json"]["length"] = static_cast<Json::UInt>(signed_snapshot.length());
  timestamp["meta"]["snapshot.json"]["version"] = 1;
  Utils::writeFile(repo_dir_ / "timestamp.json",
                   Utils::jsonToCanonicalStr(signTuf(Uptane::Role::Timestamp(), timestamp)));
  if (repo_type_ == Uptane::RepositoryType::Director()) {
    Utils::writeFile(path_ / DirectorRepo::dir / "manifest", std::string());  // just empty file to work with put method
  }
}

Json::Value Repo::getTarget(const std::string &target_name) {
  const Json::Value image_targets = Utils::parseJSONFile(repo_dir_ / "targets.json")["signed"];
  if (image_targets["targets"].isMember(target_name)) {
    return image_targets["targets"][target_name];
  } else if (repo_type_ == Uptane::RepositoryType::Image()) {
    if (!boost::filesystem::is_directory(repo_dir_ / "delegations")) {
      return {};
    }
    for (auto &p : boost::filesystem::directory_iterator(repo_dir_ / "delegations")) {
      if (Uptane::Role::IsReserved(p.path().stem().string())) {
        continue;
      }
      auto targets = Utils::parseJSONFile(p)["signed"];
      if (targets["targets"].isMember(target_name)) {
        return targets["targets"][target_name];
      }
    }
  }
  return {};
}

void Repo::readKeys() {
  auto keys_path = path_ / "keys" / repo_type_.toString();
  for (auto &p : boost::filesystem::directory_iterator(keys_path)) {
    std::string public_key_string = Utils::readFile(p / "public.key");
    std::istringstream key_type_str(Utils::readFile(p / "key_type"));
    KeyType key_type;
    key_type_str >> key_type;
    std::string private_key_string(Utils::readFile(p / "private.key"));
    auto name = p.path().filename().string();
    keys_[Uptane::Role(name, !Uptane::Role::IsReserved(name))] =
        KeyPair(PublicKey(public_key_string, key_type), private_key_string);
  }
}

Delegation::Delegation(const boost::filesystem::path &repo_path, std::string delegation_name)
    : name(std::move(delegation_name)) {
  if (Uptane::Role::IsReserved(name)) {
    throw std::runtime_error("Delegation name " + name + " is reserved.");
  }
  boost::filesystem::path delegation_path(((repo_path / ImageRepo::dir / "delegations") / name).string() + ".json");
  boost::filesystem::path targets_path(repo_path / ImageRepo::dir / "targets.json");
  if (!boost::filesystem::exists(delegation_path) || !boost::filesystem::exists(targets_path)) {
    throw std::runtime_error(std::string("delegation ") + delegation_path.string() + " does not exist");
  }

  pattern = findPatternInTree(repo_path, name, Utils::parseJSONFile(targets_path)["signed"]);

  if (pattern.empty()) {
    throw std::runtime_error("Could not find delegation role in the delegation tree");
  }
}

std::string Delegation::findPatternInTree(const boost::filesystem::path &repo_path, const std::string &name,
                                          const Json::Value &targets_json) {
  Json::Value delegations = targets_json["delegations"];
  for (const auto &role : delegations["roles"]) {
    auto role_name = role["name"].asString();
    if (role_name == name) {
      auto pattern = role["paths"][0].asString();
      if (pattern.back() == '/') {
        pattern.append("**");
      }
      return pattern;
    } else {
      auto pattern = findPatternInTree(
          repo_path, name,
          Utils::parseJSONFile((repo_path / ImageRepo::dir / "delegations") / (role_name + ".json"))["signed"]);
      if (!pattern.empty()) {
        return pattern;
      }
    }
  }

  return "";
}
<|endoftext|>


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

// Syslog_facility weak default printf

#include <util/syslog_facility.hpp>

// Weak
void Syslog_facility::syslog(const std::string& log_message) {
	if (logopt_ & LOG_CONS /*and priority_ == LOG_ERR*/)
		std::cout << log_message.c_str() << '\n';

  if (logopt_ & LOG_PERROR)
    std::cerr << log_message.c_str() << '\n';

	printf("%s\n", log_message.c_str());
}

// Weak
Syslog_facility::~Syslog_facility() {}

// Weak
void Syslog_facility::open_socket() {}

// Weak
void Syslog_facility::close_socket() {}

// Weak
void Syslog_facility::send_udp_data(const std::string&) {}
<commit_msg>Syslog warning: Fix to remove unused sock_ warning for weak version of Syslog_facility<commit_after>// This file is a part of the IncludeOS unikernel - www.includeos.org
//
// Copyright 2015 Oslo and Akershus University College of Applied Sciences
// and Alfred Bratterud
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Syslog_facility weak default printf

#include <util/syslog_facility.hpp>

// Weak
void Syslog_facility::syslog(const std::string& log_message) {
	if (logopt_ & LOG_CONS /*and priority_ == LOG_ERR*/)
		std::cout << log_message.c_str() << '\n';

  if (logopt_ & LOG_PERROR)
    std::cerr << log_message.c_str() << '\n';

	printf("%s\n", log_message.c_str());
}

// Weak
Syslog_facility::~Syslog_facility() {}

// Weak
void Syslog_facility::open_socket() {}

// Weak
void Syslog_facility::close_socket() { sock_ = nullptr; }

// Weak
void Syslog_facility::send_udp_data(const std::string&) {}
<|endoftext|>


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

#include "pointcloud.h"

static const char kVertexShader[] = "attribute vec4 vertex;\n"
    "uniform mat4 mvp;\n"
    "varying vec4 v_color;\n"
    "void main() {\n"
    "  gl_PointSize = 4.0;\n"
    "  gl_Position = mvp*vertex;\n"
    "  v_color = vertex;\n"
    "}\n";

static const char kFragmentShader[] = "varying vec4 v_color;\n"
    "void main() {\n"
    "  gl_FragColor = vec4(v_color);\n"
    "}\n";

static const glm::mat4 inverse_z_mat = glm::mat4(1.0f, 0.0f, 0.0f, 0.0f,
                                                 0.0f, 1.0f, 0.0f, 0.0f,
                                                 0.0f, 0.0f, -1.0f, 0.0f,
                                                 0.0f, 0.0f, 0.0f, 1.0f);

Pointcloud::Pointcloud() {
  glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
  shader_program_ = GlUtil::CreateProgram(kVertexShader, kFragmentShader);
  if (!shader_program_) {
    LOGE("Could not create program.");
  }
  uniform_mvp_mat_ = glGetUniformLocation(shader_program_, "mvp");
  attrib_vertices_ = glGetAttribLocation(shader_program_, "vertex");
  glGenBuffers(1, &vertex_buffers_);
}

void Pointcloud::Render(glm::mat4 view_projection_mat, float depth_buffer_size,
                        float *depth_data_buffer) {

  glUseProgram(shader_program_);
  // Calculate model view projection matrix.
  glm::mat4 model_mat = glm::mat4(1.0f);
  glm::mat4 mvp_mat = view_projection_mat * model_mat * inverse_z_mat;
  glUniformMatrix4fv(uniform_mvp_mat_, 1, GL_FALSE, glm::value_ptr(mvp_mat));

  // Bind vertex buffer.
  glBindBuffer(GL_ARRAY_BUFFER, vertex_buffers_);
  glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * depth_buffer_size,
               depth_data_buffer, GL_STATIC_DRAW);
  glEnableVertexAttribArray(attrib_vertices_);
  glVertexAttribPointer(attrib_vertices_, 3, GL_FLOAT, GL_FALSE, 0,
                        (const void*) 0);
  glBindBuffer(GL_ARRAY_BUFFER, 0);

  glDrawArrays(GL_POINTS, 0, 3 * depth_buffer_size);
  GlUtil::CheckGlError("glDrawArray()");
  glUseProgram(0);
  GlUtil::CheckGlError("glUseProgram()");
}
<commit_msg>- inverse y-axis on point cloud data.<commit_after>/*
 * Copyright 2014 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "pointcloud.h"

static const char kVertexShader[] = "attribute vec4 vertex;\n"
    "uniform mat4 mvp;\n"
    "varying vec4 v_color;\n"
    "void main() {\n"
    "  gl_PointSize = 4.0;\n"
    "  gl_Position = mvp*vertex;\n"
    "  v_color = vertex;\n"
    "}\n";

static const char kFragmentShader[] = "varying vec4 v_color;\n"
    "void main() {\n"
    "  gl_FragColor = vec4(v_color);\n"
    "}\n";

static const glm::mat4 inverse_z_mat = glm::mat4(1.0f, 0.0f, 0.0f, 0.0f,
                                                 0.0f, -1.0f, 0.0f, 0.0f,
                                                 0.0f, 0.0f, -1.0f, 0.0f,
                                                 0.0f, 0.0f, 0.0f, 1.0f);

Pointcloud::Pointcloud() {
  glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
  shader_program_ = GlUtil::CreateProgram(kVertexShader, kFragmentShader);
  if (!shader_program_) {
    LOGE("Could not create program.");
  }
  uniform_mvp_mat_ = glGetUniformLocation(shader_program_, "mvp");
  attrib_vertices_ = glGetAttribLocation(shader_program_, "vertex");
  glGenBuffers(1, &vertex_buffers_);
}

void Pointcloud::Render(glm::mat4 view_projection_mat, float depth_buffer_size,
                        float *depth_data_buffer) {

  glUseProgram(shader_program_);
  // Calculate model view projection matrix.
  glm::mat4 model_mat = glm::mat4(1.0f);
  glm::mat4 mvp_mat = view_projection_mat * model_mat * inverse_z_mat;
  glUniformMatrix4fv(uniform_mvp_mat_, 1, GL_FALSE, glm::value_ptr(mvp_mat));

  // Bind vertex buffer.
  glBindBuffer(GL_ARRAY_BUFFER, vertex_buffers_);
  glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * depth_buffer_size,
               depth_data_buffer, GL_STATIC_DRAW);
  glEnableVertexAttribArray(attrib_vertices_);
  glVertexAttribPointer(attrib_vertices_, 3, GL_FLOAT, GL_FALSE, 0,
                        (const void*) 0);
  glBindBuffer(GL_ARRAY_BUFFER, 0);

  glDrawArrays(GL_POINTS, 0, 3 * depth_buffer_size);
  GlUtil::CheckGlError("glDrawArray()");
  glUseProgram(0);
  GlUtil::CheckGlError("glUseProgram()");
}
<|endoftext|>


<commit_before>// KMail Account

#include "kmaccount.h"

#include <config.h>
#include <stdlib.h>
#include <unistd.h>

#include <assert.h>
#include <kapplication.h>

#include <klocale.h>
#include <kmessagebox.h>
#include <kdebug.h>

#include "kmacctmgr.h"
#include "kmacctfolder.h"
#include "kmfoldermgr.h"
#include "kmfiltermgr.h"
#include "kmsender.h"
#include "kmbroadcaststatus.h"
#include "kmmessage.h"

//----------------------
#include "kmaccount.moc"

//-----------------------------------------------------------------------------
KMPrecommand::KMPrecommand(const QString &precommand, QObject *parent)
  : QObject(parent), mPrecommand(precommand)
{
  KMBroadcastStatus::instance()->setStatusMsg(
      i18n("Executing precommand %1").arg(precommand ));

#if KDE_VERSION >= 305
  mPrecommandProcess.setUseShell(true);
#endif
  mPrecommandProcess << precommand;

  connect(&mPrecommandProcess, SIGNAL(processExited(KProcess *)),
          SLOT(precommandExited(KProcess *)));
}

//-----------------------------------------------------------------------------
KMPrecommand::~KMPrecommand()
{
}

//-----------------------------------------------------------------------------
bool KMPrecommand::start()
{
  bool ok = mPrecommandProcess.start( KProcess::NotifyOnExit );
  if (!ok) KMessageBox::error(0, i18n("Couldn't execute precommand '%1'.")
    .arg(mPrecommand));
  return ok;
}

//-----------------------------------------------------------------------------
void KMPrecommand::precommandExited(KProcess *p)
{
  int exitCode = p->normalExit() ? p->exitStatus() : -1;
  if (exitCode)
    KMessageBox::error(0, i18n("The precommand exited with code %1:\n%2")
      .arg(exitCode).arg(strerror(exitCode)));
  emit finished(!exitCode);
}

//-----------------------------------------------------------------------------
KMAccount::KMAccount(KMAcctMgr* aOwner, const QString& aName)
  : mName(aName),
    mTrash(KMKernel::self()->trashFolder()->idString()),
    mOwner(aOwner),
    mFolder(0),
    mTimer(0),
    mInterval(0),
    mResource(false),
    mExclude(false),
    mCheckingMail(false),
    mPrecommandSuccess(true)
{
  assert(aOwner != 0);

  connect(&mReceiptTimer,SIGNAL(timeout()),SLOT(sendReceipts()));
}

void KMAccount::init() {
  mTrash = kernel->trashFolder()->idString();
  mResource = false;
  mExclude = false;
  mInterval = 0;
}

//-----------------------------------------------------------------------------
KMAccount::~KMAccount()
{
  if (!kernel->shuttingDown() && mFolder) mFolder->removeAccount(this);
  if (mTimer) deinstallTimer();
}

//-----------------------------------------------------------------------------
void KMAccount::setName(const QString& aName)
{
  mName = (aName.isEmpty()) ? i18n("Unnamed") : aName;
}

//-----------------------------------------------------------------------------
void KMAccount::clearPasswd()
{
}

//-----------------------------------------------------------------------------
void KMAccount::setFolder(KMFolder* aFolder, bool addAccount)
{
  if(!aFolder)
    {
    kdDebug(5006) << "KMAccount::setFolder() : aFolder == 0" << endl;
    mFolder = 0;
    return;
    }
  mFolder = (KMAcctFolder*)aFolder;
  if (addAccount) mFolder->addAccount(this);
}

//-----------------------------------------------------------------------------
void KMAccount::readConfig(KConfig& config)
{
  QString folderName;

  mFolder = 0;
  folderName = config.readEntry("Folder", "");
  setCheckInterval(config.readNumEntry("check-interval", 0));
  setTrash(config.readEntry("trash", kernel->trashFolder()->idString()));
  setResource(config.readBoolEntry("resource", false) );
  setCheckExclude(config.readBoolEntry("check-exclude", false));
  setPrecommand(config.readEntry("precommand"));

  if (!folderName.isEmpty())
  {
    setFolder(kernel->folderMgr()->findIdString(folderName), true);
  }

  if( mResource ) {
      int numResourceEntries = config.readNumEntry( "numResourceEntries", 0 );
      int count = 0;
      for( int i = 0; i < numResourceEntries; i++, count++ ) {
          QDateTime start = config.readDateTimeEntry( QString( "resource%1-start" ).arg( i ) );
          QDateTime end = config.readDateTimeEntry( QString( "resource%1-end" ).arg( i ) );
          mIntervals.append( qMakePair(start,end) );
      }
  }
}

//-----------------------------------------------------------------------------
void KMAccount::writeConfig(KConfig& config)
{
  config.writeEntry("Type", type());
  config.writeEntry("Name", mName);
  config.writeEntry("Folder", mFolder ? mFolder->idString() : QString::null);
  config.writeEntry("check-interval", mInterval);
  config.writeEntry("resource", mResource);
  config.writeEntry("check-exclude", mExclude);
  config.writeEntry("precommand", mPrecommand);
  config.writeEntry("trash", mTrash);

  // Write the resource management data
  if( mResource ) {
      config.writeEntry("numResourceEntries", mIntervals.count() );
      int count = 0;
      for( QValueList<QPair< QDateTime, QDateTime> >::Iterator it = mIntervals.begin(); it != mIntervals.end(); ++it, count++ ) {
          config.writeEntry( QString( "resource%1-start" ).arg( count ),
                             (*it).first );
          config.writeEntry( QString( "resource%1-end" ).arg( count ),
                             (*it).second );
      }
  }
}

//-----------------------------------------------------------------------------
void KMAccount::sendReceipt(KMMessage* aMsg)
{
  KConfig* cfg = KMKernel::config();
  bool sendReceipts;

  KConfigGroupSaver saver(cfg, "General");

  sendReceipts = cfg->readBoolEntry("send-receipts", false);
  if (!sendReceipts) return;

  KMMessage *newMsg = aMsg->createDeliveryReceipt();
  if (newMsg) {
    mReceipts.append(newMsg);
    mReceiptTimer.start(0,true);
  }
}

//-----------------------------------------------------------------------------
bool KMAccount::processNewMsg(KMMessage* aMsg)
{
  int rc, processResult;

  assert(aMsg != 0);

  // checks whether we should send delivery receipts
  // and sends them.
  sendReceipt(aMsg);

  // Set status of new messages that are marked as old to read, otherwise
  // the user won't see which messages newly arrived.
  if (aMsg->status()==KMMsgStatusOld)
    aMsg->setStatus(KMMsgStatusUnread);  // -sanders
  //    aMsg->setStatus(KMMsgStatusRead);
  else aMsg->setStatus(KMMsgStatusNew);
/*
QFile fileD0( "testdat_xx-kmaccount-0" );
if( fileD0.open( IO_WriteOnly ) ) {
    QDataStream ds( &fileD0 );
    ds.writeRawBytes( aMsg->asString(), aMsg->asString().length() );
    fileD0.close();  // If data is 0 we just create a zero length file.
}
*/
  // 0==message moved; 1==processing ok, no move; 2==critical error, abort!

  // Automatic resource handling: Give the Groupware code a chance to
  // answer this message automatically, but only if this is a resource
  // account.
  if( resource() ) {
      if( kernel->groupware().incomingResourceMessage( this, aMsg ) )
          // If it was a resource message, we have already answered it.
          aMsg->setStatus( KMMsgStatusReplied );
  }

  processResult = kernel->filterMgr()->process(aMsg,KMFilterMgr::Inbound);
  if (processResult == 2) {
    perror("Critical error: Unable to collect mail (out of space?)");
    KMessageBox::information(0,(i18n("Critical error: "
      "Unable to collect mail (out of space?)")));
    return false;
  }
  else if (processResult == 1)
  {
    kernel->filterMgr()->tempOpenFolder(mFolder);
    rc = mFolder->addMsg(aMsg);
/*
QFile fileD0( "testdat_xx-kmaccount-1" );
if( fileD0.open( IO_WriteOnly ) ) {
    QDataStream ds( &fileD0 );
    ds.writeRawBytes( aMsg->asString(), aMsg->asString().length() );
    fileD0.close();  // If data is 0 we just create a zero length file.
}
*/
    if (rc) {
      perror("failed to add message");
      KMessageBox::information(0, i18n("Failed to add message:\n") +
			       QString(strerror(rc)));
      return false;
    }
    int count = mFolder->count();
    // If count == 1, the message is immediately displayed
    if (count != 1) mFolder->unGetMsg(count - 1);
  }
  return true; //Everything's fine - message has been added by filter  }
}

//-----------------------------------------------------------------------------
void KMAccount::setCheckInterval(int aInterval)
{
  if (aInterval <= 0)
  {
    mInterval = 0;
    deinstallTimer();
  }
  else
  {
    mInterval = aInterval;
    installTimer();
  }
}

//----------------------------------------------------------------------------
void KMAccount::deleteFolderJobs()
{
  mJobList.setAutoDelete(true);
  mJobList.clear();
  mJobList.setAutoDelete(false);
}

//----------------------------------------------------------------------------
void KMAccount::ignoreJobsForMessage( KMMessage* msg )
{
  for( KMFolderJob *it = mJobList.first(); it;
       it = mJobList.next() ) {
    if ((*it).msgList().first() == msg) {
      mJobList.remove( it );
      delete it;
      break;
    }
  }
}

//-----------------------------------------------------------------------------
void KMAccount::setCheckExclude(bool aExclude)
{
  mExclude = aExclude;
}

//-----------------------------------------------------------------------------
void KMAccount::setResource(bool aResource)
{
  mResource = aResource;
}

//-----------------------------------------------------------------------------
void KMAccount::installTimer()
{
  if (mInterval <= 0) return;
  if(!mTimer)
  {
    mTimer = new QTimer();
    connect(mTimer,SIGNAL(timeout()),SLOT(mailCheck()));
  }
  else
  {
    mTimer->stop();
  }
  mTimer->start(mInterval*60000);
}

//-----------------------------------------------------------------------------
void KMAccount::deinstallTimer()
{
  delete mTimer;
  mTimer = 0;
}

//-----------------------------------------------------------------------------
bool KMAccount::runPrecommand(const QString &precommand)
{
  // Run the pre command if there is one
  if ( precommand.isEmpty() )
    return true;

  KMPrecommand precommandProcess(precommand, this);

  KMBroadcastStatus::instance()->setStatusMsg(
      i18n("Executing precommand %1").arg(precommand ));

  connect(&precommandProcess, SIGNAL(finished(bool)),
          SLOT(precommandExited(bool)));

  kdDebug(5006) << "Running precommand " << precommand << endl;
  if (!precommandProcess.start()) return false;

  kapp->enter_loop();

  return mPrecommandSuccess;
}

//-----------------------------------------------------------------------------
void KMAccount::precommandExited(bool success)
{
  mPrecommandSuccess = success;
  kapp->exit_loop();
}

//-----------------------------------------------------------------------------
void KMAccount::mailCheck()
{
 if (mCheckingMail) return;
 mCheckingMail = TRUE;
 kernel->acctMgr()->singleCheckMail(this,false);
 mCheckingMail = FALSE;
}

//-----------------------------------------------------------------------------
void KMAccount::sendReceipts()
{
  // re-entrant
  QValueList<KMMessage*> receipts;
  QValueList<KMMessage*>::Iterator it;
  for(it = mReceipts.begin(); it != mReceipts.end(); ++it)
    receipts.append(*it);
  mReceipts.clear();

  for(it = receipts.begin(); it != receipts.end(); ++it)
    kernel->msgSender()->send(*it);  //might process events
}

//-----------------------------------------------------------------------------
QString KMAccount::encryptStr(const QString &aStr)
{
  QString result;
  for (uint i = 0; i < aStr.length(); i++)
    result += (aStr[i].unicode() < 0x20) ? aStr[i] :
      QChar(0x1001F - aStr[i].unicode());
  return result;
}

//-----------------------------------------------------------------------------
QString KMAccount::importPassword(const QString &aStr)
{
  unsigned int i, val;
  unsigned int len = aStr.length();
  QCString result;
  result.resize(len+1);

  for (i=0; i<len; i++)
  {
    val = aStr[i] - ' ';
    val = (255-' ') - val;
    result[i] = (char)(val + ' ');
  }
  result[i] = '\0';

  return encryptStr(result);
}

/*!
  Registers a new allocated interval in which the resource represented
  by this account is busy.
*/

void KMAccount::addInterval( const QPair<QDateTime,QDateTime>& iv )
{
    mIntervals.append( iv );
}

/*!
  Returns the intervals in which this resource is busy
*/
QValueList<QPair<QDateTime, QDateTime> > KMAccount::intervals() const
{
    return mIntervals;
}

/*!
  Resets all intervals in which this resource is busy.
*/

void KMAccount::clearIntervals()
{
    mIntervals.clear();
}

/*!
  Resets all intervals in which this resource is busy and which are
  entirely in the past.
*/
void KMAccount::clearOldIntervals()
{
    QDateTime now = QDateTime::currentDateTime();
    for( QValueList<QPair<QDateTime, QDateTime> >::iterator it = mIntervals.begin(); it != mIntervals.end(); ++it ) {
        if( (*it).second < now )
            mIntervals.erase( it );
    }
}

void KMAccount::setIntervals( const QValueList<QPair<QDateTime, QDateTime> >& newIntervals )
{
    mIntervals = newIntervals;
}

void KMAccount::invalidateIMAPFolders()
{
  // Default: Don't do anything. The IMAP account will handle it
}

void KMAccount::pseudoAssign( const KMAccount * a ) {
  if ( !a ) return;

  setName( a->name() );
  setCheckInterval( a->checkInterval() );
  setResource( a->resource() );
  setIntervals( a->intervals() );
  setCheckExclude( a->checkExclude() );
  setFolder( a->folder() );
  setPrecommand( a->precommand() );
  setTrash( a->trash() );
}
<commit_msg>Hold on to the groupware functionality until it's in HEAD<commit_after>// KMail Account

#include "kmaccount.h"

#include <config.h>
#include <stdlib.h>
#include <unistd.h>

#include <assert.h>
#include <kapplication.h>

#include <klocale.h>
#include <kmessagebox.h>
#include <kdebug.h>

#include "kmacctmgr.h"
#include "kmacctfolder.h"
#include "kmfoldermgr.h"
#include "kmfiltermgr.h"
#include "kmsender.h"
#include "kmbroadcaststatus.h"
#include "kmmessage.h"

//----------------------
#include "kmaccount.moc"

//-----------------------------------------------------------------------------
KMPrecommand::KMPrecommand(const QString &precommand, QObject *parent)
  : QObject(parent), mPrecommand(precommand)
{
  KMBroadcastStatus::instance()->setStatusMsg(
      i18n("Executing precommand %1").arg(precommand ));

#if KDE_VERSION >= 305
  mPrecommandProcess.setUseShell(true);
#endif
  mPrecommandProcess << precommand;

  connect(&mPrecommandProcess, SIGNAL(processExited(KProcess *)),
          SLOT(precommandExited(KProcess *)));
}

//-----------------------------------------------------------------------------
KMPrecommand::~KMPrecommand()
{
}

//-----------------------------------------------------------------------------
bool KMPrecommand::start()
{
  bool ok = mPrecommandProcess.start( KProcess::NotifyOnExit );
  if (!ok) KMessageBox::error(0, i18n("Couldn't execute precommand '%1'.")
    .arg(mPrecommand));
  return ok;
}

//-----------------------------------------------------------------------------
void KMPrecommand::precommandExited(KProcess *p)
{
  int exitCode = p->normalExit() ? p->exitStatus() : -1;
  if (exitCode)
    KMessageBox::error(0, i18n("The precommand exited with code %1:\n%2")
      .arg(exitCode).arg(strerror(exitCode)));
  emit finished(!exitCode);
}

//-----------------------------------------------------------------------------
KMAccount::KMAccount(KMAcctMgr* aOwner, const QString& aName)
  : mName(aName),
    mTrash(KMKernel::self()->trashFolder()->idString()),
    mOwner(aOwner),
    mFolder(0),
    mTimer(0),
    mInterval(0),
    mResource(false),
    mExclude(false),
    mCheckingMail(false),
    mPrecommandSuccess(true)
{
  assert(aOwner != 0);

  connect(&mReceiptTimer,SIGNAL(timeout()),SLOT(sendReceipts()));
}

void KMAccount::init() {
  mTrash = kernel->trashFolder()->idString();
  mResource = false;
  mExclude = false;
  mInterval = 0;
}

//-----------------------------------------------------------------------------
KMAccount::~KMAccount()
{
  if (!kernel->shuttingDown() && mFolder) mFolder->removeAccount(this);
  if (mTimer) deinstallTimer();
}

//-----------------------------------------------------------------------------
void KMAccount::setName(const QString& aName)
{
  mName = (aName.isEmpty()) ? i18n("Unnamed") : aName;
}

//-----------------------------------------------------------------------------
void KMAccount::clearPasswd()
{
}

//-----------------------------------------------------------------------------
void KMAccount::setFolder(KMFolder* aFolder, bool addAccount)
{
  if(!aFolder)
    {
    kdDebug(5006) << "KMAccount::setFolder() : aFolder == 0" << endl;
    mFolder = 0;
    return;
    }
  mFolder = (KMAcctFolder*)aFolder;
  if (addAccount) mFolder->addAccount(this);
}

//-----------------------------------------------------------------------------
void KMAccount::readConfig(KConfig& config)
{
  QString folderName;

  mFolder = 0;
  folderName = config.readEntry("Folder", "");
  setCheckInterval(config.readNumEntry("check-interval", 0));
  setTrash(config.readEntry("trash", kernel->trashFolder()->idString()));
  setResource(config.readBoolEntry("resource", false) );
  setCheckExclude(config.readBoolEntry("check-exclude", false));
  setPrecommand(config.readEntry("precommand"));

  if (!folderName.isEmpty())
  {
    setFolder(kernel->folderMgr()->findIdString(folderName), true);
  }

  if( mResource ) {
      int numResourceEntries = config.readNumEntry( "numResourceEntries", 0 );
      int count = 0;
      for( int i = 0; i < numResourceEntries; i++, count++ ) {
          QDateTime start = config.readDateTimeEntry( QString( "resource%1-start" ).arg( i ) );
          QDateTime end = config.readDateTimeEntry( QString( "resource%1-end" ).arg( i ) );
          mIntervals.append( qMakePair(start,end) );
      }
  }
}

//-----------------------------------------------------------------------------
void KMAccount::writeConfig(KConfig& config)
{
  config.writeEntry("Type", type());
  config.writeEntry("Name", mName);
  config.writeEntry("Folder", mFolder ? mFolder->idString() : QString::null);
  config.writeEntry("check-interval", mInterval);
  config.writeEntry("resource", mResource);
  config.writeEntry("check-exclude", mExclude);
  config.writeEntry("precommand", mPrecommand);
  config.writeEntry("trash", mTrash);

  // Write the resource management data
  if( mResource ) {
      config.writeEntry("numResourceEntries", mIntervals.count() );
      int count = 0;
      for( QValueList<QPair< QDateTime, QDateTime> >::Iterator it = mIntervals.begin(); it != mIntervals.end(); ++it, count++ ) {
          config.writeEntry( QString( "resource%1-start" ).arg( count ),
                             (*it).first );
          config.writeEntry( QString( "resource%1-end" ).arg( count ),
                             (*it).second );
      }
  }
}

//-----------------------------------------------------------------------------
void KMAccount::sendReceipt(KMMessage* aMsg)
{
  KConfig* cfg = KMKernel::config();
  bool sendReceipts;

  KConfigGroupSaver saver(cfg, "General");

  sendReceipts = cfg->readBoolEntry("send-receipts", false);
  if (!sendReceipts) return;

  KMMessage *newMsg = aMsg->createDeliveryReceipt();
  if (newMsg) {
    mReceipts.append(newMsg);
    mReceiptTimer.start(0,true);
  }
}

//-----------------------------------------------------------------------------
bool KMAccount::processNewMsg(KMMessage* aMsg)
{
  int rc, processResult;

  assert(aMsg != 0);

  // checks whether we should send delivery receipts
  // and sends them.
  sendReceipt(aMsg);

  // Set status of new messages that are marked as old to read, otherwise
  // the user won't see which messages newly arrived.
  if (aMsg->status()==KMMsgStatusOld)
    aMsg->setStatus(KMMsgStatusUnread);  // -sanders
  //    aMsg->setStatus(KMMsgStatusRead);
  else aMsg->setStatus(KMMsgStatusNew);
/*
QFile fileD0( "testdat_xx-kmaccount-0" );
if( fileD0.open( IO_WriteOnly ) ) {
    QDataStream ds( &fileD0 );
    ds.writeRawBytes( aMsg->asString(), aMsg->asString().length() );
    fileD0.close();  // If data is 0 we just create a zero length file.
}
*/
  // 0==message moved; 1==processing ok, no move; 2==critical error, abort!

  // Automatic resource handling: Give the Groupware code a chance to
  // answer this message automatically, but only if this is a resource
  // account.
  if( resource() ) {
#if 0
      if( kernel->groupware().incomingResourceMessage( this, aMsg ) )
          // If it was a resource message, we have already answered it.
          aMsg->setStatus( KMMsgStatusReplied );
#endif
  }

  processResult = kernel->filterMgr()->process(aMsg,KMFilterMgr::Inbound);
  if (processResult == 2) {
    perror("Critical error: Unable to collect mail (out of space?)");
    KMessageBox::information(0,(i18n("Critical error: "
      "Unable to collect mail (out of space?)")));
    return false;
  }
  else if (processResult == 1)
  {
    kernel->filterMgr()->tempOpenFolder(mFolder);
    rc = mFolder->addMsg(aMsg);
/*
QFile fileD0( "testdat_xx-kmaccount-1" );
if( fileD0.open( IO_WriteOnly ) ) {
    QDataStream ds( &fileD0 );
    ds.writeRawBytes( aMsg->asString(), aMsg->asString().length() );
    fileD0.close();  // If data is 0 we just create a zero length file.
}
*/
    if (rc) {
      perror("failed to add message");
      KMessageBox::information(0, i18n("Failed to add message:\n") +
			       QString(strerror(rc)));
      return false;
    }
    int count = mFolder->count();
    // If count == 1, the message is immediately displayed
    if (count != 1) mFolder->unGetMsg(count - 1);
  }
  return true; //Everything's fine - message has been added by filter  }
}

//-----------------------------------------------------------------------------
void KMAccount::setCheckInterval(int aInterval)
{
  if (aInterval <= 0)
  {
    mInterval = 0;
    deinstallTimer();
  }
  else
  {
    mInterval = aInterval;
    installTimer();
  }
}

//----------------------------------------------------------------------------
void KMAccount::deleteFolderJobs()
{
  mJobList.setAutoDelete(true);
  mJobList.clear();
  mJobList.setAutoDelete(false);
}

//----------------------------------------------------------------------------
void KMAccount::ignoreJobsForMessage( KMMessage* msg )
{
  for( KMFolderJob *it = mJobList.first(); it;
       it = mJobList.next() ) {
    if ((*it).msgList().first() == msg) {
      mJobList.remove( it );
      delete it;
      break;
    }
  }
}

//-----------------------------------------------------------------------------
void KMAccount::setCheckExclude(bool aExclude)
{
  mExclude = aExclude;
}

//-----------------------------------------------------------------------------
void KMAccount::setResource(bool aResource)
{
  mResource = aResource;
}

//-----------------------------------------------------------------------------
void KMAccount::installTimer()
{
  if (mInterval <= 0) return;
  if(!mTimer)
  {
    mTimer = new QTimer();
    connect(mTimer,SIGNAL(timeout()),SLOT(mailCheck()));
  }
  else
  {
    mTimer->stop();
  }
  mTimer->start(mInterval*60000);
}

//-----------------------------------------------------------------------------
void KMAccount::deinstallTimer()
{
  delete mTimer;
  mTimer = 0;
}

//-----------------------------------------------------------------------------
bool KMAccount::runPrecommand(const QString &precommand)
{
  // Run the pre command if there is one
  if ( precommand.isEmpty() )
    return true;

  KMPrecommand precommandProcess(precommand, this);

  KMBroadcastStatus::instance()->setStatusMsg(
      i18n("Executing precommand %1").arg(precommand ));

  connect(&precommandProcess, SIGNAL(finished(bool)),
          SLOT(precommandExited(bool)));

  kdDebug(5006) << "Running precommand " << precommand << endl;
  if (!precommandProcess.start()) return false;

  kapp->enter_loop();

  return mPrecommandSuccess;
}

//-----------------------------------------------------------------------------
void KMAccount::precommandExited(bool success)
{
  mPrecommandSuccess = success;
  kapp->exit_loop();
}

//-----------------------------------------------------------------------------
void KMAccount::mailCheck()
{
 if (mCheckingMail) return;
 mCheckingMail = TRUE;
 kernel->acctMgr()->singleCheckMail(this,false);
 mCheckingMail = FALSE;
}

//-----------------------------------------------------------------------------
void KMAccount::sendReceipts()
{
  // re-entrant
  QValueList<KMMessage*> receipts;
  QValueList<KMMessage*>::Iterator it;
  for(it = mReceipts.begin(); it != mReceipts.end(); ++it)
    receipts.append(*it);
  mReceipts.clear();

  for(it = receipts.begin(); it != receipts.end(); ++it)
    kernel->msgSender()->send(*it);  //might process events
}

//-----------------------------------------------------------------------------
QString KMAccount::encryptStr(const QString &aStr)
{
  QString result;
  for (uint i = 0; i < aStr.length(); i++)
    result += (aStr[i].unicode() < 0x20) ? aStr[i] :
      QChar(0x1001F - aStr[i].unicode());
  return result;
}

//-----------------------------------------------------------------------------
QString KMAccount::importPassword(const QString &aStr)
{
  unsigned int i, val;
  unsigned int len = aStr.length();
  QCString result;
  result.resize(len+1);

  for (i=0; i<len; i++)
  {
    val = aStr[i] - ' ';
    val = (255-' ') - val;
    result[i] = (char)(val + ' ');
  }
  result[i] = '\0';

  return encryptStr(result);
}

/*!
  Registers a new allocated interval in which the resource represented
  by this account is busy.
*/

void KMAccount::addInterval( const QPair<QDateTime,QDateTime>& iv )
{
    mIntervals.append( iv );
}

/*!
  Returns the intervals in which this resource is busy
*/
QValueList<QPair<QDateTime, QDateTime> > KMAccount::intervals() const
{
    return mIntervals;
}

/*!
  Resets all intervals in which this resource is busy.
*/

void KMAccount::clearIntervals()
{
    mIntervals.clear();
}

/*!
  Resets all intervals in which this resource is busy and which are
  entirely in the past.
*/
void KMAccount::clearOldIntervals()
{
    QDateTime now = QDateTime::currentDateTime();
    for( QValueList<QPair<QDateTime, QDateTime> >::iterator it = mIntervals.begin(); it != mIntervals.end(); ++it ) {
        if( (*it).second < now )
            mIntervals.erase( it );
    }
}

void KMAccount::setIntervals( const QValueList<QPair<QDateTime, QDateTime> >& newIntervals )
{
    mIntervals = newIntervals;
}

void KMAccount::invalidateIMAPFolders()
{
  // Default: Don't do anything. The IMAP account will handle it
}

void KMAccount::pseudoAssign( const KMAccount * a ) {
  if ( !a ) return;

  setName( a->name() );
  setCheckInterval( a->checkInterval() );
  setResource( a->resource() );
  setIntervals( a->intervals() );
  setCheckExclude( a->checkExclude() );
  setFolder( a->folder() );
  setPrecommand( a->precommand() );
  setTrash( a->trash() );
}
<|endoftext|>


<commit_before>///
/// CameraTag.cpp
/// starlight
///
/// Created by reworks on 28/10/2017.
/// MIT License.
/// Refer to LICENSE.txt for more details.
///

#include "sl/core/World.hpp"
#include "sl/libs/sol2/sol.hpp"
#include "sl/core/ServiceLocator.hpp"
#include "sl/components/TransformComponent.hpp"

#include "CameraTag.hpp"

namespace sl
{
	CameraTag::CameraTag()
	{
		LOG_S(FATAL) << "Tried to construct a default-initialized CameraTag!";
	}

	CameraTag::CameraTag(const sol::table& table)
	{
		m_bounds.m_x = 0;
		m_bounds.m_y = 0;
		m_bounds.m_width = table.get<int>("width");
		m_bounds.m_height = table.get<int>("height");
	}

	CameraTag::CameraTag(const Rect<float, int>& bounds)
		:m_bounds(bounds)
	{
	}

	CameraTag& CameraTag::operator=(const CameraTag &)
	{
		return *this;
	}

	void CameraTag::update(unsigned int playerEntity)
	{
		if (Locator::world->m_currentLevel)
		{
			TransformComponent& tc = Locator::world->m_registry.get<TransformComponent>(playerEntity);

			m_bounds.m_x = (tc.m_rect.m_x + tc.m_rect.m_width / 2) - m_bounds.m_width / 2;
			m_bounds.m_y = (tc.m_rect.m_y + tc.m_rect.m_height / 2) - m_bounds.m_height / 2;

			if (m_bounds.m_x < 0) { m_bounds.m_x = 0; }
			if (m_bounds.m_y < 0) { m_bounds.m_y = 0; }
			if (m_bounds.m_x > Locator::world->m_currentLevel->getBounds().m_width - m_bounds.m_width) { m_bounds.m_x = (float)Locator::world->m_currentLevel->getBounds().m_width - (float)m_bounds.m_width; }
			if (m_bounds.m_y > Locator::world->m_currentLevel->getBounds().m_height - m_bounds.m_height) { m_bounds.m_y = (float)Locator::world->m_currentLevel->getBounds().m_height - (float)m_bounds.m_height; }
		}
	}
}<commit_msg>fixed released build<commit_after>///
/// CameraTag.cpp
/// starlight
///
/// Created by reworks on 28/10/2017.
/// MIT License.
/// Refer to LICENSE.txt for more details.
///

#include "sl/core/World.hpp"
#include "sl/libs/sol2/sol.hpp"
#include "sl/libs/loguru/loguru.hpp"
#include "sl/core/ServiceLocator.hpp"
#include "sl/components/TransformComponent.hpp"

#include "CameraTag.hpp"

namespace sl
{
	CameraTag::CameraTag()
	{
		LOG_S(FATAL) << "Tried to construct a default-initialized CameraTag!";
	}

	CameraTag::CameraTag(const sol::table& table)
	{
		m_bounds.m_x = 0;
		m_bounds.m_y = 0;
		m_bounds.m_width = table.get<int>("width");
		m_bounds.m_height = table.get<int>("height");
	}

	CameraTag::CameraTag(const Rect<float, int>& bounds)
		:m_bounds(bounds)
	{
	}

	CameraTag& CameraTag::operator=(const CameraTag &)
	{
		return *this;
	}

	void CameraTag::update(unsigned int playerEntity)
	{
		if (Locator::world->m_currentLevel)
		{
			TransformComponent& tc = Locator::world->m_registry.get<TransformComponent>(playerEntity);

			m_bounds.m_x = (tc.m_rect.m_x + tc.m_rect.m_width / 2) - m_bounds.m_width / 2;
			m_bounds.m_y = (tc.m_rect.m_y + tc.m_rect.m_height / 2) - m_bounds.m_height / 2;

			if (m_bounds.m_x < 0) { m_bounds.m_x = 0; }
			if (m_bounds.m_y < 0) { m_bounds.m_y = 0; }
			if (m_bounds.m_x > Locator::world->m_currentLevel->getBounds().m_width - m_bounds.m_width) { m_bounds.m_x = (float)Locator::world->m_currentLevel->getBounds().m_width - (float)m_bounds.m_width; }
			if (m_bounds.m_y > Locator::world->m_currentLevel->getBounds().m_height - m_bounds.m_height) { m_bounds.m_y = (float)Locator::world->m_currentLevel->getBounds().m_height - (float)m_bounds.m_height; }
		}
	}
}<|endoftext|>


<commit_before>/***************************************************************************
**
** Copyright (C) 2010, 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (directui@nokia.com)
**
** This file is part of libmeegotouch.
**
** If you have questions regarding the use of this file, please contact
** Nokia at directui@nokia.com.
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation
** and appearing in the file LICENSE.LGPL included in the packaging
** of this file.
**
****************************************************************************/

#include <QGraphicsLinearLayout>
#include <QGraphicsSceneMouseEvent>
#include <MLabel>
#include <MImageWidget>
#include <MSeparator>
#include <MProgressIndicator>

#include <QCoreApplication>
#include <QSizePolicy>

#include "mcontainerview.h"
#include "mcontainerview_p.h"
#include "mcontainerheader_p.h"
#include "mcontainer.h"

#include "mscalableimage.h"
#include "mviewcreator.h"
#include "mtheme.h"

/*
 * layout:
 *
 *   + controller +
 *                |
 *                +- mainLayout +- header -+- headerLayout  +- icon
 *                              |                           |
 *                              |                           +- title
 *                              +- centralWidget            |
 *                                                          +- text
 *                                                          |
 *                                                          +- spinner
 */

MContainerViewPrivate::MContainerViewPrivate()
    : controller(0)
    , headerLayout(0)
    , header(0)
    , separator(0)
    , icon(0) // created only if needed
    , title(0)
    , text(0)
    , background(0)
    , headerPressed(false)
    , progressIndicator(0)
    , q_ptr(0)
{
}

MContainerViewPrivate::~MContainerViewPrivate()
{
    delete icon;
}

void MContainerViewPrivate::init()
{
    controller->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred));

    QGraphicsLinearLayout* mainLayout = new QGraphicsLinearLayout(Qt::Vertical);

    // pack
    mainLayout->setContentsMargins(0, 0, 0, 0);
    mainLayout->setSpacing(0);
    mainLayout->addItem(controller->centralWidget());
    controller->setLayout(mainLayout);
}

/*
 * creates the header by adding a header widget, a layout and
 * labels
 */

void MContainerViewPrivate::createHeader()
{
    Q_Q(MContainerView);

    if (!header) {
        header = new MContainerHeader();

        headerLayout = new QGraphicsLinearLayout(Qt::Horizontal);
        headerLayout->setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum));
        header->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed));
        header->setStyleName(q->style()->headerStyleName());

        headerLayout->setContentsMargins(0, 0, 0, 0);
        headerLayout->setSpacing(0);
        header->setLayout(headerLayout);

        separator = new MSeparator(header, Qt::Horizontal);
        separator->setStyleName(q->style()->separatorStyleName());
        separator->setSizePolicy(QSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred));

        title = new MLabel(header);
        title->setObjectName("MContainerTitle");
        title->setStyleName(q->style()->titleStyleName());

        headerLayout->addItem(separator);
        headerLayout->setAlignment(separator, Qt::AlignVCenter | Qt::AlignLeft);
        separator->show();

        headerLayout->addItem(title);
        headerLayout->setAlignment(title,  Qt::AlignVCenter | Qt::AlignRight);
        title->show();

        // insert icon if available
        if (icon) {
            headerLayout->insertItem(1, icon);
            headerLayout->setAlignment(icon,  Qt::AlignVCenter | Qt::AlignLeft);
            icon->show();
        }

        QGraphicsLinearLayout* mainLayout = dynamic_cast<QGraphicsLinearLayout*>(controller->layout());

        if (mainLayout)
            mainLayout->insertItem(0, header);
    }
}

/*
 * delete header, mainLayout will now reuse the space previously
 * demanded by the header
 */

void MContainerViewPrivate::removeHeader()
{
    if (header) {
        // Remove the item from the layout. deleteLater() will NOT remove it properly but leaves the layout size incorrect and the item on the scene. See bug #231743.
        QGraphicsLinearLayout* mainLayout = dynamic_cast<QGraphicsLinearLayout*>(controller->layout());
        if (mainLayout)
            mainLayout->removeItem(header);

        /*
           Delete header and its children. The header must be deleted with
           deleteLater() as this gets called from a slot. However, the item
           MUST be removed from the layout before this.
        */
        header->deleteLater();
        header = 0;
        title = 0;
        text = 0;
        icon = 0;
        separator = 0;
        progressIndicator = 0;
        headerLayout = 0;
    }
}

void MContainerViewPrivate::setupTextLabel()
{
    if (!text)
        text = new MLabel();

    text->setAlignment(Qt::AlignVCenter | Qt::AlignRight);

    if (header) {
        headerLayout->addItem(text);
        headerLayout->setAlignment(text,  Qt::AlignVCenter | Qt::AlignRight);
        text->show();
    }
}

/*
 * create icon if it doesn't exist
 */

void MContainerViewPrivate::setupIcon(const QSize &size)
{
    if (!icon)
        icon = new MImageWidget;

    icon->setImage(controller->model()->icon(), size);
    icon->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);

    // insert it if header is available
    if (header) {
        headerLayout->insertItem(1, icon);
        headerLayout->setAlignment(icon,  Qt::AlignVCenter | Qt::AlignLeft);
        icon->show();
    }
}

void MContainerViewPrivate::createProgressIndicator()
{
    Q_Q(MContainerView);

    if (!progressIndicator)
        progressIndicator = new MProgressIndicator;
    progressIndicator->setUnknownDuration(true);
    progressIndicator->setStyleName(q->style()->progressIndicatorStyleName());
}

void MContainerViewPrivate::layoutProgressIndicator()
{
    if (header) {
        headerLayout->insertItem(1, progressIndicator);
        headerLayout->setAlignment(progressIndicator,  Qt::AlignVCenter | Qt::AlignRight);
        progressIndicator->show();
    }
}

MContainerView::MContainerView(MContainer *controller) :
    MWidgetView(*new MContainerViewPrivate, controller)
{
    Q_D(MContainerView);
    d->q_ptr = this;
    d->controller = controller;

    // setup main infrastructure
    d->init();

    connect(this, SIGNAL(headerClicked()), controller, SIGNAL(headerClicked()));
}

MContainerView::MContainerView(MContainerViewPrivate &dd, MContainer *controller) :
    MWidgetView(dd, controller)
{
    Q_D(MContainerView);
    d->q_ptr = this;
    d->controller = controller;

    d->init();

    connect(this, SIGNAL(headerClicked()), controller, SIGNAL(headerClicked()));
}

MContainerView::~MContainerView()
{
}

void MContainerView::drawBackground(QPainter *painter, const QStyleOptionGraphicsItem *option) const
{
    Q_UNUSED(option);
    Q_D(const MContainerView);

    // draw the background
    qreal oldOpacity = painter->opacity();
    painter->setOpacity(style()->backgroundOpacity() * effectiveOpacity());
    if (style()->backgroundImage()) {
        const QSizeF _size = d->controller->centralWidget()->geometry().size();
        const qreal headerHeight = d->header ? d->header->size().height() : 0;
        style()->backgroundImage()->draw(0.0, headerHeight, _size.width(), _size.height(), painter);
    }
    painter->setOpacity(oldOpacity);
}

void MContainerView::applyStyle()
{
    Q_D(MContainerView);

    MWidgetView::applyStyle();

    if (d->separator) {
        d->separator->setStyleName(style()->separatorStyleName());
    }

    if (d->title) {
        d->title->setStyleName(style()->titleStyleName());
    }

    if (d->progressIndicator) {
        d->progressIndicator->setStyleName(style()->progressIndicatorStyleName());
    }

    if (d->header) {
        d->header->setStyleName(style()->headerStyleName());
    }

    //  get background from style
    d->background = style()->backgroundImage();
}

void MContainerView::updateData(const QList<const char *>& modifications)
{
    Q_D(MContainerView);
    MWidgetView::updateData(modifications);

    const MContainerModel *model = MContainerView::model();

    // make sure the header exists before icons or centralWidget are set
    // or modified
    if (model->headerVisible()) {
        d->createHeader();

        QObject::connect(d->header, SIGNAL(pressed()), this, SLOT(headerPressed()));
        QObject::connect(d->header, SIGNAL(released()), this, SLOT(headerReleased()));
        QObject::connect(d->header, SIGNAL(moved()), this, SLOT(headerMoved()));
        QObject::connect(d->header, SIGNAL(canceled()), this, SLOT(headerCanceled()));

        // update labels
        d->title->setText(model->title());

        // create the text label if necessary
        if (!model->text().isEmpty()) {
            d->setupTextLabel();
            d->text->setText(model->text());
        }

        // make sure the icon is present if headerVisible() changed at runtime
        if (!model->icon().isEmpty())
            d->setupIcon(style()->iconSize());

        // same for the progress indicator
        if (model->progressIndicatorVisible()) {
            d->createProgressIndicator();
            d->layoutProgressIndicator();
        }

    } else {
        d->removeHeader();
    }

    const char *member;
    foreach(member, modifications) {
        if (member == MContainerModel::CentralWidget) {
            QGraphicsLinearLayout* mainLayout = dynamic_cast<QGraphicsLinearLayout*>(d->controller->layout());
            if (mainLayout) {
                // Remove the old central widget but don't destroy since the controller does it
                mainLayout->removeAt(mainLayout->count() - 1);
                // Add the new central widget
                mainLayout->addItem(d->controller->centralWidget());
            }
            // icon value changed
        } else if (member == MContainerModel::Icon) {
            // set new icon
            if (!model->icon().isEmpty()) {
                d->setupIcon(style()->iconSize());
            } else {
                d->headerLayout->removeItem(d->icon);
                d->icon->hide();
            }
        } else if (member == MContainerModel::ProgressIndicatorVisible) {
            if (model->progressIndicatorVisible()) {
                d->createProgressIndicator();
                d->layoutProgressIndicator();
            } else {
                delete d->progressIndicator;
                d->progressIndicator = 0;
            }
        }
    }

    // update visuals
    update();
}

void MContainerView::setupModel()
{
    Q_D(MContainerView);
    MWidgetView::setupModel();

    // initially creating the header if defined in the model
    if (model()->headerVisible()) {
        d->createHeader();

        QObject::connect(d->header, SIGNAL(pressed()), this, SLOT(headerPressed()));
        QObject::connect(d->header, SIGNAL(released()), this, SLOT(headerReleased()));

        d->title->setText(model()->title());
        if (!model()->text().isEmpty())
            d->text->setText(model()->text());

        // create icon if it is set to be shown by the model
        if (!model()->icon().isEmpty())
            d->setupIcon(style()->iconSize());

    }

    int spacing = style()->internalItemSpacing();
    int margin = style()->internalMargins();

    // In case of strange or missing values while reading css
    if (spacing < 0 || spacing > 100)
        spacing = 0;
    if (margin < 0 || margin > 100)
        margin = 0;

    QGraphicsLinearLayout* mainLayout = dynamic_cast<QGraphicsLinearLayout*>(d->controller->layout());
    if (mainLayout) {
        mainLayout->setContentsMargins(margin, margin, margin, margin);
        mainLayout->setSpacing(spacing);
        mainLayout->addItem(d->controller->centralWidget());
    }

    if (model()->progressIndicatorVisible()) {
        d->createProgressIndicator();
        d->layoutProgressIndicator();
    }
}

void MContainerView::headerMoved()
{
    Q_D(MContainerView);

    if (d->headerPressed) {
        d->headerPressed = false;
        update();
    }
}

void MContainerView::headerCanceled()
{
    Q_D(MContainerView);

    if (d->headerPressed) {
        d->headerPressed = false;
        update();
    }
}

void MContainerView::headerPressed()
{
    Q_D(MContainerView);
    d->headerPressed = true;
}

void MContainerView::headerReleased()
{
    Q_D(MContainerView);

    if (d->headerPressed) {
        emit headerClicked();
        d->headerPressed = false;
        update();
    }
}

// bind view and controller together
M_REGISTER_VIEW_NEW(MContainerView, MContainer)
<commit_msg>Fixes: NB#258052 - MContainer and instantaneous bad position of progress indicator after using toggleProgressIndicatorVisible()<commit_after>/***************************************************************************
**
** Copyright (C) 2010, 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (directui@nokia.com)
**
** This file is part of libmeegotouch.
**
** If you have questions regarding the use of this file, please contact
** Nokia at directui@nokia.com.
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation
** and appearing in the file LICENSE.LGPL included in the packaging
** of this file.
**
****************************************************************************/

#include <QGraphicsLinearLayout>
#include <QGraphicsSceneMouseEvent>
#include <MLabel>
#include <MImageWidget>
#include <MSeparator>
#include <MProgressIndicator>

#include <QCoreApplication>
#include <QSizePolicy>

#include "mcontainerview.h"
#include "mcontainerview_p.h"
#include "mcontainerheader_p.h"
#include "mcontainer.h"

#include "mscalableimage.h"
#include "mviewcreator.h"
#include "mtheme.h"

/*
 * layout:
 *
 *   + controller +
 *                |
 *                +- mainLayout +- header -+- headerLayout  +- icon
 *                              |                           |
 *                              |                           +- title
 *                              +- centralWidget            |
 *                                                          +- text
 *                                                          |
 *                                                          +- spinner
 */

MContainerViewPrivate::MContainerViewPrivate()
    : controller(0)
    , headerLayout(0)
    , header(0)
    , separator(0)
    , icon(0) // created only if needed
    , title(0)
    , text(0)
    , background(0)
    , headerPressed(false)
    , progressIndicator(0)
    , q_ptr(0)
{
}

MContainerViewPrivate::~MContainerViewPrivate()
{
    delete icon;
}

void MContainerViewPrivate::init()
{
    controller->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred));

    QGraphicsLinearLayout* mainLayout = new QGraphicsLinearLayout(Qt::Vertical);

    // pack
    mainLayout->setContentsMargins(0, 0, 0, 0);
    mainLayout->setSpacing(0);
    mainLayout->addItem(controller->centralWidget());
    controller->setLayout(mainLayout);
}

/*
 * creates the header by adding a header widget, a layout and
 * labels
 */

void MContainerViewPrivate::createHeader()
{
    Q_Q(MContainerView);

    if (!header) {
        header = new MContainerHeader();

        headerLayout = new QGraphicsLinearLayout(Qt::Horizontal);
        headerLayout->setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum));
        header->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed));
        header->setStyleName(q->style()->headerStyleName());

        headerLayout->setContentsMargins(0, 0, 0, 0);
        headerLayout->setSpacing(0);
        header->setLayout(headerLayout);

        separator = new MSeparator(header, Qt::Horizontal);
        separator->setStyleName(q->style()->separatorStyleName());
        separator->setSizePolicy(QSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred));

        title = new MLabel(header);
        title->setObjectName("MContainerTitle");
        title->setStyleName(q->style()->titleStyleName());

        headerLayout->addItem(separator);
        headerLayout->setAlignment(separator, Qt::AlignVCenter | Qt::AlignLeft);
        separator->show();

        headerLayout->addItem(title);
        headerLayout->setAlignment(title,  Qt::AlignVCenter | Qt::AlignRight);
        title->show();

        // insert icon if available
        if (icon) {
            headerLayout->insertItem(1, icon);
            headerLayout->setAlignment(icon,  Qt::AlignVCenter | Qt::AlignLeft);
            icon->show();
        }

        QGraphicsLinearLayout* mainLayout = dynamic_cast<QGraphicsLinearLayout*>(controller->layout());

        if (mainLayout)
            mainLayout->insertItem(0, header);
    }
}

/*
 * delete header, mainLayout will now reuse the space previously
 * demanded by the header
 */

void MContainerViewPrivate::removeHeader()
{
    if (header) {
        // Remove the item from the layout. deleteLater() will NOT remove it properly but leaves the layout size incorrect and the item on the scene. See bug #231743.
        QGraphicsLinearLayout* mainLayout = dynamic_cast<QGraphicsLinearLayout*>(controller->layout());
        if (mainLayout)
            mainLayout->removeItem(header);

        /*
           Delete header and its children. The header must be deleted with
           deleteLater() as this gets called from a slot. However, the item
           MUST be removed from the layout before this.
        */
        header->deleteLater();
        header = 0;
        title = 0;
        text = 0;
        icon = 0;
        separator = 0;
        progressIndicator = 0;
        headerLayout = 0;
    }
}

void MContainerViewPrivate::setupTextLabel()
{
    if (!text)
        text = new MLabel();

    text->setAlignment(Qt::AlignVCenter | Qt::AlignRight);

    if (header) {
        headerLayout->addItem(text);
        headerLayout->setAlignment(text,  Qt::AlignVCenter | Qt::AlignRight);
        text->show();
    }
}

/*
 * create icon if it doesn't exist
 */

void MContainerViewPrivate::setupIcon(const QSize &size)
{
    if (!icon)
        icon = new MImageWidget;

    icon->setImage(controller->model()->icon(), size);
    icon->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);

    // insert it if header is available
    if (header) {
        headerLayout->insertItem(1, icon);
        headerLayout->setAlignment(icon,  Qt::AlignVCenter | Qt::AlignLeft);
        icon->show();
    }
}

void MContainerViewPrivate::createProgressIndicator()
{
    Q_Q(MContainerView);

    if (!progressIndicator)
        progressIndicator = new MProgressIndicator;
    progressIndicator->setUnknownDuration(true);
    progressIndicator->setStyleName(q->style()->progressIndicatorStyleName());
}

void MContainerViewPrivate::layoutProgressIndicator()
{
    if (header) {
        headerLayout->insertItem(1, progressIndicator);
        headerLayout->setAlignment(progressIndicator,  Qt::AlignVCenter | Qt::AlignRight);

        // otherwise it will be shown on the top left for an instant before
        // settling down on its correct position.
        headerLayout->activate();

        progressIndicator->show();
    }
}

MContainerView::MContainerView(MContainer *controller) :
    MWidgetView(*new MContainerViewPrivate, controller)
{
    Q_D(MContainerView);
    d->q_ptr = this;
    d->controller = controller;

    // setup main infrastructure
    d->init();

    connect(this, SIGNAL(headerClicked()), controller, SIGNAL(headerClicked()));
}

MContainerView::MContainerView(MContainerViewPrivate &dd, MContainer *controller) :
    MWidgetView(dd, controller)
{
    Q_D(MContainerView);
    d->q_ptr = this;
    d->controller = controller;

    d->init();

    connect(this, SIGNAL(headerClicked()), controller, SIGNAL(headerClicked()));
}

MContainerView::~MContainerView()
{
}

void MContainerView::drawBackground(QPainter *painter, const QStyleOptionGraphicsItem *option) const
{
    Q_UNUSED(option);
    Q_D(const MContainerView);

    // draw the background
    qreal oldOpacity = painter->opacity();
    painter->setOpacity(style()->backgroundOpacity() * effectiveOpacity());
    if (style()->backgroundImage()) {
        const QSizeF _size = d->controller->centralWidget()->geometry().size();
        const qreal headerHeight = d->header ? d->header->size().height() : 0;
        style()->backgroundImage()->draw(0.0, headerHeight, _size.width(), _size.height(), painter);
    }
    painter->setOpacity(oldOpacity);
}

void MContainerView::applyStyle()
{
    Q_D(MContainerView);

    MWidgetView::applyStyle();

    if (d->separator) {
        d->separator->setStyleName(style()->separatorStyleName());
    }

    if (d->title) {
        d->title->setStyleName(style()->titleStyleName());
    }

    if (d->progressIndicator) {
        d->progressIndicator->setStyleName(style()->progressIndicatorStyleName());
    }

    if (d->header) {
        d->header->setStyleName(style()->headerStyleName());
    }

    //  get background from style
    d->background = style()->backgroundImage();
}

void MContainerView::updateData(const QList<const char *>& modifications)
{
    Q_D(MContainerView);
    MWidgetView::updateData(modifications);

    const MContainerModel *model = MContainerView::model();

    // make sure the header exists before icons or centralWidget are set
    // or modified
    if (model->headerVisible()) {
        d->createHeader();

        QObject::connect(d->header, SIGNAL(pressed()), this, SLOT(headerPressed()));
        QObject::connect(d->header, SIGNAL(released()), this, SLOT(headerReleased()));
        QObject::connect(d->header, SIGNAL(moved()), this, SLOT(headerMoved()));
        QObject::connect(d->header, SIGNAL(canceled()), this, SLOT(headerCanceled()));

        // update labels
        d->title->setText(model->title());

        // create the text label if necessary
        if (!model->text().isEmpty()) {
            d->setupTextLabel();
            d->text->setText(model->text());
        }

        // make sure the icon is present if headerVisible() changed at runtime
        if (!model->icon().isEmpty())
            d->setupIcon(style()->iconSize());

        // same for the progress indicator
        if (model->progressIndicatorVisible()) {
            d->createProgressIndicator();
            d->layoutProgressIndicator();
        }

    } else {
        d->removeHeader();
    }

    const char *member;
    foreach(member, modifications) {
        if (member == MContainerModel::CentralWidget) {
            QGraphicsLinearLayout* mainLayout = dynamic_cast<QGraphicsLinearLayout*>(d->controller->layout());
            if (mainLayout) {
                // Remove the old central widget but don't destroy since the controller does it
                mainLayout->removeAt(mainLayout->count() - 1);
                // Add the new central widget
                mainLayout->addItem(d->controller->centralWidget());
            }
            // icon value changed
        } else if (member == MContainerModel::Icon) {
            // set new icon
            if (!model->icon().isEmpty()) {
                d->setupIcon(style()->iconSize());
            } else {
                d->headerLayout->removeItem(d->icon);
                d->icon->hide();
            }
        } else if (member == MContainerModel::ProgressIndicatorVisible) {
            if (model->progressIndicatorVisible()) {
                d->createProgressIndicator();
                d->layoutProgressIndicator();
            } else {
                delete d->progressIndicator;
                d->progressIndicator = 0;
            }
        }
    }

    // update visuals
    update();
}

void MContainerView::setupModel()
{
    Q_D(MContainerView);
    MWidgetView::setupModel();

    // initially creating the header if defined in the model
    if (model()->headerVisible()) {
        d->createHeader();

        QObject::connect(d->header, SIGNAL(pressed()), this, SLOT(headerPressed()));
        QObject::connect(d->header, SIGNAL(released()), this, SLOT(headerReleased()));

        d->title->setText(model()->title());
        if (!model()->text().isEmpty())
            d->text->setText(model()->text());

        // create icon if it is set to be shown by the model
        if (!model()->icon().isEmpty())
            d->setupIcon(style()->iconSize());

    }

    int spacing = style()->internalItemSpacing();
    int margin = style()->internalMargins();

    // In case of strange or missing values while reading css
    if (spacing < 0 || spacing > 100)
        spacing = 0;
    if (margin < 0 || margin > 100)
        margin = 0;

    QGraphicsLinearLayout* mainLayout = dynamic_cast<QGraphicsLinearLayout*>(d->controller->layout());
    if (mainLayout) {
        mainLayout->setContentsMargins(margin, margin, margin, margin);
        mainLayout->setSpacing(spacing);
        mainLayout->addItem(d->controller->centralWidget());
    }

    if (model()->progressIndicatorVisible()) {
        d->createProgressIndicator();
        d->layoutProgressIndicator();
    }
}

void MContainerView::headerMoved()
{
    Q_D(MContainerView);

    if (d->headerPressed) {
        d->headerPressed = false;
        update();
    }
}

void MContainerView::headerCanceled()
{
    Q_D(MContainerView);

    if (d->headerPressed) {
        d->headerPressed = false;
        update();
    }
}

void MContainerView::headerPressed()
{
    Q_D(MContainerView);
    d->headerPressed = true;
}

void MContainerView::headerReleased()
{
    Q_D(MContainerView);

    if (d->headerPressed) {
        emit headerClicked();
        d->headerPressed = false;
        update();
    }
}

// bind view and controller together
M_REGISTER_VIEW_NEW(MContainerView, MContainer)
<|endoftext|>