root/src/kits/debugger/settings/TeamSettings.cpp
/*
 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de.
 * Copyright 2013-2015, Rene Gollent, rene@gollent.com.
 * Distributed under the terms of the MIT License.
 */


#include "TeamSettings.h"

#include <new>

#include <Message.h>

#include <AutoLocker.h>

#include "ArchivingUtils.h"
#include "BreakpointSetting.h"
#include "Team.h"
#include "TeamFileManagerSettings.h"
#include "TeamSignalSettings.h"
#include "TeamUiSettings.h"
#include "TeamUiSettingsFactory.h"
#include "UserBreakpoint.h"


TeamSettings::TeamSettings()
{
        fFileManagerSettings = new TeamFileManagerSettings();
        fSignalSettings = new TeamSignalSettings();
}


TeamSettings::TeamSettings(const TeamSettings& other)
{
        try {
                *this = other;
        } catch (...) {
                _Unset();
                throw;
        }
}


TeamSettings::~TeamSettings()
{
        _Unset();
        delete fFileManagerSettings;
        delete fSignalSettings;
}


status_t
TeamSettings::SetTo(Team* team)
{
        _Unset();

        AutoLocker<Team> locker(team);

        fTeamName = team->Name();

        // add breakpoints
        for (UserBreakpointList::ConstIterator it
                        = team->UserBreakpoints().GetIterator();
                UserBreakpoint* breakpoint = it.Next();) {
                BreakpointSetting* breakpointSetting
                        = new(std::nothrow) BreakpointSetting;
                if (breakpointSetting == NULL)
                        return B_NO_MEMORY;

                status_t error = breakpointSetting->SetTo(breakpoint->Location(),
                        breakpoint->IsEnabled(), breakpoint->IsHidden(),
                        breakpoint->Condition());
                if (error == B_OK && !fBreakpoints.AddItem(breakpointSetting))
                        error = B_NO_MEMORY;
                if (error != B_OK) {
                        delete breakpointSetting;
                        return error;
                }
        }

        // add signal configuration

        fSignalSettings->SetDefaultSignalDisposition(
                team->DefaultSignalDisposition());

        const SignalDispositionMappings& mappings
                = team->GetSignalDispositionMappings();

        for (SignalDispositionMappings::const_iterator it = mappings.begin();
                it != mappings.end(); ++it) {
                status_t error = fSignalSettings->AddCustomSignalDisposition(
                        it->first, it->second);
                if (error != B_OK)
                        return error;
        }

        return B_OK;
}


status_t
TeamSettings::SetTo(const BMessage& archive,
        const TeamUiSettingsFactory& factory)
{
        _Unset();

        status_t error = archive.FindString("teamName", &fTeamName);
        if (error != B_OK)
                return error;

        // add breakpoints
        BMessage childArchive;
        for (int32 i = 0; archive.FindMessage("breakpoints", i, &childArchive)
                        == B_OK; i++) {
                BreakpointSetting* breakpointSetting
                        = new(std::nothrow) BreakpointSetting;
                if (breakpointSetting == NULL)
                        return B_NO_MEMORY;

                error = breakpointSetting->SetTo(childArchive);
                if (error == B_OK && !fBreakpoints.AddItem(breakpointSetting))
                        error = B_NO_MEMORY;
                if (error != B_OK) {
                        delete breakpointSetting;
                        return error;
                }
        }

        // add UI settings
        for (int32 i = 0; archive.FindMessage("uisettings", i, &childArchive)
                == B_OK; i++) {
                TeamUiSettings* setting = NULL;
                error = factory.Create(childArchive, setting);
                if (error == B_OK && !fUiSettings.AddItem(setting))
                        error = B_NO_MEMORY;
                if (error != B_OK) {
                        delete setting;
                        return error;
                }
        }

        if (archive.FindMessage("filemanagersettings", &childArchive) == B_OK) {
                error = fFileManagerSettings->SetTo(childArchive);
                if (error != B_OK)
                        return error;
        }

        if (archive.FindMessage("signalsettings", &childArchive) == B_OK) {
                error = fSignalSettings->SetTo(childArchive);
                if (error != B_OK)
                        return error;
        }

        return B_OK;
}


status_t
TeamSettings::WriteTo(BMessage& archive) const
{
        status_t error = archive.AddString("teamName", fTeamName);
        if (error != B_OK)
                return error;

        BMessage childArchive;
        for (int32 i = 0; BreakpointSetting* breakpoint = fBreakpoints.ItemAt(i);
                        i++) {
                error = breakpoint->WriteTo(childArchive);
                if (error != B_OK)
                        return error;

                error = archive.AddMessage("breakpoints", &childArchive);
                if (error != B_OK)
                        return error;
        }

        for (int32 i = 0; TeamUiSettings* uiSetting = fUiSettings.ItemAt(i);
                        i++) {
                error = uiSetting->WriteTo(childArchive);
                if (error != B_OK)
                        return error;

                error = archive.AddMessage("uisettings", &childArchive);
                if (error != B_OK)
                        return error;
        }

        error = fFileManagerSettings->WriteTo(childArchive);
        if (error != B_OK)
                return error;

        error = archive.AddMessage("filemanagersettings", &childArchive);
        if (error != B_OK)
                return error;

        error = fSignalSettings->WriteTo(childArchive);
        if (error != B_OK)
                return error;

        error = archive.AddMessage("signalsettings", &childArchive);
        if (error != B_OK)
                return error;

        return B_OK;
}


int32
TeamSettings::CountBreakpoints() const
{
        return fBreakpoints.CountItems();
}


const BreakpointSetting*
TeamSettings::BreakpointAt(int32 index) const
{
        return fBreakpoints.ItemAt(index);
}


int32
TeamSettings::CountUiSettings() const
{
        return fUiSettings.CountItems();
}


const TeamUiSettings*
TeamSettings::UiSettingAt(int32 index) const
{
        return fUiSettings.ItemAt(index);
}


const TeamUiSettings*
TeamSettings::UiSettingFor(const char* id) const
{
        for (int32 i = 0; i < fUiSettings.CountItems(); i++) {
                TeamUiSettings* settings = fUiSettings.ItemAt(i);
                if (strcmp(settings->ID(), id) == 0)
                        return settings;
        }

        return NULL;
}


status_t
TeamSettings::AddUiSettings(TeamUiSettings* settings)
{
        if (!fUiSettings.AddItem(settings))
                return B_NO_MEMORY;

        return B_OK;
}


TeamSettings&
TeamSettings::operator=(const TeamSettings& other)
{
        if (this == &other)
                return *this;

        _Unset();

        fTeamName = other.fTeamName;

        for (int32 i = 0; BreakpointSetting* breakpoint
                        = other.fBreakpoints.ItemAt(i); i++) {
                BreakpointSetting* clonedBreakpoint
                        = new BreakpointSetting(*breakpoint);
                if (!fBreakpoints.AddItem(clonedBreakpoint)) {
                        delete clonedBreakpoint;
                        throw std::bad_alloc();
                }
        }

        for (int32 i = 0; TeamUiSettings* uiSetting
                        = other.fUiSettings.ItemAt(i); i++) {
                TeamUiSettings* clonedSetting
                        = uiSetting->Clone();
                if (!fUiSettings.AddItem(clonedSetting)) {
                        delete clonedSetting;
                        throw std::bad_alloc();
                }
        }

        *fFileManagerSettings = *other.fFileManagerSettings;

        *fSignalSettings = *other.fSignalSettings;

        return *this;
}


TeamFileManagerSettings*
TeamSettings::FileManagerSettings() const
{
        return fFileManagerSettings;
}


status_t
TeamSettings::SetFileManagerSettings(TeamFileManagerSettings* settings)
{
        try {
                *fFileManagerSettings = *settings;
        } catch (...) {
                return B_NO_MEMORY;
        }

        return B_OK;
}


TeamSignalSettings*
TeamSettings::SignalSettings() const
{
        return fSignalSettings;
}


status_t
TeamSettings::SetSignalSettings(TeamSignalSettings* settings)
{
        try {
                *fSignalSettings = *settings;
        } catch (...) {
                return B_NO_MEMORY;
        }

        return B_OK;
}


void
TeamSettings::_Unset()
{
        for (int32 i = 0; BreakpointSetting* breakpoint = fBreakpoints.ItemAt(i);
                        i++) {
                delete breakpoint;
        }

        for (int32 i = 0; TeamUiSettings* uiSetting = fUiSettings.ItemAt(i); i++)
                delete uiSetting;

        fBreakpoints.MakeEmpty();
        fUiSettings.MakeEmpty();
        fSignalSettings->Unset();

        fTeamName.Truncate(0);
}