/***************************************************************************
 *   Copyright (C) 2005-09 by the Quassel Project                          *
 *   devel@quassel-irc.org                                                 *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program 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 General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************
 * This is a subset of the API of KDE's KActionCollection.                 *
 ***************************************************************************/

#ifndef ACTIONCOLLECTION_H_
#define ACTIONCOLLECTION_H_

#include <QList>
#include <QMap>
#include <QObject>
#include <QString>

class Action;
class QAction;
class QWidget;
class QIcon;

class ActionCollection : public QObject {
	Q_OBJECT

public:
	explicit ActionCollection(QObject* parent);
	~ActionCollection() override;

	static void setMainWidget(QWidget* w);
	static ActionCollection* get();
	Action* createAction(const QString& name, const QString& text, const char* icon = nullptr, const QString& whatsThis = QString());
	Action* createAction(const QString& name, const QString& text, const QIcon& icon, const QString& whatsThis = QString());

	/// Clears the entire action collection, deleting all actions.
	void clear();

	/// Associate all action in this collection to the given \a widget.
	/** Not that this only adds all current actions in the collection to that widget;
     *  subsequently added actions won't be added automatically.
     */
	void associateWidget(QWidget* widget) const;

	/// Associate all actions in this collection to the given \a widget.
	/** Subsequently added actions will be automagically associated with this widget as well.
     */
	void addAssociatedWidget(QWidget* widget);

	void removeAssociatedWidget(QWidget* widget);
	QList<QWidget*> associatedWidgets() const;
	void clearAssociatedWidgets();

	void readSettings();
	void writeSettings() const;

	int count() const { return actions().count(); }
	bool isEmpty() const { return 0 == actions().count(); }

	QAction* action(int index) const;
	QAction* action(const QString& name) const;
	QList<QAction*> actions() const;

	QAction* addAction(const QString& name, QAction* action);
	Action* addAction(const QString& name, Action* action);
	Action* addAction(const QString& name, const QObject* receiver = nullptr, const char* member = nullptr);
	void removeAction(QAction* action);
	QAction* takeAction(QAction* action);

	/// Create new action under the given name, add it to the collection and connect its triggered(bool) signal to the specified receiver.
	template<class ActionType>
	ActionType* add(const QString& name, const QObject* receiver = nullptr, const char* member = nullptr)
	{
		ActionType* a = new ActionType(this);
		if (receiver && member)
			connect(a, SIGNAL(triggered(bool)), receiver, member);
		addAction(name, a);
		return a;
	}

	void updateToolTips();

Q_SIGNALS:
	void inserted(QAction* action);
	void actionHovered(QAction* action);
	void actionTriggered(QAction* action);
	void tooltipUpdated(QAction*);

protected Q_SLOTS:
	virtual void slotActionTriggered();

protected:
	void connectNotify(const QMetaMethod& signal) override;

private Q_SLOTS:
	void slotActionHovered();
	void actionDestroyed(QObject*);
	void associatedWidgetDestroyed(QObject*);

private:
	bool unlistAction(QAction*);
	QString configKey() const;

	QMap<QString, QAction*> _actionByName;
	QList<QAction*> _actions;
	QList<QWidget*> _associatedWidgets;

	bool _connectHovered;
	bool _connectTriggered;
};

#endif
