<commit_before>/*
 * Xdg.cpp
 *
 * Copyright (C) 2020 by RStudio, PBC
 *
 * Unless you have received this program directly from RStudio pursuant
 * to the terms of a commercial license agreement with RStudio, then
 * this program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

#ifdef _WIN32
#include <Windows.h>
#include <ShlObj_core.h>
#include <KnownFolders.h>
#endif

#include <core/Algorithm.hpp>
#include <shared_core/SafeConvert.hpp>

#include <core/system/Environment.hpp>
#include <core/system/System.hpp>
#include <core/system/Xdg.hpp>

namespace rstudio {
namespace core {
namespace system {
namespace xdg {
namespace {

FilePath resolveXdgDir(const std::string& envVar,
#ifdef _WIN32
      const GUID windowsFolderId,
#endif
      const std::string& defaultDir,
      const boost::optional<std::string>& user,
      const boost::optional<FilePath>& homeDir)
{
   FilePath xdgHome;
   std::string env = getenv(envVar);
   if (env.empty())
   {
      // No root specified for xdg home; we will need to generate one.
#ifdef _WIN32
      // On Windows, the default path is in Application Data/Roaming.
      wchar_t *path = nullptr;
      HRESULT hr = ::SHGetKnownFolderPath(
            windowsFolderId,
            0,
            nullptr, // current user
            &path);

      if (hr == S_OK)
      {
         xdgHome = FilePath(std::wstring(path));
      }
      else
      {
         LOG_ERROR_MESSAGE("Unable to retrieve app settings path. HRESULT:  " +
                           safe_convert::numberToString(hr));
      }

      // Free memory if allocated
      if (path != nullptr)
      {
         ::CoTaskMemFree(path);
      }

#endif
      if (xdgHome.isEmpty())
      {
         // Use the default subdir for POSIX. We also use this folder as a fallback on Windows
         //if we couldn't read the app settings path.
         xdgHome = FilePath(defaultDir);
      }
   }
   else
   {
      // We have a manually specified xdg directory from an environment variable.
      xdgHome = FilePath(env);
   }

   // expand HOME and USER if given
   core::system::Options environment;
   core::system::setenv(&environment, "HOME",
                        homeDir ? homeDir->getAbsolutePath() :
                                  userHomePath().getAbsolutePath());
   core::system::setenv(&environment, "USER",
                        user ? *user : username());
   std::string expanded = core::system::expandEnvVars(environment, xdgHome.getAbsolutePath());

   // resolve aliases in the path
   xdgHome = FilePath::resolveAliasedPath(expanded, homeDir ? *homeDir : userHomePath());

   return xdgHome.completePath(
#ifdef _WIN32
      "RStudio"
#else
      "rstudio"
#endif
   );
}

} // anonymous namespace

FilePath userConfigDir(
        const boost::optional<std::string>& user,
        const boost::optional<FilePath>& homeDir)
{
   return resolveXdgDir("XDG_CONFIG_HOME",
#ifdef _WIN32
         FOLDERID_RoamingAppData,
#endif
         "~/.config",
         user,
         homeDir
   );
}

FilePath userDataDir(
        const boost::optional<std::string>& user,
        const boost::optional<FilePath>& homeDir)
{
   return resolveXdgDir("XDG_DATA_HOME",
#ifdef _WIN32
         FOLDERID_LocalAppData,
#endif
         "~/.local/share",
         user,
         homeDir
   );
}

FilePath systemConfigDir()
{
#ifndef _WIN32
   // On POSIX operating systems, it's possible to specify multiple config directories.
    // We have to select one, so read the list and take the first one that contains an
    // "rstudio" folder.
   std::string env = getenv("XDG_CONFIG_DIRS");
   if (env.find_first_of(":") != std::string::npos)
   {
      std::vector<std::string> dirs = algorithm::split(env, ":");
      for (const std::string& dir: dirs)
      {
         FilePath resolved = FilePath(dir).completePath("rstudio");
         if (resolved.exists())
         {
            return resolved;
         }
      }
   }
#endif
   return resolveXdgDir("XDG_CONFIG_DIRS",
#ifdef _WIN32
         FOLDERID_ProgramData,
#endif
         "/etc",
         boost::none,  // no specific user
         boost::none   // no home folder resolution
   );
}

FilePath systemConfigFile(const std::string& filename)
{
#ifdef _WIN32
    // Passthrough on Windows
    return systemConfigDir().completeChildPath(filename);
#else
   // On POSIX, check for a search path.
   std::string env = getenv("XDG_CONFIG_DIRS");
   if (env.find_first_of(":") != std::string::npos)
   {
      // This is a search path; check each element for the file.
      std::vector<std::string> dirs = algorithm::split(env, ":");
      for (const std::string& dir: dirs)
      {
         FilePath resolved = FilePath(dir).completePath("rstudio")
                 .completeChildPath(filename);
         if (resolved.exists())
         {
            return resolved;
         }
      }
   }

   // We didn't find the file on the search path, so return the location where
   // we expected to find it.
   return systemConfigDir().completeChildPath(filename);
#endif
}

void forwardXdgEnvVars(Options *pEnvironment)
{
   // forward relevant XDG environment variables (i.e. all those we respect above)
   for (auto&& xdgVar: {"XDG_CONFIG_HOME", "XDG_CONFIG_DIRS",
                        "XDG_DATA_HOME",   "XDG_DATA_DIRS"})
   {
      // only forward value if non-empty; avoid overwriting a previously set
      // value with an empty one
      std::string val = core::system::getenv(xdgVar);
      if (!val.empty())
      {
         // warn if we're changing values; we typically are forwarding values in
         // order to ensure a consistent view of configuration and state across
         // RStudio processes, which merits overwriting, but it's also hard to
         // imagine that these vars would be set unintentionally in the existing
         // environment.
         std::string oldVal = core::system::getenv(*pEnvironment, xdgVar);
         if (!oldVal.empty() && oldVal != val)
         {
             LOG_WARNING_MESSAGE("Overriding " + std::string(xdgVar) +
                                 ": '" + oldVal + "' => '" + val + "'");
         }
         core::system::setenv(pEnvironment, xdgVar, val);
      }
   }
}

} // namespace xdg
} // namespace system
} // namespace core
} // namespace rstudio

<commit_msg>add a check for writeability to userConfigDir<commit_after>/*
 * Xdg.cpp
 *
 * Copyright (C) 2020 by RStudio, PBC
 *
 * Unless you have received this program directly from RStudio pursuant
 * to the terms of a commercial license agreement with RStudio, then
 * this program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

#ifdef _WIN32
#include <Windows.h>
#include <ShlObj_core.h>
#include <KnownFolders.h>
#endif

#include <core/Algorithm.hpp>
#include <core/system/Environment.hpp>
#include <core/system/System.hpp>
#include <core/system/Xdg.hpp>

#include <shared_core/SafeConvert.hpp>
#include <shared_core/system/User.hpp>

namespace rstudio {
namespace core {
namespace system {
namespace xdg {
namespace {

FilePath resolveXdgDir(const std::string& envVar,
#ifdef _WIN32
      const GUID windowsFolderId,
#endif
      const std::string& defaultDir,
      const boost::optional<std::string>& user,
      const boost::optional<FilePath>& homeDir)
{
   FilePath xdgHome;
   std::string env = getenv(envVar);
   if (env.empty())
   {
      // No root specified for xdg home; we will need to generate one.
#ifdef _WIN32
      // On Windows, the default path is in Application Data/Roaming.
      wchar_t *path = nullptr;
      HRESULT hr = ::SHGetKnownFolderPath(
            windowsFolderId,
            0,
            nullptr, // current user
            &path);

      if (hr == S_OK)
      {
         xdgHome = FilePath(std::wstring(path));
      }
      else
      {
         LOG_ERROR_MESSAGE("Unable to retrieve app settings path. HRESULT:  " +
                           safe_convert::numberToString(hr));
      }

      // Free memory if allocated
      if (path != nullptr)
      {
         ::CoTaskMemFree(path);
      }

#endif
      if (xdgHome.isEmpty())
      {
         // Use the default subdir for POSIX. We also use this folder as a fallback on Windows
         //if we couldn't read the app settings path.
         xdgHome = FilePath(defaultDir);
      }
   }
   else
   {
      // We have a manually specified xdg directory from an environment variable.
      xdgHome = FilePath(env);
   }

   // expand HOME and USER if given
   core::system::Options environment;
   core::system::setenv(&environment, "HOME",
                        homeDir ? homeDir->getAbsolutePath() :
                                  userHomePath().getAbsolutePath());
   core::system::setenv(&environment, "USER",
                        user ? *user : username());
   std::string expanded = core::system::expandEnvVars(environment, xdgHome.getAbsolutePath());

   // resolve aliases in the path
   xdgHome = FilePath::resolveAliasedPath(expanded, homeDir ? *homeDir : userHomePath());

   return xdgHome.completePath(
#ifdef _WIN32
      "RStudio"
#else
      "rstudio"
#endif
   );
}

} // anonymous namespace

FilePath userConfigDir(
   const boost::optional<std::string>& user,
   const boost::optional<FilePath>& homeDir)
{
   FilePath confDir = resolveXdgDir("XDG_CONFIG_HOME",
#ifdef _WIN32
         FOLDERID_RoamingAppData,
#endif
         "~/.config",
         user,
         homeDir
   );

   Error permError;
   Error error = confDir.ensureDirectory();
   if (!error)
   {
      // Test permissions here.
      error = confDir.testWritePermissions();
      if (error)
      {
         permError = Error(
            error.getName(),
            error.getCode(),
            "Missing write permissions to " + confDir.getAbsolutePath() + ". Some features may not work correctly.",
            ERROR_LOCATION);

         system::User currUser;
         error = system::User::getUserFromIdentifier(system::username(), currUser);
         if (!error)
            error = confDir.changeOwnership(currUser, true);
      }
   }

   if (error)
   {
      std::string message;
      message.append("Encounterd an issue while testing config dir \"")
         .append(confDir.getAbsolutePath())
         .append(":\n  ")
         .append(error.asString());
      if (permError)
         message.append("\n  ").append(permError.asString());

      log::logWarningMessage(message, ERROR_LOCATION);
   }

   return confDir;
}

FilePath userDataDir(
        const boost::optional<std::string>& user,
        const boost::optional<FilePath>& homeDir)
{
   return resolveXdgDir("XDG_DATA_HOME",
#ifdef _WIN32
         FOLDERID_LocalAppData,
#endif
         "~/.local/share",
         user,
         homeDir
   );
}

FilePath systemConfigDir()
{
#ifndef _WIN32
   // On POSIX operating systems, it's possible to specify multiple config directories.
    // We have to select one, so read the list and take the first one that contains an
    // "rstudio" folder.
   std::string env = getenv("XDG_CONFIG_DIRS");
   if (env.find_first_of(":") != std::string::npos)
   {
      std::vector<std::string> dirs = algorithm::split(env, ":");
      for (const std::string& dir: dirs)
      {
         FilePath resolved = FilePath(dir).completePath("rstudio");
         if (resolved.exists())
         {
            return resolved;
         }
      }
   }
#endif
   return resolveXdgDir("XDG_CONFIG_DIRS",
#ifdef _WIN32
         FOLDERID_ProgramData,
#endif
         "/etc",
         boost::none,  // no specific user
         boost::none   // no home folder resolution
   );
}

FilePath systemConfigFile(const std::string& filename)
{
#ifdef _WIN32
    // Passthrough on Windows
    return systemConfigDir().completeChildPath(filename);
#else
   // On POSIX, check for a search path.
   std::string env = getenv("XDG_CONFIG_DIRS");
   if (env.find_first_of(":") != std::string::npos)
   {
      // This is a search path; check each element for the file.
      std::vector<std::string> dirs = algorithm::split(env, ":");
      for (const std::string& dir: dirs)
      {
         FilePath resolved = FilePath(dir).completePath("rstudio")
                 .completeChildPath(filename);
         if (resolved.exists())
         {
            return resolved;
         }
      }
   }

   // We didn't find the file on the search path, so return the location where
   // we expected to find it.
   return systemConfigDir().completeChildPath(filename);
#endif
}

void forwardXdgEnvVars(Options *pEnvironment)
{
   // forward relevant XDG environment variables (i.e. all those we respect above)
   for (auto&& xdgVar: {"XDG_CONFIG_HOME", "XDG_CONFIG_DIRS",
                        "XDG_DATA_HOME",   "XDG_DATA_DIRS"})
   {
      // only forward value if non-empty; avoid overwriting a previously set
      // value with an empty one
      std::string val = core::system::getenv(xdgVar);
      if (!val.empty())
      {
         // warn if we're changing values; we typically are forwarding values in
         // order to ensure a consistent view of configuration and state across
         // RStudio processes, which merits overwriting, but it's also hard to
         // imagine that these vars would be set unintentionally in the existing
         // environment.
         std::string oldVal = core::system::getenv(*pEnvironment, xdgVar);
         if (!oldVal.empty() && oldVal != val)
         {
             LOG_WARNING_MESSAGE("Overriding " + std::string(xdgVar) +
                                 ": '" + oldVal + "' => '" + val + "'");
         }
         core::system::setenv(pEnvironment, xdgVar, val);
      }
   }
}

} // namespace xdg
} // namespace system
} // namespace core
} // namespace rstudio

<|endoftext|>


<commit_before>// Licensed under the Apache License, Version 2.0.
// Author: Jin Qing (http://blog.csdn.net/jq0123)

#include <grpc_cb/status.h>

namespace grpc_cb {

const Status& Status::OK = Status();
const Status& Status::CANCELLED = Status(GRPC_STATUS_CANCELLED, "");
const Status& Status::UNIMPLEMENTED = Status(GRPC_STATUS_UNIMPLEMENTED, "");

Status Status::InternalError(const std::string& details) {
  return Status(GRPC_STATUS_INTERNAL, details);
}

void Status::SetInternalError(const std::string& error_msg) {
  code_ = GRPC_STATUS_INTERNAL;
  details_ = error_msg;
}

}  // namespace grpc_cb
<commit_msg>Set Status detail.<commit_after>// Licensed under the Apache License, Version 2.0.
// Author: Jin Qing (http://blog.csdn.net/jq0123)

#include <grpc_cb/status.h>

namespace grpc_cb {

const Status& Status::OK = Status();
const Status& Status::CANCELLED = Status(GRPC_STATUS_CANCELLED, "Cancelled");
const Status& Status::UNIMPLEMENTED = Status(GRPC_STATUS_UNIMPLEMENTED, "Unimplemented");

Status Status::InternalError(const std::string& details) {
  return Status(GRPC_STATUS_INTERNAL, details);
}

void Status::SetInternalError(const std::string& error_msg) {
  code_ = GRPC_STATUS_INTERNAL;
  details_ = error_msg;
}

}  // namespace grpc_cb
<|endoftext|>


<commit_before>/*   This file is part of fus.
 *
 *   fus is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU Affero General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   fus 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 Affero General Public License for more details.
 *
 *   You should have received a copy of the GNU Affero General Public License
 *   along with fus.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "admin_private.h"
#include "core/errors.h"
#include "daemon_base.h"
#include <new>
#include "protocol/admin.h"

// =================================================================================

void fus::admin_server_init(fus::admin_server_t* client)
{
    tcp_stream_free_cb((tcp_stream_t*)client, (tcp_free_cb)admin_server_free);
    crypt_stream_init((crypt_stream_t*)client);
    new(&client->m_link) FUS_LIST_LINK(admin_server_t);
}

void fus::admin_server_free(fus::admin_server_t* client)
{
    client->m_link.~list_link();
}

// =================================================================================

static inline bool admin_check_read(fus::admin_server_t* client, ssize_t nread)
{
    if (nread < 0) {
        s_adminDaemon->m_log.write_debug("[{}]: Read failed: {}",
                                        fus::tcp_stream_peeraddr((fus::tcp_stream_t*)client),
                                        uv_strerror(nread));
        fus::tcp_stream_shutdown((fus::tcp_stream_t*)client);
        return false;
    }
    return true;
}

static void admin_pingpong(fus::admin_server_t* client, ssize_t nread, fus::protocol::admin_pingRequest* msg)
{
    if (!admin_check_read(client, nread))
        return;

    fus::protocol::msg_std_header header;
    header.set_type(fus::protocol::admin2client::e_pingReply);
    fus::tcp_stream_write((fus::tcp_stream_t*)client, &header, sizeof(header));

    // Message reply is a bitwise copy, so we'll just throw the request back.
    fus::tcp_stream_write((fus::tcp_stream_t*)client, msg, nread);

    // Continue reading
    fus::admin_server_read(client);
}

static void admin_wall(fus::admin_server_t* client, ssize_t nread, fus::protocol::admin_wallRequest* msg)
{
    if (!admin_check_read(client, nread))
        return;

    ST::string senderaddr = fus::tcp_stream_peeraddr((fus::tcp_stream_t*)client);

    fus::protocol::admin_msg<fus::protocol::admin_wallBCast> bcast;
    bcast.m_header.set_type(fus::protocol::admin2client::e_wallBCast);
    bcast.m_contents.set_sender(senderaddr);
    bcast.m_contents.set_text(msg->get_text());

    auto it = s_adminDaemon->m_clients.front();
    while (it) {
        fus::tcp_stream_write((fus::tcp_stream_t*)it, bcast, sizeof(bcast));
        it = s_adminDaemon->m_clients.next(it);
    }

    // Continue reading
    fus::admin_server_read(client);
}

// =================================================================================

static void admin_msg_pump(fus::admin_server_t* client, ssize_t nread, fus::protocol::msg_std_header* msg)
{
    if (!admin_check_read(client, nread))
        return;

    switch (msg->get_type()) {
    case fus::protocol::client2admin::e_pingRequest:
        admin_read<fus::protocol::admin_pingRequest>(client, admin_pingpong);
        break;
    case fus::protocol::client2admin::e_wallRequest:
        admin_read<fus::protocol::admin_wallRequest>(client, admin_wall);
        break;
    default:
        s_adminDaemon->m_log.write_error("Received unimplemented message type 0x{04X} -- kicking client", msg->get_type());
        fus::tcp_stream_shutdown((fus::tcp_stream_t*)client);
    }
}

void fus::admin_server_read(fus::admin_server_t* client)
{
    admin_read<protocol::msg_std_header>(client, admin_msg_pump);
}
<commit_msg>Log all wall requests<commit_after>/*   This file is part of fus.
 *
 *   fus is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU Affero General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   fus 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 Affero General Public License for more details.
 *
 *   You should have received a copy of the GNU Affero General Public License
 *   along with fus.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "admin_private.h"
#include "core/errors.h"
#include "daemon_base.h"
#include <new>
#include "protocol/admin.h"

// =================================================================================

void fus::admin_server_init(fus::admin_server_t* client)
{
    tcp_stream_free_cb((tcp_stream_t*)client, (tcp_free_cb)admin_server_free);
    crypt_stream_init((crypt_stream_t*)client);
    new(&client->m_link) FUS_LIST_LINK(admin_server_t);
}

void fus::admin_server_free(fus::admin_server_t* client)
{
    client->m_link.~list_link();
}

// =================================================================================

static inline bool admin_check_read(fus::admin_server_t* client, ssize_t nread)
{
    if (nread < 0) {
        s_adminDaemon->m_log.write_debug("[{}]: Read failed: {}",
                                        fus::tcp_stream_peeraddr((fus::tcp_stream_t*)client),
                                        uv_strerror(nread));
        fus::tcp_stream_shutdown((fus::tcp_stream_t*)client);
        return false;
    }
    return true;
}

static void admin_pingpong(fus::admin_server_t* client, ssize_t nread, fus::protocol::admin_pingRequest* msg)
{
    if (!admin_check_read(client, nread))
        return;

    fus::protocol::msg_std_header header;
    header.set_type(fus::protocol::admin2client::e_pingReply);
    fus::tcp_stream_write((fus::tcp_stream_t*)client, &header, sizeof(header));

    // Message reply is a bitwise copy, so we'll just throw the request back.
    fus::tcp_stream_write((fus::tcp_stream_t*)client, msg, nread);

    // Continue reading
    fus::admin_server_read(client);
}

static void admin_wall(fus::admin_server_t* client, ssize_t nread, fus::protocol::admin_wallRequest* msg)
{
    if (!admin_check_read(client, nread))
        return;

    ST::string senderaddr = fus::tcp_stream_peeraddr((fus::tcp_stream_t*)client);
    s_adminDaemon->m_log.write("[{}] wall: {}", senderaddr, msg->get_text());

    fus::protocol::admin_msg<fus::protocol::admin_wallBCast> bcast;
    bcast.m_header.set_type(fus::protocol::admin2client::e_wallBCast);
    bcast.m_contents.set_sender(senderaddr);
    bcast.m_contents.set_text(msg->get_text());

    auto it = s_adminDaemon->m_clients.front();
    while (it) {
        fus::tcp_stream_write((fus::tcp_stream_t*)it, bcast, sizeof(bcast));
        it = s_adminDaemon->m_clients.next(it);
    }

    // Continue reading
    fus::admin_server_read(client);
}

// =================================================================================

static void admin_msg_pump(fus::admin_server_t* client, ssize_t nread, fus::protocol::msg_std_header* msg)
{
    if (!admin_check_read(client, nread))
        return;

    switch (msg->get_type()) {
    case fus::protocol::client2admin::e_pingRequest:
        admin_read<fus::protocol::admin_pingRequest>(client, admin_pingpong);
        break;
    case fus::protocol::client2admin::e_wallRequest:
        admin_read<fus::protocol::admin_wallRequest>(client, admin_wall);
        break;
    default:
        s_adminDaemon->m_log.write_error("Received unimplemented message type 0x{04X} -- kicking client", msg->get_type());
        fus::tcp_stream_shutdown((fus::tcp_stream_t*)client);
    }
}

void fus::admin_server_read(fus::admin_server_t* client)
{
    admin_read<protocol::msg_std_header>(client, admin_msg_pump);
}
<|endoftext|>


<commit_before>#include "FlashCardApp.h"
#include "TempBackground.h"
#include "CardReader.h"

#include <algorithm>
#include <math.h>
#include <time.h>

FlashCardApp::FlashCardApp()
{
    currentStringIndex = 0;
    windowManager = new GL_SDL_WindowManager();
    eventDispatcher = new SDLEventDispatcher();
    eventDispatcher->setEventHandler(this);
    screenWidth = 800;
    screenHeight = 600;
    frustum = new Frustum(screenWidth, screenHeight, .45, 1, 5000);
    userQuit = false;
}

void FlashCardApp::clearScreen()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}

void FlashCardApp::addTextBox(string s, unsigned char red, unsigned char green, unsigned char blue)
{
    strings.push_back(s);

    TextModel *textModel = new TextModel(s.c_str(), 20, red, green, blue);
    textModel->setPosition(0, 0);
    textModels.push_back(textModel);
}

void FlashCardApp::keyPressed()
{
    currentStringIndex++;
    strings.clear();
    textModels.clear();
    if (currentStringIndex < cardValues.size())
        addTextBox(cardValues[currentStringIndex], 0, 0, 0);
}

void FlashCardApp::run()
{
    srand(time(0));

    string cardFile;
    cout << "file?\n";
    cin >> cardFile;

    CardReader reader(cardFile);
    reader.getFileContents();
    reader.sendStringsToApp(this);

    vector<int> indices;
    while (indices.size() < cardValues.size())
    {
        int choice = rand() % cardValues.size();
        int randomIndex = 2 * (int)(choice / 2);
        if (find(indices.begin(), indices.end(), randomIndex) == indices.end())
        {
            indices.push_back(randomIndex);
            indices.push_back(randomIndex + 1);
        }
    }

    vector<string> randomValues;
    for (int i = 0; i < indices.size(); ++i)
       randomValues.push_back(cardValues[indices[i]]);

    cardValues.clear();
    for (int i = 0; i < randomValues.size(); ++i)
       cardValues.push_back(randomValues[i]);

    windowManager->createWindow(screenWidth, screenHeight);

    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    glMatrixMode(GL_PROJECTION);

    vector<float> values = frustum->getProjectionMatrix();

    init_background();

    addTextBox(cardValues[currentStringIndex], 0, 0, 0);

    //ProjectManager projects;
    //projects.fetchProjects(this);

    float matrix[16];
    std::copy(values.begin(), values.end(), matrix);
    glMultMatrixf(matrix);

    long previousTickCount = 0;

    while (1) {
        long currentTickCount = SDL_GetTicks();
        long ticksSinceLastFrame = currentTickCount - previousTickCount;
        previousTickCount = currentTickCount;

        int framesPerSecons = 1000L / ticksSinceLastFrame;

        eventDispatcher->pollEvents();

        if (currentStringIndex >= cardValues.size())
            break;

        clearScreen();

        draw_background();

        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();

        float x = -.58;
        float y = .44;

        for (int i = 0; i < strings.size(); ++i)
        {
            TextModel *textModel = textModels[i];
            textModel->setPosition(x, y);
            y -= .04;
            textModel->draw();
        }

        windowManager->swapBuffers();
    }

    SDL_Quit();
}

// END OF FILE
<commit_msg>Place long strings on multiple lines to fit screen space.<commit_after>#include "FlashCardApp.h"
#include "TempBackground.h"
#include "CardReader.h"

#include <algorithm>
#include <math.h>
#include <time.h>

FlashCardApp::FlashCardApp()
{
    currentStringIndex = 0;
    windowManager = new GL_SDL_WindowManager();
    eventDispatcher = new SDLEventDispatcher();
    eventDispatcher->setEventHandler(this);
    screenWidth = 800;
    screenHeight = 600;
    frustum = new Frustum(screenWidth, screenHeight, .45, 1, 5000);
    userQuit = false;
}

void FlashCardApp::clearScreen()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}

void FlashCardApp::addTextBox(string s, unsigned char red, unsigned char green, unsigned char blue)
{
    strings.push_back(s);

    TextModel *textModel = new TextModel(s.c_str(), 20, red, green, blue);
    textModel->setPosition(0, 0);
    textModels.push_back(textModel);
}

void FlashCardApp::keyPressed()
{
    currentStringIndex++;
    strings.clear();
    textModels.clear();
    if (currentStringIndex < cardValues.size())
    {
        string s = cardValues[currentStringIndex];
        int currentPosition = 0;
        int totalLength = s.size();
        int maxLength = 60;

        while (totalLength - currentPosition > maxLength)
        {
            int subLength = maxLength;
            while (subLength > 0 && s[currentPosition + subLength] != ' ')
                subLength--;
            if (subLength == 0)
                subLength = maxLength;
            addTextBox(s.substr(currentPosition, subLength), 0, 0, 0);
            currentPosition += subLength;
        }
        while (s[currentPosition] == ' ' && currentPosition < totalLength)
            currentPosition++;
        addTextBox(s.substr(currentPosition, totalLength - currentPosition), 0, 0, 0);
    }
}

void FlashCardApp::run()
{
    srand(time(0));

    string cardFile;
    cout << "file?\n";
    cin >> cardFile;

    CardReader reader(cardFile);
    reader.getFileContents();
    reader.sendStringsToApp(this);

    vector<int> indices;
    while (indices.size() < cardValues.size())
    {
        int choice = rand() % cardValues.size();
        int randomIndex = 2 * (int)(choice / 2);
        if (find(indices.begin(), indices.end(), randomIndex) == indices.end())
        {
            indices.push_back(randomIndex);
            indices.push_back(randomIndex + 1);
        }
    }

    vector<string> randomValues;
    for (int i = 0; i < indices.size(); ++i)
       randomValues.push_back(cardValues[indices[i]]);

    cardValues.clear();
    for (int i = 0; i < randomValues.size(); ++i)
       cardValues.push_back(randomValues[i]);

    windowManager->createWindow(screenWidth, screenHeight);

    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    glMatrixMode(GL_PROJECTION);

    vector<float> values = frustum->getProjectionMatrix();

    init_background();

    addTextBox(cardValues[currentStringIndex], 0, 0, 0);

    //ProjectManager projects;
    //projects.fetchProjects(this);

    float matrix[16];
    std::copy(values.begin(), values.end(), matrix);
    glMultMatrixf(matrix);

    long previousTickCount = 0;

    while (1) {
        long currentTickCount = SDL_GetTicks();
        long ticksSinceLastFrame = currentTickCount - previousTickCount;
        previousTickCount = currentTickCount;

        int framesPerSecons = 1000L / ticksSinceLastFrame;

        eventDispatcher->pollEvents();

        if (currentStringIndex >= cardValues.size())
            break;

        clearScreen();

        draw_background();

        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();

        float x = -.50;
        float y = .30;

        for (int i = 0; i < strings.size(); ++i)
        {
            TextModel *textModel = textModels[i];
            textModel->setPosition(x, y);
            y -= .04;
            textModel->draw();
        }

        windowManager->swapBuffers();
    }

    SDL_Quit();
}

// END OF FILE
<|endoftext|>


<commit_before>#include <algorithm>
#include <ranges>
#include <vector>
#include <string>
#include <sstream>
#include <iostream>
#include <iterator>

std::istringstream open_str(std::string const& str) {
    return std::istringstream{str};
}

int count_lines(std::istringstream strstream) {
    return std::count(
        std::istreambuf_iterator<char>(strstream),
        std::istreambuf_iterator<char>(),
        '\n');
}

std::vector<int> count_lines_in_files(std::vector<std::string> const& strs) {
    auto const& tmp_vals = strs
        | std::ranges::views::transform(open_str)
        | std::ranges::views::transform(count_lines);

    std::vector<int> cnts{};
    std::copy(std::cbegin(tmp_vals), std::cend(tmp_vals), std::back_inserter(cnts));

    return cnts;
}

int main() {
    for (auto const line_count : count_lines_in_files( { "1\n2\n3" }))
       std::cout << line_count << " line(s)\n";

    return 0;
}
<commit_msg>[i_cukic-func_prgr_in_cpp][ch 01] slightly rewrite a more elaborate example with ranges<commit_after>#include <algorithm>
#include <iostream>
#include <iterator>
#include <ranges>
#include <sstream>
#include <string>
#include <vector>
namespace test {

std::istringstream open_str(std::string const& str) { return std::istringstream{str}; }

int count_lines(std::istringstream strstream) {
    return std::count(
        std::istreambuf_iterator<char>{strstream},
        std::istreambuf_iterator<char>{},
        '\n');
}

std::vector<int> countLines(std::vector<std::string> const& strs) {
    std::vector<int> ret{};

    auto const& vals = strs
        | std::ranges::views::transform(open_str)
        | std::ranges::views::transform(count_lines);

    std::copy(std::cbegin(vals), std::cend(vals), std::back_inserter(ret));

    return ret;
}

void run() {
    for (auto const cnt: countLines( { "1\n2\n3", "1\n2\n3", "1\n2\n3" } ))
        std::cout << "line count: " << cnt << std::endl;
}
} // test

int main() {
    std::cout << "test => [ok]" << std::endl; test::run(); std::cout << std::endl;

    return 0;
}
<|endoftext|>


<commit_before>// This file is a part of the OpenSurgSim project.
// Copyright 2012-2013, SimQuest Solutions Inc.
//
// 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.

/// \file
/// Tests for the Group class.

#include "SurgSim/Graphics/UnitTests/MockObjects.h"
#include "SurgSim/Graphics/UnitTests/MockOsgObjects.h"

#include "SurgSim/Graphics/OsgGroup.h"

#include "gtest/gtest.h"

using SurgSim::Graphics::Actor;
using SurgSim::Graphics::Group;
using SurgSim::Graphics::OsgActor;
using SurgSim::Graphics::OsgGroup;

TEST(OsgGroupTests, InitTest)
{
	ASSERT_NO_THROW({std::shared_ptr<Group> group = std::make_shared<OsgGroup>("test name");});
}

TEST(OsgGroupTests, OsgNodesTest)
{
	std::shared_ptr<OsgGroup> osgGroup = std::make_shared<OsgGroup>("test group");

	osg::ref_ptr<osg::Switch> osgSwitch = dynamic_cast<osg::Switch*>(osgGroup->getOsgGroup().get());
	ASSERT_TRUE(osgSwitch.valid()) << "Group's OSG node should be a switch!";
}

TEST(OsgGroupTests, VisibilityTest)
{
	std::shared_ptr<OsgGroup> osgGroup = std::make_shared<OsgGroup>("test group");
	std::shared_ptr<Group> group = osgGroup;

	EXPECT_TRUE(group->isVisible());

	group->setVisible(true);
	EXPECT_TRUE(group->isVisible());
}

TEST(OsgGroupTests, AddRemoveTest)
{
	std::shared_ptr<OsgGroup> osgGroup = std::make_shared<OsgGroup>("test group");
	std::shared_ptr<Group> group = osgGroup;

	EXPECT_EQ(0u, group->getActors().size());
	EXPECT_EQ(0u, group->getGroups().size());

	osg::ref_ptr<osg::Switch> osgSwitch = dynamic_cast<osg::Switch*>(osgGroup->getOsgGroup().get());
	ASSERT_TRUE(osgSwitch.valid()) << "Group's OSG node should be a switch!";
	EXPECT_EQ(0u, osgSwitch->getNumChildren());

	/// Add an actor and make sure the osg::Switch value for it is set correctly (should be true)
	std::shared_ptr<OsgActor> actor1 = std::make_shared<MockOsgActor>("test actor 1");
	group->addActor(actor1);
	EXPECT_EQ(1u, group->getActors().size());
	EXPECT_EQ(1u, osgSwitch->getNumChildren());
	EXPECT_EQ(0u, osgSwitch->getChildIndex(actor1->getOsgNode()));
	EXPECT_TRUE(osgSwitch->getChildValue(actor1->getOsgNode())) << "Actor 1 should be visible!";

	/// Set group to not visible and check the osg::Switch values
	group->setVisible(false);
	EXPECT_FALSE(group->isVisible());
	EXPECT_FALSE(osgSwitch->getChildValue(actor1->getOsgNode())) << "Actor 1 should not be visible!";

	/// Add another actor and make sure the osg::Switch value for it is set correctly (should be false)
	std::shared_ptr<OsgActor> actor2 = std::make_shared<MockOsgActor>("test actor 2");
	group->addActor(actor2);
	EXPECT_EQ(2u, group->getActors().size());
	EXPECT_EQ(2u, osgSwitch->getNumChildren());
	EXPECT_EQ(1u, osgSwitch->getChildIndex(actor2->getOsgNode()));
	EXPECT_FALSE(osgSwitch->getChildValue(actor2->getOsgNode())) << "Actor 2 should not be visible!";

	/// Set group to visible and check the osg::Switch values
	group->setVisible(true);
	EXPECT_TRUE(group->isVisible());
	EXPECT_TRUE(osgSwitch->getChildValue(actor1->getOsgNode())) << "Actor 1 should be visible!";
	EXPECT_TRUE(osgSwitch->getChildValue(actor2->getOsgNode())) << "Actor 2 should be visible!";

	/// Add a group and make sure the osg::Switch value for it is set correctly (should be true)
	std::shared_ptr<OsgGroup> subGroup1 = std::make_shared<OsgGroup>("test sub-group 1");
	group->addGroup(subGroup1);
	EXPECT_EQ(1u, group->getGroups().size());
	EXPECT_EQ(3u, osgSwitch->getNumChildren());
	EXPECT_EQ(2u, osgSwitch->getChildIndex(subGroup1->getOsgGroup()));
	EXPECT_TRUE(osgSwitch->getChildValue(subGroup1->getOsgGroup())) << "Group 1 should be visible!";

	/// Set group to not visible and check the osg::Switch values
	group->setVisible(false);
	EXPECT_FALSE(group->isVisible());
	EXPECT_FALSE(osgSwitch->getChildValue(actor1->getOsgNode())) << "Actor 1 should not be visible!";
	EXPECT_FALSE(osgSwitch->getChildValue(actor2->getOsgNode())) << "Actor 1 should not be visible!";
	EXPECT_FALSE(osgSwitch->getChildValue(subGroup1->getOsgGroup())) << "Group 1 should not be visible!";

	/// Add another group and make sure the osg::Switch value for it is set correctly (should be false)
	std::shared_ptr<OsgGroup> subGroup2 = std::make_shared<OsgGroup>("test sub-group 1");
	group->addGroup(subGroup2);
	EXPECT_EQ(2u, group->getGroups().size());
	EXPECT_EQ(4u, osgSwitch->getNumChildren());
	EXPECT_EQ(3u, osgSwitch->getChildIndex(subGroup2->getOsgGroup()));
	EXPECT_FALSE(osgSwitch->getChildValue(subGroup2->getOsgGroup())) << "Group 2 should not be visible!";

	/// Set group to visible and check the osg::Switch values
	group->setVisible(true);
	EXPECT_TRUE(group->isVisible());
	EXPECT_TRUE(osgSwitch->getChildValue(actor1->getOsgNode())) << "Actor 1 should be visible!";
	EXPECT_TRUE(osgSwitch->getChildValue(actor2->getOsgNode())) << "Actor 2 should be visible!";
	EXPECT_TRUE(osgSwitch->getChildValue(subGroup1->getOsgGroup())) << "Group 1 should be visible!";
	EXPECT_TRUE(osgSwitch->getChildValue(subGroup2->getOsgGroup())) << "Group 2 should be visible!";

	/// Try to add a duplicate actor
	EXPECT_FALSE(group->addActor(actor1));
	EXPECT_EQ(2u, group->getActors().size());
	EXPECT_EQ(4u, osgSwitch->getNumChildren());

	/// Try to add a duplicate group
	EXPECT_FALSE(group->addGroup(subGroup2));
	EXPECT_EQ(2u, group->getGroups().size());
	EXPECT_EQ(4u, osgSwitch->getNumChildren());

	/// Remove a group
	EXPECT_TRUE(group->removeGroup(subGroup2));
	EXPECT_EQ(3u, osgSwitch->getNumChildren());
	EXPECT_EQ(3u, osgSwitch->getChildIndex(subGroup2->getOsgGroup()));

	/// Remove an actor
	EXPECT_TRUE(group->removeActor(actor1));
	EXPECT_EQ(2u, osgSwitch->getNumChildren());
	EXPECT_EQ(2u, osgSwitch->getChildIndex(actor1->getOsgNode()));

	/// Try to remove a group that is not in the group
	EXPECT_FALSE(group->removeGroup(subGroup2));
	EXPECT_EQ(2u, osgSwitch->getChildIndex(subGroup2->getOsgGroup()));

	/// Try to remove an actor that is not in the group
	EXPECT_FALSE(group->removeActor(actor1));
	EXPECT_EQ(2u, osgSwitch->getChildIndex(actor1->getOsgNode()));

	/// Try to add a non-OSG actor
	std::shared_ptr<MockActor> nonOsgActor = std::make_shared<MockActor>("non-osg actor");
	EXPECT_FALSE(group->addActor(nonOsgActor)) << "OsgGroup should only succeed on actors that derive from OsgActor!";
	EXPECT_EQ(1u, group->getActors().size());
	EXPECT_EQ(group->getActors().end(), std::find(group->getActors().begin(), group->getActors().end(), nonOsgActor));
	EXPECT_EQ(2u, osgSwitch->getNumChildren());

	/// Try to add a non-OSG group
	std::shared_ptr<MockGroup> nonOsgSubgroup = std::make_shared<MockGroup>("non-osg group");
	EXPECT_FALSE(group->addGroup(nonOsgSubgroup)) <<
		"OsgGroup should only succeed on groups that derive from OsgGroup!";
	EXPECT_EQ(1u, group->getGroups().size());
	EXPECT_EQ(group->getGroups().end(), std::find(group->getGroups().begin(),group->getGroups().end(), nonOsgSubgroup));
	EXPECT_EQ(2u, osgSwitch->getNumChildren());
}
<commit_msg>Add clear tests for OsgGroup<commit_after>// This file is a part of the OpenSurgSim project.
// Copyright 2012-2013, SimQuest Solutions Inc.
//
// 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.

/// \file
/// Tests for the Group class.

#include "SurgSim/Graphics/UnitTests/MockObjects.h"
#include "SurgSim/Graphics/UnitTests/MockOsgObjects.h"

#include "SurgSim/Graphics/OsgGroup.h"

#include "gtest/gtest.h"

using SurgSim::Graphics::Actor;
using SurgSim::Graphics::Group;
using SurgSim::Graphics::OsgActor;
using SurgSim::Graphics::OsgGroup;

TEST(OsgGroupTests, InitTest)
{
	ASSERT_NO_THROW({std::shared_ptr<Group> group = std::make_shared<OsgGroup>("test name");});
}

TEST(OsgGroupTests, OsgNodesTest)
{
	std::shared_ptr<OsgGroup> osgGroup = std::make_shared<OsgGroup>("test group");

	osg::ref_ptr<osg::Switch> osgSwitch = dynamic_cast<osg::Switch*>(osgGroup->getOsgGroup().get());
	ASSERT_TRUE(osgSwitch.valid()) << "Group's OSG node should be a switch!";
}

TEST(OsgGroupTests, VisibilityTest)
{
	std::shared_ptr<OsgGroup> osgGroup = std::make_shared<OsgGroup>("test group");
	std::shared_ptr<Group> group = osgGroup;

	EXPECT_TRUE(group->isVisible());

	group->setVisible(true);
	EXPECT_TRUE(group->isVisible());
}

TEST(OsgGroupTests, AddRemoveTest)
{
	std::shared_ptr<OsgGroup> osgGroup = std::make_shared<OsgGroup>("test group");
	std::shared_ptr<Group> group = osgGroup;

	EXPECT_EQ(0u, group->getActors().size());
	EXPECT_EQ(0u, group->getGroups().size());

	osg::ref_ptr<osg::Switch> osgSwitch = dynamic_cast<osg::Switch*>(osgGroup->getOsgGroup().get());
	ASSERT_TRUE(osgSwitch.valid()) << "Group's OSG node should be a switch!";
	EXPECT_EQ(0u, osgSwitch->getNumChildren());

	/// Add an actor and make sure the osg::Switch value for it is set correctly (should be true)
	std::shared_ptr<OsgActor> actor1 = std::make_shared<MockOsgActor>("test actor 1");
	group->addActor(actor1);
	EXPECT_EQ(1u, group->getActors().size());
	EXPECT_EQ(1u, osgSwitch->getNumChildren());
	EXPECT_EQ(0u, osgSwitch->getChildIndex(actor1->getOsgNode()));
	EXPECT_TRUE(osgSwitch->getChildValue(actor1->getOsgNode())) << "Actor 1 should be visible!";

	/// Set group to not visible and check the osg::Switch values
	group->setVisible(false);
	EXPECT_FALSE(group->isVisible());
	EXPECT_FALSE(osgSwitch->getChildValue(actor1->getOsgNode())) << "Actor 1 should not be visible!";

	/// Add another actor and make sure the osg::Switch value for it is set correctly (should be false)
	std::shared_ptr<OsgActor> actor2 = std::make_shared<MockOsgActor>("test actor 2");
	group->addActor(actor2);
	EXPECT_EQ(2u, group->getActors().size());
	EXPECT_EQ(2u, osgSwitch->getNumChildren());
	EXPECT_EQ(1u, osgSwitch->getChildIndex(actor2->getOsgNode()));
	EXPECT_FALSE(osgSwitch->getChildValue(actor2->getOsgNode())) << "Actor 2 should not be visible!";

	/// Set group to visible and check the osg::Switch values
	group->setVisible(true);
	EXPECT_TRUE(group->isVisible());
	EXPECT_TRUE(osgSwitch->getChildValue(actor1->getOsgNode())) << "Actor 1 should be visible!";
	EXPECT_TRUE(osgSwitch->getChildValue(actor2->getOsgNode())) << "Actor 2 should be visible!";

	/// Add a group and make sure the osg::Switch value for it is set correctly (should be true)
	std::shared_ptr<OsgGroup> subGroup1 = std::make_shared<OsgGroup>("test sub-group 1");
	group->addGroup(subGroup1);
	EXPECT_EQ(1u, group->getGroups().size());
	EXPECT_EQ(3u, osgSwitch->getNumChildren());
	EXPECT_EQ(2u, osgSwitch->getChildIndex(subGroup1->getOsgGroup()));
	EXPECT_TRUE(osgSwitch->getChildValue(subGroup1->getOsgGroup())) << "Group 1 should be visible!";

	/// Set group to not visible and check the osg::Switch values
	group->setVisible(false);
	EXPECT_FALSE(group->isVisible());
	EXPECT_FALSE(osgSwitch->getChildValue(actor1->getOsgNode())) << "Actor 1 should not be visible!";
	EXPECT_FALSE(osgSwitch->getChildValue(actor2->getOsgNode())) << "Actor 1 should not be visible!";
	EXPECT_FALSE(osgSwitch->getChildValue(subGroup1->getOsgGroup())) << "Group 1 should not be visible!";

	/// Add another group and make sure the osg::Switch value for it is set correctly (should be false)
	std::shared_ptr<OsgGroup> subGroup2 = std::make_shared<OsgGroup>("test sub-group 1");
	group->addGroup(subGroup2);
	EXPECT_EQ(2u, group->getGroups().size());
	EXPECT_EQ(4u, osgSwitch->getNumChildren());
	EXPECT_EQ(3u, osgSwitch->getChildIndex(subGroup2->getOsgGroup()));
	EXPECT_FALSE(osgSwitch->getChildValue(subGroup2->getOsgGroup())) << "Group 2 should not be visible!";

	/// Set group to visible and check the osg::Switch values
	group->setVisible(true);
	EXPECT_TRUE(group->isVisible());
	EXPECT_TRUE(osgSwitch->getChildValue(actor1->getOsgNode())) << "Actor 1 should be visible!";
	EXPECT_TRUE(osgSwitch->getChildValue(actor2->getOsgNode())) << "Actor 2 should be visible!";
	EXPECT_TRUE(osgSwitch->getChildValue(subGroup1->getOsgGroup())) << "Group 1 should be visible!";
	EXPECT_TRUE(osgSwitch->getChildValue(subGroup2->getOsgGroup())) << "Group 2 should be visible!";

	/// Try to add a duplicate actor
	EXPECT_FALSE(group->addActor(actor1));
	EXPECT_EQ(2u, group->getActors().size());
	EXPECT_EQ(4u, osgSwitch->getNumChildren());

	/// Try to add a duplicate group
	EXPECT_FALSE(group->addGroup(subGroup2));
	EXPECT_EQ(2u, group->getGroups().size());
	EXPECT_EQ(4u, osgSwitch->getNumChildren());

	/// Remove a group
	EXPECT_TRUE(group->removeGroup(subGroup2));
	EXPECT_EQ(3u, osgSwitch->getNumChildren());
	EXPECT_EQ(3u, osgSwitch->getChildIndex(subGroup2->getOsgGroup()));

	/// Remove an actor
	EXPECT_TRUE(group->removeActor(actor1));
	EXPECT_EQ(2u, osgSwitch->getNumChildren());
	EXPECT_EQ(2u, osgSwitch->getChildIndex(actor1->getOsgNode()));

	/// Try to remove a group that is not in the group
	EXPECT_FALSE(group->removeGroup(subGroup2));
	EXPECT_EQ(2u, osgSwitch->getChildIndex(subGroup2->getOsgGroup()));

	/// Try to remove an actor that is not in the group
	EXPECT_FALSE(group->removeActor(actor1));
	EXPECT_EQ(2u, osgSwitch->getChildIndex(actor1->getOsgNode()));

	/// Try to add a non-OSG actor
	std::shared_ptr<MockActor> nonOsgActor = std::make_shared<MockActor>("non-osg actor");
	EXPECT_FALSE(group->addActor(nonOsgActor)) << "OsgGroup should only succeed on actors that derive from OsgActor!";
	EXPECT_EQ(1u, group->getActors().size());
	EXPECT_EQ(group->getActors().end(), std::find(group->getActors().begin(), group->getActors().end(), nonOsgActor));
	EXPECT_EQ(2u, osgSwitch->getNumChildren());

	/// Try to add a non-OSG group
	std::shared_ptr<MockGroup> nonOsgSubgroup = std::make_shared<MockGroup>("non-osg group");
	EXPECT_FALSE(group->addGroup(nonOsgSubgroup)) <<
		"OsgGroup should only succeed on groups that derive from OsgGroup!";
	EXPECT_EQ(1u, group->getGroups().size());
	EXPECT_EQ(group->getGroups().end(), std::find(group->getGroups().begin(),group->getGroups().end(), nonOsgSubgroup));
	EXPECT_EQ(2u, osgSwitch->getNumChildren());
}

TEST(OsgGroupTests, ClearTests)
{
    std::shared_ptr<OsgGroup> osgGroup = std::make_shared<OsgGroup>("test name");
	std::shared_ptr<Group> group = osgGroup;

	std::shared_ptr<Actor> actor1 = std::make_shared<MockOsgActor>("test actor 1");
	std::shared_ptr<Actor> actor2 = std::make_shared<MockOsgActor>("test actor 2");
	std::shared_ptr<Group> group1 = std::make_shared<OsgGroup>("test group 1");
	std::shared_ptr<Group> group2 = std::make_shared<OsgGroup>("test group 2");

    osg::ref_ptr<osg::Switch> osgSwitch = dynamic_cast<osg::Switch*>(osgGroup->getOsgGroup().get());
	ASSERT_TRUE(osgSwitch.valid()) << "Group's OSG node should be a switch!";

	EXPECT_EQ(0u, group->getActors().size());
	EXPECT_EQ(0u, group->getGroups().size());
    EXPECT_EQ(0u, osgSwitch->getNumChildren());

    // Add actors and groups
    group->addActor(actor1);
    group->addActor(actor2);
    group->addGroup(group1);
    group->addGroup(group2);
    EXPECT_EQ(2u, group->getActors().size());
	EXPECT_EQ(2u, group->getGroups().size());
    EXPECT_EQ(4u, osgSwitch->getNumChildren());

    // Remove all actors
    group->clearActors();
    EXPECT_EQ(0u, group->getActors().size());
	EXPECT_EQ(2u, group->getGroups().size());
    EXPECT_EQ(2u, osgSwitch->getNumChildren());

    // Add actors again
    group->addActor(actor1);
    group->addActor(actor2);
    EXPECT_EQ(2u, group->getActors().size());
	EXPECT_EQ(2u, group->getGroups().size());
    EXPECT_EQ(4u, osgSwitch->getNumChildren());

    // Remove all groups
    group->clearGroups();
    EXPECT_EQ(2u, group->getActors().size());
	EXPECT_EQ(0u, group->getGroups().size());
    EXPECT_EQ(2u, osgSwitch->getNumChildren());

    // Add groups again
    group->addGroup(group1);
    group->addGroup(group2);
    EXPECT_EQ(2u, group->getActors().size());
	EXPECT_EQ(2u, group->getGroups().size());
    EXPECT_EQ(4u, osgSwitch->getNumChildren());

    // Remove everything
    group->clear();
    EXPECT_EQ(0u, group->getActors().size());
	EXPECT_EQ(0u, group->getGroups().size());
    EXPECT_EQ(0u, osgSwitch->getNumChildren());
}<|endoftext|>


<commit_before>//
// TextureUnitManager.cpp
//
// Originally written by RJ.
//
// Copyright (c) 2006-2007 Virtual Terrain Project
// Free for all uses, see license.txt for details.
//

#include "vtlib/vtlib.h"
#include "TextureUnitManager.h"

//
// RJ's warning: NONE OF THIS IS THREAD SAFE!!!
//

vtTextureUnitManager::vtTextureUnitManager(void)
{
	m_bInitialised = false;
	m_pAllocationArray = NULL;
}

vtTextureUnitManager::~vtTextureUnitManager(void)
{
	if (NULL != m_pAllocationArray)
		delete[] m_pAllocationArray;
}

void vtTextureUnitManager::Initialise()
{
	// Ensure this thread has a valid graphics context
	// The following code will create
	// 1. A OSG Traits object
	// 2. A new OSG GraphicsContext object
	// 3. A new zero sized window
	// 4. A new OpenGL rendering context
	// 5. A new OSG contextID
	// The ref_ptrs will ensure all these things will be destroyed when this routine returns
	// although OSG may spit out a warning about destroying a valid window!
	osg::ref_ptr<osg::GraphicsContext::Traits> pTraits = new osg::GraphicsContext::Traits;
	osg::ref_ptr<osg::GraphicsContext> pGraphicsContext = osg::GraphicsContext::createGraphicsContext(pTraits.get());
	pGraphicsContext->realize();
	pGraphicsContext->makeCurrent();
	osg::ref_ptr<osg::Texture::Extensions> pTextureExtensions = osg::Texture::getExtensions(pGraphicsContext->getState()->getContextID(), true);
	m_iNumTextureUnits = pTextureExtensions->numTextureUnits();
	if (m_iNumTextureUnits < 0)
	{
		// got a bogus value, probably because there is no OpenGL context yet.
		m_iNumTextureUnits = 4;
	}

	m_pAllocationArray = new bool[m_iNumTextureUnits];
	for (int i = 0; i < m_iNumTextureUnits; i++)
		m_pAllocationArray[i] = false;
	m_bInitialised = true;
}

int vtTextureUnitManager::ReserveTextureUnit(bool bHighest)
{
	int iUnit = -1;
	if (!m_bInitialised)
		Initialise();
	if (bHighest)
	{
		for (int i = m_iNumTextureUnits - 1; i >= 0; i--)
		{
			if (m_pAllocationArray[i] == false)
			{
				m_pAllocationArray[i] = true;
				iUnit = i;
				break;
			}
		}
	}
	else
	{
		for (int i = 0; i < m_iNumTextureUnits; i++)
		{
			if (m_pAllocationArray[i] == false)
			{
				m_pAllocationArray[i] = true;
				iUnit = i;
				break;
			}
		}
	}
	return iUnit;
}

void vtTextureUnitManager::FreeTextureUnit(int iUnit)
{
	if (!m_bInitialised || (iUnit >= m_iNumTextureUnits))
		return;
	m_pAllocationArray[iUnit] = false;
}

<commit_msg>X11 GTK does not like zero size windows<commit_after>//
// TextureUnitManager.cpp
//
// Originally written by RJ.
//
// Copyright (c) 2006-2007 Virtual Terrain Project
// Free for all uses, see license.txt for details.
//

#include "vtlib/vtlib.h"
#include "TextureUnitManager.h"

//
// RJ's warning: NONE OF THIS IS THREAD SAFE!!!
//

vtTextureUnitManager::vtTextureUnitManager(void)
{
	m_bInitialised = false;
	m_pAllocationArray = NULL;
}

vtTextureUnitManager::~vtTextureUnitManager(void)
{
	if (NULL != m_pAllocationArray)
		delete[] m_pAllocationArray;
}

void vtTextureUnitManager::Initialise()
{
	// Ensure this thread has a valid graphics context
	// The following code will create
	// 1. A OSG Traits object
	// 2. A new OSG GraphicsContext object
	// 3. A new zero sized window
	// 4. A new OpenGL rendering context
	// 5. A new OSG contextID
	// The ref_ptrs will ensure all these things will be destroyed when this routine returns
	// although OSG may spit out a warning about destroying a valid window!
	osg::ref_ptr<osg::GraphicsContext::Traits> pTraits = new osg::GraphicsContext::Traits;
	pTraits->width = 1;
	pTraits->height = 1;
	osg::ref_ptr<osg::GraphicsContext> pGraphicsContext = osg::GraphicsContext::createGraphicsContext(pTraits.get());
	pGraphicsContext->realize();
	pGraphicsContext->makeCurrent();
	osg::ref_ptr<osg::Texture::Extensions> pTextureExtensions = osg::Texture::getExtensions(pGraphicsContext->getState()->getContextID(), true);
	m_iNumTextureUnits = pTextureExtensions->numTextureUnits();
	if (m_iNumTextureUnits < 0)
	{
		// got a bogus value, probably because there is no OpenGL context yet.
		m_iNumTextureUnits = 4;
	}

	m_pAllocationArray = new bool[m_iNumTextureUnits];
	for (int i = 0; i < m_iNumTextureUnits; i++)
		m_pAllocationArray[i] = false;
	m_bInitialised = true;
}

int vtTextureUnitManager::ReserveTextureUnit(bool bHighest)
{
	int iUnit = -1;
	if (!m_bInitialised)
		Initialise();
	if (bHighest)
	{
		for (int i = m_iNumTextureUnits - 1; i >= 0; i--)
		{
			if (m_pAllocationArray[i] == false)
			{
				m_pAllocationArray[i] = true;
				iUnit = i;
				break;
			}
		}
	}
	else
	{
		for (int i = 0; i < m_iNumTextureUnits; i++)
		{
			if (m_pAllocationArray[i] == false)
			{
				m_pAllocationArray[i] = true;
				iUnit = i;
				break;
			}
		}
	}
	return iUnit;
}

void vtTextureUnitManager::FreeTextureUnit(int iUnit)
{
	if (!m_bInitialised || (iUnit >= m_iNumTextureUnits))
		return;
	m_pAllocationArray[iUnit] = false;
}

<|endoftext|>


<commit_before>/*
* Copyright (C) 2012 David Edmundson <kde@davidedmundson.co.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; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include "contact.h"

#include <TelepathyQt/ContactManager>
#include <TelepathyQt/Connection>
#include <TelepathyQt/ContactCapabilities>
#include <TelepathyQt/AvatarData>
#include <TelepathyQt/Utils>

#include <QBitmap>
#include <QPixmap>
#include <QPixmapCache>

#include <KIconLoader>
#include <KConfigGroup>
#include <KConfig>

#include "capabilities-hack-private.h"

KTp::Contact::Contact(Tp::ContactManager *manager, const Tp::ReferencedHandles &handle, const Tp::Features &requestedFeatures, const QVariantMap &attributes)
    : Tp::Contact(manager, handle, requestedFeatures, attributes)
{
    connect(manager->connection().data(), SIGNAL(destroyed()), SIGNAL(invalidated()));
    connect(manager->connection().data(), SIGNAL(invalidated(Tp::DBusProxy*,QString,QString)), SIGNAL(invalidated()));
    connect(this, SIGNAL(avatarTokenChanged(QString)), SLOT(invalidateAvatarCache()));
    connect(this, SIGNAL(avatarDataChanged(Tp::AvatarData)), SLOT(invalidateAvatarCache()));
}

KTp::Presence KTp::Contact::presence() const
{
    return KTp::Presence(Tp::Contact::presence());
}

bool KTp::Contact::textChatCapability() const
{
    if (!manager()->connection()) {
        return false;
    }

    return capabilities().textChats();
}

bool KTp::Contact::audioCallCapability() const
{
    if (!manager()->connection()) {
        return false;
    }

    Tp::ConnectionPtr connection = manager()->connection();
    bool contactCanStreamAudio = CapabilitiesHackPrivate::audioCalls(
                capabilities(), connection->cmName());
    bool selfCanStreamAudio = CapabilitiesHackPrivate::audioCalls(
                connection->selfContact()->capabilities(), connection->cmName());
    return contactCanStreamAudio && selfCanStreamAudio;
}

bool KTp::Contact::videoCallCapability() const
{
    if (!manager()->connection()) {
        return false;
    }

    Tp::ConnectionPtr connection = manager()->connection();
    bool contactCanStreamVideo = CapabilitiesHackPrivate::videoCalls(
                capabilities(), connection->cmName());
    bool selfCanStreamVideo = CapabilitiesHackPrivate::videoCalls(
                connection->selfContact()->capabilities(), connection->cmName());
    return contactCanStreamVideo && selfCanStreamVideo;
}

bool KTp::Contact::fileTransferCapability()  const
{
    if (!manager()->connection()) {
        return false;
    }

    bool contactCanHandleFiles = capabilities().fileTransfers();
    bool selfCanHandleFiles = manager()->connection()->selfContact()->capabilities().fileTransfers();
    return contactCanHandleFiles && selfCanHandleFiles;
}

bool KTp::Contact::collaborativeEditingCapability() const
{
    if (!manager()->connection()) {
        return false;
    }

    static const QString collab(QLatin1String("infinote"));
    bool selfCanShare = manager()->connection()->selfContact()->capabilities().streamTubes(collab);
    bool otherCanShare = capabilities().streamTubes(collab);
    return selfCanShare && otherCanShare;
}

QStringList KTp::Contact::dbusTubeServicesCapability() const
{
    if (!manager()->connection()) {
        return QStringList();
    }

    return getCommonElements(capabilities().dbusTubeServices(),
                             manager()->connection()->selfContact()->capabilities().dbusTubeServices());
}

QStringList KTp::Contact::streamTubeServicesCapability() const
{
    if (!manager()->connection()) {
        return QStringList();
    }

    return getCommonElements(capabilities().streamTubeServices(),
                             manager()->connection()->selfContact()->capabilities().streamTubeServices());
}

QStringList KTp::Contact::clientTypes() const
{
    /* Temporary workaround for upstream bug https://bugs.freedesktop.org/show_bug.cgi?id=55883)
     * Close https://bugs.kde.org/show_bug.cgi?id=308217 when fixed upstream */
    if (Tp::Contact::presence().type() == Tp::ConnectionPresenceTypeOffline) {
        return QStringList();
    }

    //supress any errors trying to access ClientTypes when we don't have them
    if (! actualFeatures().contains(Tp::Contact::FeatureClientTypes)) {
        return QStringList();
    }

    return Tp::Contact::clientTypes();
}

QPixmap KTp::Contact::avatarPixmap()
{
    QPixmap avatar;

    //check pixmap cache for the avatar, if not present, load the avatar
    if (!QPixmapCache::find(keyCache(), avatar)){
        QString file = avatarData().fileName;

        //if contact does not provide path, let's see if we have avatar for the stored token
        if (file.isEmpty()) {
            KConfig config(QLatin1String("ktelepathy-avatarsrc"));
            KConfigGroup avatarTokenGroup = config.group(id());
            QString avatarToken = avatarTokenGroup.readEntry(QLatin1String("avatarToken"));
            //only bother loading the pixmap if the token is not empty
            if (!avatarToken.isEmpty()) {
                avatar.load(buildAvatarPath(avatarToken));
            }
        } else {
            avatar.load(file);
        }

        //if neither above succeeded, we need to load the icon
        if (avatar.isNull()) {
            avatar = KIconLoader::global()->loadIcon(QLatin1String("im-user"), KIconLoader::NoGroup, 96);
        }

        //if the contact is offline, gray it out
        if (presence().type() == Tp::ConnectionPresenceTypeOffline) {
            avatarToGray(avatar);
        }

        //insert the contact into pixmap cache for faster lookup
        QPixmapCache::insert(keyCache(), avatar);
    }

    return avatar;
}

void KTp::Contact::avatarToGray(QPixmap &avatar)
{
    QImage image = avatar.toImage();
    QPixmap alpha= avatar.alphaChannel();
    for (int i = 0; i < image.width(); ++i) {
        for (int j = 0; j < image.height(); ++j) {
            int colour = qGray(image.pixel(i, j));
            image.setPixel(i, j, qRgb(colour, colour, colour));
        }
    }
    avatar = avatar.fromImage(image);
    avatar.setAlphaChannel(alpha);
}

QString KTp::Contact::keyCache() const
{
    return id() + (presence().type() == Tp::ConnectionPresenceTypeOffline ? QLatin1String("-offline") : QLatin1String("-online"));
}

QString KTp::Contact::buildAvatarPath(const QString &avatarToken)
{
    QString cacheDir = QString::fromLatin1(qgetenv("XDG_CACHE_HOME"));
    if (cacheDir.isEmpty()) {
        cacheDir = QString::fromLatin1("%1/.cache").arg(QLatin1String(qgetenv("HOME")));
    }

    if (manager().isNull()) {
        return QString();
    }

    if (manager()->connection().isNull()) {
        return QString();
    }

    Tp::ConnectionPtr conn = manager()->connection();
    QString path = QString::fromLatin1("%1/telepathy/avatars/%2/%3").
        arg(cacheDir).arg(conn->cmName()).arg(conn->protocolName());

    QString avatarFileName = QString::fromLatin1("%1/%2").arg(path).arg(Tp::escapeAsIdentifier(avatarToken));

    return avatarFileName;
}

void KTp::Contact::invalidateAvatarCache()
{
    QPixmapCache::remove(id() + QLatin1String("-offline"));
    QPixmapCache::remove(id() + QLatin1String("-online"));
}

QStringList KTp::Contact::getCommonElements(const QStringList &list1, const QStringList &list2)
{
    /* QStringList::contains(QString) perform iterative comparsion, so there is no reason
     * to select smaller list as base for this cycle. */
    QStringList commonElements;
    Q_FOREACH(const QString &i, list1) {
        if (list2.contains(i)) {
            commonElements << i;
        }
    }
    return commonElements;
}
<commit_msg>KTp::Contact: Check manager() pointer for null in *Capability() methods.<commit_after>/*
* Copyright (C) 2012 David Edmundson <kde@davidedmundson.co.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; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include "contact.h"

#include <TelepathyQt/ContactManager>
#include <TelepathyQt/Connection>
#include <TelepathyQt/ContactCapabilities>
#include <TelepathyQt/AvatarData>
#include <TelepathyQt/Utils>

#include <QBitmap>
#include <QPixmap>
#include <QPixmapCache>

#include <KIconLoader>
#include <KConfigGroup>
#include <KConfig>

#include "capabilities-hack-private.h"

KTp::Contact::Contact(Tp::ContactManager *manager, const Tp::ReferencedHandles &handle, const Tp::Features &requestedFeatures, const QVariantMap &attributes)
    : Tp::Contact(manager, handle, requestedFeatures, attributes)
{
    connect(manager->connection().data(), SIGNAL(destroyed()), SIGNAL(invalidated()));
    connect(manager->connection().data(), SIGNAL(invalidated(Tp::DBusProxy*,QString,QString)), SIGNAL(invalidated()));
    connect(this, SIGNAL(avatarTokenChanged(QString)), SLOT(invalidateAvatarCache()));
    connect(this, SIGNAL(avatarDataChanged(Tp::AvatarData)), SLOT(invalidateAvatarCache()));
}

KTp::Presence KTp::Contact::presence() const
{
    return KTp::Presence(Tp::Contact::presence());
}

bool KTp::Contact::textChatCapability() const
{
    if (!manager() || !manager()->connection()) {
        return false;
    }

    return capabilities().textChats();
}

bool KTp::Contact::audioCallCapability() const
{
    if (!manager() || !manager()->connection()) {
        return false;
    }

    Tp::ConnectionPtr connection = manager()->connection();
    bool contactCanStreamAudio = CapabilitiesHackPrivate::audioCalls(
                capabilities(), connection->cmName());
    bool selfCanStreamAudio = CapabilitiesHackPrivate::audioCalls(
                connection->selfContact()->capabilities(), connection->cmName());
    return contactCanStreamAudio && selfCanStreamAudio;
}

bool KTp::Contact::videoCallCapability() const
{
    if (!manager() || !manager()->connection()) {
        return false;
    }

    Tp::ConnectionPtr connection = manager()->connection();
    bool contactCanStreamVideo = CapabilitiesHackPrivate::videoCalls(
                capabilities(), connection->cmName());
    bool selfCanStreamVideo = CapabilitiesHackPrivate::videoCalls(
                connection->selfContact()->capabilities(), connection->cmName());
    return contactCanStreamVideo && selfCanStreamVideo;
}

bool KTp::Contact::fileTransferCapability()  const
{
    if (!manager() || !manager()->connection()) {
        return false;
    }

    bool contactCanHandleFiles = capabilities().fileTransfers();
    bool selfCanHandleFiles = manager()->connection()->selfContact()->capabilities().fileTransfers();
    return contactCanHandleFiles && selfCanHandleFiles;
}

bool KTp::Contact::collaborativeEditingCapability() const
{
    if (!manager() || !manager()->connection()) {
        return false;
    }

    static const QString collab(QLatin1String("infinote"));
    bool selfCanShare = manager()->connection()->selfContact()->capabilities().streamTubes(collab);
    bool otherCanShare = capabilities().streamTubes(collab);
    return selfCanShare && otherCanShare;
}

QStringList KTp::Contact::dbusTubeServicesCapability() const
{
    if (!manager() || !manager()->connection()) {
        return QStringList();
    }

    return getCommonElements(capabilities().dbusTubeServices(),
                             manager()->connection()->selfContact()->capabilities().dbusTubeServices());
}

QStringList KTp::Contact::streamTubeServicesCapability() const
{
    if (!manager() || !manager()->connection()) {
        return QStringList();
    }

    return getCommonElements(capabilities().streamTubeServices(),
                             manager()->connection()->selfContact()->capabilities().streamTubeServices());
}

QStringList KTp::Contact::clientTypes() const
{
    /* Temporary workaround for upstream bug https://bugs.freedesktop.org/show_bug.cgi?id=55883)
     * Close https://bugs.kde.org/show_bug.cgi?id=308217 when fixed upstream */
    if (Tp::Contact::presence().type() == Tp::ConnectionPresenceTypeOffline) {
        return QStringList();
    }

    //supress any errors trying to access ClientTypes when we don't have them
    if (! actualFeatures().contains(Tp::Contact::FeatureClientTypes)) {
        return QStringList();
    }

    return Tp::Contact::clientTypes();
}

QPixmap KTp::Contact::avatarPixmap()
{
    QPixmap avatar;

    //check pixmap cache for the avatar, if not present, load the avatar
    if (!QPixmapCache::find(keyCache(), avatar)){
        QString file = avatarData().fileName;

        //if contact does not provide path, let's see if we have avatar for the stored token
        if (file.isEmpty()) {
            KConfig config(QLatin1String("ktelepathy-avatarsrc"));
            KConfigGroup avatarTokenGroup = config.group(id());
            QString avatarToken = avatarTokenGroup.readEntry(QLatin1String("avatarToken"));
            //only bother loading the pixmap if the token is not empty
            if (!avatarToken.isEmpty()) {
                avatar.load(buildAvatarPath(avatarToken));
            }
        } else {
            avatar.load(file);
        }

        //if neither above succeeded, we need to load the icon
        if (avatar.isNull()) {
            avatar = KIconLoader::global()->loadIcon(QLatin1String("im-user"), KIconLoader::NoGroup, 96);
        }

        //if the contact is offline, gray it out
        if (presence().type() == Tp::ConnectionPresenceTypeOffline) {
            avatarToGray(avatar);
        }

        //insert the contact into pixmap cache for faster lookup
        QPixmapCache::insert(keyCache(), avatar);
    }

    return avatar;
}

void KTp::Contact::avatarToGray(QPixmap &avatar)
{
    QImage image = avatar.toImage();
    QPixmap alpha= avatar.alphaChannel();
    for (int i = 0; i < image.width(); ++i) {
        for (int j = 0; j < image.height(); ++j) {
            int colour = qGray(image.pixel(i, j));
            image.setPixel(i, j, qRgb(colour, colour, colour));
        }
    }
    avatar = avatar.fromImage(image);
    avatar.setAlphaChannel(alpha);
}

QString KTp::Contact::keyCache() const
{
    return id() + (presence().type() == Tp::ConnectionPresenceTypeOffline ? QLatin1String("-offline") : QLatin1String("-online"));
}

QString KTp::Contact::buildAvatarPath(const QString &avatarToken)
{
    QString cacheDir = QString::fromLatin1(qgetenv("XDG_CACHE_HOME"));
    if (cacheDir.isEmpty()) {
        cacheDir = QString::fromLatin1("%1/.cache").arg(QLatin1String(qgetenv("HOME")));
    }

    if (manager().isNull()) {
        return QString();
    }

    if (manager()->connection().isNull()) {
        return QString();
    }

    Tp::ConnectionPtr conn = manager()->connection();
    QString path = QString::fromLatin1("%1/telepathy/avatars/%2/%3").
        arg(cacheDir).arg(conn->cmName()).arg(conn->protocolName());

    QString avatarFileName = QString::fromLatin1("%1/%2").arg(path).arg(Tp::escapeAsIdentifier(avatarToken));

    return avatarFileName;
}

void KTp::Contact::invalidateAvatarCache()
{
    QPixmapCache::remove(id() + QLatin1String("-offline"));
    QPixmapCache::remove(id() + QLatin1String("-online"));
}

QStringList KTp::Contact::getCommonElements(const QStringList &list1, const QStringList &list2)
{
    /* QStringList::contains(QString) perform iterative comparsion, so there is no reason
     * to select smaller list as base for this cycle. */
    QStringList commonElements;
    Q_FOREACH(const QString &i, list1) {
        if (list2.contains(i)) {
            commonElements << i;
        }
    }
    return commonElements;
}
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/accessors/p9_mvpd_ring_funcs.H $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2012,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* 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.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
// $Id: p9_mvpd_ring_funcs.H,v 1.4 2014/07/16 19:07:08 cswenson Exp $
/**
 *  @file p9_mvpd_ring_funcs.H
 *
 *  @brief Prototype for p9_mvpd_ring_funcs()
 */

#ifndef    _HWP_MVPDRINGFUNCS_
#define    _HWP_MVPDRINGFUNCS_

#include   <fapi2.H>

namespace fapi2
{

///
/// @brief Enumeration of mvpdRingFunc ops
///
enum mvpdRingFuncOp
{
    MVPD_RING_GET,
    MVPD_RING_SET,
};

typedef ReturnCode (*mvpdRingFuncs_FP_t) (
    mvpdRingFuncOp,
    MvpdRecord,
    MvpdKeyword,
    const Target<TARGET_TYPE_PROC_CHIP>&,
    const uint8_t,
    const uint64_t,
    const uint8_t,
    uint8_t*,
    uint32_t& );

extern "C"
{

    /**
     * @brief   get or set the requested ring for the record and keyword
     *          for the specified target CPU.
     *
     *          detailed comments on get and set are in the
     *          getMvpdRing.H and setMvpdRing.H and apply here as well.
     *
     * @param i_mvpdRingFuncOp - indicate get or set via enum mvpdRingFuncOp
     * @param i_record         - Record enumerator
     * @param i_keyword        - Keyword enumerator
     * @param i_fapiTarget     - cpu target
     * @param i_chipletId      - Chiplet ID
     * @param i_evenOddMask    - Even (0) or odd (1) EX. Disregarded for other chiplets.
     * @param i_ringId         - Ring ID
     * @param i_pRingBuf       - The buffer to receive or send the ring
     * @param io_rRingBufsize  - Size of ring / ring buffer
     *
     * @return fapi2::ReturnCode -   FAPI_RC_SUCCESS if success,
     *                              relevant error code for failure.
     */
    ReturnCode mvpdRingFunc( mvpdRingFuncOp       i_mvpdRingFuncOp,
                             MvpdRecord           i_record,
                             MvpdKeyword          i_keyword,
                             const Target<TARGET_TYPE_PROC_CHIP>&
                             i_fapiTarget,
                             const uint8_t        i_chipletId,
                             const uint8_t        i_evenOdd,
                             const uint8_t        i_ringId,
                             uint8_t*             i_pRingBuf,
                             uint32_t&            io_rRingBufsize );

} // extern "C"
} // namespace fapi
#endif
<commit_msg>L3 review and update to p9_mvpd_ring_funcs_errors.xml and<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/accessors/p9_mvpd_ring_funcs.H $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2012,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* 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.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
// $Id: p9_mvpd_ring_funcs.H,v 1.4 2014/07/16 19:07:08 cswenson Exp $
/**
 *  @file p9_mvpd_ring_funcs.H
 *
 *  @brief Prototype for p9_mvpd_ring_funcs()
 */

#ifndef    _HWP_MVPDRINGFUNCS_
#define    _HWP_MVPDRINGFUNCS_

#include   <fapi2.H>

namespace fapi2
{

///
/// @brief Enumeration of mvpdRingFunc ops
///
enum mvpdRingFuncOp
{
    MVPD_RING_GET,
    MVPD_RING_SET,
};

typedef ReturnCode (*mvpdRingFuncs_FP_t) (
    const Target<TARGET_TYPE_PROC_CHIP>&,
    mvpdRingFuncOp,
    MvpdRecord,
    MvpdKeyword,
    const uint8_t,
    const uint64_t,
    const uint8_t,
    uint8_t*,
    uint32_t& );

extern "C"
{

    /**
     * @brief   get or set the requested ring for the record and keyword
     *          for the specified target CPU.
     *
     *          detailed comments on get and set are in the
     *          getMvpdRing.H and setMvpdRing.H and apply here as well.
     *
     * @param i_fapiTarget     - cpu target
     * @param i_mvpdRingFuncOp - indicate get or set via enum mvpdRingFuncOp
     * @param i_record         - Record enumerator
     * @param i_keyword        - Keyword enumerator
     * @param i_chipletId      - Chiplet ID
     * @param i_evenOddMask    - Even (0) or odd (1) EX. Disregarded for other chiplets.
     * @param i_ringId         - Ring ID
     * @param o_pRingBuf       - The buffer to receive or send the ring
     * @param io_rRingBufsize  - Size of ring / ring buffer
     *
     * @return fapi2::ReturnCode -   FAPI_RC_SUCCESS if success,
     *                              relevant error code for failure.
     */
    ReturnCode mvpdRingFunc( const Target<TARGET_TYPE_PROC_CHIP>&
                             i_fapiTarget,
                             mvpdRingFuncOp       i_mvpdRingFuncOp,
                             MvpdRecord           i_record,
                             MvpdKeyword          i_keyword,
                             const uint8_t        i_chipletId,
                             const uint8_t        i_evenOdd,
                             const uint8_t        i_ringId,
                             uint8_t*             o_pRingBuf,
                             uint32_t&            io_rRingBufsize );

} // extern "C"
} // namespace fapi
#endif
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/initfiles/p9_fbc_ioe_dl_scom.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2016,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* 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.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
#include "p9_fbc_ioe_dl_scom.H"
#include <stdint.h>
#include <stddef.h>
#include <fapi2.H>

using namespace fapi2;

constexpr uint64_t literal_0x0B = 0x0B;
constexpr uint64_t literal_0x0 = 0x0;
constexpr uint64_t literal_0xE00 = 0xE00;
constexpr uint64_t literal_0x0000 = 0x0000;
constexpr uint64_t literal_0b11 = 0b11;

fapi2::ReturnCode p9_fbc_ioe_dl_scom(const fapi2::Target<fapi2::TARGET_TYPE_XBUS>& TGT0,
                                     const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& TGT1)
{
    {
        fapi2::ATTR_EC_Type   l_chip_ec;
        fapi2::ATTR_NAME_Type l_chip_id;
        FAPI_TRY(FAPI_ATTR_GET_PRIVILEGED(fapi2::ATTR_NAME, TGT1, l_chip_id));
        FAPI_TRY(FAPI_ATTR_GET_PRIVILEGED(fapi2::ATTR_EC, TGT1, l_chip_ec));
        fapi2::buffer<uint64_t> l_scom_buffer;
        {
            FAPI_TRY(fapi2::getScom( TGT0, 0x601180aull, l_scom_buffer ));

            constexpr auto l_PB_IOE_LL1_CONFIG_LINK_PAIR_ON = 0x1;
            l_scom_buffer.insert<0, 1, 63, uint64_t>(l_PB_IOE_LL1_CONFIG_LINK_PAIR_ON );
            constexpr auto l_PB_IOE_LL1_CONFIG_CRC_LANE_ID_ON = 0x1;
            l_scom_buffer.insert<2, 1, 63, uint64_t>(l_PB_IOE_LL1_CONFIG_CRC_LANE_ID_ON );

            if (((l_chip_id == 0x5) && (l_chip_ec == 0x10)) )
            {
                l_scom_buffer.insert<12, 4, 60, uint64_t>(literal_0x0B );
            }
            else if (((l_chip_id == 0x5) && (l_chip_ec == 0x20)) || ((l_chip_id == 0x5) && (l_chip_ec == 0x21))
                     || ((l_chip_id == 0x6) && (l_chip_ec == 0x10)) )
            {
                l_scom_buffer.insert<11, 5, 59, uint64_t>(literal_0x0B );
            }

            l_scom_buffer.insert<28, 4, 60, uint64_t>(literal_0x0 );
            constexpr auto l_PB_IOE_LL1_CONFIG_SL_UE_CRC_ERR_ON = 0x1;
            l_scom_buffer.insert<4, 1, 63, uint64_t>(l_PB_IOE_LL1_CONFIG_SL_UE_CRC_ERR_ON );
            FAPI_TRY(fapi2::putScom(TGT0, 0x601180aull, l_scom_buffer));
        }
        {
            FAPI_TRY(fapi2::getScom( TGT0, 0x6011818ull, l_scom_buffer ));

            l_scom_buffer.insert<8, 3, 61, uint64_t>(literal_0xE00 );
            l_scom_buffer.insert<32, 16, 48, uint64_t>(literal_0x0000 );
            l_scom_buffer.insert<48, 16, 48, uint64_t>(literal_0x0000 );
            l_scom_buffer.insert<4, 4, 60, uint64_t>(literal_0x0 );
            l_scom_buffer.insert<0, 4, 60, uint64_t>(literal_0x0 );
            FAPI_TRY(fapi2::putScom(TGT0, 0x6011818ull, l_scom_buffer));
        }
        {
            FAPI_TRY(fapi2::getScom( TGT0, 0x6011819ull, l_scom_buffer ));

            if (((l_chip_id == 0x5) && (l_chip_ec == 0x10)) )
            {
                l_scom_buffer.insert<8, 2, 62, uint64_t>(literal_0b11 );
            }
            else if (((l_chip_id == 0x5) && (l_chip_ec == 0x20)) || ((l_chip_id == 0x5) && (l_chip_ec == 0x21))
                     || ((l_chip_id == 0x6) && (l_chip_ec == 0x10)) )
            {
                l_scom_buffer.insert<8, 3, 61, uint64_t>(literal_0b11 );
            }

            l_scom_buffer.insert<32, 16, 48, uint64_t>(literal_0x0000 );
            l_scom_buffer.insert<48, 16, 48, uint64_t>(literal_0x0000 );
            l_scom_buffer.insert<4, 4, 60, uint64_t>(literal_0x0 );
            l_scom_buffer.insert<0, 4, 60, uint64_t>(literal_0x0 );
            FAPI_TRY(fapi2::putScom(TGT0, 0x6011819ull, l_scom_buffer));
        }

    };
fapi_try_exit:
    return fapi2::current_err;
}
<commit_msg>DLL RAS Fir settings update<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/initfiles/p9_fbc_ioe_dl_scom.C $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2016,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* 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.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
#include "p9_fbc_ioe_dl_scom.H"
#include <stdint.h>
#include <stddef.h>
#include <fapi2.H>

using namespace fapi2;

constexpr uint64_t literal_0x0B = 0x0B;
constexpr uint64_t literal_0xF = 0xF;
constexpr uint64_t literal_0b111 = 0b111;
constexpr uint64_t literal_0x6 = 0x6;
constexpr uint64_t literal_0x7 = 0x7;

fapi2::ReturnCode p9_fbc_ioe_dl_scom(const fapi2::Target<fapi2::TARGET_TYPE_XBUS>& TGT0,
                                     const fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& TGT1)
{
    {
        fapi2::ATTR_EC_Type   l_chip_ec;
        fapi2::ATTR_NAME_Type l_chip_id;
        FAPI_TRY(FAPI_ATTR_GET_PRIVILEGED(fapi2::ATTR_NAME, TGT1, l_chip_id));
        FAPI_TRY(FAPI_ATTR_GET_PRIVILEGED(fapi2::ATTR_EC, TGT1, l_chip_ec));
        fapi2::buffer<uint64_t> l_scom_buffer;
        {
            FAPI_TRY(fapi2::getScom( TGT0, 0x601180aull, l_scom_buffer ));

            constexpr auto l_PB_IOE_LL1_CONFIG_LINK_PAIR_ON = 0x1;
            l_scom_buffer.insert<0, 1, 63, uint64_t>(l_PB_IOE_LL1_CONFIG_LINK_PAIR_ON );
            constexpr auto l_PB_IOE_LL1_CONFIG_CRC_LANE_ID_ON = 0x1;
            l_scom_buffer.insert<2, 1, 63, uint64_t>(l_PB_IOE_LL1_CONFIG_CRC_LANE_ID_ON );

            if (((l_chip_id == 0x5) && (l_chip_ec == 0x10)) )
            {
                l_scom_buffer.insert<12, 4, 60, uint64_t>(literal_0x0B );
            }
            else if (((l_chip_id == 0x5) && (l_chip_ec == 0x20)) || ((l_chip_id == 0x5) && (l_chip_ec == 0x21))
                     || ((l_chip_id == 0x6) && (l_chip_ec == 0x10)) )
            {
                l_scom_buffer.insert<11, 5, 59, uint64_t>(literal_0x0B );
            }

            l_scom_buffer.insert<28, 4, 60, uint64_t>(literal_0xF );
            constexpr auto l_PB_IOE_LL1_CONFIG_SL_UE_CRC_ERR_ON = 0x1;
            l_scom_buffer.insert<4, 1, 63, uint64_t>(l_PB_IOE_LL1_CONFIG_SL_UE_CRC_ERR_ON );
            FAPI_TRY(fapi2::putScom(TGT0, 0x601180aull, l_scom_buffer));
        }
        {
            FAPI_TRY(fapi2::getScom( TGT0, 0x6011818ull, l_scom_buffer ));

            l_scom_buffer.insert<8, 3, 61, uint64_t>(literal_0b111 );
            l_scom_buffer.insert<4, 4, 60, uint64_t>(literal_0xF );
            l_scom_buffer.insert<0, 4, 60, uint64_t>(literal_0x6 );
            FAPI_TRY(fapi2::putScom(TGT0, 0x6011818ull, l_scom_buffer));
        }
        {
            FAPI_TRY(fapi2::getScom( TGT0, 0x6011819ull, l_scom_buffer ));

            if (((l_chip_id == 0x5) && (l_chip_ec == 0x10)) )
            {
                l_scom_buffer.insert<8, 2, 62, uint64_t>(literal_0b111 );
            }
            else if (((l_chip_id == 0x5) && (l_chip_ec == 0x20)) || ((l_chip_id == 0x5) && (l_chip_ec == 0x21))
                     || ((l_chip_id == 0x6) && (l_chip_ec == 0x10)) )
            {
                l_scom_buffer.insert<8, 3, 61, uint64_t>(literal_0b111 );
            }

            l_scom_buffer.insert<4, 4, 60, uint64_t>(literal_0xF );
            l_scom_buffer.insert<0, 4, 60, uint64_t>(literal_0x7 );
            FAPI_TRY(fapi2::putScom(TGT0, 0x6011819ull, l_scom_buffer));
        }

    };
fapi_try_exit:
    return fapi2::current_err;
}
<|endoftext|>


<commit_before>#include "startPosition.h"

using namespace twoDModel::items;

const QSizeF size = QSizeF(13, 13);
const int lineWidth = 3;

StartPosition::StartPosition(QGraphicsItem *parent)
	: RotateItem(parent)
{
	RotateItem::init();
}

QRectF StartPosition::boundingRect() const
{
	return QRectF(-size.width() / 2, -size.height() / 2, size.width(), size.height());
}

void StartPosition::drawItem(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
	Q_UNUSED(option)
	Q_UNUSED(widget)
	painter->save();
	QPen pen(Qt::red);
	pen.setWidth(lineWidth);
	painter->setPen(pen);
	painter->drawLine(-size.width() / 2, -size.height() / 2, size.width() / 2, size.height() / 2);
	painter->drawLine(-size.width() / 2, size.height() / 2, size.width() / 2, -size.height() / 2);
	painter->restore();
}

void StartPosition::serialize(QDomElement &robotElement, QDomDocument &target) const
{
	QDomElement startPositionElement = target.createElement("startPosition");
	startPositionElement.setAttribute("startPosX", scenePos().x());
	startPositionElement.setAttribute("startPosY", scenePos().y());
	startPositionElement.setAttribute("direction", rotation());
	robotElement.appendChild(startPositionElement);
}

void StartPosition::deserialize(const QDomElement &robotElement)
{
	const QDomElement startPositionElement = robotElement.firstChildElement("startPosition");
	if (startPositionElement.isNull()) {
		const QStringList robotPositionParts = robotElement.attribute("position").split(":");
		const QString robotX = robotPositionParts.count() != 2 ? "0" : robotPositionParts[0];
		const QString robotY = robotPositionParts.count() != 2 ? "0" : robotPositionParts[1];
		const QString startPositionX = robotElement.hasAttribute("startPosX")
				? robotElement.attribute("startPosX")
				: robotX;
		const QString startPositionY = robotElement.hasAttribute("startPosY")
				? robotElement.attribute("startPosY")
				: robotY;
		setX(startPositionX.toDouble());
		setY(startPositionY.toDouble());
	} else {
		setX(startPositionElement.attribute("x").toDouble());
		setX(startPositionElement.attribute("y").toDouble());
		setRotation(startPositionElement.attribute("direction").toDouble());
	}
}

void StartPosition::drawFieldForResizeItem(QPainter *painter)
{
	Q_UNUSED(painter)
}

void StartPosition::changeDragState(qreal x, qreal y)
{
	Q_UNUSED(x)
	Q_UNUSED(y)
	mDragState = None;
}
<commit_msg>Fixed first appering of start position of 2D model close to the center of the robot<commit_after>#include "startPosition.h"

#include "src/engine/model/constants.h"

using namespace twoDModel::items;

const QSizeF size = QSizeF(13, 13);
const int lineWidth = 3;

StartPosition::StartPosition(QGraphicsItem *parent)
	: RotateItem(parent)
{
	setX(robotWidth / 2);
	setY(robotHeight / 2);
	RotateItem::init();
}

QRectF StartPosition::boundingRect() const
{
	return QRectF(-size.width() / 2, -size.height() / 2, size.width(), size.height());
}

void StartPosition::drawItem(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
	Q_UNUSED(option)
	Q_UNUSED(widget)
	painter->save();
	QPen pen(Qt::red);
	pen.setWidth(lineWidth);
	painter->setPen(pen);
	painter->drawLine(-size.width() / 2, -size.height() / 2, size.width() / 2, size.height() / 2);
	painter->drawLine(-size.width() / 2, size.height() / 2, size.width() / 2, -size.height() / 2);
	painter->restore();
}

void StartPosition::serialize(QDomElement &robotElement, QDomDocument &target) const
{
	QDomElement startPositionElement = target.createElement("startPosition");
	startPositionElement.setAttribute("startPosX", scenePos().x());
	startPositionElement.setAttribute("startPosY", scenePos().y());
	startPositionElement.setAttribute("direction", rotation());
	robotElement.appendChild(startPositionElement);
}

void StartPosition::deserialize(const QDomElement &robotElement)
{
	const QDomElement startPositionElement = robotElement.firstChildElement("startPosition");
	if (startPositionElement.isNull()) {
		const QStringList robotPositionParts = robotElement.attribute("position").split(":");
		const QString robotX = robotPositionParts.count() != 2 ? "0" : robotPositionParts[0];
		const QString robotY = robotPositionParts.count() != 2 ? "0" : robotPositionParts[1];
		const QString startPositionX = robotElement.hasAttribute("startPosX")
				? robotElement.attribute("startPosX")
				: robotX;
		const QString startPositionY = robotElement.hasAttribute("startPosY")
				? robotElement.attribute("startPosY")
				: robotY;
		setX(startPositionX.toDouble() + robotWidth / 2);
		setY(startPositionY.toDouble() + robotHeight / 2);
		setRotation(robotElement.attribute("direction").toDouble());
	} else {
		setX(startPositionElement.attribute("x").toDouble());
		setX(startPositionElement.attribute("y").toDouble());
		setRotation(startPositionElement.attribute("direction").toDouble());
	}
}

void StartPosition::drawFieldForResizeItem(QPainter *painter)
{
	Q_UNUSED(painter)
}

void StartPosition::changeDragState(qreal x, qreal y)
{
	Q_UNUSED(x)
	Q_UNUSED(y)
	mDragState = None;
}
<|endoftext|>