<commit_before>/*********************************************************************************
 *
 * Copyright (c) 2017 Josef Adamsson, Denise Härnström
 *
 * Inviwo - Interactive Visualization Workshop
 *
 * Copyright (c) 2017 Inviwo Foundation
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *********************************************************************************/

#include <modules/crystalvisualization/processors/structuremesh.h>
#include <inviwo/core/datastructures/geometry/basicmesh.h>

#include <inviwo/core/interaction/events/pickingevent.h>
#include <inviwo/core/interaction/events/mouseevent.h>
#include <inviwo/core/datastructures/buffer/bufferramprecision.h>
#include <inviwo/core/datastructures/buffer/buffer.h>

namespace inviwo {

// The Class Identifier has to be globally unique. Use a reverse DNS naming scheme
const ProcessorInfo StructureMesh::processorInfo_{
    "envision.StructureMesh",      // Class identifier
    "Structure Mesh",                // Display name
    "Crystal",              // Category
    CodeState::Experimental,  // Code state
    Tags::None,               // Tags
};
const ProcessorInfo StructureMesh::getProcessorInfo() const {
    return processorInfo_;
}

StructureMesh::StructureMesh()
    : Processor()
    , structure_("coordinates")
    , mesh_("mesh")
    , scalingFactor_("scalingFactor", "Scaling factor", 1.f)
    , basis_("basis", "Basis", glm::mat3x3())
    , fullMesh_("fullMesh", "Full mesh", false)
    , animation_("animation", "Animation", false)
    , timestep_("timestep", "Time step", false)
    , enablePicking_("enablePicking", "Enable Picking", false)
    , spherePicking_(this, 0, [&](PickingEvent* p) { handlePicking(p); })
    , inds_("inds", "Picked atoms") {
    addPort(structure_);
    addPort(mesh_);
    addProperty(scalingFactor_);
    addProperty(basis_);
    addProperty(fullMesh_);
    addProperty(animation_);
    addProperty(timestep_);
    addProperty(enablePicking_);
    addProperty(inds_);

    structure_.onChange([&](){
        const auto data = structure_.getVectorData();
        for(int i = colors_.size(); i < data.size(); ++i) {
            colors_.push_back(std::make_unique<FloatVec4Property>("color" + toString(i), "Color " + toString(i),
                                                vec4(1.0f, 1.0f, 1.0f, 1.0f), vec4(0.0f), vec4(1.0f), vec4(0.01f),
                                                InvalidationLevel::InvalidOutput, PropertySemantics::Color));
            addProperty(colors_.back().get(), false);

            radii_.push_back(std::make_unique<FloatProperty>("radius"+ toString(i), "Atom Radius"+ toString(i), 1.0f));
            addProperty(radii_.back().get(), false);
            num_.push_back(std::make_unique<IntProperty>("atoms" + toString(i), "Atoms" + toString(i), 0));
            addProperty(num_.back().get(), false);
        }
        int numSpheres = 0;
        for (const auto &strucs : structure_)
            numSpheres += strucs->size();
        spherePicking_.resize(numSpheres);

    });

}

void StructureMesh::process() {
    if (fullMesh_.get()) {
	auto mesh = std::make_shared<BasicMesh>();
	mesh_.setData(mesh);
	size_t ind = 0;
	for (const auto &strucs : structure_) {
	    for (long long j = 0; j < static_cast<long long>(strucs->size()); ++j) {
        auto center = scalingFactor_.get() * basis_.get() * strucs->at(j) - 0.5f * (basis_.get()[0] + basis_.get()[1] + basis_.get()[2]);
		BasicMesh::sphere(center, radii_[ind]->get(), colors_[ind]->get(), mesh);
	    }
	    ++ind;
	}
    } else {
        if (structure_.isChanged() || animation_.isModified() || std::any_of(num_.begin(), num_.end(),
            [](const std::unique_ptr<IntProperty>& property) {
            return property->isModified();
            }) || enablePicking_.isModified()) {
            int numSpheres = 0;
            size_t pInd = 0;
            for (const auto &strucs : structure_) {
                if (animation_.get()) {
                    numSpheres += num_[pInd]->get();
                    ++pInd;
                }
                else {
                    numSpheres += strucs->size();
                }
            }
            vertexRAM_ = std::make_shared<BufferRAMPrecision<vec3>>(numSpheres);
            colorRAM_ = std::make_shared<BufferRAMPrecision<vec4>>(numSpheres);
            radiiRAM_ = std::make_shared<BufferRAMPrecision<float>>(numSpheres);
            auto mesh = std::make_shared<Mesh>(DrawType::Points, ConnectivityType::None);
            mesh->addBuffer(Mesh::BufferInfo(BufferType::PositionAttrib),
                std::make_shared<Buffer<vec3>>(vertexRAM_));
            mesh->addBuffer(Mesh::BufferInfo(BufferType::ColorAttrib),
                std::make_shared<Buffer<vec4>>(colorRAM_));
            mesh->addBuffer(Mesh::BufferInfo(BufferType::NumberOfBufferTypes, 5),
                std::make_shared<Buffer<float>>(radiiRAM_));

            mesh_.setData(mesh);

            if (enablePicking_.get()) {
                auto pickingRAM = std::make_shared<BufferRAMPrecision<uint32_t>>(numSpheres);
                auto& data = pickingRAM->getDataContainer();
                // fill in picking IDs
                std::iota(data.begin(), data.end(), static_cast<uint32_t>(spherePicking_.getPickingId(0)));

                mesh->addBuffer(Mesh::BufferInfo(BufferType::NumberOfBufferTypes, 4),
                    std::make_shared<Buffer<uint32_t>>(pickingRAM));
            }
        }

        auto& vertices = vertexRAM_->getDataContainer();
        auto& colors = colorRAM_->getDataContainer();
        auto& radii = radiiRAM_->getDataContainer();

        size_t portInd = 0;
        size_t sphereInd = 0;
        for (const auto &strucs : structure_) {
            long long j_start, j_stop;
            j_start = 0;
            j_stop = static_cast<long long>(strucs->size());
            if (animation_.get()) {
                j_start = num_[portInd]->get() * timestep_.get();
                j_stop = num_[portInd]->get() * (timestep_.get() + 1);
            }
            for (long long j = j_start; j < j_stop ; ++j) {
                auto center = scalingFactor_.get() * basis_.get() * strucs->at(j); //- 0.5f * (basis_.get()[0] + basis_.get()[1] + basis_.get()[2]);
                vertices[sphereInd] = center;
                colors[sphereInd] = colors_[portInd]->get();
                radii[sphereInd] = radii_[portInd]->get();
                ++sphereInd;
            }
            ++portInd;
        }
        if (enablePicking_.get()) {
            //Set alpha-layer of picked atoms
            if (!inds_.get().empty()) {
                for (const auto &ind : inds_.get()) {
                    if (ind < sphereInd) {
                        colors[ind].w = 0.5;
                    }
                }
            }
        }
        colorRAM_->getOwner()->invalidateAllOther(colorRAM_.get());
        vertexRAM_->getOwner()->invalidateAllOther(vertexRAM_.get());
        radiiRAM_->getOwner()->invalidateAllOther(radiiRAM_.get());
        invalidate(InvalidationLevel::InvalidOutput);
    }

}

void StructureMesh::handlePicking(PickingEvent* p) {
    if (enablePicking_.get()) {
        if (p->getState() == PickingState::Updated &&
            p->getEvent()->hash() == MouseEvent::chash()) {
            auto me = p->getEventAs<MouseEvent>();
            if ((me->buttonState() & MouseButton::Left) && me->state() != MouseState::Move) {
                auto& color = colorRAM_->getDataContainer();
                std::vector<int> temp = inds_.get();
                auto picked = p->getPickedId();

                if( std::none_of(temp.begin(), temp.end(), [&](unsigned int i){return i == picked;}) ) {
                    temp.push_back(picked);
                    color[picked].w = 0.5;
                } else {
                    temp.erase(std::remove(temp.begin(), temp.end(), picked), temp.end());
                    color[picked].w = 1;
                }
                inds_.set(temp);

                colorRAM_->getOwner()->invalidateAllOther(colorRAM_.get());
                invalidate(InvalidationLevel::InvalidOutput);
                p->markAsUsed();
            }
        }
    }

}

} // namespace

<commit_msg>Update of the BSD2 license.<commit_after>/*********************************************************************************
 *
 * Copyright (c) 2017 Josef Adamsson, Denise Härnström, Anders Rehult
 *
 * Inviwo - Interactive Visualization Workshop
 *
 * Copyright (c) 2017 Inviwo Foundation
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright notice,
 * this list of conditions and the following disclaimer in the documentation
 * and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *********************************************************************************/

#include <modules/crystalvisualization/processors/structuremesh.h>
#include <inviwo/core/datastructures/geometry/basicmesh.h>

#include <inviwo/core/interaction/events/pickingevent.h>
#include <inviwo/core/interaction/events/mouseevent.h>
#include <inviwo/core/datastructures/buffer/bufferramprecision.h>
#include <inviwo/core/datastructures/buffer/buffer.h>

namespace inviwo {

// The Class Identifier has to be globally unique. Use a reverse DNS naming scheme
const ProcessorInfo StructureMesh::processorInfo_{
    "envision.StructureMesh",      // Class identifier
    "Structure Mesh",                // Display name
    "Crystal",              // Category
    CodeState::Experimental,  // Code state
    Tags::None,               // Tags
};
const ProcessorInfo StructureMesh::getProcessorInfo() const {
    return processorInfo_;
}

StructureMesh::StructureMesh()
    : Processor()
    , structure_("coordinates")
    , mesh_("mesh")
    , scalingFactor_("scalingFactor", "Scaling factor", 1.f)
    , basis_("basis", "Basis", glm::mat3x3())
    , fullMesh_("fullMesh", "Full mesh", false)
    , animation_("animation", "Animation", false)
    , timestep_("timestep", "Time step", false)
    , enablePicking_("enablePicking", "Enable Picking", false)
    , spherePicking_(this, 0, [&](PickingEvent* p) { handlePicking(p); })
    , inds_("inds", "Picked atoms") {
    addPort(structure_);
    addPort(mesh_);
    addProperty(scalingFactor_);
    addProperty(basis_);
    addProperty(fullMesh_);
    addProperty(animation_);
    addProperty(timestep_);
    addProperty(enablePicking_);
    addProperty(inds_);

    structure_.onChange([&](){
        const auto data = structure_.getVectorData();
        for(int i = colors_.size(); i < data.size(); ++i) {
            colors_.push_back(std::make_unique<FloatVec4Property>("color" + toString(i), "Color " + toString(i),
                                                vec4(1.0f, 1.0f, 1.0f, 1.0f), vec4(0.0f), vec4(1.0f), vec4(0.01f),
                                                InvalidationLevel::InvalidOutput, PropertySemantics::Color));
            addProperty(colors_.back().get(), false);

            radii_.push_back(std::make_unique<FloatProperty>("radius"+ toString(i), "Atom Radius"+ toString(i), 1.0f));
            addProperty(radii_.back().get(), false);
            num_.push_back(std::make_unique<IntProperty>("atoms" + toString(i), "Atoms" + toString(i), 0));
            addProperty(num_.back().get(), false);
        }
        int numSpheres = 0;
        for (const auto &strucs : structure_)
            numSpheres += strucs->size();
        spherePicking_.resize(numSpheres);

    });

}

void StructureMesh::process() {
    if (fullMesh_.get()) {
	auto mesh = std::make_shared<BasicMesh>();
	mesh_.setData(mesh);
	size_t ind = 0;
	for (const auto &strucs : structure_) {
	    for (long long j = 0; j < static_cast<long long>(strucs->size()); ++j) {
        auto center = scalingFactor_.get() * basis_.get() * strucs->at(j) - 0.5f * (basis_.get()[0] + basis_.get()[1] + basis_.get()[2]);
		BasicMesh::sphere(center, radii_[ind]->get(), colors_[ind]->get(), mesh);
	    }
	    ++ind;
	}
    } else {
        if (structure_.isChanged() || animation_.isModified() || std::any_of(num_.begin(), num_.end(),
            [](const std::unique_ptr<IntProperty>& property) {
            return property->isModified();
            }) || enablePicking_.isModified()) {
            int numSpheres = 0;
            size_t pInd = 0;
            for (const auto &strucs : structure_) {
                if (animation_.get()) {
                    numSpheres += num_[pInd]->get();
                    ++pInd;
                }
                else {
                    numSpheres += strucs->size();
                }
            }
            vertexRAM_ = std::make_shared<BufferRAMPrecision<vec3>>(numSpheres);
            colorRAM_ = std::make_shared<BufferRAMPrecision<vec4>>(numSpheres);
            radiiRAM_ = std::make_shared<BufferRAMPrecision<float>>(numSpheres);
            auto mesh = std::make_shared<Mesh>(DrawType::Points, ConnectivityType::None);
            mesh->addBuffer(Mesh::BufferInfo(BufferType::PositionAttrib),
                std::make_shared<Buffer<vec3>>(vertexRAM_));
            mesh->addBuffer(Mesh::BufferInfo(BufferType::ColorAttrib),
                std::make_shared<Buffer<vec4>>(colorRAM_));
            mesh->addBuffer(Mesh::BufferInfo(BufferType::NumberOfBufferTypes, 5),
                std::make_shared<Buffer<float>>(radiiRAM_));

            mesh_.setData(mesh);

            if (enablePicking_.get()) {
                auto pickingRAM = std::make_shared<BufferRAMPrecision<uint32_t>>(numSpheres);
                auto& data = pickingRAM->getDataContainer();
                // fill in picking IDs
                std::iota(data.begin(), data.end(), static_cast<uint32_t>(spherePicking_.getPickingId(0)));

                mesh->addBuffer(Mesh::BufferInfo(BufferType::NumberOfBufferTypes, 4),
                    std::make_shared<Buffer<uint32_t>>(pickingRAM));
            }
        }

        auto& vertices = vertexRAM_->getDataContainer();
        auto& colors = colorRAM_->getDataContainer();
        auto& radii = radiiRAM_->getDataContainer();

        size_t portInd = 0;
        size_t sphereInd = 0;
        for (const auto &strucs : structure_) {
            long long j_start, j_stop;
            j_start = 0;
            j_stop = static_cast<long long>(strucs->size());
            if (animation_.get()) {
                j_start = num_[portInd]->get() * timestep_.get();
                j_stop = num_[portInd]->get() * (timestep_.get() + 1);
            }
            for (long long j = j_start; j < j_stop ; ++j) {
                auto center = scalingFactor_.get() * basis_.get() * strucs->at(j); //- 0.5f * (basis_.get()[0] + basis_.get()[1] + basis_.get()[2]);
                vertices[sphereInd] = center;
                colors[sphereInd] = colors_[portInd]->get();
                radii[sphereInd] = radii_[portInd]->get();
                ++sphereInd;
            }
            ++portInd;
        }
        if (enablePicking_.get()) {
            //Set alpha-layer of picked atoms
            if (!inds_.get().empty()) {
                for (const auto &ind : inds_.get()) {
                    if (ind < sphereInd) {
                        colors[ind].w = 0.5;
                    }
                }
            }
        }
        colorRAM_->getOwner()->invalidateAllOther(colorRAM_.get());
        vertexRAM_->getOwner()->invalidateAllOther(vertexRAM_.get());
        radiiRAM_->getOwner()->invalidateAllOther(radiiRAM_.get());
        invalidate(InvalidationLevel::InvalidOutput);
    }

}

void StructureMesh::handlePicking(PickingEvent* p) {
    if (enablePicking_.get()) {
        if (p->getState() == PickingState::Updated &&
            p->getEvent()->hash() == MouseEvent::chash()) {
            auto me = p->getEventAs<MouseEvent>();
            if ((me->buttonState() & MouseButton::Left) && me->state() != MouseState::Move) {
                auto& color = colorRAM_->getDataContainer();
                std::vector<int> temp = inds_.get();
                auto picked = p->getPickedId();

                if( std::none_of(temp.begin(), temp.end(), [&](unsigned int i){return i == picked;}) ) {
                    temp.push_back(picked);
                    color[picked].w = 0.5;
                } else {
                    temp.erase(std::remove(temp.begin(), temp.end(), picked), temp.end());
                    color[picked].w = 1;
                }
                inds_.set(temp);

                colorRAM_->getOwner()->invalidateAllOther(colorRAM_.get());
                invalidate(InvalidationLevel::InvalidOutput);
                p->markAsUsed();
            }
        }
    }

}

} // namespace

<|endoftext|>


<commit_before>/*************************************************************************/
/*  grid_container.cpp                                                   */
/*************************************************************************/
/*                       This file is part of:                           */
/*                           GODOT ENGINE                                */
/*                      https://godotengine.org                          */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur.                 */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md).   */
/*                                                                       */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the       */
/* "Software"), to deal in the Software without restriction, including   */
/* without limitation the rights to use, copy, modify, merge, publish,   */
/* distribute, sublicense, and/or sell copies of the Software, and to    */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions:                                             */
/*                                                                       */
/* The above copyright notice and this permission notice shall be        */
/* included in all copies or substantial portions of the Software.       */
/*                                                                       */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
/*************************************************************************/

#include "grid_container.h"
#include "core/templates/rb_set.h"

void GridContainer::_notification(int p_what) {
	switch (p_what) {
		case NOTIFICATION_SORT_CHILDREN: {
			RBMap<int, int> col_minw; // Max of min_width of all controls in each col (indexed by col).
			RBMap<int, int> row_minh; // Max of min_height of all controls in each row (indexed by row).
			RBSet<int> col_expanded; // Columns which have the SIZE_EXPAND flag set.
			RBSet<int> row_expanded; // Rows which have the SIZE_EXPAND flag set.

			int hsep = get_theme_constant(SNAME("h_separation"));
			int vsep = get_theme_constant(SNAME("v_separation"));
			int max_col = MIN(get_child_count(), columns);
			int max_row = ceil((float)get_child_count() / (float)columns);

			// Compute the per-column/per-row data.
			int valid_controls_index = 0;
			for (int i = 0; i < get_child_count(); i++) {
				Control *c = Object::cast_to<Control>(get_child(i));
				if (!c || !c->is_visible_in_tree()) {
					continue;
				}
				if (c->is_set_as_top_level()) {
					continue;
				}

				int row = valid_controls_index / columns;
				int col = valid_controls_index % columns;
				valid_controls_index++;

				Size2i ms = c->get_combined_minimum_size();
				if (col_minw.has(col)) {
					col_minw[col] = MAX(col_minw[col], ms.width);
				} else {
					col_minw[col] = ms.width;
				}
				if (row_minh.has(row)) {
					row_minh[row] = MAX(row_minh[row], ms.height);
				} else {
					row_minh[row] = ms.height;
				}

				if (c->get_h_size_flags() & SIZE_EXPAND) {
					col_expanded.insert(col);
				}
				if (c->get_v_size_flags() & SIZE_EXPAND) {
					row_expanded.insert(row);
				}
			}

			// Consider all empty columns expanded.
			for (int i = valid_controls_index; i < columns; i++) {
				col_expanded.insert(i);
			}

			// Evaluate the remaining space for expanded columns/rows.
			Size2 remaining_space = get_size();
			for (const KeyValue<int, int> &E : col_minw) {
				if (!col_expanded.has(E.key)) {
					remaining_space.width -= E.value;
				}
			}

			for (const KeyValue<int, int> &E : row_minh) {
				if (!row_expanded.has(E.key)) {
					remaining_space.height -= E.value;
				}
			}
			remaining_space.height -= vsep * MAX(max_row - 1, 0);
			remaining_space.width -= hsep * MAX(max_col - 1, 0);

			bool can_fit = false;
			while (!can_fit && col_expanded.size() > 0) {
				// Check if all minwidth constraints are OK if we use the remaining space.
				can_fit = true;
				int max_index = col_expanded.front()->get();
				for (const int &E : col_expanded) {
					if (col_minw[E] > col_minw[max_index]) {
						max_index = E;
					}
					if (can_fit && (remaining_space.width / col_expanded.size()) < col_minw[E]) {
						can_fit = false;
					}
				}

				// If not, the column with maximum minwidth is not expanded.
				if (!can_fit) {
					col_expanded.erase(max_index);
					remaining_space.width -= col_minw[max_index];
				}
			}

			can_fit = false;
			while (!can_fit && row_expanded.size() > 0) {
				// Check if all minheight constraints are OK if we use the remaining space.
				can_fit = true;
				int max_index = row_expanded.front()->get();
				for (const int &E : row_expanded) {
					if (row_minh[E] > row_minh[max_index]) {
						max_index = E;
					}
					if (can_fit && (remaining_space.height / row_expanded.size()) < row_minh[E]) {
						can_fit = false;
					}
				}

				// If not, the row with maximum minheight is not expanded.
				if (!can_fit) {
					row_expanded.erase(max_index);
					remaining_space.height -= row_minh[max_index];
				}
			}

			// Finally, fit the nodes.
			int col_remaining_pixel = 0;
			int col_expand = 0;
			if (col_expanded.size() > 0) {
				col_expand = remaining_space.width / col_expanded.size();
				col_remaining_pixel = remaining_space.width - col_expanded.size() * col_expand;
			}

			int row_remaining_pixel = 0;
			int row_expand = 0;
			if (row_expanded.size() > 0) {
				row_expand = remaining_space.height / row_expanded.size();
				row_remaining_pixel = remaining_space.height - row_expanded.size() * row_expand;
			}

			bool rtl = is_layout_rtl();

			int col_ofs = 0;
			int row_ofs = 0;

			// Calculate the index of rows and columns that receive the remaining pixel.
			int col_remaining_pixel_index = 0;
			for (int i = 0; i < max_col; i++) {
				if (col_remaining_pixel == 0) {
					break;
				}
				if (col_expanded.has(i)) {
					col_remaining_pixel_index = i + 1;
					col_remaining_pixel--;
				}
			}
			int row_remaining_pixel_index = 0;
			for (int i = 0; i < max_row; i++) {
				if (row_remaining_pixel == 0) {
					break;
				}
				if (row_expanded.has(i)) {
					row_remaining_pixel_index = i + 1;
					row_remaining_pixel--;
				}
			}

			valid_controls_index = 0;
			for (int i = 0; i < get_child_count(); i++) {
				Control *c = Object::cast_to<Control>(get_child(i));
				if (!c || !c->is_visible_in_tree()) {
					continue;
				}
				int row = valid_controls_index / columns;
				int col = valid_controls_index % columns;
				valid_controls_index++;

				if (col == 0) {
					if (rtl) {
						col_ofs = get_size().width;
					} else {
						col_ofs = 0;
					}
					if (row > 0) {
						row_ofs += (row_expanded.has(row - 1) ? row_expand : row_minh[row - 1]) + vsep;

						if (row_expanded.has(row - 1) && row - 1 < row_remaining_pixel_index) {
							// Apply the remaining pixel of the previous row.
							row_ofs++;
						}
					}
				}

				Size2 s(col_expanded.has(col) ? col_expand : col_minw[col], row_expanded.has(row) ? row_expand : row_minh[row]);

				// Add the remaining pixel to the expanding columns and rows, starting from left and top.
				if (col_expanded.has(col) && col < col_remaining_pixel_index) {
					s.x++;
				}
				if (row_expanded.has(row) && row < row_remaining_pixel_index) {
					s.y++;
				}

				if (rtl) {
					Point2 p(col_ofs - s.width, row_ofs);
					fit_child_in_rect(c, Rect2(p, s));
					col_ofs -= s.width + hsep;
				} else {
					Point2 p(col_ofs, row_ofs);
					fit_child_in_rect(c, Rect2(p, s));
					col_ofs += s.width + hsep;
				}
			}
		} break;

		case NOTIFICATION_THEME_CHANGED: {
			update_minimum_size();
		} break;

		case NOTIFICATION_TRANSLATION_CHANGED:
		case NOTIFICATION_LAYOUT_DIRECTION_CHANGED: {
			queue_sort();
		} break;
	}
}

void GridContainer::set_columns(int p_columns) {
	ERR_FAIL_COND(p_columns < 1);
	columns = p_columns;
	queue_sort();
	update_minimum_size();
}

int GridContainer::get_columns() const {
	return columns;
}

void GridContainer::_bind_methods() {
	ClassDB::bind_method(D_METHOD("set_columns", "columns"), &GridContainer::set_columns);
	ClassDB::bind_method(D_METHOD("get_columns"), &GridContainer::get_columns);

	ADD_PROPERTY(PropertyInfo(Variant::INT, "columns", PROPERTY_HINT_RANGE, "1,1024,1"), "set_columns", "get_columns");
}

Size2 GridContainer::get_minimum_size() const {
	RBMap<int, int> col_minw;
	RBMap<int, int> row_minh;

	int hsep = get_theme_constant(SNAME("h_separation"));
	int vsep = get_theme_constant(SNAME("v_separation"));

	int max_row = 0;
	int max_col = 0;

	int valid_controls_index = 0;
	for (int i = 0; i < get_child_count(); i++) {
		Control *c = Object::cast_to<Control>(get_child(i));
		if (!c || !c->is_visible()) {
			continue;
		}
		int row = valid_controls_index / columns;
		int col = valid_controls_index % columns;
		valid_controls_index++;

		Size2i ms = c->get_combined_minimum_size();
		if (col_minw.has(col)) {
			col_minw[col] = MAX(col_minw[col], ms.width);
		} else {
			col_minw[col] = ms.width;
		}

		if (row_minh.has(row)) {
			row_minh[row] = MAX(row_minh[row], ms.height);
		} else {
			row_minh[row] = ms.height;
		}
		max_col = MAX(col, max_col);
		max_row = MAX(row, max_row);
	}

	Size2 ms;

	for (const KeyValue<int, int> &E : col_minw) {
		ms.width += E.value;
	}

	for (const KeyValue<int, int> &E : row_minh) {
		ms.height += E.value;
	}

	ms.height += vsep * max_row;
	ms.width += hsep * max_col;

	return ms;
}

GridContainer::GridContainer() {}
<commit_msg>Fixed bug in grid_container with hidden children<commit_after>/*************************************************************************/
/*  grid_container.cpp                                                   */
/*************************************************************************/
/*                       This file is part of:                           */
/*                           GODOT ENGINE                                */
/*                      https://godotengine.org                          */
/*************************************************************************/
/* Copyright (c) 2007-2022 Juan Linietsky, Ariel Manzur.                 */
/* Copyright (c) 2014-2022 Godot Engine contributors (cf. AUTHORS.md).   */
/*                                                                       */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the       */
/* "Software"), to deal in the Software without restriction, including   */
/* without limitation the rights to use, copy, modify, merge, publish,   */
/* distribute, sublicense, and/or sell copies of the Software, and to    */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions:                                             */
/*                                                                       */
/* The above copyright notice and this permission notice shall be        */
/* included in all copies or substantial portions of the Software.       */
/*                                                                       */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */
/*************************************************************************/

#include "grid_container.h"
#include "core/templates/rb_set.h"

void GridContainer::_notification(int p_what) {
	switch (p_what) {
		case NOTIFICATION_SORT_CHILDREN: {
			RBMap<int, int> col_minw; // Max of min_width of all controls in each col (indexed by col).
			RBMap<int, int> row_minh; // Max of min_height of all controls in each row (indexed by row).
			RBSet<int> col_expanded; // Columns which have the SIZE_EXPAND flag set.
			RBSet<int> row_expanded; // Rows which have the SIZE_EXPAND flag set.

			int hsep = get_theme_constant(SNAME("h_separation"));
			int vsep = get_theme_constant(SNAME("v_separation"));

			// Compute the per-column/per-row data.
			int valid_controls_index = 0;
			for (int i = 0; i < get_child_count(); i++) {
				Control *c = Object::cast_to<Control>(get_child(i));
				if (!c || !c->is_visible_in_tree()) {
					continue;
				}
				if (c->is_set_as_top_level()) {
					continue;
				}

				int row = valid_controls_index / columns;
				int col = valid_controls_index % columns;
				valid_controls_index++;

				Size2i ms = c->get_combined_minimum_size();
				if (col_minw.has(col)) {
					col_minw[col] = MAX(col_minw[col], ms.width);
				} else {
					col_minw[col] = ms.width;
				}
				if (row_minh.has(row)) {
					row_minh[row] = MAX(row_minh[row], ms.height);
				} else {
					row_minh[row] = ms.height;
				}

				if (c->get_h_size_flags() & SIZE_EXPAND) {
					col_expanded.insert(col);
				}
				if (c->get_v_size_flags() & SIZE_EXPAND) {
					row_expanded.insert(row);
				}
			}

			int max_col = MIN(valid_controls_index, columns);
			int max_row = ceil((float)valid_controls_index / (float)columns);

			// Consider all empty columns expanded.
			for (int i = valid_controls_index; i < columns; i++) {
				col_expanded.insert(i);
			}

			// Evaluate the remaining space for expanded columns/rows.
			Size2 remaining_space = get_size();
			for (const KeyValue<int, int> &E : col_minw) {
				if (!col_expanded.has(E.key)) {
					remaining_space.width -= E.value;
				}
			}

			for (const KeyValue<int, int> &E : row_minh) {
				if (!row_expanded.has(E.key)) {
					remaining_space.height -= E.value;
				}
			}
			remaining_space.height -= vsep * MAX(max_row - 1, 0);
			remaining_space.width -= hsep * MAX(max_col - 1, 0);

			bool can_fit = false;
			while (!can_fit && col_expanded.size() > 0) {
				// Check if all minwidth constraints are OK if we use the remaining space.
				can_fit = true;
				int max_index = col_expanded.front()->get();
				for (const int &E : col_expanded) {
					if (col_minw[E] > col_minw[max_index]) {
						max_index = E;
					}
					if (can_fit && (remaining_space.width / col_expanded.size()) < col_minw[E]) {
						can_fit = false;
					}
				}

				// If not, the column with maximum minwidth is not expanded.
				if (!can_fit) {
					col_expanded.erase(max_index);
					remaining_space.width -= col_minw[max_index];
				}
			}

			can_fit = false;
			while (!can_fit && row_expanded.size() > 0) {
				// Check if all minheight constraints are OK if we use the remaining space.
				can_fit = true;
				int max_index = row_expanded.front()->get();
				for (const int &E : row_expanded) {
					if (row_minh[E] > row_minh[max_index]) {
						max_index = E;
					}
					if (can_fit && (remaining_space.height / row_expanded.size()) < row_minh[E]) {
						can_fit = false;
					}
				}

				// If not, the row with maximum minheight is not expanded.
				if (!can_fit) {
					row_expanded.erase(max_index);
					remaining_space.height -= row_minh[max_index];
				}
			}

			// Finally, fit the nodes.
			int col_remaining_pixel = 0;
			int col_expand = 0;
			if (col_expanded.size() > 0) {
				col_expand = remaining_space.width / col_expanded.size();
				col_remaining_pixel = remaining_space.width - col_expanded.size() * col_expand;
			}

			int row_remaining_pixel = 0;
			int row_expand = 0;
			if (row_expanded.size() > 0) {
				row_expand = remaining_space.height / row_expanded.size();
				row_remaining_pixel = remaining_space.height - row_expanded.size() * row_expand;
			}

			bool rtl = is_layout_rtl();

			int col_ofs = 0;
			int row_ofs = 0;

			// Calculate the index of rows and columns that receive the remaining pixel.
			int col_remaining_pixel_index = 0;
			for (int i = 0; i < max_col; i++) {
				if (col_remaining_pixel == 0) {
					break;
				}
				if (col_expanded.has(i)) {
					col_remaining_pixel_index = i + 1;
					col_remaining_pixel--;
				}
			}
			int row_remaining_pixel_index = 0;
			for (int i = 0; i < max_row; i++) {
				if (row_remaining_pixel == 0) {
					break;
				}
				if (row_expanded.has(i)) {
					row_remaining_pixel_index = i + 1;
					row_remaining_pixel--;
				}
			}

			valid_controls_index = 0;
			for (int i = 0; i < get_child_count(); i++) {
				Control *c = Object::cast_to<Control>(get_child(i));
				if (!c || !c->is_visible_in_tree()) {
					continue;
				}
				int row = valid_controls_index / columns;
				int col = valid_controls_index % columns;
				valid_controls_index++;

				if (col == 0) {
					if (rtl) {
						col_ofs = get_size().width;
					} else {
						col_ofs = 0;
					}
					if (row > 0) {
						row_ofs += (row_expanded.has(row - 1) ? row_expand : row_minh[row - 1]) + vsep;

						if (row_expanded.has(row - 1) && row - 1 < row_remaining_pixel_index) {
							// Apply the remaining pixel of the previous row.
							row_ofs++;
						}
					}
				}

				Size2 s(col_expanded.has(col) ? col_expand : col_minw[col], row_expanded.has(row) ? row_expand : row_minh[row]);

				// Add the remaining pixel to the expanding columns and rows, starting from left and top.
				if (col_expanded.has(col) && col < col_remaining_pixel_index) {
					s.x++;
				}
				if (row_expanded.has(row) && row < row_remaining_pixel_index) {
					s.y++;
				}

				if (rtl) {
					Point2 p(col_ofs - s.width, row_ofs);
					fit_child_in_rect(c, Rect2(p, s));
					col_ofs -= s.width + hsep;
				} else {
					Point2 p(col_ofs, row_ofs);
					fit_child_in_rect(c, Rect2(p, s));
					col_ofs += s.width + hsep;
				}
			}
		} break;

		case NOTIFICATION_THEME_CHANGED: {
			update_minimum_size();
		} break;

		case NOTIFICATION_TRANSLATION_CHANGED:
		case NOTIFICATION_LAYOUT_DIRECTION_CHANGED: {
			queue_sort();
		} break;
	}
}

void GridContainer::set_columns(int p_columns) {
	ERR_FAIL_COND(p_columns < 1);
	columns = p_columns;
	queue_sort();
	update_minimum_size();
}

int GridContainer::get_columns() const {
	return columns;
}

void GridContainer::_bind_methods() {
	ClassDB::bind_method(D_METHOD("set_columns", "columns"), &GridContainer::set_columns);
	ClassDB::bind_method(D_METHOD("get_columns"), &GridContainer::get_columns);

	ADD_PROPERTY(PropertyInfo(Variant::INT, "columns", PROPERTY_HINT_RANGE, "1,1024,1"), "set_columns", "get_columns");
}

Size2 GridContainer::get_minimum_size() const {
	RBMap<int, int> col_minw;
	RBMap<int, int> row_minh;

	int hsep = get_theme_constant(SNAME("h_separation"));
	int vsep = get_theme_constant(SNAME("v_separation"));

	int max_row = 0;
	int max_col = 0;

	int valid_controls_index = 0;
	for (int i = 0; i < get_child_count(); i++) {
		Control *c = Object::cast_to<Control>(get_child(i));
		if (!c || !c->is_visible()) {
			continue;
		}
		int row = valid_controls_index / columns;
		int col = valid_controls_index % columns;
		valid_controls_index++;

		Size2i ms = c->get_combined_minimum_size();
		if (col_minw.has(col)) {
			col_minw[col] = MAX(col_minw[col], ms.width);
		} else {
			col_minw[col] = ms.width;
		}

		if (row_minh.has(row)) {
			row_minh[row] = MAX(row_minh[row], ms.height);
		} else {
			row_minh[row] = ms.height;
		}
		max_col = MAX(col, max_col);
		max_row = MAX(row, max_row);
	}

	Size2 ms;

	for (const KeyValue<int, int> &E : col_minw) {
		ms.width += E.value;
	}

	for (const KeyValue<int, int> &E : row_minh) {
		ms.height += E.value;
	}

	ms.height += vsep * max_row;
	ms.width += hsep * max_col;

	return ms;
}

GridContainer::GridContainer() {}
<|endoftext|>


<commit_before>/*
    KPeople
    Copyright (C) 2012  Aleix Pol Gonzalez <aleixpol@blue-systems.com>
    Copyright (C) 2013  Martin Klapetek <mklapetek@kde.org>

    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 Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include "persondata.h"
#include "persons-model.h"
#include "person-item.h"
#include "persons-presence-model.h"

#include <Nepomuk2/Resource>
#include <Nepomuk2/Query/Query>
#include <Nepomuk2/ResourceManager>
#include <Nepomuk2/ResourceWatcher>
#include <Nepomuk2/Vocabulary/PIMO>
#include <Nepomuk2/Vocabulary/NCO>
#include <Nepomuk2/Vocabulary/NIE>
#include <Nepomuk2/Variant>

#include <Soprano/Model>
#include <Soprano/QueryResultIterator>

#include <KDebug>

using namespace Nepomuk2::Vocabulary;

class PersonDataPrivate {
public:
    QString uri;
    QString id;
    Nepomuk2::Resource res;
};

K_GLOBAL_STATIC(PersonsPresenceModel, s_presenceModel)

PersonData::PersonData(QObject *parent)
    : QObject(parent),
    d_ptr(new PersonDataPrivate)
{
}

PersonData::PersonData(const QString &uri, QObject *parent)
    : QObject(parent),
      d_ptr(new PersonDataPrivate)
{
    setUri(uri);
}

void PersonData::setContactId(const QString &id)
{
    Q_D(PersonData);
    if (d->id == id) {
        return;
    }

    d->id = id;

    QString query = QString::fromUtf8(
        "select DISTINCT ?uri "
        "WHERE { "
            "?uri a nco:PersonContact. "
            "?uri nco:hasContactMedium ?a . "
            "?a ?b \"%1\"^^xsd:string . "
        "}").arg(id);

    Soprano::Model *model = Nepomuk2::ResourceManager::instance()->mainModel();
    Soprano::QueryResultIterator it = model->executeQuery(query, Soprano::Query::QueryLanguageSparqlNoInference);
    QString uri;
    while (it.next()) {
        uri = it[0].uri().toString();
    }

    if (d->uri != uri) {
        d->uri = uri;
        d->res = Nepomuk2::Resource(uri);
        d->res.setWatchEnabled(true);
    }
}

QString PersonData::contactId() const
{
    Q_D(const PersonData);
    return d->id;
}

QString PersonData::uri() const
{
    Q_D(const PersonData);
    return d->uri;
}

void PersonData::setUri(const QString &uri)
{
    Q_D(PersonData);

    d->uri = uri;
    d->res = Nepomuk2::Resource(uri);
    d->res.setWatchEnabled(true);

    Nepomuk2::ResourceWatcher *watcher = new Nepomuk2::ResourceWatcher(this);
    watcher->addResource(d->res);

    connect(watcher, SIGNAL(propertyChanged(Nepomuk2::Resource,Nepomuk2::Types::Property,QVariantList,QVariantList)),
            this, SIGNAL(dataChanged()));

    connect(s_presenceModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
            this, SLOT(presenceModelChange(QModelIndex,QModelIndex)));

    emit uriChanged();
    emit dataChanged();
}

QString PersonData::status() const
{
    Q_D(const PersonData);

    QStringList presenceList;

    if (d->res.type() == PIMO::Person()) {
        Q_FOREACH (const Nepomuk2::Resource &resource, d->res.property(PIMO::groundingOccurrence()).toResourceList()) {
            if (resource.hasProperty(NCO::hasIMAccount())) {
                QString imID = resource.property(NCO::hasIMAccount()).toResource().property(NCO::imID()).toString();
                presenceList << s_presenceModel->dataForContactId(imID, PersonsModel::StatusStringRole).toString();
            }
        }

        return findMostOnlinePresence(presenceList);
    } else {
        QString imID = d->res.property(NCO::hasIMAccount()).toResource().property(NCO::imID()).toString();
        return s_presenceModel->dataForContactId(imID, PersonsModel::StatusStringRole).toString();
    }
}

QUrl PersonData::avatar() const
{
    Q_D(const PersonData);

    Nepomuk2::Resource r;

    if (d->res.type() == PIMO::Person()) {
        Q_FOREACH (const Nepomuk2::Resource &resource, d->res.property(PIMO::groundingOccurrence()).toResourceList()) {
            if (resource.hasProperty(NCO::photo())) {
                r = resource;
                break;
            }
        }
    } else {
        r = d->res;
    }

    return r.property(NCO::photo()).toResource().property(NIE::url()).toUrl();
}

QString PersonData::name() const
{
    Q_D(const PersonData);

    QString label;
    Nepomuk2::Resource r;

    if (d->res.type() == PIMO::Person()) {
        //simply pick the first GO for now
        r = d->res.property(PIMO::groundingOccurrence()).toResource();
    } else {
        r = d->res;
    }

    label = r.property(NCO::fullname()).toString();

    if (!label.isEmpty()) {
        return label;
    }

    label = r.property(NCO::hasIMAccount()).toResource().property(NCO::imNickname()).toString();

    if (!label.isEmpty()) {
        return label;
    }

    return d->res.property(NCO::hasContactMedium()).toResource().genericLabel();
}

QStringList PersonData::emails() const
{
    Q_D(const PersonData);

    QStringList emails;

    if (d->res.type() == PIMO::Person()) {
        Q_FOREACH (const Nepomuk2::Resource &resource, d->res.property(PIMO::groundingOccurrence()).toResourceList()) {
            if (resource.hasProperty(NCO::hasEmailAddress())) {
                Q_FOREACH (const Nepomuk2::Resource &email, resource.property(NCO::hasEmailAddress()).toResourceList()) {
                    emails << email.property(NCO::emailAddress()).toString();
                }
            }
        }
    } else {
        if (d->res.hasProperty(NCO::hasEmailAddress())) {
            Q_FOREACH (const Nepomuk2::Resource &email, d->res.property(NCO::hasEmailAddress()).toResourceList()) {
                emails << email.property(NCO::emailAddress()).toString();
            }
        }
    }

    return emails;
}

QStringList PersonData::phones() const
{
    Q_D(const PersonData);

    QStringList phones;

    if (d->res.type() == PIMO::Person()) {
        Q_FOREACH (const Nepomuk2::Resource &resource, d->res.property(PIMO::groundingOccurrence()).toResourceList()) {
            if (resource.hasProperty(NCO::hasPhoneNumber())) {
                Q_FOREACH (const Nepomuk2::Resource &phone, resource.property(NCO::hasPhoneNumber()).toResourceList()) {
                    phones << phone.property(NCO::phoneNumber()).toString();
                }
            }
        }
    } else {
        if (d->res.hasProperty(NCO::hasPhoneNumber())) {
            Q_FOREACH (const Nepomuk2::Resource &phone, d->res.property(NCO::hasPhoneNumber()).toResourceList()) {
                phones << phone.property(NCO::phoneNumber()).toString();
            }
        }
    }

    return phones;
}

QStringList PersonData::imAccounts() const
{
    Q_D(const PersonData);

    QStringList ims;

    if (d->res.type() == PIMO::Person()) {
        Q_FOREACH (const Nepomuk2::Resource &resource, d->res.property(PIMO::groundingOccurrence()).toResourceList()) {
            if (resource.hasProperty(NCO::hasIMAccount())) {
                Q_FOREACH (const Nepomuk2::Resource &im, resource.property(NCO::hasIMAccount()).toResourceList()) {
                    ims << im.property(NCO::imAccountType()).toString();
                    ims << im.property(NCO::imNickname()).toString();
                    ims << im.property(NCO::imID()).toString();
                }
            }
        }
    } else {
        if (d->res.hasProperty(NCO::hasIMAccount())) {
            Q_FOREACH (const Nepomuk2::Resource &im, d->res.property(NCO::hasIMAccount()).toResourceList()) {
                ims << im.property(NCO::imAccountType()).toString();
                ims << im.property(NCO::imNickname()).toString();
                ims << im.property(NCO::imID()).toString();
            }
        }
    }

    return ims;
}

KDateTime PersonData::birthday() const
{
    Q_D(const PersonData);

    if (d->res.type() == PIMO::Person()) {
        //we'll go through all the dates we have and from every date we
        //get msecs from epoch and then we'll check whichever is greater
        //If the date has only month and a year, it will be counted
        //to 1st day of that month. If the real date is actually 15th day,
        //it means the more complete date will have more msecs from the epoch
        KDateTime bd;

        Q_FOREACH (const Nepomuk2::Resource &resource, d->res.property(PIMO::groundingOccurrence()).toResourceList()) {
            if (resource.hasProperty(NCO::birthDate())) {

                KDateTime bdTemp(d->res.property(NCO::birthDate()).toDateTime());
                if (bdTemp.isValid() && bdTemp.dateTime().toMSecsSinceEpoch() > bd.dateTime().toMSecsSinceEpoch()) {
                    bd = bdTemp;
                }
            }
        }

        return bd;
    } else {
        return KDateTime(d->res.property(NCO::birthDate()).toDateTime());
    }
}

QStringList PersonData::groups() const
{
    Q_D(const PersonData);

    QStringList groups;

    if (d->res.type() == PIMO::Person()) {

        Q_FOREACH (const Nepomuk2::Resource &resource, d->res.property(PIMO::groundingOccurrence()).toResourceList()) {
            Nepomuk2::Variant groupProperties = resource.property(NCO::belongsToGroup());
            if (!groupProperties.isValid()) {
                continue;
            }

            Q_FOREACH (const Nepomuk2::Resource &groupResource, groupProperties.toResourceList()) {
                groups << groupResource.property(NCO::contactGroupName()).toString();
            }
        }

    } else {
        Nepomuk2::Variant groupProperties = d->res.property(NCO::belongsToGroup());

        Q_FOREACH (const Nepomuk2::Resource &groupResource, groupProperties.toResourceList()) {
            groups << groupResource.property(NCO::contactGroupName()).toString();
        }
    }

    return groups;
}

// QStringList PersonData::bareContacts() const
// {
//     return personIndex().data(PersonsModel::ContactIdRole).toStringList();
// }
//
// QModelIndex PersonData::personIndex() const
// {
//     Q_D(const PersonData);
//     Q_ASSERT(d->model->rowCount()>0);
//     QModelIndex idx = d->model->index(0,0);
//     Q_ASSERT(idx.isValid());
//     return idx;
// }
//

bool PersonData::isPerson() const
{
    Q_D(const PersonData);
    return d->res.type() == PIMO::Person();
}

QString PersonData::findMostOnlinePresence(const QStringList &presences) const
{
    if (presences.contains("available")) {
        return "available";
    }
    if (presences.contains("away")) {
        return "away";
    }
    if (presences.contains("busy") || presences.contains("dnd")) {
        return "busy";
    }
    if (presences.contains("xa")) {
        return "xa";
    }

    return "offline";
}

void PersonData::presenceModelChange(const QModelIndex &topLeft, const QModelIndex &bottomRight)
{
    Q_D(PersonData);

    if (topLeft != bottomRight) {
        return;
    }

    if (topLeft.data(PersonsModel::UriRole).toString() == d->uri) {
        emit dataChanged();
    }
}
<commit_msg>Simplify PersonData code<commit_after>/*
    KPeople
    Copyright (C) 2012  Aleix Pol Gonzalez <aleixpol@blue-systems.com>
    Copyright (C) 2013  Martin Klapetek <mklapetek@kde.org>

    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 Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include "persondata.h"
#include "persons-model.h"
#include "person-item.h"
#include "persons-presence-model.h"

#include <Nepomuk2/Resource>
#include <Nepomuk2/Query/Query>
#include <Nepomuk2/ResourceManager>
#include <Nepomuk2/ResourceWatcher>
#include <Nepomuk2/Vocabulary/PIMO>
#include <Nepomuk2/Vocabulary/NCO>
#include <Nepomuk2/Vocabulary/NIE>
#include <Nepomuk2/Variant>

#include <Soprano/Model>
#include <Soprano/QueryResultIterator>

#include <KDebug>

using namespace Nepomuk2::Vocabulary;

class PersonDataPrivate {
public:
    QString uri;
    QString id;
    QPointer<Nepomuk2::ResourceWatcher> watcher;
    Nepomuk2::Resource personResource;
    QList<Nepomuk2::Resource> contactResources;
};

K_GLOBAL_STATIC(PersonsPresenceModel, s_presenceModel)

PersonData::PersonData(QObject *parent)
    : QObject(parent),
    d_ptr(new PersonDataPrivate)
{
}

PersonData::PersonData(const QString &uri, QObject *parent)
    : QObject(parent),
      d_ptr(new PersonDataPrivate)
{
    setUri(uri);
}

void PersonData::setContactId(const QString &id)
{
    Q_D(PersonData);
    if (d->id == id) {
        return;
    }

    d->id = id;

    QString query = QString::fromUtf8(
        "select DISTINCT ?uri "
        "WHERE { "
            "?uri a nco:PersonContact. "
            "?uri nco:hasContactMedium ?a . "
            "?a ?b \"%1\"^^xsd:string . "
        "}").arg(id);

    Soprano::Model *model = Nepomuk2::ResourceManager::instance()->mainModel();
    Soprano::QueryResultIterator it = model->executeQuery(query, Soprano::Query::QueryLanguageSparqlNoInference);
    QString uri;
    while (it.next()) {
        uri = it[0].uri().toString();
    }

    if (d->uri != uri) {
        setUri(uri);
    }
}

QString PersonData::contactId() const
{
    Q_D(const PersonData);
    return d->id;
}

QString PersonData::uri() const
{
    Q_D(const PersonData);
    return d->uri;
}

void PersonData::setUri(const QString &uri)
{
    Q_D(PersonData);

    d->uri = uri;
    d->contactResources.clear();
    d->personResource = Nepomuk2::Resource();

    Nepomuk2::Resource r(uri);

    if (!d->watcher.isNull()) {
        delete d->watcher;
    }

    d->watcher = new Nepomuk2::ResourceWatcher(this);

    if (r.type() == PIMO::Person()) {
        d->personResource = r;
        d->contactResources = r.property(PIMO::groundingOccurrence()).toResourceList();

        Q_FOREACH (Nepomuk2::Resource res, d->contactResources) { //cannot use const here as we're modifying the resource
            d->watcher->addResource(res);
            res.setWatchEnabled(true);
        }
    } else {
        d->contactResources = QList<Nepomuk2::Resource>() << r;
    }

    r.setWatchEnabled(true);
    d->watcher->addResource(r);

    connect(d->watcher.data(), SIGNAL(propertyChanged(Nepomuk2::Resource,Nepomuk2::Types::Property,QVariantList,QVariantList)),
            this, SIGNAL(dataChanged()));

    connect(s_presenceModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
            this, SLOT(presenceModelChange(QModelIndex,QModelIndex)));

    emit uriChanged();
    emit dataChanged();
}

QString PersonData::status() const
{
    Q_D(const PersonData);

    QStringList presenceList;

    Q_FOREACH (const Nepomuk2::Resource &resource, d->contactResources) {
        if (resource.hasProperty(NCO::hasIMAccount())) {
            QString imID = resource.property(NCO::hasIMAccount()).toResource().property(NCO::imID()).toString();
            presenceList << s_presenceModel->dataForContactId(imID, PersonsModel::StatusStringRole).toString();
        }
    }

    return findMostOnlinePresence(presenceList);
}

QUrl PersonData::avatar() const
{
    Q_D(const PersonData);

    Q_FOREACH (const Nepomuk2::Resource &resource, d->contactResources) {
        if (resource.hasProperty(NCO::photo())) {
            return resource.property(NCO::photo()).toResource().property(NIE::url()).toUrl();
        }
    }

    return QUrl();
}

QString PersonData::name() const
{
    Q_D(const PersonData);

    QString label;
    //simply pick the first for now
    Nepomuk2::Resource r = d->contactResources.first();

    label = r.property(NCO::fullname()).toString();

    if (!label.isEmpty()) {
        return label;
    }

    label = r.property(NCO::hasIMAccount()).toResource().property(NCO::imNickname()).toString();

    if (!label.isEmpty()) {
        return label;
    }

    return r.property(NCO::hasContactMedium()).toResource().genericLabel();
}

QStringList PersonData::emails() const
{
    Q_D(const PersonData);

    QStringList emails;

    Q_FOREACH (const Nepomuk2::Resource &resource, d->contactResources) {
        if (resource.hasProperty(NCO::hasEmailAddress())) {
            Q_FOREACH (const Nepomuk2::Resource &email, resource.property(NCO::hasEmailAddress()).toResourceList()) {
                emails << email.property(NCO::emailAddress()).toString();
            }
        }
    }

    return emails;
}

QStringList PersonData::phones() const
{
    Q_D(const PersonData);

    QStringList phones;

    Q_FOREACH (const Nepomuk2::Resource &resource, d->contactResources) {
        if (resource.hasProperty(NCO::hasPhoneNumber())) {
            Q_FOREACH (const Nepomuk2::Resource &phone, resource.property(NCO::hasPhoneNumber()).toResourceList()) {
                phones << phone.property(NCO::phoneNumber()).toString();
            }
        }
    }

    return phones;
}

QStringList PersonData::imAccounts() const
{
    Q_D(const PersonData);

    QStringList ims;

    Q_FOREACH (const Nepomuk2::Resource &resource, d->contactResources) {
        if (resource.hasProperty(NCO::hasIMAccount())) {
            Q_FOREACH (const Nepomuk2::Resource &im, resource.property(NCO::hasIMAccount()).toResourceList()) {
                ims << im.property(NCO::imAccountType()).toString();
                ims << im.property(NCO::imNickname()).toString();
                ims << im.property(NCO::imID()).toString();
            }
        }
    }

    return ims;
}

KDateTime PersonData::birthday() const
{
    Q_D(const PersonData);

    //we'll go through all the dates we have and from every date we
    //get msecs from epoch and then we'll check whichever is greater
    //If the date has only month and a year, it will be counted
    //to 1st day of that month. If the real date is actually 15th day,
    //it means the more complete date will have more msecs from the epoch
    KDateTime bd;

    Q_FOREACH (const Nepomuk2::Resource &resource, d->contactResources) {
        if (resource.hasProperty(NCO::birthDate())) {

            KDateTime bdTemp(resource.property(NCO::birthDate()).toDateTime());
            if (bdTemp.isValid() && bdTemp.dateTime().toMSecsSinceEpoch() > bd.dateTime().toMSecsSinceEpoch()) {
                bd = bdTemp;
            }
        }
    }

    return bd;
}

QStringList PersonData::groups() const
{
    Q_D(const PersonData);

    QStringList groups;

    Q_FOREACH (const Nepomuk2::Resource &resource, d->contactResources) {
        Nepomuk2::Variant groupProperties = resource.property(NCO::belongsToGroup());
        if (!groupProperties.isValid()) {
            continue;
        }

        Q_FOREACH (const Nepomuk2::Resource &groupResource, groupProperties.toResourceList()) {
            groups << groupResource.property(NCO::contactGroupName()).toString();
        }
    }

    return groups;
}

// QStringList PersonData::bareContacts() const
// {
//     return personIndex().data(PersonsModel::ContactIdRole).toStringList();
// }
//
// QModelIndex PersonData::personIndex() const
// {
//     Q_D(const PersonData);
//     Q_ASSERT(d->model->rowCount()>0);
//     QModelIndex idx = d->model->index(0,0);
//     Q_ASSERT(idx.isValid());
//     return idx;
// }
//

bool PersonData::isPerson() const
{
    Q_D(const PersonData);
    return d->personResource.isValid();
}

QString PersonData::findMostOnlinePresence(const QStringList &presences) const
{
    if (presences.contains("available")) {
        return "available";
    }
    if (presences.contains("away")) {
        return "away";
    }
    if (presences.contains("busy") || presences.contains("dnd")) {
        return "busy";
    }
    if (presences.contains("xa")) {
        return "xa";
    }

    return "offline";
}

void PersonData::presenceModelChange(const QModelIndex &topLeft, const QModelIndex &bottomRight)
{
    Q_D(PersonData);

    if (topLeft != bottomRight) {
        return;
    }

    if (topLeft.data(PersonsModel::UriRole).toString() == d->uri) {
        emit dataChanged();
    }
}
<|endoftext|>


<commit_before>#include "ElectrocardioIC.h"
#include <math.h>

template<>
InputParameters validParams<ElectrocardioIC>()
{
  InputParameters params = validParams<InitialCondition>();
  return params;
}

ElectrocardioIC::ElectrocardioIC(const std::string & name,
                     InputParameters parameters) :
    InitialCondition(name, parameters)
{
}

ElectrocardioIC::~ElectrocardioIC()
{
}

Real
ElectrocardioIC::value(const Point & p)
{
  /// The value -90.272 is the resting potential of the bernus model for all except one case...
  /// \todo TODO: make this more general: different ion models have different resting potentials
  return -90.272;
}
<commit_msg>modified resting potential for bernus model; apparently the ewe implementation does not exactly reproduce the -90.272mV; have to check parameters<commit_after>#include "ElectrocardioIC.h"
#include <math.h>

template<>
InputParameters validParams<ElectrocardioIC>()
{
  InputParameters params = validParams<InitialCondition>();
  return params;
}

ElectrocardioIC::ElectrocardioIC(const std::string & name,
                     InputParameters parameters) :
    InitialCondition(name, parameters)
{
}

ElectrocardioIC::~ElectrocardioIC()
{
}

Real
ElectrocardioIC::value(const Point & p)
{
  /// The value -90.272 is the resting potential of the bernus model for all except one case...
  /// \todo TODO: make this more general: different ion models have different resting potentials
 // return -90.272;
  return -92.189; // for some reason, my Bernus model has a slightly different resting potential.. probably a slighly wrong parameter?
}
<|endoftext|>


<commit_before>#include <iostream>
#include <typeclass/functor.h>
#include <typeclass/functor_list.h>
#include <typeclass/functor_vector.h>
#include <typeclass/functor_optional.h>
#include <typeclass/eq_primitive.h>
#include <typeclass/eq_list.h>
#include <typeclass/eq.h>
#include <typeclass/monoid.h>
#include <typeclass/monoid_primitive.h>
#include <typeclass/monoid_list.h>
#include <typeclass/monad.h>
#include <typeclass/monad_list.h>
#include <typeclass/monad_free.h>
#include <boost/variant.hpp>

#define ASSERT(...) if(!(__VA_ARGS__)) throw  "Assertion that " #__VA_ARGS__ " failed"
#define ASSERT_NOT(...) if(__VA_ARGS__) throw "Assertion that not " #__VA_ARGS__ " failed"

using namespace funcpp::typeclass;

void testEqPrimitive() {
	using namespace funcpp::typeclass::eq;
	ASSERT(equal(1,1));
	ASSERT_NOT(equal(2,1));
	ASSERT(equal(1.0,1.0));
	ASSERT_NOT(equal(1.1,1.0));
}

void testEqList() {
	using namespace funcpp::typeclass::eq;
	ASSERT(equal(std::list<int>{1,2,3},std::list<int>{1,2,3}));
	ASSERT_NOT(equal(std::list<int>{1,2,3},std::list<int>{1,0,3}));
	ASSERT_NOT(equal(std::list<int>{0,2,3},std::list<int>{1,0,3}));
}

void testFunctorList() {
	std::list<int> in {1,2,3};
	std::list<double> out = functor::fmap([](int x) { return 2.0*x; }, in);
}

void testMonoidPrimitive() {
	using namespace monoid;
	ASSERT(42+100 == mappend(42,100));
	ASSERT(42+100 == mappend<int,std::plus<int>>(42,100));
	ASSERT(42*100 == mappend<int,std::multiplies<int>>(42,100));
}

void testMonoidList() {
	using namespace monoid;
	std::list<int> a{1,2,3,4}, b{1,2}, c{3,4};
	ASSERT(a == b + c);
}

void testMonadList() {
	using namespace monad;
	std::list<int> a{42}, b{1,2}, c{3,4};
	ASSERT(a == mreturn<std::list>(42));
	ASSERT(std::list<int>{84} == (instance<std::list>::mreturn(42) >>= [](int x){ return instance<std::list>::mreturn(2*x); }));
	ASSERT(a >> std::list<int>{72} == std::list<int>{72});
}

using unit = std::tuple<>;

template <typename Next>
struct Prog {
	struct Read {
		std::function<Next(int)> next;
	};

	template <typename F>
	static Prog<std::result_of_t<F(int)>> read(F next) {
	  return { Read{next} };
	}

	struct Write {
		int x;
		std::function<Next(unit)> next;
	};

	template <typename F>
	static Prog<std::result_of_t<F(unit)>> write(int x, F next) {
		return { Write{x, next} };
	}
	boost::variant<Read, Write> v;
};

template <typename Fun, typename Next>
Prog<std::result_of_t<Fun(Next)>>
fmap(Fun&& fun, const Prog<Next>& prog) {
	using Res = std::result_of_t<Fun(Next)>;
	struct Visitor {
		Fun& fun;
		// fmap f (Read n) = Read (f . n)
		Prog<Res> operator()(const typename Prog<Next>::Read& read) const {
			return Prog<Res>::read(compose(fun, read.next));
		}
		// fmap f (Write x n) = Write x (f . n)
		Prog<Res> operator()(const typename Prog<Next>::Write& write) const {
			return Prog<Res>::write(write.x, compose(fun, write.next));
		}
	};
	return boost::apply_visitor(Visitor{fun}, prog.v);
}

void testMonadFree() {
	using namespace monad;
	using namespace funcpp::free;
}

int main() {
	try {
		testEqPrimitive();
		testEqList();
		testMonoidPrimitive();
		testMonoidList();
		testMonadList();
		testMonadFree();

		std::cout << "***************************************\n";
		std::cout << "**  ALL TESTS OK                     **\n";
		std::cout << "***************************************\n";
	}
	catch(const char* ex) {
		std::cout << "***************************************\n";
		std::cout << "**  TESTS FAILED:                    **\n";
		std::cout << "***************************************\n";
		std::cout << ex << std::endl;
	}

}<commit_msg>Quick sketch of referentially transparent file-i/o<commit_after>
#include <iostream>
#include <fstream>
#include <vector>
#include <type_traits>
#include <map>
#include <experimental/optional>

namespace std {
    using namespace std::experimental;

    template< class, class = std::void_t<> >
    struct is_callable : std::false_type { };

    template< class T >
    struct is_callable<T, std::void_t<decltype(std::declval<T>()())>> : std::true_type { };

}

template <typename T> struct with_type { using type = T; };

struct unit_t : std::tuple<> {};

constexpr unit_t unit {};

template <typename T>
class IO : public with_type<T> {
    std::function<T()> m_action;

public:
    template <typename Fn>
    IO(Fn&& action)
        : m_action{ std::forward<Fn>(action) }
    {}

    template <typename U>
    IO(IO<U> & action)
        : m_action{ action.m_action }
    {}

    template <typename U>
    IO(IO<U> const & action)
        : m_action{ action.m_action }
    {}

    template <typename U>
    IO(IO<U>&& action)
        : m_action{ std::move(action.m_action) }
    {}

    IO(IO&&) = default;
    IO(IO const&) = default;

    IO& operator= (IO&&) = default;
    IO& operator= (IO const&) = default;

    template <typename Fn>
    auto then(Fn&& cont) const {
        using res_t = decltype(cont(m_action()));
        return res_t{ [cont=std::forward<Fn>(cont),action=m_action]() mutable {
            return cont(action()).run();
        }};
    }

    T run() { return m_action(); }
};

template <typename U>
auto yield(U&& val) -> IO<std::decay_t<U>> {
    return IO<std::decay_t<U>> { [val=std::forward<U>(val)]() -> std::decay_t<U> {
        return val;
    }};
}

class SharedResource {
protected:
    struct Details {
        virtual ~Details() {}
    };

private:
    std::shared_ptr<Details> m_impl;

public:
    SharedResource(std::shared_ptr<Details> impl)
        : m_impl{ std::move(impl) }
    {}
};

template <typename T>
class ReadStore {
protected:
    struct Details {
        virtual IO<std::optional<T>> read_impl() const = 0;
        virtual ~Details() {}
    };

private:
    std::shared_ptr<Details> m_impl;

public:
    ReadStore(std::shared_ptr<Details> impl) : m_impl{ std::move(impl) } {}

    IO<std::optional<T>>
    read() { return m_impl->read_impl(); }
};

template <typename T>
class WriteStore {
protected:
    struct Details {
        virtual IO<std::optional<unit_t>> write_impl(T value) const = 0;
        virtual ~Details() {}
    };

private:
    std::shared_ptr<Details> m_impl;
public:
    WriteStore(std::shared_ptr<Details> impl) : m_impl{ std::move(impl) } {}

    IO<std::optional<unit_t>>
    write(T value) { return m_impl->write_impl(std::move(value)); }
};

template <typename T>
class Store
    : public ReadStore<T>
    , public WriteStore<T>
{
protected:
    struct Details : ReadStore<T>::Details, WriteStore<T>::Details {};

public:
    Store(std::shared_ptr<Details> impl)
        : ReadStore<T>(impl)
        , WriteStore<T>(impl)
    {}
};

class SDCardMounted : SharedResource {
    struct Details : SharedResource::Details {
        std::string m_dev;

        virtual ~Details() override {
            std::cout << "Executing SD-card unmount action for device " << m_dev << std::endl;
        }

        Details(std::string dev)
            : m_dev{ std::move(dev) }
        {
            std::cout << "Executing SD-card mount action for device " << m_dev << std::endl;
        }
    };
public:
    SDCardMounted(std::string dev)
        : SharedResource(std::make_shared<Details>(std::move(dev))) {}
};

class FileStore final
    : public Store<std::vector<uint8_t>>
{
    struct Details : Store<std::vector<uint8_t>>::Details {
        std::string m_filename;

        virtual IO<std::optional<unit_t>> write_impl(std::vector<uint8_t> value) const override {
            return IO<std::optional<unit_t>>([fname=m_filename, value=std::move(value)]() mutable -> std::optional<unit_t> {
                try {
                    std::ofstream(fname, std::ios::binary).write(reinterpret_cast<char const*>(value.data()),value.size());
                    return std::make_optional(unit);
                } catch(...) {
                    return std::nullopt;
                }
            });
        }

        virtual IO<std::optional<std::vector<uint8_t>>> read_impl() const override {
            return IO<std::optional<std::vector<uint8_t>>>([fname=m_filename]() mutable -> std::optional<std::vector<uint8_t>> {
                try {
                    std::ifstream file(fname, std::ios::binary | std::ios::ate);
                    auto const size = file.tellg();
                    file.seekg(0, std::ios::beg);

                    std::vector<uint8_t> buffer(size);
                    if(!file.read(reinterpret_cast<char*>(buffer.data()), size))
                        return std::nullopt;
                    return std::make_optional(std::move(buffer));
                }
                catch(...) {
                    return std::nullopt;
                }
            });
        }

        Details(std::string filename)
            : m_filename{std::move(filename)} {}
    };

public:
    FileStore(std::string filename)
        : Store<std::vector<uint8_t>>(std::make_shared<Details>(std::move(filename)))
    {}
};

class MountedFileStore final
    : public Store<std::vector<uint8_t>>
{
    struct Details : Store<std::vector<uint8_t>>::Details {
        IO<std::optional<SDCardMounted>> m_mountedState;
        FileStore m_file;

        virtual IO<std::optional<unit_t>> write_impl(std::vector<uint8_t> value) const override {
            return m_mountedState.then([file=m_file, val=std::move(value)](std::optional<SDCardMounted> mounted) mutable {
                if(!mounted) return yield<std::optional<unit_t>>(std::nullopt); // TODO: monad transformers
                return file.write(std::move(val));
            });
        }

        virtual IO<std::optional<std::vector<uint8_t>>> read_impl() const override {
            return m_mountedState.then([file=m_file](std::optional<SDCardMounted> mounted) mutable {
                if(!mounted) return yield<std::optional<std::vector<uint8_t>>>(std::nullopt); // TODO: monad transformers
                return file.read();
            });
        }

        Details(IO<std::optional<SDCardMounted>> mountedState, FileStore file)
            : m_mountedState{ std::move(mountedState) }
            , m_file{std::move(file)} {}
    };

public:
    MountedFileStore(IO<std::optional<SDCardMounted>> mountedState, std::string filename)
        : Store<std::vector<uint8_t>>(std::make_shared<Details>(std::move(mountedState), FileStore(filename)))
    {
    }
};

class Console {
public:
    IO<std::ostream&> cout() const {
        return { []() -> std::ostream& { return { std::cout }; }};
    }
};

class SDCardMounter {
    using device_id_t = std::size_t;
    std::map<device_id_t, std::string> m_devMap;

public:
    SDCardMounter()
        : m_devMap{ {0, "/dev/mmcblk1p1"}, {1, "/dev/sda1"} }
    {}

    IO<std::optional<SDCardMounted>> mounted(device_id_t devId) const {
        return { [device=m_devMap.at(devId)]() -> std::optional<SDCardMounted> {
            return std::make_optional(SDCardMounted{device});
        }};
    }
};

template <typename T>
class StreamWriteStore final
    : public WriteStore<T>
{
    struct Details
        : WriteStore<T>::Details
    {
        IO<std::ostream&> m_stream;

        virtual IO<std::optional<unit_t>> write_impl(T value) const override {
            return m_stream.then([value=std::move(value)](std::ostream & stream) mutable -> IO<std::optional<unit_t>> {
                try {
                    stream << std::move(value);
                    return yield<std::optional<unit_t>>(std::make_optional(unit));
                } catch(...) {
                    return yield<std::optional<unit_t>>(std::nullopt);
                }
            });
        }

        Details(IO<std::ostream&> stream)
            : m_stream{std::move(stream)} {}
    };

public:
    StreamWriteStore(IO<std::ostream&> stream)
        : WriteStore<T>(std::make_shared<Details>(std::move(stream)))
    {}
};

int main() {
    auto const mountedCard = SDCardMounter().mounted(/*devId*/0);
    Store<std::vector<uint8_t>> store = MountedFileStore{mountedCard, "file1"};

    WriteStore<std::vector<uint8_t>> writeStore = store; // slicing has no effect :-)
    ReadStore<std::vector<uint8_t>> readStore = store;

    {
        std::vector<uint8_t> data{1,2,3,4,5};
        auto action = writeStore.write(data).then([](auto res) -> IO<unit_t> {
            if(res)
                std::cout << "successfully wrote file" << std::endl;
            return yield(unit);
        });

        action.run();
    }

    {
        std::vector<uint8_t> dataIn;
        auto readAction = readStore.read();

        if(auto readResult = readAction.run()) {
            std::cout << "successfully read file" << std::endl;
            for(auto const& i : *readResult)
                std::cout << (int)i << std::endl;
        }
        else {
            std::cout << "failure reading file" << std::endl;
        }
    }

    {
        auto c = Console{}.cout();
        StreamWriteStore<double> doubles(c);
        StreamWriteStore<std::string> strings(c);
        std::vector<IO<std::optional<unit_t>>> actions {
            strings.write("Hello "),
            strings.write("World\n"),
            doubles.write(3.14159)
        };
        for(auto& action : actions)
            action.run();
    }
}<|endoftext|>


<commit_before>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <string>

#include "base/memory/scoped_ptr.h"
#include "base/message_loop.h"
#include "base/string16.h"
#include "base/string_number_conversions.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
#include "chrome/browser/chromeos/cros/mock_network_library.h"
#include "chrome/browser/chromeos/cros/network_library.h"
#include "chrome/browser/chromeos/login/mock_screen_observer.h"
#include "chrome/browser/chromeos/login/network_screen.h"
#include "chrome/browser/chromeos/login/view_screen.h"
#include "chrome/browser/chromeos/login/wizard_controller.h"
#include "chrome/browser/chromeos/login/wizard_in_process_browser_test.h"
#include "chrome/browser/chromeos/login/wizard_screen.h"
#include "chrome/test/base/ui_test_utils.h"
#include "chromeos/dbus/mock_dbus_thread_manager.h"
#include "chromeos/dbus/mock_session_manager_client.h"
#include "grit/generated_resources.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/views/controls/button/text_button.h"

namespace chromeos {
using ::testing::A;
using ::testing::AnyNumber;
using ::testing::InvokeWithoutArgs;
using ::testing::Return;
using ::testing::ReturnRef;
using ::testing::_;
using views::Button;

class DummyButtonListener : public views::ButtonListener {
 public:
  virtual void ButtonPressed(views::Button* sender,
                             const views::Event& event) {}
};

class NetworkScreenTest : public WizardInProcessBrowserTest {
 public:
  NetworkScreenTest(): WizardInProcessBrowserTest("network"),
                       mock_network_library_(NULL) {
  }

 protected:
  virtual void SetUpInProcessBrowserTestFixture() {
    MockDBusThreadManager* mock_dbus_thread_manager =
        new MockDBusThreadManager;
    DBusThreadManager::InitializeForTesting(mock_dbus_thread_manager);
    cros_mock_->InitStatusAreaMocks();
    mock_network_library_ = cros_mock_->mock_network_library();
    MockSessionManagerClient* mock_session_manager_client =
        mock_dbus_thread_manager->mock_session_manager_client();
    cellular_.reset(new NetworkDevice("cellular"));
    EXPECT_CALL(*mock_session_manager_client, EmitLoginPromptReady())
        .Times(1);
    EXPECT_CALL(*mock_session_manager_client, RetrieveDevicePolicy(_))
        .Times(AnyNumber());

    // Minimal set of expectations needed on NetworkScreen initialization.
    // Status bar expectations are defined with RetiresOnSaturation() so
    // these mocks will be active once status bar is initialized.
    EXPECT_CALL(*mock_network_library_, AddUserActionObserver(_))
        .Times(AnyNumber());
    EXPECT_CALL(*mock_network_library_, wifi_connected())
        .Times(1)
        .WillRepeatedly(Return(false));
    EXPECT_CALL(*mock_network_library_, FindWifiDevice())
        .Times(AnyNumber());
    EXPECT_CALL(*mock_network_library_, FindEthernetDevice())
        .Times(AnyNumber());

    cros_mock_->SetStatusAreaMocksExpectations();

    // Override these return values, but do not set specific expectation:
    EXPECT_CALL(*mock_network_library_, wifi_available())
        .Times(AnyNumber())
        .WillRepeatedly((Return(true)));
    EXPECT_CALL(*mock_network_library_, wifi_enabled())
        .Times(AnyNumber())
        .WillRepeatedly((Return(true)));
    EXPECT_CALL(*mock_network_library_, wifi_busy())
        .Times(AnyNumber())
        .WillRepeatedly((Return(false)));
    EXPECT_CALL(*mock_network_library_, wifi_connecting())
        .Times(AnyNumber())
        .WillRepeatedly((Return(false)));
    EXPECT_CALL(*mock_network_library_, wifi_scanning())
        .Times(AnyNumber())
        .WillRepeatedly((Return(false)));
    EXPECT_CALL(*mock_network_library_, cellular_available())
        .Times(AnyNumber())
        .WillRepeatedly((Return(true)));
    EXPECT_CALL(*mock_network_library_, cellular_enabled())
        .Times(AnyNumber())
        .WillRepeatedly((Return(true)));
    EXPECT_CALL(*mock_network_library_, cellular_busy())
        .Times(AnyNumber())
        .WillRepeatedly((Return(false)));
    EXPECT_CALL(*mock_network_library_, cellular_connecting())
        .Times(AnyNumber())
        .WillRepeatedly((Return(false)));

    EXPECT_CALL(*mock_network_library_, FindCellularDevice())
        .Times(AnyNumber())
        .WillRepeatedly((Return(cellular_.get())));
  }

  virtual void SetUpOnMainThread() {
    WizardInProcessBrowserTest::SetUpOnMainThread();
    mock_screen_observer_.reset(new MockScreenObserver());
    ASSERT_TRUE(WizardController::default_controller() != NULL);
    network_screen_ =
        WizardController::default_controller()->GetNetworkScreen();
    ASSERT_TRUE(network_screen_ != NULL);
    ASSERT_EQ(WizardController::default_controller()->current_screen(),
              network_screen_);
    network_screen_->screen_observer_ = mock_screen_observer_.get();
    ASSERT_TRUE(network_screen_->actor() != NULL);
  }

  virtual void TearDownInProcessBrowserTestFixture() {
    CrosInProcessBrowserTest::TearDownInProcessBrowserTestFixture();
    DBusThreadManager::Shutdown();
  }

  void EmulateContinueButtonExit(NetworkScreen* network_screen) {
    EXPECT_CALL(*mock_screen_observer_,
                OnExit(ScreenObserver::NETWORK_CONNECTED))
        .Times(1);
    EXPECT_CALL(*mock_network_library_, Connected())
        .WillOnce(Return(true));
    network_screen->OnContinuePressed();
    ui_test_utils::RunAllPendingInMessageLoop();
  }

  scoped_ptr<MockScreenObserver> mock_screen_observer_;
  MockNetworkLibrary* mock_network_library_;
  scoped_ptr<NetworkDevice> cellular_;
  NetworkScreen* network_screen_;

 private:
  DISALLOW_COPY_AND_ASSIGN(NetworkScreenTest);
};

IN_PROC_BROWSER_TEST_F(NetworkScreenTest, Ethernet) {
  EXPECT_CALL(*mock_network_library_, ethernet_connected())
      .WillOnce((Return(false)));
  EXPECT_CALL(*mock_network_library_, wifi_connected())
      .WillOnce((Return(false)));
  EXPECT_CALL(*mock_network_library_, cellular_connected())
      .WillOnce((Return(false)));
  EXPECT_CALL(*mock_network_library_, ethernet_connecting())
      .WillOnce((Return(true)));
  // EXPECT_FALSE(actor_->IsContinueEnabled());
  network_screen_->OnNetworkManagerChanged(mock_network_library_);

  EXPECT_CALL(*mock_network_library_, ethernet_connected())
      .WillOnce(Return(true));
  EXPECT_CALL(*mock_network_library_, Connected())
      .Times(3)
      .WillRepeatedly(Return(true));
  // TODO(nkostylev): Add integration with WebUI actor http://crosbug.com/22570
  // EXPECT_FALSE(actor_->IsContinueEnabled());
  // EXPECT_FALSE(actor_->IsConnecting());
  network_screen_->OnNetworkManagerChanged(mock_network_library_);

  // EXPECT_TRUE(actor_->IsContinueEnabled());
  EmulateContinueButtonExit(network_screen_);
}

IN_PROC_BROWSER_TEST_F(NetworkScreenTest, Wifi) {
  EXPECT_CALL(*mock_network_library_, ethernet_connected())
      .WillOnce((Return(false)));
  EXPECT_CALL(*mock_network_library_, wifi_connected())
      .WillOnce((Return(false)));
  EXPECT_CALL(*mock_network_library_, cellular_connected())
      .WillOnce((Return(false)));
  EXPECT_CALL(*mock_network_library_, ethernet_connecting())
      .WillOnce((Return(false)));
  EXPECT_CALL(*mock_network_library_, wifi_connecting())
      .WillOnce((Return(true)));
  scoped_ptr<WifiNetwork> wifi(new WifiNetwork("wifi"));
  WifiNetworkVector wifi_networks;
  wifi_networks.push_back(wifi.get());
  EXPECT_CALL(*mock_network_library_, wifi_network())
      .WillRepeatedly(Return(wifi.get()));
  EXPECT_CALL(*mock_network_library_, wifi_networks())
      .WillRepeatedly(ReturnRef(wifi_networks));
  // EXPECT_FALSE(actor_->IsContinueEnabled());
  network_screen_->OnNetworkManagerChanged(mock_network_library_);

  EXPECT_CALL(*mock_network_library_, ethernet_connected())
      .WillOnce(Return(true));
  EXPECT_CALL(*mock_network_library_, Connected())
        .Times(3)
        .WillRepeatedly(Return(true));
  // TODO(nkostylev): Add integration with WebUI actor http://crosbug.com/22570
  // EXPECT_FALSE(actor_->IsContinueEnabled());
  // EXPECT_FALSE(actor_->IsConnecting());
  network_screen_->OnNetworkManagerChanged(mock_network_library_);

  // EXPECT_TRUE(actor_->IsContinueEnabled());
  EmulateContinueButtonExit(network_screen_);
}

IN_PROC_BROWSER_TEST_F(NetworkScreenTest, Cellular) {
  EXPECT_CALL(*mock_network_library_, ethernet_connected())
      .WillOnce((Return(false)));
  EXPECT_CALL(*mock_network_library_, wifi_connected())
      .WillOnce((Return(false)));
  EXPECT_CALL(*mock_network_library_, cellular_connected())
      .WillOnce((Return(false)));
  EXPECT_CALL(*mock_network_library_, ethernet_connecting())
      .WillOnce((Return(false)));
  EXPECT_CALL(*mock_network_library_, wifi_connecting())
      .WillOnce((Return(false)));
  EXPECT_CALL(*mock_network_library_, cellular_connecting())
      .WillOnce((Return(true)));
  scoped_ptr<CellularNetwork> cellular(new CellularNetwork("cellular"));
  EXPECT_CALL(*mock_network_library_, cellular_network())
      .WillOnce(Return(cellular.get()));
  // EXPECT_FALSE(actor_->IsContinueEnabled());
  network_screen_->OnNetworkManagerChanged(mock_network_library_);

  EXPECT_CALL(*mock_network_library_, ethernet_connected())
      .WillOnce(Return(true));
  EXPECT_CALL(*mock_network_library_, Connected())
      .Times(3)
      .WillRepeatedly(Return(true));
  // TODO(nkostylev): Add integration with WebUI actor http://crosbug.com/22570
  // EXPECT_FALSE(actor_->IsContinueEnabled());
  // EXPECT_FALSE(actor_->IsConnecting());
  network_screen_->OnNetworkManagerChanged(mock_network_library_);

  // EXPECT_TRUE(actor_->IsContinueEnabled());
  EmulateContinueButtonExit(network_screen_);
}

// See crbug.com/89392
#if defined(OS_LINUX)
#define MAYBE_Timeout DISABLED_Timeout
#else
#define MAYBE_Timeout Timeout
#endif
IN_PROC_BROWSER_TEST_F(NetworkScreenTest, MAYBE_Timeout) {
  EXPECT_CALL(*mock_network_library_, ethernet_connected())
      .WillOnce((Return(false)));
  EXPECT_CALL(*mock_network_library_, wifi_connected())
      .WillOnce((Return(false)));
  EXPECT_CALL(*mock_network_library_, cellular_connected())
      .WillOnce((Return(false)));
  EXPECT_CALL(*mock_network_library_, ethernet_connecting())
      .WillOnce((Return(false)));
  EXPECT_CALL(*mock_network_library_, wifi_connecting())
      .WillOnce((Return(true)));
  scoped_ptr<WifiNetwork> wifi(new WifiNetwork("wifi"));
  EXPECT_CALL(*mock_network_library_, wifi_network())
      .WillOnce(Return(wifi.get()));
  // EXPECT_FALSE(actor_->IsContinueEnabled());
  network_screen_->OnNetworkManagerChanged(mock_network_library_);

  EXPECT_CALL(*mock_network_library_, Connected())
      .Times(2)
      .WillRepeatedly(Return(false));
  // TODO(nkostylev): Add integration with WebUI actor http://crosbug.com/22570
  // EXPECT_FALSE(actor_->IsContinueEnabled());
  // EXPECT_FALSE(actor_->IsConnecting());
  network_screen_->OnConnectionTimeout();

  // Close infobubble with error message - it makes the test stable.
  // EXPECT_FALSE(actor_->IsContinueEnabled());
  // EXPECT_FALSE(actor_->IsConnecting());
  // actor_->ClearErrors();
}

}  // namespace chromeos
<commit_msg>Fix test expectations to include wimax<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <string>

#include "base/memory/scoped_ptr.h"
#include "base/message_loop.h"
#include "base/string16.h"
#include "base/string_number_conversions.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
#include "chrome/browser/chromeos/cros/mock_network_library.h"
#include "chrome/browser/chromeos/cros/network_library.h"
#include "chrome/browser/chromeos/login/mock_screen_observer.h"
#include "chrome/browser/chromeos/login/network_screen.h"
#include "chrome/browser/chromeos/login/view_screen.h"
#include "chrome/browser/chromeos/login/wizard_controller.h"
#include "chrome/browser/chromeos/login/wizard_in_process_browser_test.h"
#include "chrome/browser/chromeos/login/wizard_screen.h"
#include "chrome/test/base/ui_test_utils.h"
#include "chromeos/dbus/mock_dbus_thread_manager.h"
#include "chromeos/dbus/mock_session_manager_client.h"
#include "grit/generated_resources.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/views/controls/button/text_button.h"

namespace chromeos {
using ::testing::A;
using ::testing::AnyNumber;
using ::testing::InvokeWithoutArgs;
using ::testing::Return;
using ::testing::ReturnRef;
using ::testing::_;
using views::Button;

class DummyButtonListener : public views::ButtonListener {
 public:
  virtual void ButtonPressed(views::Button* sender,
                             const views::Event& event) {}
};

class NetworkScreenTest : public WizardInProcessBrowserTest {
 public:
  NetworkScreenTest(): WizardInProcessBrowserTest("network"),
                       mock_network_library_(NULL) {
  }

 protected:
  virtual void SetUpInProcessBrowserTestFixture() {
    MockDBusThreadManager* mock_dbus_thread_manager =
        new MockDBusThreadManager;
    DBusThreadManager::InitializeForTesting(mock_dbus_thread_manager);
    cros_mock_->InitStatusAreaMocks();
    mock_network_library_ = cros_mock_->mock_network_library();
    MockSessionManagerClient* mock_session_manager_client =
        mock_dbus_thread_manager->mock_session_manager_client();
    cellular_.reset(new NetworkDevice("cellular"));
    EXPECT_CALL(*mock_session_manager_client, EmitLoginPromptReady())
        .Times(1);
    EXPECT_CALL(*mock_session_manager_client, RetrieveDevicePolicy(_))
        .Times(AnyNumber());

    // Minimal set of expectations needed on NetworkScreen initialization.
    // Status bar expectations are defined with RetiresOnSaturation() so
    // these mocks will be active once status bar is initialized.
    EXPECT_CALL(*mock_network_library_, AddUserActionObserver(_))
        .Times(AnyNumber());
    EXPECT_CALL(*mock_network_library_, wifi_connected())
        .Times(1)
        .WillRepeatedly(Return(false));
    EXPECT_CALL(*mock_network_library_, FindWifiDevice())
        .Times(AnyNumber());
    EXPECT_CALL(*mock_network_library_, FindEthernetDevice())
        .Times(AnyNumber());

    cros_mock_->SetStatusAreaMocksExpectations();

    // Override these return values, but do not set specific expectation:
    EXPECT_CALL(*mock_network_library_, wifi_available())
        .Times(AnyNumber())
        .WillRepeatedly((Return(true)));
    EXPECT_CALL(*mock_network_library_, wifi_enabled())
        .Times(AnyNumber())
        .WillRepeatedly((Return(true)));
    EXPECT_CALL(*mock_network_library_, wifi_busy())
        .Times(AnyNumber())
        .WillRepeatedly((Return(false)));
    EXPECT_CALL(*mock_network_library_, wifi_connecting())
        .Times(AnyNumber())
        .WillRepeatedly((Return(false)));
    EXPECT_CALL(*mock_network_library_, wifi_scanning())
        .Times(AnyNumber())
        .WillRepeatedly((Return(false)));
    EXPECT_CALL(*mock_network_library_, cellular_available())
        .Times(AnyNumber())
        .WillRepeatedly((Return(true)));
    EXPECT_CALL(*mock_network_library_, cellular_enabled())
        .Times(AnyNumber())
        .WillRepeatedly((Return(true)));
    EXPECT_CALL(*mock_network_library_, cellular_busy())
        .Times(AnyNumber())
        .WillRepeatedly((Return(false)));
    EXPECT_CALL(*mock_network_library_, cellular_connecting())
        .Times(AnyNumber())
        .WillRepeatedly((Return(false)));
    EXPECT_CALL(*mock_network_library_, wimax_available())
        .Times(AnyNumber())
        .WillRepeatedly((Return(true)));
    EXPECT_CALL(*mock_network_library_, wimax_enabled())
        .Times(AnyNumber())
        .WillRepeatedly((Return(true)));
    EXPECT_CALL(*mock_network_library_, wimax_connected())
        .Times(AnyNumber())
        .WillRepeatedly((Return(false)));
    EXPECT_CALL(*mock_network_library_, wimax_connecting())
        .Times(AnyNumber())
        .WillRepeatedly((Return(false)));

    EXPECT_CALL(*mock_network_library_, FindCellularDevice())
        .Times(AnyNumber())
        .WillRepeatedly((Return(cellular_.get())));
  }

  virtual void SetUpOnMainThread() {
    WizardInProcessBrowserTest::SetUpOnMainThread();
    mock_screen_observer_.reset(new MockScreenObserver());
    ASSERT_TRUE(WizardController::default_controller() != NULL);
    network_screen_ =
        WizardController::default_controller()->GetNetworkScreen();
    ASSERT_TRUE(network_screen_ != NULL);
    ASSERT_EQ(WizardController::default_controller()->current_screen(),
              network_screen_);
    network_screen_->screen_observer_ = mock_screen_observer_.get();
    ASSERT_TRUE(network_screen_->actor() != NULL);
  }

  virtual void TearDownInProcessBrowserTestFixture() {
    CrosInProcessBrowserTest::TearDownInProcessBrowserTestFixture();
    DBusThreadManager::Shutdown();
  }

  void EmulateContinueButtonExit(NetworkScreen* network_screen) {
    EXPECT_CALL(*mock_screen_observer_,
                OnExit(ScreenObserver::NETWORK_CONNECTED))
        .Times(1);
    EXPECT_CALL(*mock_network_library_, Connected())
        .WillOnce(Return(true));
    network_screen->OnContinuePressed();
    ui_test_utils::RunAllPendingInMessageLoop();
  }

  scoped_ptr<MockScreenObserver> mock_screen_observer_;
  MockNetworkLibrary* mock_network_library_;
  scoped_ptr<NetworkDevice> cellular_;
  NetworkScreen* network_screen_;

 private:
  DISALLOW_COPY_AND_ASSIGN(NetworkScreenTest);
};

IN_PROC_BROWSER_TEST_F(NetworkScreenTest, Ethernet) {
  EXPECT_CALL(*mock_network_library_, ethernet_connected())
      .WillOnce((Return(false)));
  EXPECT_CALL(*mock_network_library_, wifi_connected())
      .WillOnce((Return(false)));
  EXPECT_CALL(*mock_network_library_, cellular_connected())
      .WillOnce((Return(false)));
  EXPECT_CALL(*mock_network_library_, ethernet_connecting())
      .WillOnce((Return(true)));
  // EXPECT_FALSE(actor_->IsContinueEnabled());
  network_screen_->OnNetworkManagerChanged(mock_network_library_);

  EXPECT_CALL(*mock_network_library_, ethernet_connected())
      .WillOnce(Return(true));
  EXPECT_CALL(*mock_network_library_, Connected())
      .Times(3)
      .WillRepeatedly(Return(true));
  // TODO(nkostylev): Add integration with WebUI actor http://crosbug.com/22570
  // EXPECT_FALSE(actor_->IsContinueEnabled());
  // EXPECT_FALSE(actor_->IsConnecting());
  network_screen_->OnNetworkManagerChanged(mock_network_library_);

  // EXPECT_TRUE(actor_->IsContinueEnabled());
  EmulateContinueButtonExit(network_screen_);
}

IN_PROC_BROWSER_TEST_F(NetworkScreenTest, Wifi) {
  EXPECT_CALL(*mock_network_library_, ethernet_connected())
      .WillOnce((Return(false)));
  EXPECT_CALL(*mock_network_library_, wifi_connected())
      .WillOnce((Return(false)));
  EXPECT_CALL(*mock_network_library_, cellular_connected())
      .WillOnce((Return(false)));
  EXPECT_CALL(*mock_network_library_, ethernet_connecting())
      .WillOnce((Return(false)));
  EXPECT_CALL(*mock_network_library_, wifi_connecting())
      .WillOnce((Return(true)));
  scoped_ptr<WifiNetwork> wifi(new WifiNetwork("wifi"));
  WifiNetworkVector wifi_networks;
  wifi_networks.push_back(wifi.get());
  EXPECT_CALL(*mock_network_library_, wifi_network())
      .WillRepeatedly(Return(wifi.get()));
  EXPECT_CALL(*mock_network_library_, wifi_networks())
      .WillRepeatedly(ReturnRef(wifi_networks));
  // EXPECT_FALSE(actor_->IsContinueEnabled());
  network_screen_->OnNetworkManagerChanged(mock_network_library_);

  EXPECT_CALL(*mock_network_library_, ethernet_connected())
      .WillOnce(Return(true));
  EXPECT_CALL(*mock_network_library_, Connected())
        .Times(3)
        .WillRepeatedly(Return(true));
  // TODO(nkostylev): Add integration with WebUI actor http://crosbug.com/22570
  // EXPECT_FALSE(actor_->IsContinueEnabled());
  // EXPECT_FALSE(actor_->IsConnecting());
  network_screen_->OnNetworkManagerChanged(mock_network_library_);

  // EXPECT_TRUE(actor_->IsContinueEnabled());
  EmulateContinueButtonExit(network_screen_);
}

IN_PROC_BROWSER_TEST_F(NetworkScreenTest, Cellular) {
  EXPECT_CALL(*mock_network_library_, ethernet_connected())
      .WillOnce((Return(false)));
  EXPECT_CALL(*mock_network_library_, wifi_connected())
      .WillOnce((Return(false)));
  EXPECT_CALL(*mock_network_library_, cellular_connected())
      .WillOnce((Return(false)));
  EXPECT_CALL(*mock_network_library_, ethernet_connecting())
      .WillOnce((Return(false)));
  EXPECT_CALL(*mock_network_library_, wifi_connecting())
      .WillOnce((Return(false)));
  EXPECT_CALL(*mock_network_library_, cellular_connecting())
      .WillOnce((Return(true)));
  scoped_ptr<CellularNetwork> cellular(new CellularNetwork("cellular"));
  EXPECT_CALL(*mock_network_library_, cellular_network())
      .WillOnce(Return(cellular.get()));
  // EXPECT_FALSE(actor_->IsContinueEnabled());
  network_screen_->OnNetworkManagerChanged(mock_network_library_);

  EXPECT_CALL(*mock_network_library_, ethernet_connected())
      .WillOnce(Return(true));
  EXPECT_CALL(*mock_network_library_, Connected())
      .Times(3)
      .WillRepeatedly(Return(true));
  // TODO(nkostylev): Add integration with WebUI actor http://crosbug.com/22570
  // EXPECT_FALSE(actor_->IsContinueEnabled());
  // EXPECT_FALSE(actor_->IsConnecting());
  network_screen_->OnNetworkManagerChanged(mock_network_library_);

  // EXPECT_TRUE(actor_->IsContinueEnabled());
  EmulateContinueButtonExit(network_screen_);
}

// See crbug.com/89392
#if defined(OS_LINUX)
#define MAYBE_Timeout DISABLED_Timeout
#else
#define MAYBE_Timeout Timeout
#endif
IN_PROC_BROWSER_TEST_F(NetworkScreenTest, MAYBE_Timeout) {
  EXPECT_CALL(*mock_network_library_, ethernet_connected())
      .WillOnce((Return(false)));
  EXPECT_CALL(*mock_network_library_, wifi_connected())
      .WillOnce((Return(false)));
  EXPECT_CALL(*mock_network_library_, cellular_connected())
      .WillOnce((Return(false)));
  EXPECT_CALL(*mock_network_library_, ethernet_connecting())
      .WillOnce((Return(false)));
  EXPECT_CALL(*mock_network_library_, wifi_connecting())
      .WillOnce((Return(true)));
  scoped_ptr<WifiNetwork> wifi(new WifiNetwork("wifi"));
  EXPECT_CALL(*mock_network_library_, wifi_network())
      .WillOnce(Return(wifi.get()));
  // EXPECT_FALSE(actor_->IsContinueEnabled());
  network_screen_->OnNetworkManagerChanged(mock_network_library_);

  EXPECT_CALL(*mock_network_library_, Connected())
      .Times(2)
      .WillRepeatedly(Return(false));
  // TODO(nkostylev): Add integration with WebUI actor http://crosbug.com/22570
  // EXPECT_FALSE(actor_->IsContinueEnabled());
  // EXPECT_FALSE(actor_->IsConnecting());
  network_screen_->OnConnectionTimeout();

  // Close infobubble with error message - it makes the test stable.
  // EXPECT_FALSE(actor_->IsContinueEnabled());
  // EXPECT_FALSE(actor_->IsConnecting());
  // actor_->ClearErrors();
}

}  // namespace chromeos
<|endoftext|>