/***************************************************************************
                          rkmdiwindow  -  description
                             -------------------
    begin                : Tue Sep 26 2006
    copyright            : (C) 2006 - 2020 by Thomas Friedrichsmeier
    email                : thomas.friedrichsmeier@kdemail.net
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 ***************************************************************************/

#ifndef RKMDIWINDOW_H
#define RKMDIWINDOW_H

#include <QFrame>
#include <QMap>
#include <QUrl>

#include <kparts/part.h>

#include "../settings/rksettings.h"

class QEvent;
class QPaintEvent;
class RKWorkplace;
class RKToolWindowBar;
class KMessageWidget;
class RCommand;

class RKMDIStandardActionClient : public KXMLGUIClient {
public:
	RKMDIStandardActionClient ();
	~RKMDIStandardActionClient ();
};

/** Base class for rkward document mdi windows */
class RKMDIWindow : public QFrame {
	Q_OBJECT
public:
	enum Type {
		DataEditorWindow=1 << 0,
		CommandEditorWindow=1 << 1,
		OutputWindow=1 << 2,
		HelpWindow=1 << 3,
		X11Window=1 << 4,
		ObjectWindow=1 << 5,
		ConsoleWindow=1 << 10,
		CommandLogWindow=1 << 11,
		WorkspaceBrowserWindow=1 << 12,
		SearchHelpWindow=1 << 13,
		PendingJobsWindow=1 << 14,
		FileBrowserWindow=1 << 15,
		DebugConsoleWindow=1 << 16,
		CallstackViewerWindow=1 << 17,
		DebugMessageWindow=1 << 18,
		KatePluginWindow=1 << 19,

		DocumentWindow=1 << 29,
		ToolWindow=1 << 30,
		AnyType=DocumentWindow | ToolWindow
	};

	enum State {
		Attached=1,
		Detached=2,
		AnyWindowState=Attached | Detached
	};
protected:
/** constructor
@param parent parent widget
@param type Type of window (see RKMDIWindow::Type).*/
	RKMDIWindow (QWidget *parent, int type, bool tool_window=false, const char *name=0);
	virtual ~RKMDIWindow ();
public slots:
/** Reimplemented from QWidget::setCaption () to emit the signal captionChanged () when the caption is changed. */
	void setCaption (const QString &caption);
public:
/** @returns true, if the window's document was modified (and would need to be saved) */
	virtual bool isModified () { return false; };
/** @returns A long / complete caption. Default implementation simply calls shortCaption () */
	virtual QString fullCaption ();
/** @returns A short caption (e.g. only the filename without the path). Default implementation simply calls QWidget::caption () */
	virtual QString shortCaption ();
/** @returns The corresponding KPart for this window */
	KParts::Part *getPart () { return part; };
/** Is this window attached (or detached)?
@returns true if attached, false if detached */
	bool isAttached () const { return (state == Attached); };
/** Is this a tool window? */
	bool isToolWindow () const { return (type & ToolWindow); };
/** Returns the type of this window */
	bool isType (Type t) const { return (type & t); };
/** Activate (raise) this window, regardless of whether it is attached or detached
@param with_focus Should the window also get keyboard focus? */
	virtual void activate (bool with_focus=true);
/** If your mdi window should perform any adjustments before being attached, reimplement this function. Default implementation does nothing, but raises an assert, if this is a tool window */
	virtual void prepareToBeAttached ();
/** If your mdi window should perform any adjustments before being detached, reimplement this function. Default implementation does nothing, but raises an assert, if this is a tool window */
	virtual void prepareToBeDetached ();
/** Tool windows will only hide themselves, and ignore the also_delete flag */
	virtual bool close (bool also_delete);
/** Set a status message to be shown in a popup inside the window. The message persists until the given R command has finished, or until this function is called with an empty string.
This should be used, when the information shown is currently out-of-date (e.g. when refreshing a preview / loading a plot from history), _not_ when the window
is simply busy (e.g. when saving the current plot to history). */
	void setStatusMessage (const QString& message, RCommand* command=0);
/** Set a style hint for the window. So far the only interpreted style hint is "preview", and not all windows implement it. Base implements hiding of "active" indicator border for "preview"s. */
	virtual void setWindowStyleHint (const QString& hint);

	bool eventFilter (QObject *watched, QEvent *e) override;
	bool acceptsEventsFor (QObject *object);
/** Whether the window is active. This seems to be more reliable than hasFocus () */
	bool isActive ();
/** Like isActive (), but also returns true, if this window _would_ be the active one, if the parent topLevelWindow() _was_ the active Window. */
	bool isActiveInsideToplevelWindow ();
/** Returns a pointer to an action collection suitable to place RKStandardAction in. This collection (and the corresponding KXMLGUIClient) is created on the fly. */
	KActionCollection *standardActionCollection ();
/** plugin-accessible properties of this object in the global context. Currently used only by RKEditorDataFrame to give information on the currently active data.frame. NOTE: ATM, you cannot set arbitrary properties. Only those supported in RKStandardComponent will have an effect. */
	QString globalContextProperty (const QString& property) { return global_context_properties.value (property); };
signals:
/** This signal is emitted, whenever the window caption was changed.
@param RKMDIWindow* a pointer to this window */
	void captionChanged (RKMDIWindow *);
/** This signal is emitted, when the window was activated *with* focus */
	void windowActivated (RKMDIWindow *);
protected slots:
	void showWindowHelp ();
	void showWindowSettings ();
	void clearStatusMessage ();
protected:
	void setPart (KParts::Part *p) { part = p; };
	void setMetaInfo (const QString& generic_window_name, const QUrl& help_url, RKSettings::SettingsPage settings_page=RKSettings::NoPage);
	void initializeActivationSignals ();
	void paintEvent (QPaintEvent *e) override;
	void changeEvent (QEvent *event) override;

/** reimplemented from QWidget to emulate focus-follows-mouse behavior */
	void enterEvent (QEvent *event) override;
/** @see globalContextProperty() */
	void setGlobalContextProperty (const QString& property, const QString& value) { global_context_properties.insert (property, value); };

	KMessageWidget* status_popup;
	QWidget* status_popup_container;
	void resizeEvent (QResizeEvent *ev) override;

friend class RKWorkplace;
/** type of this window */
	int type;
private slots:
	void slotActivateForFocusFollowsMouse ();
private:
friend class RKToolWindowBar;
/** state of this window (attached / detached). This is usually set from the RKWorkplace */
	KParts::Part *part;
	State state;
	RKToolWindowBar *tool_window_bar;
	bool active;
	bool no_border_when_active;
	RKMDIStandardActionClient *standard_client;
/** @see globalContextProperty() */
	QMap<QString, QString> global_context_properties;
	QString generic_window_name;
	QUrl help_url;
	RKSettings::SettingsPage settings_page;
};

#endif
