<commit_before>#pragma once
//=====================================================================//
/*!	@file
	@brief	GUI widget_menu クラス
    @author 平松邦仁 (hira@rvf-rc45.net)
	@copyright	Copyright (C) 2017 Kunihito Hiramatsu @n
				Released under the MIT license @n
				https://github.com/hirakuni45/glfw_app/blob/master/LICENSE
*/
//=====================================================================//
#include "widgets/widget_director.hpp"
#include "widgets/widget_label.hpp"

namespace gui {

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief	GUI widget_menu クラス
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	struct widget_menu : public widget {

		typedef widget_menu value_type;

		typedef std::function<void (const std::string& select_text, uint32_t select_pos)> select_func_type;

		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		/*!
			@brief	widget_menu パラメーター
		*/
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		struct param {
			plate_param	plate_param_;	///< プレート・パラメーター
			color_param	color_param_;	///< カラー・パラメーター
			text_param	text_param_;	///< テキスト描画のパラメーター
			color_param	color_param_select_;	///< 選択時カラー・パラメーター

			utils::strings	text_list_;	///< テキスト・リスト

			uint32_t	list_limit_;	///< 最大表示数（「０」の場合最大数）
			bool		round_;			///< 角をラウンドしない場合「false」

			std::string	select_text_;	///< 選択位置のテキスト
			uint32_t	select_pos_;	///< テキスト・リストの選択位置

			select_func_type	select_func_;	///< セレクト関数

			param(const std::string& text = "") :
				plate_param_(),
				color_param_(widget_director::default_list_color_),
				text_param_(text, img::rgba8(255, 255), img::rgba8(0, 255),
				vtx::placement(vtx::placement::holizontal::LEFT,
				vtx::placement::vertical::CENTER)),
				color_param_select_(widget_director::default_list_color_select_),
				text_list_(), list_limit_(0), round_(true), select_text_(), select_pos_(0),
				select_func_(nullptr)
			{ }
		};

	private:
		widget_director&	wd_;

		param				param_;

		widget_labels		list_;

		int32_t				select_pos_;
		uint32_t			select_id_;

		void build_list_()
		{
			widget::param wp(vtx::irect(vtx::spos(0), get_rect().size), this);
			widget_label::param wp_;
			wp_.plate_param_ = param_.plate_param_;
			wp_.color_param_ = param_.color_param_select_;
			wp_.plate_param_.frame_width_ = 0;
			int n = 0;
			for(const std::string& s : param_.text_list_) {
				wp_.text_param_.set_text(s);
				if(n == 0 && param_.round_) {
					wp_.plate_param_.round_radius_ = param_.plate_param_.round_radius_;
					wp_.plate_param_.round_style_
						= widget::plate_param::round_style::TOP;
				} else if(n == (param_.text_list_.size() - 1) && param_.round_) {
					wp_.plate_param_.round_radius_ = param_.plate_param_.round_radius_;
					wp_.plate_param_.round_style_
						= widget::plate_param::round_style::BOTTOM;
				} else {
					wp_.plate_param_.round_radius_ = 0;
					wp_.plate_param_.round_style_
						= widget::plate_param::round_style::ALL;
				}
				widget_label* w = wd_.add_widget<widget_label>(wp, wp_);
				w->set_state(widget::state::ENABLE, false);
				list_.push_back(w);
				wp.rect_.org.y += get_rect().size.y;
				++n;
			}
		}

		void destroy_()
		{
			for(widget_label* w : list_) {
				wd_.del_widget(w);
			}
			list_.clear();
		}

	public:
		//-----------------------------------------------------------------//
		/*!
			@brief	コンストラクター
		*/
		//-----------------------------------------------------------------//
		widget_menu(widget_director& wd, const widget::param& wp, const param& p) :
			widget(wp), wd_(wd), param_(p),
			list_(), select_pos_(-1), select_id_(0)
		{ }

		//-----------------------------------------------------------------//
		/*!
			@brief	デストラクター
		*/
		//-----------------------------------------------------------------//
		virtual ~widget_menu() { destroy_(); }

		//-----------------------------------------------------------------//
		/*!
			@brief	型を取得
		*/
		//-----------------------------------------------------------------//
		type_id type() const override { return get_type_id<value_type>(); }

		//-----------------------------------------------------------------//
		/*!
			@brief	widget 型の基本名称を取得
			@return widget 型の基本名称
		*/
		//-----------------------------------------------------------------//
		const char* type_name() const override { return "menu"; }

		//-----------------------------------------------------------------//
		/*!
			@brief	ハイブリッド・ウィジェットのサイン
			@return ハイブリッド・ウィジェットの場合「true」を返す。
		*/
		//-----------------------------------------------------------------//
		bool hybrid() const override { return true; }

		//-----------------------------------------------------------------//
		/*!
			@brief	個別パラメーターへの取得(ro)
			@return 個別パラメーター
		*/
		//-----------------------------------------------------------------//
		const param& get_local_param() const { return param_; }

		//-----------------------------------------------------------------//
		/*!
			@brief	個別パラメーターへの取得
			@return 個別パラメーター
		*/
		//-----------------------------------------------------------------//
		param& at_local_param() { return param_; }

		//-----------------------------------------------------------------//
		/*!
			@brief	有効・無効の設定
			@param[in]	f	無効にする場合「false」
		*/
		//-----------------------------------------------------------------//
		void enable(bool f = true) { wd_.enable(this, f, true); }

		//-----------------------------------------------------------------//
		/*!
			@brief	選択 ID の取得 @n
					選択される毎に＋１される
			@return 選択 ID
		*/
		//-----------------------------------------------------------------//
		uint32_t get_select_id() const { return select_id_; }

		//-----------------------------------------------------------------//
		/*!
			@brief	選択テキストの取得
			@return 選択テキスト
		*/
		//-----------------------------------------------------------------//
		const std::string& get_select_text() const { return param_.select_text_; }

		//-----------------------------------------------------------------//
		/*!
			@brief	選択位置の取得
			@return 選択位置
		*/
		//-----------------------------------------------------------------//
		uint32_t get_select_pos() const { return param_.select_pos_; }

		//-----------------------------------------------------------------//
		/*!
			@brief	メニューの再構築 @n
					※「text_list_」を作り直してから呼ぶ事で、以前のリスト @n
					が廃棄され、新規リストになる。
		*/
		//-----------------------------------------------------------------//
		void build()
		{
			destroy_();
			build_list_();
			param_.select_text_.clear();
			param_.select_pos_ = 0;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	初期化
		*/
		//-----------------------------------------------------------------//
		void initialize() override
		{
			// 標準的に固定、リサイズ不可
			at_param().state_.set(widget::state::SERVICE);
			at_param().state_.set(widget::state::POSITION_LOCK);
			at_param().state_.set(widget::state::SIZE_LOCK);
			at_param().state_.set(widget::state::ENABLE, false);

			build_list_();
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	アップデート
		*/
		//-----------------------------------------------------------------//
		void update() override
		{
			if(!get_state(widget::state::ENABLE) || list_.empty()) {
				return;
			}

			wd_.top_widget(this);

			uint32_t n = 0;
			for(widget_label* w : list_) {
				if(w->get_select()) {
					param_.select_pos_ = n;
					at_local_param().text_param_.text_ = w->get_local_param().text_param_.text_;
					w->set_action(widget::action::SELECT_HIGHLIGHT);
				} else if(w->get_selected()) {
					select_pos_ = param_.select_pos_;
					if(select_pos_ < list_.size()) {
						param_.select_text_ = list_[select_pos_]->get_local_param().text_param_.get_text();
					}
					++select_id_;
				} else {
					w->set_action(widget::action::SELECT_HIGHLIGHT, false);
				}
				++n;
			}

			// list_limit_ は実装中
			// ・list_limit_ は、表示するラベルの制限を行う
			// ・スクロール・ダイアルで、リストのスクロールを行う
#if 0
			if(select_pos_ < 0) {
				const vtx::spos& scr = wd_.get_scroll();
				if(get_focus() && scr.y != 0) {
					int pos = param_.select_pos_;
					pos += scr.y;
					if(pos < 0) {
						pos = 0;
					} else if(pos >= static_cast<int>(list_.size())) {
						pos = list_.size() - 1;
					}
					param_.select_pos_ = pos;
				}
			}
#endif
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	サービス
		*/
		//-----------------------------------------------------------------//
		void service() override
		{
			if(select_pos_ >= 0 && static_cast<uint32_t>(select_pos_) < list_.size()) {
				wd_.enable(this, false, true);
				if(param_.select_func_ != nullptr) {
					param_.select_func_(param_.select_text_, param_.select_pos_);
				}
				select_pos_ = -1;
			}
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	レンダリング
		*/
		//-----------------------------------------------------------------//
		void render() override { }

		//-----------------------------------------------------------------//
		/*!
			@brief	状態のセーブ
			@param[in]	pre	プリファレンス参照
			@return エラーが無い場合「true」
		*/
		//-----------------------------------------------------------------//
		bool save(sys::preference& pre) override { return true; }

		//-----------------------------------------------------------------//
		/*!
			@brief	状態のロード
			@param[in]	pre	プリファレンス参照
			@return エラーが無い場合「true」
		*/
		//-----------------------------------------------------------------//
		bool load(const sys::preference& pre) override { return true; }
	};
}
<commit_msg>update menu management<commit_after>#pragma once
//=====================================================================//
/*!	@file
	@brief	GUI widget_menu クラス @n
			※メニューの文字列リストは、操作性を考慮して二重に持っている。@n
			※あまりに巨大なメニューには向いていない。@n
			※メニューは単なるテキストの集合なので、同じ文字列が許容される。
    @author 平松邦仁 (hira@rvf-rc45.net)
	@copyright	Copyright (C) 2017 Kunihito Hiramatsu @n
				Released under the MIT license @n
				https://github.com/hirakuni45/glfw_app/blob/master/LICENSE
*/
//=====================================================================//
#include "widgets/widget_director.hpp"
#include "widgets/widget_label.hpp"
#include "utils/format.hpp"

namespace gui {

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief	GUI widget_menu クラス @n
				※widget_label を並べた、ハイブリッド・モデル
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	struct widget_menu : public widget {

		typedef widget_menu value_type;

		typedef utils::strings strings;

		typedef std::function<void (const std::string& select_text, uint32_t select_pos)> select_func_type;

		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		/*!
			@brief	widget_menu パラメーター
		*/
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		struct param {
			plate_param	plate_param_;	///< プレート・パラメーター
			color_param	color_param_;	///< カラー・パラメーター
			text_param	text_param_;	///< テキスト描画のパラメーター
			color_param	color_param_select_;	///< 選択時カラー・パラメーター

			strings		text_list_;	///< テキスト・リスト

			uint32_t	list_limit_;	///< 最大表示数（「０」の場合最大数）
			bool		round_;			///< 角をラウンドしない場合「false」

			std::string	select_text_;	///< 選択位置のテキスト
			uint32_t	select_pos_;	///< テキスト・リストの選択位置

			select_func_type	select_func_;	///< セレクト関数

			param(const std::string& text = "") :
				plate_param_(),
				color_param_(widget_director::default_list_color_),
				text_param_(text, img::rgba8(255, 255), img::rgba8(0, 255),
				vtx::placement(vtx::placement::holizontal::LEFT,
				vtx::placement::vertical::CENTER)),
				color_param_select_(widget_director::default_list_color_select_),
				text_list_(), list_limit_(0), round_(true), select_text_(), select_pos_(0),
				select_func_(nullptr)
			{ }
		};

	private:
		widget_director&	wd_;

		param				param_;

		widget_labels		list_;

		int32_t				select_pos_;
		uint32_t			select_id_;

		widget_label* build_menu_(uint32_t pos, const widget::param& wp, widget_label::param& wp_, bool mono)
		{
			if(pos == 0 && param_.round_) {
				wp_.plate_param_.round_radius_ = param_.plate_param_.round_radius_;
				if(mono) {
					wp_.plate_param_.round_style_ = widget::plate_param::round_style::ALL;
				} else {
					wp_.plate_param_.round_style_ = widget::plate_param::round_style::TOP;
				}
			} else if(pos == (param_.text_list_.size() - 1) && param_.round_) {
				wp_.plate_param_.round_radius_ = param_.plate_param_.round_radius_;
				wp_.plate_param_.round_style_ = widget::plate_param::round_style::BOTTOM;
			} else {
				wp_.plate_param_.round_radius_ = 0;
				wp_.plate_param_.round_style_ = widget::plate_param::round_style::ALL;
			}
			widget_label* w = wd_.add_widget<widget_label>(wp, wp_);
			return w;
		}

		void build_list_()
		{
			widget::param wp(vtx::irect(vtx::spos(0), get_rect().size), this);
			widget_label::param wp_;
			wp_.plate_param_ = param_.plate_param_;
			wp_.color_param_ = param_.color_param_select_;
			wp_.plate_param_.frame_width_ = 0;
			int n = 0;
			bool mono = param_.text_list_.size() == 1 ? true : false;
			for(const std::string& s : param_.text_list_) {
				wp_.text_param_.set_text(s);
				widget_label* w = build_menu_(n, wp, wp_, mono);
				list_.push_back(w);
				wp.rect_.org.y += get_rect().size.y;
				++n;
			}
		}

		void destroy_()
		{
			for(widget_label* w : list_) {
				wd_.del_widget(w);
			}
			list_.clear();
		}

	public:
		//-----------------------------------------------------------------//
		/*!
			@brief	コンストラクター
		*/
		//-----------------------------------------------------------------//
		widget_menu(widget_director& wd, const widget::param& wp, const param& p) :
			widget(wp), wd_(wd), param_(p),
			list_(), select_pos_(-1), select_id_(0)
		{ }

		//-----------------------------------------------------------------//
		/*!
			@brief	デストラクター
		*/
		//-----------------------------------------------------------------//
		virtual ~widget_menu() { destroy_(); }

		//-----------------------------------------------------------------//
		/*!
			@brief	型を取得
		*/
		//-----------------------------------------------------------------//
		type_id type() const override { return get_type_id<value_type>(); }

		//-----------------------------------------------------------------//
		/*!
			@brief	widget 型の基本名称を取得
			@return widget 型の基本名称
		*/
		//-----------------------------------------------------------------//
		const char* type_name() const override { return "menu"; }

		//-----------------------------------------------------------------//
		/*!
			@brief	ハイブリッド・ウィジェットのサイン
			@return ハイブリッド・ウィジェットの場合「true」を返す。
		*/
		//-----------------------------------------------------------------//
		bool hybrid() const override { return true; }

		//-----------------------------------------------------------------//
		/*!
			@brief	個別パラメーターへの取得(ro)
			@return 個別パラメーター
		*/
		//-----------------------------------------------------------------//
		const param& get_local_param() const { return param_; }

		//-----------------------------------------------------------------//
		/*!
			@brief	個別パラメーターへの取得
			@return 個別パラメーター
		*/
		//-----------------------------------------------------------------//
		param& at_local_param() { return param_; }

		//-----------------------------------------------------------------//
		/*!
			@brief	有効・無効の設定
			@param[in]	f	無効にする場合「false」
		*/
		//-----------------------------------------------------------------//
		void enable(bool f = true) { wd_.enable(this, f, true); }

		//-----------------------------------------------------------------//
		/*!
			@brief	文字列リストの参照（ＲＯ）
			@return 文字列リスト
		*/
		//-----------------------------------------------------------------//
		const strings& get_list() const { return param_.text_list_; }

		//-----------------------------------------------------------------//
		/*!
			@brief	文字列リストの参照
			@return 文字列リスト
		*/
		//-----------------------------------------------------------------//
		strings& at_list() { return param_.text_list_; }

		//-----------------------------------------------------------------//
		/*!
			@brief	メニューのサイズを取得
			@return メニューのサイズ
		*/
		//-----------------------------------------------------------------//
		uint32_t size() const { return param_.text_list_.size(); }

		//-----------------------------------------------------------------//
		/*!
			@brief	メニューの全クリア
		*/
		//-----------------------------------------------------------------//
		void clear() {
			param_.text_list_.clear();
			destroy_();
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	メニューの消去
			@param[in]	pos	消去位置
			@return 成功したら「true」
		*/
		//-----------------------------------------------------------------//
		bool erase(uint32_t pos)
		{
			if(pos >= list_.size()) return false;

			int h = get_rect().size.y;
			param_.text_list_.erase(param_.text_list_.begin() + pos);
			wd_.del_widget(list_[pos]);
			list_.erase(list_.begin() + pos);

			for(uint32_t n = pos; n < list_.size(); ++n) {
				list_[n]->at_rect().org.y -= h;
			}

			// プレートのスタイルを変更
			if(param_.round_ && !list_.empty()) {
				if(list_.size() == 1) {
					widget_label* w = list_[0];
					w->at_local_param().plate_param_.round_radius_ = param_.plate_param_.round_radius_;
					w->at_local_param().plate_param_.round_style_ = widget::plate_param::round_style::ALL;
					w->build_plate();
				} else if(pos == 0) {
					widget_label* w = list_[0];
					w->at_local_param().plate_param_.round_radius_ = param_.plate_param_.round_radius_;
					w->at_local_param().plate_param_.round_style_ = widget::plate_param::round_style::TOP;
					w->build_plate();
				} else {
					widget_label* w = list_[list_.size() - 1];
					w->at_local_param().plate_param_.round_radius_ = param_.plate_param_.round_radius_;
					w->at_local_param().plate_param_.round_style_ = widget::plate_param::round_style::BOTTOM;
					w->build_plate();
				}
			}

			return true;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	メニューへテキストを挿入
			@param[in]	text	テキスト
			@param[in]	pos		位置
			@return 挿入できたら「true」
		*/
		//-----------------------------------------------------------------//
		bool insert(const std::string& text, uint32_t pos)
		{
			if(pos > list_.size()) return false;

			param_.text_list_.insert(param_.text_list_.begin() + pos, text);

			int h = get_rect().size.y;
			widget::param wp(vtx::irect(vtx::spos(0, pos * h), get_rect().size), this);
			widget_label::param wp_;
			wp_.plate_param_ = param_.plate_param_;
			wp_.color_param_ = param_.color_param_select_;
			wp_.plate_param_.frame_width_ = 0;
			wp_.text_param_.set_text(text);

			widget_label* w = build_menu_(pos, wp, wp_, false);

			list_.insert(list_.begin() + pos, w);
			++pos;
			for(uint32_t n = pos; n < list_.size(); ++n) {
				list_[n]->at_rect().org.y += h;
			}

			if(param_.round_) {
				if(pos == 1 && list_.size() > 1) {
					widget_label* w = list_[pos];
					w->at_local_param().plate_param_.round_radius_ = 0;
					w->at_local_param().plate_param_.round_style_ = widget::plate_param::round_style::ALL;
					w->build_plate();
				} else if(pos == list_.size()) {
					widget_label* w = list_[pos - 2];
					w->at_local_param().plate_param_.round_radius_ = 0;
					w->at_local_param().plate_param_.round_style_ = widget::plate_param::round_style::ALL;
					w->build_plate();
				}
			}

			return true;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	メニューの最後尾へ追加
			@param[in]	text	テキスト
			@return 挿入できたら「true」
		*/
		//-----------------------------------------------------------------//
		bool push_back(const std::string& text) { return insert(text, list_.size()); }

		//-----------------------------------------------------------------//
		/*!
			@brief	選択 ID の取得 @n
					選択される毎に＋１される
			@return 選択 ID
		*/
		//-----------------------------------------------------------------//
		uint32_t get_select_id() const { return select_id_; }

		//-----------------------------------------------------------------//
		/*!
			@brief	選択テキストの取得
			@return 選択テキスト
		*/
		//-----------------------------------------------------------------//
		const std::string& get_select_text() const { return param_.select_text_; }

		//-----------------------------------------------------------------//
		/*!
			@brief	選択位置の取得
			@return 選択位置
		*/
		//-----------------------------------------------------------------//
		uint32_t get_select_pos() const { return param_.select_pos_; }

		//-----------------------------------------------------------------//
		/*!
			@brief	メニューの再構築 @n
					※「text_list_」を作り直してから呼ぶ事で、以前のリスト @n
					が廃棄され、新規リストになる。
		*/
		//-----------------------------------------------------------------//
		void build()
		{
			destroy_();
			build_list_();
			param_.select_text_.clear();
			param_.select_pos_ = 0;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	初期化
		*/
		//-----------------------------------------------------------------//
		void initialize() override
		{
			// 標準的に固定、リサイズ不可、サービス呼び出し
			at_param().state_.set(widget::state::SERVICE);
			at_param().state_.set(widget::state::POSITION_LOCK);
			at_param().state_.set(widget::state::SIZE_LOCK);
			at_param().state_.set(widget::state::ENABLE, false);

			build_list_();
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	アップデート
		*/
		//-----------------------------------------------------------------//
		void update() override
		{
			if(!get_state(widget::state::ENABLE) || list_.empty()) {
				return;
			}

			wd_.top_widget(this);

			uint32_t n = 0;
			for(widget_label* w : list_) {
				if(w->get_select()) {
					param_.select_pos_ = n;
					at_local_param().text_param_.text_ = w->get_local_param().text_param_.text_;
					w->set_action(widget::action::SELECT_HIGHLIGHT);
				} else if(w->get_selected()) {
					select_pos_ = param_.select_pos_;
					if(select_pos_ < list_.size()) {
						param_.select_text_ = list_[select_pos_]->get_local_param().text_param_.get_text();
					}
					++select_id_;
				} else {
					w->set_action(widget::action::SELECT_HIGHLIGHT, false);
				}
				++n;
			}

			// list_limit_ は実装中
			// ・list_limit_ は、表示するラベルの制限を行う
			// ・スクロール・ダイアルで、リストのスクロールを行う
#if 0
			if(select_pos_ < 0) {
				const vtx::spos& scr = wd_.get_scroll();
				if(get_focus() && scr.y != 0) {
					int pos = param_.select_pos_;
					pos += scr.y;
					if(pos < 0) {
						pos = 0;
					} else if(pos >= static_cast<int>(list_.size())) {
						pos = list_.size() - 1;
					}
					param_.select_pos_ = pos;
				}
			}
#endif
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	サービス
		*/
		//-----------------------------------------------------------------//
		void service() override
		{
			if(select_pos_ >= 0 && static_cast<uint32_t>(select_pos_) < list_.size()) {
				wd_.enable(this, false, true);
				if(param_.select_func_ != nullptr) {
					param_.select_func_(param_.select_text_, param_.select_pos_);
				}
				select_pos_ = -1;
			}
		}

		//-----------------------------------------------------------------//
		/*!
			@brief	レンダリング
		*/
		//-----------------------------------------------------------------//
		void render() override { }

		//-----------------------------------------------------------------//
		/*!
			@brief	状態のセーブ
			@param[in]	pre	プリファレンス参照
			@return エラーが無い場合「true」
		*/
		//-----------------------------------------------------------------//
		bool save(sys::preference& pre) override { return true; }

		//-----------------------------------------------------------------//
		/*!
			@brief	状態のロード
			@param[in]	pre	プリファレンス参照
			@return エラーが無い場合「true」
		*/
		//-----------------------------------------------------------------//
		bool load(const sys::preference& pre) override { return true; }
	};
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: dlgeps.cxx,v $
 *
 *  $Revision: 1.10 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 02:43:49 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#ifndef GCC
#pragma hdrstop
#endif

#include <tools/ref.hxx>
#include <vcl/msgbox.hxx>
#include <svtools/FilterConfigItem.hxx>
#include "dlgeps.hxx"
#include "dlgeps.hrc"
#include "strings.hrc"

/*************************************************************************
|*
|* Ctor
|*
\************************************************************************/

DlgExportEPS::DlgExportEPS( FltCallDialogParameter& rPara ) :
                ModalDialog         ( rPara.pWindow, ResId( DLG_EXPORT_EPS, rPara.pResMgr ) ),
                aGrpPreview         ( this, ResId( GRP_PREVIEW ) ),
                aCBPreviewTiff      ( this, ResId( CB_PREVIEW_TIFF ) ),
                aCBPreviewEPSI      ( this, ResId( CB_PREVIEW_EPSI ) ),
                aGrpVersion         ( this, ResId( GRP_VERSION ) ),
                aRBLevel1           ( this, ResId( RB_LEVEL1 ) ),
                aRBLevel2           ( this, ResId( RB_LEVEL2 ) ),
                aGrpColor           ( this, ResId( GRP_COLOR ) ),
                aRBColor            ( this, ResId( RB_COLOR ) ),
                aRBGrayscale        ( this, ResId( RB_GRAYSCALE ) ),
                aGrpCompression     ( this, ResId( GRP_COMPRESSION ) ),
                aRBCompressionLZW   ( this, ResId( RB_COMPRESSION_LZW ) ),
                aRBCompressionNone  ( this, ResId( RB_COMPRESSION_NONE ) ),
                aBtnOK              ( this, ResId( BTN_OK ) ),
                aBtnCancel          ( this, ResId( BTN_CANCEL ) ),
                aBtnHelp            ( this, ResId( BTN_HELP ) ),
                pMgr                ( rPara.pResMgr ),
                rFltCallPara        ( rPara )
{
    FreeResource();

    String  aFilterConfigPath( RTL_CONSTASCII_USTRINGPARAM( "Office.Common/Filter/Graphic/Export/EPS" ) );
    pConfigItem = new FilterConfigItem( aFilterConfigPath, &rPara.aFilterData );

    // Config-Parameter lesen
    String sPreview( RTL_CONSTASCII_USTRINGPARAM( "Preview" ) );
    String sVersion( RTL_CONSTASCII_USTRINGPARAM( "Version" ) );
    String sColorFormat( RTL_CONSTASCII_USTRINGPARAM( "ColorFormat" ) );
    String sCompressionMode( RTL_CONSTASCII_USTRINGPARAM( "CompressionMode" ) );
    String sTextMode( RTL_CONSTASCII_USTRINGPARAM( "TextMode" ) );

    sal_Int32   nPreview = pConfigItem->ReadInt32( sPreview, 0 );
    sal_Int32   nVersion = pConfigItem->ReadInt32( sVersion, 2 );
    sal_Int32   nColor = pConfigItem->ReadInt32( sColorFormat, 0 );
    sal_Int32   nCompr = pConfigItem->ReadInt32( sCompressionMode, 2 );

    /* SJ: The following line is not superfluous, reading the item will also    #106652#
       create the corresponding FilterData Property. Since all filter
       are no longer accessing the configuration itself, we have fill the
       FilterData sequence with all available configuration items */
    pConfigItem->ReadInt32( sTextMode, 0 );

    BOOL bCheck = FALSE;
    if ( nPreview & 1 )
        bCheck = TRUE;
    aCBPreviewTiff.Check( bCheck );
    if ( nPreview & 2 )
        bCheck = TRUE;
    aCBPreviewEPSI.Check( bCheck );

    bCheck = FALSE;
    if ( nVersion == 1 )
        bCheck ^= TRUE;
    aRBLevel1.Check( bCheck );
    bCheck ^= TRUE;
    aRBLevel2.Check( bCheck );

    bCheck = FALSE;
    if ( nColor == 1 )
        bCheck ^= TRUE;
    aRBColor.Check( bCheck );
    bCheck ^= TRUE;
    aRBGrayscale.Check( bCheck );

    bCheck = FALSE;
    if ( nCompr == 1 )
        bCheck ^= TRUE;
    aRBCompressionLZW.Check( bCheck );
    bCheck ^= TRUE;
    aRBCompressionNone.Check( bCheck );

    if ( aRBLevel1.IsChecked() )
    {
        aRBColor.Disable();
        aRBGrayscale.Disable();
        aRBCompressionNone.Disable();
        aRBCompressionLZW.Disable();
        aRBCompressionNone.Disable();
    }

    aBtnOK.SetClickHdl( LINK( this, DlgExportEPS, OK ) );
    aRBLevel1.SetClickHdl( LINK( this, DlgExportEPS, LEVEL1 ) );
    aRBLevel2.SetClickHdl( LINK( this, DlgExportEPS, LEVEL2 ) );
}

DlgExportEPS::~DlgExportEPS()
{
    delete pConfigItem;
}

/*************************************************************************
|*
|* Speichert eingestellte Werte in ini-Datei
|*
\************************************************************************/

IMPL_LINK( DlgExportEPS, OK, void *, EMPTYARG )
{

    // Config-Parameter schreiben
    sal_Int32 nCheck = 0;
    if ( aCBPreviewTiff.IsChecked() )
        nCheck++;
    if ( aCBPreviewEPSI.IsChecked() )
        nCheck += 2;

    String sPreview( RTL_CONSTASCII_USTRINGPARAM( "Preview" ) );
    pConfigItem->WriteInt32( sPreview, nCheck );

    nCheck = 1;
    if ( aRBLevel2.IsChecked() )
        nCheck++;
    String sVersion( RTL_CONSTASCII_USTRINGPARAM( "Version" ) );
    pConfigItem->WriteInt32( sVersion, nCheck );

    nCheck = 1;
    if ( aRBGrayscale.IsChecked() )
        nCheck++;
    String sColorFormat( RTL_CONSTASCII_USTRINGPARAM( "ColorFormat" ) );
    pConfigItem->WriteInt32( sColorFormat, nCheck );

    nCheck = 1;
    if ( aRBCompressionNone.IsChecked() )
        nCheck++;
    String sCompressionMode( RTL_CONSTASCII_USTRINGPARAM( "CompressionMode" ) );
    pConfigItem->WriteInt32( sCompressionMode, nCheck );

    rFltCallPara.aFilterData = pConfigItem->GetFilterData();
    EndDialog( RET_OK );

    return 0;
}

//------------------------------------------------------------------------

IMPL_LINK( DlgExportEPS, LEVEL1, void*, EMPTYARG )
{
    if ( aRBLevel1.IsChecked() )
    {
        aRBColor.Disable();
        aRBGrayscale.Disable();
        aRBCompressionLZW.Disable();
        aRBCompressionNone.Disable();
    }
    return 0;
}

//------------------------------------------------------------------------

IMPL_LINK( DlgExportEPS, LEVEL2, void*, EMPTYARG )
{
    if ( aRBLevel2.IsChecked() )
    {
        aRBColor.Enable();
        aRBGrayscale.Enable();
        aRBCompressionLZW.Enable();
        aRBCompressionNone.Enable();
    }
    return 0;
}
<commit_msg>INTEGRATION: CWS warnings01 (1.10.28); FILE MERGED 2005/10/27 15:21:08 sj 1.10.28.1: #i55991# warning free code<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: dlgeps.cxx,v $
 *
 *  $Revision: 1.11 $
 *
 *  last change: $Author: hr $ $Date: 2006-06-19 21:43:03 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/
#ifndef GCC
#pragma hdrstop
#endif

#include <tools/ref.hxx>
#include <vcl/msgbox.hxx>
#include <svtools/FilterConfigItem.hxx>
#include "dlgeps.hxx"
#include "dlgeps.hrc"
#include "strings.hrc"

/*************************************************************************
|*
|* Ctor
|*
\************************************************************************/

DlgExportEPS::DlgExportEPS( FltCallDialogParameter& rPara ) :
                ModalDialog         ( rPara.pWindow, ResId( DLG_EXPORT_EPS, rPara.pResMgr ) ),
                rFltCallPara        ( rPara ),
                aGrpPreview         ( this, ResId( GRP_PREVIEW ) ),
                aCBPreviewTiff      ( this, ResId( CB_PREVIEW_TIFF ) ),
                aCBPreviewEPSI      ( this, ResId( CB_PREVIEW_EPSI ) ),
                aGrpVersion         ( this, ResId( GRP_VERSION ) ),
                aRBLevel1           ( this, ResId( RB_LEVEL1 ) ),
                aRBLevel2           ( this, ResId( RB_LEVEL2 ) ),
                aGrpColor           ( this, ResId( GRP_COLOR ) ),
                aRBColor            ( this, ResId( RB_COLOR ) ),
                aRBGrayscale        ( this, ResId( RB_GRAYSCALE ) ),
                aGrpCompression     ( this, ResId( GRP_COMPRESSION ) ),
                aRBCompressionLZW   ( this, ResId( RB_COMPRESSION_LZW ) ),
                aRBCompressionNone  ( this, ResId( RB_COMPRESSION_NONE ) ),
                aBtnOK              ( this, ResId( BTN_OK ) ),
                aBtnCancel          ( this, ResId( BTN_CANCEL ) ),
                aBtnHelp            ( this, ResId( BTN_HELP ) ),
                pMgr                ( rPara.pResMgr )
{
    FreeResource();

    String  aFilterConfigPath( RTL_CONSTASCII_USTRINGPARAM( "Office.Common/Filter/Graphic/Export/EPS" ) );
    pConfigItem = new FilterConfigItem( aFilterConfigPath, &rPara.aFilterData );

    // Config-Parameter lesen
    String sPreview( RTL_CONSTASCII_USTRINGPARAM( "Preview" ) );
    String sVersion( RTL_CONSTASCII_USTRINGPARAM( "Version" ) );
    String sColorFormat( RTL_CONSTASCII_USTRINGPARAM( "ColorFormat" ) );
    String sCompressionMode( RTL_CONSTASCII_USTRINGPARAM( "CompressionMode" ) );
    String sTextMode( RTL_CONSTASCII_USTRINGPARAM( "TextMode" ) );

    sal_Int32   nPreview = pConfigItem->ReadInt32( sPreview, 0 );
    sal_Int32   nVersion = pConfigItem->ReadInt32( sVersion, 2 );
    sal_Int32   nColor = pConfigItem->ReadInt32( sColorFormat, 0 );
    sal_Int32   nCompr = pConfigItem->ReadInt32( sCompressionMode, 2 );

    /* SJ: The following line is not superfluous, reading the item will also    #106652#
       create the corresponding FilterData Property. Since all filter
       are no longer accessing the configuration itself, we have fill the
       FilterData sequence with all available configuration items */
    pConfigItem->ReadInt32( sTextMode, 0 );

    BOOL bCheck = FALSE;
    if ( nPreview & 1 )
        bCheck = TRUE;
    aCBPreviewTiff.Check( bCheck );
    if ( nPreview & 2 )
        bCheck = TRUE;
    aCBPreviewEPSI.Check( bCheck );

    bCheck = FALSE;
    if ( nVersion == 1 )
        bCheck ^= TRUE;
    aRBLevel1.Check( bCheck );
    bCheck ^= TRUE;
    aRBLevel2.Check( bCheck );

    bCheck = FALSE;
    if ( nColor == 1 )
        bCheck ^= TRUE;
    aRBColor.Check( bCheck );
    bCheck ^= TRUE;
    aRBGrayscale.Check( bCheck );

    bCheck = FALSE;
    if ( nCompr == 1 )
        bCheck ^= TRUE;
    aRBCompressionLZW.Check( bCheck );
    bCheck ^= TRUE;
    aRBCompressionNone.Check( bCheck );

    if ( aRBLevel1.IsChecked() )
    {
        aRBColor.Disable();
        aRBGrayscale.Disable();
        aRBCompressionNone.Disable();
        aRBCompressionLZW.Disable();
        aRBCompressionNone.Disable();
    }

    aBtnOK.SetClickHdl( LINK( this, DlgExportEPS, OK ) );
    aRBLevel1.SetClickHdl( LINK( this, DlgExportEPS, LEVEL1 ) );
    aRBLevel2.SetClickHdl( LINK( this, DlgExportEPS, LEVEL2 ) );
}

DlgExportEPS::~DlgExportEPS()
{
    delete pConfigItem;
}

/*************************************************************************
|*
|* Speichert eingestellte Werte in ini-Datei
|*
\************************************************************************/

IMPL_LINK( DlgExportEPS, OK, void *, EMPTYARG )
{

    // Config-Parameter schreiben
    sal_Int32 nCheck = 0;
    if ( aCBPreviewTiff.IsChecked() )
        nCheck++;
    if ( aCBPreviewEPSI.IsChecked() )
        nCheck += 2;

    String sPreview( RTL_CONSTASCII_USTRINGPARAM( "Preview" ) );
    pConfigItem->WriteInt32( sPreview, nCheck );

    nCheck = 1;
    if ( aRBLevel2.IsChecked() )
        nCheck++;
    String sVersion( RTL_CONSTASCII_USTRINGPARAM( "Version" ) );
    pConfigItem->WriteInt32( sVersion, nCheck );

    nCheck = 1;
    if ( aRBGrayscale.IsChecked() )
        nCheck++;
    String sColorFormat( RTL_CONSTASCII_USTRINGPARAM( "ColorFormat" ) );
    pConfigItem->WriteInt32( sColorFormat, nCheck );

    nCheck = 1;
    if ( aRBCompressionNone.IsChecked() )
        nCheck++;
    String sCompressionMode( RTL_CONSTASCII_USTRINGPARAM( "CompressionMode" ) );
    pConfigItem->WriteInt32( sCompressionMode, nCheck );

    rFltCallPara.aFilterData = pConfigItem->GetFilterData();
    EndDialog( RET_OK );

    return 0;
}

//------------------------------------------------------------------------

IMPL_LINK( DlgExportEPS, LEVEL1, void*, EMPTYARG )
{
    if ( aRBLevel1.IsChecked() )
    {
        aRBColor.Disable();
        aRBGrayscale.Disable();
        aRBCompressionLZW.Disable();
        aRBCompressionNone.Disable();
    }
    return 0;
}

//------------------------------------------------------------------------

IMPL_LINK( DlgExportEPS, LEVEL2, void*, EMPTYARG )
{
    if ( aRBLevel2.IsChecked() )
    {
        aRBColor.Enable();
        aRBGrayscale.Enable();
        aRBCompressionLZW.Enable();
        aRBCompressionNone.Enable();
    }
    return 0;
}
<|endoftext|>


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

#ifndef _PHP_PDO_CASSANDRA_H_
# define _PHP_PDO_CASSANDRA_H_

#define PHP_PDO_CASSANDRA_EXTNAME "pdo_cassandra"
#define PHP_PDO_CASSANDRA_EXTVER "@PACKAGE_VERSION@"

extern "C" {
#ifdef ZTS
# include "TSRM.h"
#endif

#include "php.h"
}

extern zend_module_entry cassandra_module_entry;
#define phpext_cassandra_ptr &cassandra_module_entry

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

#ifndef _PHP_PDO_CASSANDRA_H_
# define _PHP_PDO_CASSANDRA_H_

#define PHP_PDO_CASSANDRA_EXTNAME "pdo_cassandra"
#define PHP_PDO_CASSANDRA_EXTVER "0.3.1"

extern "C" {
#ifdef ZTS
# include "TSRM.h"
#endif

#include "php.h"
}

extern zend_module_entry cassandra_module_entry;
#define phpext_cassandra_ptr &cassandra_module_entry

#endif /* _PHP_PDO_CASSANDRA_H_ */
<|endoftext|>


<commit_before>/*
 * This File is part of Davix, The IO library for HTTP based protocols
 * Copyright (C) CERN 2013
 * Author: Adrien Devresse <adrien.devresse@cern.ch>
 *
 * 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 <cstdio>
#include <cstring>
#include <davix.hpp>
#include <sstream>
#include <unistd.h>
#include "copy_internal.hpp"
#include "delegation/delegation.hpp"
#include <utils/davix_logger_internal.hpp>
#include <utils/davix_gcloud_utils.hpp>

using namespace Davix;

const std::string COPY_SCOPE = "Davix::HttpThirdPartyCopy";

// Gets the real location of uri respect to ref
// uri can be absolute or relative to ref
static std::string _full_url(const std::string ref,
        const std::string& uri)
{
    std::string final;

    if (uri.find("://") != std::string::npos) {
        final = uri;
    }
    else if (uri[0] == '/') {
        size_t colon = ref.find(':');
        size_t slash = std::string::npos;
        if (colon != std::string::npos)
            slash = ref.find('/', colon + 3);
        if (slash != std::string::npos) {
            std::string base = ref.substr(0, slash);
            final = base + uri;
        }
    }
    else {
        final = ref + uri;
    }

    return final;
}

// Same as _full_url, but it makes sure
// that the destination is https
static std::string _full_delegation_endpoint(const std::string& ref,
        const std::string& uri, DavixError** err)
{
    std::string final = _full_url(ref, uri);
    if (final.substr(7).compare("http://") == 0) {
        DavixError::setupError(err, COPY_SCOPE, StatusCode::OperationNonSupported,
                               std::string("Plain http can not be used for delegation: ") + uri);
        final.clear();
    }
    return final;
}

DavixCopy::DavixCopy(Context &c, const RequestParams *params): d_ptr(NULL)
{
    d_ptr = new DavixCopyInternal(c, params);
}

DavixCopy::~DavixCopy()
{
    delete d_ptr;
}

void DavixCopy::copy(const Uri &source, const Uri &destination,
        unsigned nstreams, DavixError **error)
{
    d_ptr->copy(source, destination, nstreams, error);
}

void DavixCopy::setPerformanceCallback(PerformanceCallback callback, void *udata)
{
    d_ptr->setPerformanceCallback(callback, udata);
}

void DavixCopy::setCancellationCallback(CancellationCallback callback, void *udata)
{
    d_ptr->setCancellationCallback(callback, udata);
}

void DavixCopyInternal::setPerformanceCallback(DavixCopy::PerformanceCallback callback,
        void *udata)
{
    perfCallback = callback;
    perfCallbackUdata = udata;
}

void DavixCopyInternal::setCancellationCallback(DavixCopy::CancellationCallback callback, void *udata)
{
    cancCallback = callback;
    cancCallbackUdata = udata;
}

Uri dropDav(const Uri &uri) {
    Uri retval(uri);

    if(retval.getProtocol() == "dav") {
        retval.setProtocol("http");
    }
    else if(retval.getProtocol() == "davs") {
        retval.setProtocol("https");
    }

    return retval;
}

bool DavixCopyInternal::shouldCancel() {
    if(!cancCallback) {
        return false;
    }

    return cancCallback(cancCallbackUdata);
}

bool DavixCopyInternal::shouldCancel(Davix::DavixError **error) {
    if(shouldCancel()) {
        DavixError::clearError(error);
        DavixError::setupError(error, COPY_SCOPE, StatusCode::Canceled, fmt::format("Request cancellation was requested."));
        return true;
    }

    return false;
}

void DavixCopyInternal::copy(const Uri &src, const Uri &dst,
        unsigned nstreams, DavixError **error)
{
    std::string nextSrc, prevSrc, destination;
    std::string delegationEndpoint;
    DavixError *internalError = NULL;
    bool suppressFinalHead = false;

    Uri srcHttp = dropDav(src);
    Uri dstHttp = dropDav(dst);

    // set source and destination according to copy method
    if(parameters->getCopyMode() == CopyMode::Push){
        nextSrc = srcHttp.getString();
        prevSrc = srcHttp.getString();
        destination = dstHttp.getString();
    }else if(parameters->getCopyMode() == CopyMode::Pull){
        nextSrc = dstHttp.getString();
        prevSrc = dstHttp.getString();
        destination = srcHttp.getString();
    }

    // nstreams as string
    char nstreamsStr[16];
    snprintf(nstreamsStr, sizeof(nstreamsStr), "%u", nstreams);

    // Need a copy so we can modify it
    Davix::RequestParams requestParams(parameters);
    requestParams.setTransparentRedirectionSupport(false);

    size_t start_pos;

    // if destination is s3 endpoint, change prefix to http(s) and pre-sign the request as a PUT
    if(destination.compare(0,2,"s3") == 0){
        destination.replace(0, 2, "http");
        time_t expiration_time = time(NULL) +3600;
        Davix::HeaderVec vec;
        Uri tmp;
        if (parameters->getCopyMode() == CopyMode::Pull)
            tmp = Davix::S3::tokenizeRequest(requestParams, "GET", destination, vec, expiration_time);
        else
            tmp = Davix::S3::tokenizeRequest(requestParams, "PUT", destination, vec, expiration_time);
        destination = tmp.getString();
        suppressFinalHead = true;
    }

    // handle gcloud endpoint as a destination
    if(destination.compare(0,6,"gcloud") == 0){
        destination.replace(0, 6, "http");

        Davix::HeaderVec vec;
        Uri tmp;
        if (parameters->getCopyMode() == CopyMode::Pull)
            tmp = Davix::gcloud::signURI(requestParams.getGcloudCredentials(), "GET", destination, vec, 3600);
        else
            tmp = Davix::gcloud::signURI(requestParams.getGcloudCredentials(), "PUT", destination, vec, 3600);
        destination = tmp.getString();
        suppressFinalHead = true;
    }

    if(destination.compare(0, 3, "dav") == 0) {
        destination.replace(0, 3, "http");
    }

    // Perform COPY hopping through redirections
    HttpRequest* request = NULL;
    do {
        nextSrc = _full_url(prevSrc, nextSrc);
        prevSrc = nextSrc;
        if (request) {
            request->discardBody(&internalError);
            if (!internalError)
                request->endRequest(&internalError);
            if (internalError) {
                DavixError::propagatePrefixedError(error, internalError, __func__);
                break;
            }
        }
        delete request;

        DAVIX_SLOG(DAVIX_LOG_VERBOSE, DAVIX_LOG_GRID, "Hop: {}",
                     nextSrc);

        request = context.createRequest(nextSrc, &internalError);
        if (internalError) {
            DavixError::propagatePrefixedError(error, internalError, __func__);
            break;
        }

        request->setRequestMethod("COPY");
        if(parameters->getCopyMode() == CopyMode::Push){
            request->addHeaderField("Destination", destination);
        }else if(parameters->getCopyMode() == CopyMode::Pull){
            request->addHeaderField("Source", destination);
        }
        request->addHeaderField("X-Number-Of-Streams", nstreamsStr);

        // for lcgdm-dav, ask for secure redirection in all cases for COPY
        request->addHeaderField("Secure-Redirection", "1");

        // for lcgdm-dav -> S3, add NoHead flag to suppress final head-to-close request
        if(suppressFinalHead)
            request->addHeaderField("Copy-Flags", "NoHead");
        request->setParameters(requestParams);
        request->beginRequest(&internalError);
        if (internalError) {
            DavixError::propagatePrefixedError(error, internalError, __func__);
            break;
        }

        // If we get a X-Delegate-To, before continuing, delegate
        if (request->getAnswerHeader("X-Delegate-To", delegationEndpoint)) {
            delegationEndpoint = _full_delegation_endpoint(nextSrc,
                                                           delegationEndpoint,
                                                           &internalError);
            if (internalError) {
                DavixError::propagatePrefixedError(error, internalError, __func__);
                break;
            }

            DAVIX_SLOG(DAVIX_LOG_VERBOSE, DAVIX_LOG_GRID, "Got delegation endpoint: {}",
                         delegationEndpoint.c_str());

            std::string dlg_id = DavixDelegation::delegate(context, delegationEndpoint,
                    parameters, &internalError);
            if (internalError) {
                DavixError::propagatePrefixedError(error, internalError, __func__);
                break;
            }

            DAVIX_SLOG(DAVIX_LOG_VERBOSE, DAVIX_LOG_GRID, "Got delegation ID {}",
                         dlg_id.c_str());

            dlg_id.clear();
        }

    } while (!shouldCancel() && request->getAnswerHeader("Location", nextSrc) && request->getRequestCode() >= 300 && request->getRequestCode() < 400);

    if (!*error) {
        int responseStatus = request->getRequestCode();
        if (responseStatus == 404) {
            DavixError::setupError(error, COPY_SCOPE, StatusCode::FileNotFound,
                                   "Could not COPY. File not found");
        }
        else if (responseStatus == 403) {
            DavixError::setupError(error, COPY_SCOPE, StatusCode::PermissionRefused,
                                   "Could not COPY. Permission denied.");
        }
        else if (responseStatus == 501) {
            DavixError::setupError(error, COPY_SCOPE, StatusCode::OperationNonSupported,
                                   "Could not COPY. The source service does not support it");
        }
        else if (responseStatus >= 405) {
            DavixError::setupError(error, COPY_SCOPE, StatusCode::OperationNonSupported,
                                   "Could not COPY. The source service does not allow it");
        }
        else if (responseStatus == 400) {
            std::string err_msg(request->getAnswerContentVec().begin(), request->getAnswerContentVec().end());
        	DavixError::setupError(error, COPY_SCOPE, StatusCode::InvalidArgument,
                                   fmt::format("Could not COPY. The server rejected the request: {}", err_msg));
        }
        else if (responseStatus >= 300) {
            std::ostringstream msg;
            msg << "Could not COPY. Unknown error code: " << responseStatus;
            DavixError::setupError(error, COPY_SCOPE, StatusCode::UnknowError,
                                   msg.str());
        }
    }

    if(shouldCancel(error)) {
        return;
    }

    // Did we fail?
    if (*error)
        return;

    // Finished hopping
    std::string finalSource = nextSrc;

    // Just wait for it to finish
    monitorPerformanceMarkers(request, error);
    request->endRequest(&internalError);

    if(internalError && !(*error) ) {
        DavixError::propagatePrefixedError(error, internalError, __func__);
    }

    if(shouldCancel(error)) {
        return;
    }

    delete request;
}

void DavixCopyInternal::monitorPerformanceMarkers(Davix::HttpRequest *request,
        Davix::DavixError **error)
{
    Davix::DavixError* daverr = NULL;
    char buffer[1024], *p;
    dav_ssize_t line_len;

    PerformanceMarker holder;
    PerformanceData performance;
    time_t lastPerfCallback = time(NULL);

    while ((line_len = request->readLine(buffer, sizeof(buffer), &daverr)) >= 0 && !daverr && !shouldCancel())
    {
        buffer[line_len] = '\0';

        if (line_len > 0)
            DAVIX_SLOG(DAVIX_LOG_VERBOSE, DAVIX_LOG_GRID, "Received: {}", buffer);

        // Skip heading whitespaces
        p = buffer;
        while (*p && p < buffer + sizeof(buffer) && isspace(*p))
            ++p;

        if (strncasecmp("Perf Marker", p, 11) == 0)
        {
            memset(&holder, 0, sizeof(holder));
        }
        else if (strncasecmp("Timestamp:", p, 10) == 0)
        {
            holder.latest = atol(p + 10);
        }
        else if (strncasecmp("Stripe Index:", p, 13) == 0)
        {
            holder.index = atoi(p + 13);
        }
        else if (strncasecmp("Stripe Bytes Transferred:", p, 25) == 0)
        {
            holder.transferred = atol(p + 26);
        }
        else if (strncasecmp("Total Stripe Count:", p, 19) == 0)
        {
            holder.count = atoi(p + 20);
        }
        else if (strncasecmp("End", p, 3) == 0)
        {
            performance.update(holder);
            time_t now = time(NULL);
            if (now - lastPerfCallback >= 1)
            {
                if (this->perfCallback)
                    this->perfCallback(performance, this->perfCallbackUdata);
                lastPerfCallback = now;
            }
        }
        else if (strncasecmp("success", p, 7) == 0)
        {
            request->discardBody(&daverr);
            break;
        }
        else if (strncasecmp("aborted", p, 7) == 0)
        {
            Davix::DavixError::setupError(error, COPY_SCOPE, StatusCode::Canceled,
                    "Transfer aborted in the remote end");
            break;
        }
        else if (strncasecmp("failed", p, 6) == 0 || strncasecmp("failure", p, 7) == 0)
        {
            Davix::DavixError::setupError(error, COPY_SCOPE, StatusCode::RemoteError,
                    std::string("Transfer failed: ") + p);
            break;
        }
        else if(line_len> 0)
        {
            DAVIX_SLOG(DAVIX_LOG_WARNING, DAVIX_LOG_GRID, "Unknown performance marker, ignoring: {}", buffer);
        }
    }
}
<commit_msg>DMC-1171 Detect when the server terminates the connection early during TPC, and fail immediately<commit_after>/*
 * This File is part of Davix, The IO library for HTTP based protocols
 * Copyright (C) CERN 2013
 * Author: Adrien Devresse <adrien.devresse@cern.ch>
 *
 * 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 <cstdio>
#include <cstring>
#include <davix.hpp>
#include <sstream>
#include <unistd.h>
#include "copy_internal.hpp"
#include "delegation/delegation.hpp"
#include <utils/davix_logger_internal.hpp>
#include <utils/davix_gcloud_utils.hpp>

using namespace Davix;

const std::string COPY_SCOPE = "Davix::HttpThirdPartyCopy";

// Gets the real location of uri respect to ref
// uri can be absolute or relative to ref
static std::string _full_url(const std::string ref,
        const std::string& uri)
{
    std::string final;

    if (uri.find("://") != std::string::npos) {
        final = uri;
    }
    else if (uri[0] == '/') {
        size_t colon = ref.find(':');
        size_t slash = std::string::npos;
        if (colon != std::string::npos)
            slash = ref.find('/', colon + 3);
        if (slash != std::string::npos) {
            std::string base = ref.substr(0, slash);
            final = base + uri;
        }
    }
    else {
        final = ref + uri;
    }

    return final;
}

// Same as _full_url, but it makes sure
// that the destination is https
static std::string _full_delegation_endpoint(const std::string& ref,
        const std::string& uri, DavixError** err)
{
    std::string final = _full_url(ref, uri);
    if (final.substr(7).compare("http://") == 0) {
        DavixError::setupError(err, COPY_SCOPE, StatusCode::OperationNonSupported,
                               std::string("Plain http can not be used for delegation: ") + uri);
        final.clear();
    }
    return final;
}

DavixCopy::DavixCopy(Context &c, const RequestParams *params): d_ptr(NULL)
{
    d_ptr = new DavixCopyInternal(c, params);
}

DavixCopy::~DavixCopy()
{
    delete d_ptr;
}

void DavixCopy::copy(const Uri &source, const Uri &destination,
        unsigned nstreams, DavixError **error)
{
    d_ptr->copy(source, destination, nstreams, error);
}

void DavixCopy::setPerformanceCallback(PerformanceCallback callback, void *udata)
{
    d_ptr->setPerformanceCallback(callback, udata);
}

void DavixCopy::setCancellationCallback(CancellationCallback callback, void *udata)
{
    d_ptr->setCancellationCallback(callback, udata);
}

void DavixCopyInternal::setPerformanceCallback(DavixCopy::PerformanceCallback callback,
        void *udata)
{
    perfCallback = callback;
    perfCallbackUdata = udata;
}

void DavixCopyInternal::setCancellationCallback(DavixCopy::CancellationCallback callback, void *udata)
{
    cancCallback = callback;
    cancCallbackUdata = udata;
}

Uri dropDav(const Uri &uri) {
    Uri retval(uri);

    if(retval.getProtocol() == "dav") {
        retval.setProtocol("http");
    }
    else if(retval.getProtocol() == "davs") {
        retval.setProtocol("https");
    }

    return retval;
}

bool DavixCopyInternal::shouldCancel() {
    if(!cancCallback) {
        return false;
    }

    return cancCallback(cancCallbackUdata);
}

bool DavixCopyInternal::shouldCancel(Davix::DavixError **error) {
    if(shouldCancel()) {
        DavixError::clearError(error);
        DavixError::setupError(error, COPY_SCOPE, StatusCode::Canceled, fmt::format("Request cancellation was requested."));
        return true;
    }

    return false;
}

void DavixCopyInternal::copy(const Uri &src, const Uri &dst,
        unsigned nstreams, DavixError **error)
{
    std::string nextSrc, prevSrc, destination;
    std::string delegationEndpoint;
    DavixError *internalError = NULL;
    bool suppressFinalHead = false;

    Uri srcHttp = dropDav(src);
    Uri dstHttp = dropDav(dst);

    // set source and destination according to copy method
    if(parameters->getCopyMode() == CopyMode::Push){
        nextSrc = srcHttp.getString();
        prevSrc = srcHttp.getString();
        destination = dstHttp.getString();
    }else if(parameters->getCopyMode() == CopyMode::Pull){
        nextSrc = dstHttp.getString();
        prevSrc = dstHttp.getString();
        destination = srcHttp.getString();
    }

    // nstreams as string
    char nstreamsStr[16];
    snprintf(nstreamsStr, sizeof(nstreamsStr), "%u", nstreams);

    // Need a copy so we can modify it
    Davix::RequestParams requestParams(parameters);
    requestParams.setTransparentRedirectionSupport(false);

    size_t start_pos;

    // if destination is s3 endpoint, change prefix to http(s) and pre-sign the request as a PUT
    if(destination.compare(0,2,"s3") == 0){
        destination.replace(0, 2, "http");
        time_t expiration_time = time(NULL) +3600;
        Davix::HeaderVec vec;
        Uri tmp;
        if (parameters->getCopyMode() == CopyMode::Pull)
            tmp = Davix::S3::tokenizeRequest(requestParams, "GET", destination, vec, expiration_time);
        else
            tmp = Davix::S3::tokenizeRequest(requestParams, "PUT", destination, vec, expiration_time);
        destination = tmp.getString();
        suppressFinalHead = true;
    }

    // handle gcloud endpoint as a destination
    if(destination.compare(0,6,"gcloud") == 0){
        destination.replace(0, 6, "http");

        Davix::HeaderVec vec;
        Uri tmp;
        if (parameters->getCopyMode() == CopyMode::Pull)
            tmp = Davix::gcloud::signURI(requestParams.getGcloudCredentials(), "GET", destination, vec, 3600);
        else
            tmp = Davix::gcloud::signURI(requestParams.getGcloudCredentials(), "PUT", destination, vec, 3600);
        destination = tmp.getString();
        suppressFinalHead = true;
    }

    if(destination.compare(0, 3, "dav") == 0) {
        destination.replace(0, 3, "http");
    }

    // Perform COPY hopping through redirections
    HttpRequest* request = NULL;
    do {
        nextSrc = _full_url(prevSrc, nextSrc);
        prevSrc = nextSrc;
        if (request) {
            request->discardBody(&internalError);
            if (!internalError)
                request->endRequest(&internalError);
            if (internalError) {
                DavixError::propagatePrefixedError(error, internalError, __func__);
                break;
            }
        }
        delete request;

        DAVIX_SLOG(DAVIX_LOG_VERBOSE, DAVIX_LOG_GRID, "Hop: {}",
                     nextSrc);

        request = context.createRequest(nextSrc, &internalError);
        if (internalError) {
            DavixError::propagatePrefixedError(error, internalError, __func__);
            break;
        }

        request->setRequestMethod("COPY");
        if(parameters->getCopyMode() == CopyMode::Push){
            request->addHeaderField("Destination", destination);
        }else if(parameters->getCopyMode() == CopyMode::Pull){
            request->addHeaderField("Source", destination);
        }
        request->addHeaderField("X-Number-Of-Streams", nstreamsStr);

        // for lcgdm-dav, ask for secure redirection in all cases for COPY
        request->addHeaderField("Secure-Redirection", "1");

        // for lcgdm-dav -> S3, add NoHead flag to suppress final head-to-close request
        if(suppressFinalHead)
            request->addHeaderField("Copy-Flags", "NoHead");
        request->setParameters(requestParams);
        request->beginRequest(&internalError);
        if (internalError) {
            DavixError::propagatePrefixedError(error, internalError, __func__);
            break;
        }

        // If we get a X-Delegate-To, before continuing, delegate
        if (request->getAnswerHeader("X-Delegate-To", delegationEndpoint)) {
            delegationEndpoint = _full_delegation_endpoint(nextSrc,
                                                           delegationEndpoint,
                                                           &internalError);
            if (internalError) {
                DavixError::propagatePrefixedError(error, internalError, __func__);
                break;
            }

            DAVIX_SLOG(DAVIX_LOG_VERBOSE, DAVIX_LOG_GRID, "Got delegation endpoint: {}",
                         delegationEndpoint.c_str());

            std::string dlg_id = DavixDelegation::delegate(context, delegationEndpoint,
                    parameters, &internalError);
            if (internalError) {
                DavixError::propagatePrefixedError(error, internalError, __func__);
                break;
            }

            DAVIX_SLOG(DAVIX_LOG_VERBOSE, DAVIX_LOG_GRID, "Got delegation ID {}",
                         dlg_id.c_str());

            dlg_id.clear();
        }

    } while (!shouldCancel() && request->getAnswerHeader("Location", nextSrc) && request->getRequestCode() >= 300 && request->getRequestCode() < 400);

    if (!*error) {
        int responseStatus = request->getRequestCode();
        if (responseStatus == 404) {
            DavixError::setupError(error, COPY_SCOPE, StatusCode::FileNotFound,
                                   "Could not COPY. File not found");
        }
        else if (responseStatus == 403) {
            DavixError::setupError(error, COPY_SCOPE, StatusCode::PermissionRefused,
                                   "Could not COPY. Permission denied.");
        }
        else if (responseStatus == 501) {
            DavixError::setupError(error, COPY_SCOPE, StatusCode::OperationNonSupported,
                                   "Could not COPY. The source service does not support it");
        }
        else if (responseStatus >= 405) {
            DavixError::setupError(error, COPY_SCOPE, StatusCode::OperationNonSupported,
                                   "Could not COPY. The source service does not allow it");
        }
        else if (responseStatus == 400) {
            std::string err_msg(request->getAnswerContentVec().begin(), request->getAnswerContentVec().end());
        	DavixError::setupError(error, COPY_SCOPE, StatusCode::InvalidArgument,
                                   fmt::format("Could not COPY. The server rejected the request: {}", err_msg));
        }
        else if (responseStatus >= 300) {
            std::ostringstream msg;
            msg << "Could not COPY. Unknown error code: " << responseStatus;
            DavixError::setupError(error, COPY_SCOPE, StatusCode::UnknowError,
                                   msg.str());
        }
    }

    if(shouldCancel(error)) {
        return;
    }

    // Did we fail?
    if (*error)
        return;

    // Finished hopping
    std::string finalSource = nextSrc;

    // Just wait for it to finish
    monitorPerformanceMarkers(request, error);
    request->endRequest(&internalError);

    if(internalError && !(*error) ) {
        DavixError::propagatePrefixedError(error, internalError, __func__);
    }

    if(shouldCancel(error)) {
        return;
    }

    delete request;
}

void DavixCopyInternal::monitorPerformanceMarkers(Davix::HttpRequest *request,
        Davix::DavixError **error)
{
    Davix::DavixError* daverr = NULL;
    char buffer[1024], *p;
    dav_ssize_t line_len;

    PerformanceMarker holder;
    PerformanceData performance;
    time_t lastPerfCallback = time(NULL);
    bool clearOutcome = false;

    while ((line_len = request->readLine(buffer, sizeof(buffer), &daverr)) > 0 && !daverr && !shouldCancel())
    {
        buffer[line_len] = '\0';

        if (line_len > 0)
            DAVIX_SLOG(DAVIX_LOG_VERBOSE, DAVIX_LOG_GRID, "Received: {}", buffer);

        // Skip heading whitespaces
        p = buffer;
        while (*p && p < buffer + sizeof(buffer) && isspace(*p))
            ++p;

        if (strncasecmp("Perf Marker", p, 11) == 0)
        {
            memset(&holder, 0, sizeof(holder));
        }
        else if (strncasecmp("Timestamp:", p, 10) == 0)
        {
            holder.latest = atol(p + 10);
        }
        else if (strncasecmp("Stripe Index:", p, 13) == 0)
        {
            holder.index = atoi(p + 13);
        }
        else if (strncasecmp("Stripe Bytes Transferred:", p, 25) == 0)
        {
            holder.transferred = atol(p + 26);
        }
        else if (strncasecmp("Total Stripe Count:", p, 19) == 0)
        {
            holder.count = atoi(p + 20);
        }
        else if (strncasecmp("End", p, 3) == 0)
        {
            performance.update(holder);
            time_t now = time(NULL);
            if (now - lastPerfCallback >= 1)
            {
                if (this->perfCallback)
                    this->perfCallback(performance, this->perfCallbackUdata);
                lastPerfCallback = now;
            }
        }
        else if (strncasecmp("success", p, 7) == 0)
        {
            clearOutcome = true;
            request->discardBody(&daverr);
            break;
        }
        else if (strncasecmp("aborted", p, 7) == 0)
        {
            clearOutcome = true;
            Davix::DavixError::setupError(error, COPY_SCOPE, StatusCode::Canceled,
                    "Transfer aborted in the remote end");
            break;
        }
        else if (strncasecmp("failed", p, 6) == 0 || strncasecmp("failure", p, 7) == 0)
        {
            clearOutcome = true;
            Davix::DavixError::setupError(error, COPY_SCOPE, StatusCode::RemoteError,
                    std::string("Transfer failed: ") + p);
            break;
        }
        else if(line_len> 0)
        {
            DAVIX_SLOG(DAVIX_LOG_WARNING, DAVIX_LOG_GRID, "Unknown performance marker, ignoring: {}", buffer);
        }
    }

    if(!clearOutcome && !(*error)) {
        Davix::DavixError::setupError(error, COPY_SCOPE, StatusCode::UnknowError,
            std::string("Connection terminated abruptly; Status of TPC request unknown"));
    }
}
<|endoftext|>


<commit_before>/*   This file is part of the KDE project
 *
 *   Copyright (C) 2014 Dominik Haumann <dhauumann@kde.org>
 *
 *   This library is free software; you can redistribute it and/or
 *   modify it under the terms of the GNU Library General Public
 *   License as published by the Free Software Foundation; either
 *   version 2 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
 *   Library General Public License for more details.
 *
 *   You should have received a copy of the GNU Library General Public License
 *   along with this library; see the file COPYING.LIB.  If not, write to
 *   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 *   Boston, MA 02110-1301, USA.
 */

#include "katetabbutton.h"

#include <KLocalizedString>

#include <QApplication>
#include <QFontDatabase>
#include <QHBoxLayout>
#include <QMoveEvent>
#include <QPainter>
#include <QPropertyAnimation>
#include <QStyle>
#include <QStyleOption>

#include <math.h>

TabCloseButton::TabCloseButton(QWidget * parent)
    : QAbstractButton(parent)
{
    // should never have focus
    setFocusPolicy(Qt::NoFocus);

    // closing a tab closes the document
    setToolTip(i18n("Close Document"));
}

void TabCloseButton::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event)

    // get the tab this close button belongs to
    KateTabButton *tabButton = qobject_cast<KateTabButton*>(parent());
    const bool isActive = underMouse()
        || (tabButton && tabButton->isChecked());

    // set style options depending on current state
    QStyleOption opt;
    opt.init(this);
    if (isActive && !isChecked()) {
        opt.state |= QStyle::State_Raised;
    }
    if (isChecked()) {
        opt.state |= QStyle::State_Sunken;
    }

    QPainter p(this);
    style()->drawPrimitive(QStyle::PE_IndicatorTabClose, &opt, &p, this);
}

QSize TabCloseButton::sizeHint() const
{
    // make sure the widget is polished
    ensurePolished();

    // read the metrics from the style
    const int w = style()->pixelMetric(QStyle::PM_TabCloseIndicatorWidth, 0, this);
    const int h = style()->pixelMetric(QStyle::PM_TabCloseIndicatorHeight, 0, this);
    return QSize(w, h);
}

void TabCloseButton::enterEvent(QEvent *event)
{
    update(); // repaint on hover
    QAbstractButton::enterEvent(event);
}

void TabCloseButton::leaveEvent(QEvent *event)
{
    update(); // repaint on hover
    QAbstractButton::leaveEvent(event);
}

KateTabButton::KateTabButton(const QString &text, QWidget *parent)
    : QAbstractButton(parent)
    , m_geometryAnimation(0)
{
    setCheckable(true);
    setFocusPolicy(Qt::NoFocus);

    setText(text);

    // add close button
    const int margin = style()->pixelMetric(QStyle::PM_ButtonMargin, 0, this);
    m_closeButton = new TabCloseButton(this);
    QHBoxLayout * hbox = new QHBoxLayout(this);
    hbox->setSpacing(0);
    hbox->setContentsMargins(margin, 0, margin, 0);
    hbox->addStretch();
    hbox->addWidget(m_closeButton);
    setLayout(hbox);
    connect(m_closeButton, &TabCloseButton::clicked, this, &KateTabButton::closeButtonClicked);
}

void KateTabButton::closeButtonClicked()
{
    emit closeRequest(this);
}

void KateTabButton::paintEvent(QPaintEvent *ev)
{
    Q_UNUSED(ev)

    QColor barColor(palette().color(QPalette::Highlight));

    // read from the parent widget (=KateTabBar) the isActiveViewSpace property
    if (isActiveViewSpace()) {
        // if inactive, convert color to gray value
        const int g = qGray(barColor.rgb());
        barColor = QColor(g, g, g);
    }

    // compute sane margins
    const int margin = style()->pixelMetric(QStyle::PM_ButtonMargin, 0, this);
    const int barMargin = margin / 2;
    const int barHeight = ceil(height() / 10.0);

    QPainter p(this);

    // paint bar if inactive but hovered
    if (!isChecked() && underMouse()) {
        barColor.setAlpha(80);
        p.fillRect(QRect(barMargin, height() - barHeight, width() - 2 * barMargin, barHeight), barColor);
    }

    // paint bar
    if (isChecked()) {
        barColor.setAlpha(255);
        p.fillRect(QRect(barMargin, height() - barHeight, width() - 2 * barMargin, barHeight), barColor);
    }

    // icon, if applicable
    int leftMargin = margin;
    if (! icon().isNull()) {
        const int y = (height() - 16) / 2;
        icon().paint(&p, margin, y, 16, 16);
        leftMargin += 16;
        leftMargin += margin;
    }

    // the width of the text is reduced by the close button + 2 * margin
    const int w = width() // width of widget
                - m_closeButton->width() - 2 * margin // close button
                - leftMargin; // modified button

    // draw text, we need to elide to xxx...xxx is too long
    const QString elidedText = QFontMetrics(font()).elidedText (text(), Qt::ElideMiddle, w);
    const QRect textRect(leftMargin, 0, w, height());
    const QPalette pal = QApplication::palette();
    style()->drawItemText(&p, textRect, Qt::AlignHCenter | Qt::AlignVCenter, pal, true, elidedText);
}

void KateTabButton::mousePressEvent(QMouseEvent *ev)
{
    ev->accept();
    if (ev->button() == Qt::LeftButton) {
        if (! isChecked()) {
            // make sure we stay checked
            setChecked(true);
        }

        // notify that this button was activated
        emit activated(this);
    } else {
        ev->ignore();
    }
}

void KateTabButton::mouseDoubleClickEvent(QMouseEvent *event)
{
    event->accept();
}

void KateTabButton::enterEvent(QEvent *event)
{
    update(); // repaint on hover
    QAbstractButton::enterEvent(event);
}

void KateTabButton::leaveEvent(QEvent *event)
{
    update(); // repaint on hover
    QAbstractButton::leaveEvent(event);
}

void KateTabButton::moveEvent(QMoveEvent *event)
{
    // tell the tabbar to redraw its separators. Since the separators overlap
    // the tab buttons geometry, we need to adjust the width by the separator's
    // width to avoid artifacts
    if (parentWidget()) {
        const int w = style()->pixelMetric(QStyle::PM_ToolBarSeparatorExtent, 0, this);
        QRect rect = geometry();
        rect.moveLeft(event->oldPos().x());
        rect.adjust(-w, 0, w, 0);
        parentWidget()->update(rect);
    }
    QAbstractButton::moveEvent(event);
}

bool KateTabButton::isActiveViewSpace() const
{
    Q_ASSERT(parentWidget());

    // read from the parent widget (=KateTabBar) the isActiveViewSpace property
    return ! parentWidget()->property("isActiveViewSpace").toBool();
}

void KateTabButton::setAnimatedGeometry(const QRect & startGeom,
                                        const QRect & endGeom)
{
    // stop animation in case it is running
    if (m_geometryAnimation &&
        m_geometryAnimation->state() != QAbstractAnimation::Stopped) {
        m_geometryAnimation->stop();
    }

    // already at desired position
    if (startGeom == geometry() && endGeom == startGeom) {
        return;
    }

    // if the style does not want animations, just set geometry
    if (! style()->styleHint(QStyle::SH_Widget_Animate, 0, this)
        || (isVisible() && endGeom == startGeom))
    {
        setGeometry(endGeom);
        return;
    }

    if (! m_geometryAnimation) {
        m_geometryAnimation = new QPropertyAnimation(this, "geometry", this);
        m_geometryAnimation->setDuration(100);
    }

    // finally start geometry animation
    m_geometryAnimation->setStartValue(startGeom);
    m_geometryAnimation->setEndValue(endGeom);
    m_geometryAnimation->start();
}

bool KateTabButton::geometryAnimationRunning() const
{
    return m_geometryAnimation
        && (m_geometryAnimation->state() != QAbstractAnimation::Stopped);
}
<commit_msg>Tabbar: use QPalette::WindowText role instead of ButtonText role as foreground color<commit_after>/*   This file is part of the KDE project
 *
 *   Copyright (C) 2014 Dominik Haumann <dhauumann@kde.org>
 *
 *   This library is free software; you can redistribute it and/or
 *   modify it under the terms of the GNU Library General Public
 *   License as published by the Free Software Foundation; either
 *   version 2 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
 *   Library General Public License for more details.
 *
 *   You should have received a copy of the GNU Library General Public License
 *   along with this library; see the file COPYING.LIB.  If not, write to
 *   the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 *   Boston, MA 02110-1301, USA.
 */

#include "katetabbutton.h"

#include <KLocalizedString>

#include <QApplication>
#include <QFontDatabase>
#include <QHBoxLayout>
#include <QMoveEvent>
#include <QPainter>
#include <QPropertyAnimation>
#include <QStyle>
#include <QStyleOption>

#include <math.h>

TabCloseButton::TabCloseButton(QWidget * parent)
    : QAbstractButton(parent)
{
    // should never have focus
    setFocusPolicy(Qt::NoFocus);

    // closing a tab closes the document
    setToolTip(i18n("Close Document"));
}

void TabCloseButton::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event)

    // get the tab this close button belongs to
    KateTabButton *tabButton = qobject_cast<KateTabButton*>(parent());
    const bool isActive = underMouse()
        || (tabButton && tabButton->isChecked());

    // set style options depending on current state
    QStyleOption opt;
    opt.init(this);
    if (isActive && !isChecked()) {
        opt.state |= QStyle::State_Raised;
    }
    if (isChecked()) {
        opt.state |= QStyle::State_Sunken;
    }

    QPainter p(this);
    style()->drawPrimitive(QStyle::PE_IndicatorTabClose, &opt, &p, this);
}

QSize TabCloseButton::sizeHint() const
{
    // make sure the widget is polished
    ensurePolished();

    // read the metrics from the style
    const int w = style()->pixelMetric(QStyle::PM_TabCloseIndicatorWidth, 0, this);
    const int h = style()->pixelMetric(QStyle::PM_TabCloseIndicatorHeight, 0, this);
    return QSize(w, h);
}

void TabCloseButton::enterEvent(QEvent *event)
{
    update(); // repaint on hover
    QAbstractButton::enterEvent(event);
}

void TabCloseButton::leaveEvent(QEvent *event)
{
    update(); // repaint on hover
    QAbstractButton::leaveEvent(event);
}

KateTabButton::KateTabButton(const QString &text, QWidget *parent)
    : QAbstractButton(parent)
    , m_geometryAnimation(0)
{
    setCheckable(true);
    setFocusPolicy(Qt::NoFocus);

    setText(text);

    // add close button
    const int margin = style()->pixelMetric(QStyle::PM_ButtonMargin, 0, this);
    m_closeButton = new TabCloseButton(this);
    QHBoxLayout * hbox = new QHBoxLayout(this);
    hbox->setSpacing(0);
    hbox->setContentsMargins(margin, 0, margin, 0);
    hbox->addStretch();
    hbox->addWidget(m_closeButton);
    setLayout(hbox);
    connect(m_closeButton, &TabCloseButton::clicked, this, &KateTabButton::closeButtonClicked);
}

void KateTabButton::closeButtonClicked()
{
    emit closeRequest(this);
}

void KateTabButton::paintEvent(QPaintEvent *ev)
{
    Q_UNUSED(ev)

    QColor barColor(palette().color(QPalette::Highlight));

    // read from the parent widget (=KateTabBar) the isActiveViewSpace property
    if (isActiveViewSpace()) {
        // if inactive, convert color to gray value
        const int g = qGray(barColor.rgb());
        barColor = QColor(g, g, g);
    }

    // compute sane margins
    const int margin = style()->pixelMetric(QStyle::PM_ButtonMargin, 0, this);
    const int barMargin = margin / 2;
    const int barHeight = ceil(height() / 10.0);

    QPainter p(this);

    // paint bar if inactive but hovered
    if (!isChecked() && underMouse()) {
        barColor.setAlpha(80);
        p.fillRect(QRect(barMargin, height() - barHeight, width() - 2 * barMargin, barHeight), barColor);
    }

    // paint bar
    if (isChecked()) {
        barColor.setAlpha(255);
        p.fillRect(QRect(barMargin, height() - barHeight, width() - 2 * barMargin, barHeight), barColor);
    }

    // icon, if applicable
    int leftMargin = margin;
    if (! icon().isNull()) {
        const int y = (height() - 16) / 2;
        icon().paint(&p, margin, y, 16, 16);
        leftMargin += 16;
        leftMargin += margin;
    }

    // the width of the text is reduced by the close button + 2 * margin
    const int w = width() // width of widget
                - m_closeButton->width() - 2 * margin // close button
                - leftMargin; // modified button

    // draw text, we need to elide to xxx...xxx is too long
    const QString elidedText = QFontMetrics(font()).elidedText (text(), Qt::ElideMiddle, w);
    const QRect textRect(leftMargin, 0, w, height());
    const QPalette pal = QApplication::palette();
    style()->drawItemText(&p, textRect, Qt::AlignHCenter | Qt::AlignVCenter, pal, true, elidedText, QPalette::WindowText);
}

void KateTabButton::mousePressEvent(QMouseEvent *ev)
{
    ev->accept();
    if (ev->button() == Qt::LeftButton) {
        if (! isChecked()) {
            // make sure we stay checked
            setChecked(true);
        }

        // notify that this button was activated
        emit activated(this);
    } else {
        ev->ignore();
    }
}

void KateTabButton::mouseDoubleClickEvent(QMouseEvent *event)
{
    event->accept();
}

void KateTabButton::enterEvent(QEvent *event)
{
    update(); // repaint on hover
    QAbstractButton::enterEvent(event);
}

void KateTabButton::leaveEvent(QEvent *event)
{
    update(); // repaint on hover
    QAbstractButton::leaveEvent(event);
}

void KateTabButton::moveEvent(QMoveEvent *event)
{
    // tell the tabbar to redraw its separators. Since the separators overlap
    // the tab buttons geometry, we need to adjust the width by the separator's
    // width to avoid artifacts
    if (parentWidget()) {
        const int w = style()->pixelMetric(QStyle::PM_ToolBarSeparatorExtent, 0, this);
        QRect rect = geometry();
        rect.moveLeft(event->oldPos().x());
        rect.adjust(-w, 0, w, 0);
        parentWidget()->update(rect);
    }
    QAbstractButton::moveEvent(event);
}

bool KateTabButton::isActiveViewSpace() const
{
    Q_ASSERT(parentWidget());

    // read from the parent widget (=KateTabBar) the isActiveViewSpace property
    return ! parentWidget()->property("isActiveViewSpace").toBool();
}

void KateTabButton::setAnimatedGeometry(const QRect & startGeom,
                                        const QRect & endGeom)
{
    // stop animation in case it is running
    if (m_geometryAnimation &&
        m_geometryAnimation->state() != QAbstractAnimation::Stopped) {
        m_geometryAnimation->stop();
    }

    // already at desired position
    if (startGeom == geometry() && endGeom == startGeom) {
        return;
    }

    // if the style does not want animations, just set geometry
    if (! style()->styleHint(QStyle::SH_Widget_Animate, 0, this)
        || (isVisible() && endGeom == startGeom))
    {
        setGeometry(endGeom);
        return;
    }

    if (! m_geometryAnimation) {
        m_geometryAnimation = new QPropertyAnimation(this, "geometry", this);
        m_geometryAnimation->setDuration(100);
    }

    // finally start geometry animation
    m_geometryAnimation->setStartValue(startGeom);
    m_geometryAnimation->setEndValue(endGeom);
    m_geometryAnimation->start();
}

bool KateTabButton::geometryAnimationRunning() const
{
    return m_geometryAnimation
        && (m_geometryAnimation->state() != QAbstractAnimation::Stopped);
}
<|endoftext|>


<commit_before>/** \copyright
 * Copyright (c) 2013, Balazs Racz
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  - Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 *  - 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 HOLDER 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.
 *
 * \file WriteFlow.cxx
 *
 * Class that allows enqueing an outgoing message.
 *
 * @author Balazs Racz
 * @date 3 Nov 2013
 */

#include "nmranet/WriteFlow.hxx"

Executor* DefaultWriteFlowExecutor() {
  static ThreadExecutor e("write_flow", 0, 1000);
  return &e;
}

void WriteHelper::Run() {
#ifdef EVENT_NODE_CPP
  node_->write(mti_, dst_, buffer_);
#else
  HASSERT(!nmranet_node_write(node_, mti_, dst_, buffer_));
#endif
  Notifiable* d = done_;
  HASSERT(d);
  done_ = nullptr;
  d->Notify();
}

WriteHelper::buffer_type EventIdToBuffer(uint64_t eventid) {
  WriteHelper::buffer_type buffer = WriteHelper::BufferAlloc(sizeof(eventid));
  uint64_t* b = static_cast<uint64_t*>(WriteHelper::BufferDeref(buffer));
  *b = htobe64(eventid);
  WriteHelper::BufferStep(buffer, sizeof(eventid));
  return buffer;
}
<commit_msg>Adds missing include to endian.<commit_after>/** \copyright
 * Copyright (c) 2013, Balazs Racz
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  - Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 *  - 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 HOLDER 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.
 *
 * \file WriteFlow.cxx
 *
 * Class that allows enqueing an outgoing message.
 *
 * @author Balazs Racz
 * @date 3 Nov 2013
 */

#include "nmranet/WriteFlow.hxx"

#include "endian.h"

Executor* DefaultWriteFlowExecutor() {
  static ThreadExecutor e("write_flow", 0, 1000);
  return &e;
}

void WriteHelper::Run() {
#ifdef EVENT_NODE_CPP
  node_->write(mti_, dst_, buffer_);
#else
  HASSERT(!nmranet_node_write(node_, mti_, dst_, buffer_));
#endif
  Notifiable* d = done_;
  HASSERT(d);
  done_ = nullptr;
  d->Notify();
}

WriteHelper::buffer_type EventIdToBuffer(uint64_t eventid) {
  WriteHelper::buffer_type buffer = WriteHelper::BufferAlloc(sizeof(eventid));
  uint64_t* b = static_cast<uint64_t*>(WriteHelper::BufferDeref(buffer));
  *b = htobe64(eventid);
  WriteHelper::BufferStep(buffer, sizeof(eventid));
  return buffer;
}
<|endoftext|>