Blob Blame Raw
#pragma once

#ifndef DV_ITEM_VIEW_INCLUDED
#define DV_ITEM_VIEW_INCLUDED

// TnzQt includes
#include "toonzqt/selection.h"
#include "toonzqt/lineedit.h"

// TnzCore includes
#include "tfilepath.h"

// Qt includes
#include <QWidget>
#include <QScrollArea>
#include <QToolBar>

// STD includes
#include <set>

//==============================================================

//    Forward declarations

class DvItemViewer;
class DvItemSelection;
class QMimeData;

//==============================================================

//=============================================================================

class DvItemListModel
{
public:
	enum DataType {
		Name,
		Thumbnail,
		Icon,
		ToolTip,
		CreationDate,
		ModifiedDate,
		FileSize,
		FrameCount,
		FullPath,
		PlayAvailable,
		VersionControlStatus,
		FileType,
		IsFolder
	};

	enum Status {
		VC_None = 0,
		VC_ReadOnly,
		VC_Edited,
		VC_Modified,
		VC_ToUpdate,
		VC_Locked,
		VC_Unversioned,
		VC_Missing,
		VC_PartialEdited,
		VC_PartialLocked,
		VC_PartialModified
	};

public:
	DvItemListModel() : m_isDiscendent(true), m_orderType(Name) {}
	virtual ~DvItemListModel() {}

	DataType getCurrentOrderType() { return m_orderType; }
	bool isDiscendentOrder() { return m_isDiscendent; }
	void setIsDiscendentOrder(bool isDiscendentOrder) { m_isDiscendent = isDiscendentOrder; }
	void setOrderType(DataType dataType) { m_orderType = dataType; }

	// n.b. refreshData viene chiamato PRIMA di getItemCount() e getItemData()
	// vanno messe dentro refreshData() le operazioni "costose" di getItemData() e getItemCount()
	virtual void refreshData(){};
	virtual int getItemCount() const = 0;
	virtual int compareData(DataType dataType, int firstIndex, int secondIndex);
	virtual void sortByDataModel(DataType dataType, bool isDiscendent) {}
	virtual QVariant getItemData(int index, DataType dataType, bool isSelected = false) = 0;
	virtual QString getItemDataAsString(int index, DataType dataType);
	virtual QString getItemDataIdentifierName(DataType dataType);
	virtual void startDragDrop() {}
	virtual QMenu *getContextMenu(QWidget *parent, int index) { return 0; }
	virtual void enableSelectionCommands(TSelection *selection) {}
	virtual bool canRenameItem(int index) const { return false; }
	virtual void renameItem(int index, const QString &newName) {}
	virtual bool isSceneItem(int index) const { return false; }
	virtual bool acceptDrop(const QMimeData *data) const { return false; }
	virtual bool drop(const QMimeData *data) { return false; }

protected:
	bool m_isDiscendent;
	DataType m_orderType;
};

//=============================================================================

class ItemViewPlayWidget : public QWidget
{
	Q_OBJECT

	int m_currentItemIndex; //-1 -> pause
	int m_timerId;
	bool m_isSliderMode;

	class PlayManager
	{
		TFilePath m_path;
		std::vector<TFrameId> m_fids;
		int m_currentFidIndex;
		QPixmap m_pixmap;
		QSize m_iconSize;

	public:
		PlayManager();
		~PlayManager() {}

		void reset();
		void setInfo(DvItemListModel *model, int index);
		/*! Increase current frame if icon is computed; return true if frame is increased. */
		bool increaseCurrentFrame();
		/*! If icon is computed return true, overwise start to compute it. */
		bool getCurrentFrame();
		/*! Return true if current frame index is less than fids size. */
		bool isFrameIndexInRange();
		bool setCurrentFrameIndexFromXValue(int xValue, int lenght);
		double currentFrameIndexToXValue(int lenght);
		QPixmap getCurrentPixmap();
	};

	PlayManager *m_playManager;

public:
	ItemViewPlayWidget(QWidget *parent = 0);
	~ItemViewPlayWidget() {}

	void play();
	void stop();
	void clear();

	void setIsPlaying(DvItemListModel *model, int index);
	void setIsPlayingCurrentFrameIndex(DvItemListModel *model, int index, int xValue, int lenght);
	int getCurrentFramePosition(int lenght);

	bool isIndexPlaying(int index) { return m_currentItemIndex == index; }
	bool isPlaying() { return m_currentItemIndex != -1; }
	bool isSliderMode() { return m_isSliderMode; }

	void paint(QPainter *painter, QRect rect);

protected:
	void timerEvent(QTimerEvent *event);
};

//=============================================================================

class DVItemViewPlayDelegate : public QObject
{
	Q_OBJECT

	ItemViewPlayWidget *m_itemViewPlay;

public:
	DVItemViewPlayDelegate(QWidget *parent);
	~DVItemViewPlayDelegate() {}

	void paint(QPainter *painter, QRect rect, int index);

	bool setPlayWidget(DvItemListModel *model, int index, QRect rect, QPoint pos);

public slots:

	void resetPlayWidget();

protected:
	QRect getPlayButtonRect(QRect rect);
	QRect getPlaySliderRect(QRect rect);
};

//=============================================================================

class DvItemSelection : public QObject, public TSelection
{
	Q_OBJECT

	std::set<int> m_selectedIndices;
	DvItemListModel *m_model;

public:
	DvItemSelection();

	void select(int index, bool on = true);
	void select(int *indices, int indicesCount);
	void selectNone();
	void selectAll();

	bool isSelected(int index) const
	{
		return m_selectedIndices.count(index) > 0;
	}
	bool isEmpty() const
	{
		return m_selectedIndices.empty();
	}

	const std::set<int> &getSelectedIndices() const
	{
		return m_selectedIndices;
	}

	void setModel(DvItemListModel *model);
	DvItemListModel *getModel() const { return m_model; }

	void enableCommands();

signals:

	void itemSelectionChanged();
};

//=============================================================================

class DvItemViewerPanel : public QFrame, public TSelection::View
{
	Q_OBJECT

	QColor m_alternateBackground;	//alaternate bg color for teble view (170,170,170)
	QColor m_textColor;				 //text color (black)
	QColor m_selectedTextColor;		 //selected item text color (white)
	QColor m_folderTextColor;		 //folder item text color (blue)
	QColor m_selectedItemBackground; //selected item background color (0,0,128)

	Q_PROPERTY(QColor AlternateBackground READ getAlternateBackground WRITE setAlternateBackground)
	Q_PROPERTY(QColor TextColor READ getTextColor WRITE setTextColor)
	Q_PROPERTY(QColor SelectedTextColor READ getSelectedTextColor WRITE setSelectedTextColor)
	Q_PROPERTY(QColor FolderTextColor READ getFolderTextColor WRITE setFolderTextColor)
	Q_PROPERTY(QColor SelectedItemBackground READ getSelectedItemBackground WRITE setSelectedItemBackground)

public:
	enum ViewType { ListView = 0,
					TableView,
					ThumbnailView };
	void setAlternateBackground(const QColor &color) { m_alternateBackground = color; }
	QColor getAlternateBackground() const { return m_alternateBackground; }
	void setTextColor(const QColor &color) { m_textColor = color; }
	QColor getTextColor() const { return m_textColor; }
	void setSelectedTextColor(const QColor &color) { m_selectedTextColor = color; }
	QColor getSelectedTextColor() const { return m_selectedTextColor; }
	void setFolderTextColor(const QColor &color) { m_folderTextColor = color; }
	QColor getFolderTextColor() const { return m_folderTextColor; }
	void setSelectedItemBackground(const QColor &color) { m_selectedItemBackground = color; }
	QColor getSelectedItemBackground() const { return m_selectedItemBackground; }

private:
	ViewType to_enum(int n)
	{
		switch (n) {
		case 0:
			return ListView;
		case 1:
			return TableView;
		case 2:
			return ThumbnailView;
		default:
			return ThumbnailView;
		}
	}

	DvItemSelection *m_selection;
	bool m_globalSelectionEnabled;
	bool m_multiSelectionEnabled;

	DvItemViewer *m_viewer;

	DVItemViewPlayDelegate *m_itemViewPlayDelegate;
	bool m_isPlayDelegateDisable;

	DVGui::LineEdit *m_editFld;
	ViewType m_viewType;
	bool m_singleColumnEnabled;
	bool m_centerAligned;

	// view parameters
	int m_itemSpacing;
	int m_xMargin, m_yMargin, m_itemPerRow;
	QSize m_itemSize;
	QSize m_iconSize;
	bool m_noContextMenu;
	void updateViewParameters(int panelWidth);
	void updateViewParameters() { updateViewParameters(width()); }
	QPoint m_startDragPosition;
	QPoint m_lastMousePos;
	int m_currentIndex;
	std::vector<std::pair<DvItemListModel::DataType, std::pair<int, bool>>> m_columns; // type, <width, visibility>
	DvItemListModel *getModel() const;
	int getItemCount() const { return getModel() ? getModel()->getItemCount() : 0; }
	QColor m_missingColor;

public:
	DvItemViewerPanel(DvItemViewer *viewer, bool noContextMenu, bool multiselectionEnabled, QWidget *parent);

	void enableGlobalSelection(bool enabled) { m_globalSelectionEnabled = enabled; }

	void setItemViewPlayDelegate(DVItemViewPlayDelegate *playDelegate);
	DVItemViewPlayDelegate *getItemViewPlayDelegate();

	void addColumn(DvItemListModel::DataType dataType, int width);
	void setColumnWidth(DvItemListModel::DataType dataType, int width);
	void getColumns(std::vector<std::pair<DvItemListModel::DataType, std::pair<int, bool>>> &columns) { columns = m_columns; };
	bool getVisibility(DvItemListModel::DataType dataType);
	void setVisibility(DvItemListModel::DataType dataType, bool value);
	int getContentMinimumWidth();
	int getContentHeight(int width);

	QSize getItemSize() const;

	QSize getIconSize() const { return m_iconSize; }

	int pos2index(const QPoint &pos) const;
	QRect index2pos(int index) const;

	QRect getCaptionRect(int index) const;

	void paintThumbnailItem(QPainter &p, int index);
	void paintListItem(QPainter &p, int index);
	void paintTableItem(QPainter &p, int index);

	// da TSelection::View
	void onSelectionChanged() { update(); }

	const std::set<int> &getSelectedIndices() const;

	void enableSingleColumn(bool enabled) { m_singleColumnEnabled = enabled; }
	bool isSingleColumnEnabled() const { return m_singleColumnEnabled; }

	void setAlignCenter() { m_centerAligned = true; }

	DvItemSelection *getSelection() const { return m_selection; }
	void setSelection(DvItemSelection *selection); // gets ownership
	void setMissingTextColor(const QColor &color);

protected:
	void paintEvent(QPaintEvent *);
	void mousePressEvent(QMouseEvent *);
	void mouseMoveEvent(QMouseEvent *);
	void mouseReleaseEvent(QMouseEvent *);
	void mouseDoubleClickEvent(QMouseEvent *);
	void contextMenuEvent(QContextMenuEvent *);
	bool event(QEvent *event);

signals:
	void viewTypeChange(DvItemViewerPanel::ViewType viewType);

public slots:
	void setListView();
	void setTableView();
	void setThumbnailsView();
	void rename();
	// for exporting the file information to text format file
	void exportFileList();
};

//=============================================================================

class DvItemViewer : public QScrollArea
{
	Q_OBJECT

public:
	enum WindowType { Browser = 0,
					  Cast };
	WindowType m_windowType;

private:
	DvItemListModel *m_model;
	DvItemViewerPanel *m_panel;

protected:
	void resizeEvent(QResizeEvent *);

public:
	DvItemViewer(QWidget *parent, bool noContextMenu = false, bool multiSelectionEnabled = false, enum WindowType = Browser);

	void resetVerticalScrollBar();
	DvItemListModel *getModel() const { return m_model; }
	void setModel(DvItemListModel *model); // gets ownership

	const std::set<int> &getSelectedIndices() const { return m_panel->getSelectedIndices(); }

	void updateContentSize();
	void refresh();

	DvItemViewerPanel *getPanel() { return m_panel; }

	virtual void draw(QPainter &p) {}
	void notifyClick(int index)
	{
		emit clickedItem(index);
		emit selectedItems(m_panel->getSelectedIndices());
	}

	void enableGlobalSelection(bool enabled) { m_panel->enableGlobalSelection(enabled); }
	void selectNone();
	void keyPressEvent(QKeyEvent *event);

protected:
	void dragEnterEvent(QDragEnterEvent *event);
	void dropEvent(QDropEvent *event);

signals:
	void clickedItem(int index);
	void selectedItems(const std::set<int> &indexes);
};

//=============================================================================

class DvItemViewerTitleBar : public QWidget
{
	Q_OBJECT

	DvItemViewer *m_itemViewer;
	bool m_isInteractive;
	int m_dragColumnIndex;
	QPoint m_pos;

public:
	DvItemViewerTitleBar(DvItemViewer *itemViewer, QWidget *parent = 0, bool isInteractive = true);

protected slots:
	void onViewTypeChanged(DvItemViewerPanel::ViewType viewType);

protected:
	void mouseMoveEvent(QMouseEvent *);
	void openContextMenu(QMouseEvent *);
	void mousePressEvent(QMouseEvent *);
	void paintEvent(QPaintEvent *);
};

//=============================================================================

class DvItemViewerButtonBar : public QToolBar
{
	Q_OBJECT
	QAction *m_folderBack;
	QAction *m_folderFwd;

public:
	DvItemViewerButtonBar(DvItemViewer *itemViewer, QWidget *parent = 0);

public slots:
	void onHistoryChanged(bool, bool);

signals:
	void folderUp();
	void newFolder();
	void folderBack();
	void folderFwd();
};

#endif // DV_ITEM_VIEW_INCLUDED