def initializeUi(self):
		"""
		This method initializes the Component ui.
		
		:return: Method success. ( Boolean )		
		"""

		LOGGER.debug("> Initializing '{0}' Component ui.".format(self.__class__.__name__))

		self.__engine.parameters.databaseReadOnly and \
		LOGGER.info("{0} | Model edition deactivated by '{1}' command line parameter value!".format(self.__class__.__name__,
																									"databaseReadOnly"))
		self.__model = CollectionsModel(self, horizontalHeaders=self.__headers)
		self.setCollections()

		self.Collections_Outliner_treeView.setParent(None)
		self.Collections_Outliner_treeView = IblSetsCollections_QTreeView(self,
																		self.__model,
																		self.__engine.parameters.databaseReadOnly)
		self.Collections_Outliner_treeView.setObjectName("Collections_Outliner_treeView")
		self.Collections_Outliner_dockWidgetContents_gridLayout.addWidget(self.Collections_Outliner_treeView, 0, 0)
		self.__view = self.Collections_Outliner_treeView
		self.__view.setContextMenuPolicy(Qt.ActionsContextMenu)
		self.__view_addActions()

		# Signals / Slots.
		self.__engine.imagesCaches.QIcon.contentAdded.connect(self.__view.viewport().update)
		self.__view.selectionModel().selectionChanged.connect(self.__view_selectionModel__selectionChanged)
		self.refreshNodes.connect(self.__model__refreshNodes)
		if not self.__engine.parameters.databaseReadOnly:
			self.__model.dataChanged.connect(self.__model__dataChanged)

		self.initializedUi = True
		return True
	def initializeUi(self):
		"""
		Initializes the Component ui.
		
		:return: Method success.
		:rtype: bool
		"""

		LOGGER.debug("> Initializing '{0}' Component ui.".format(self.__class__.__name__))

		self.__engine.parameters.databaseReadOnly and \
		LOGGER.info("{0} | Model edition deactivated by '{1}' command line parameter value!".format(self.__class__.__name__,
																									"databaseReadOnly"))
		self.__model = CollectionsModel(self, horizontalHeaders=self.__headers)
		self.setCollections()

		self.Collections_Outliner_treeView.setParent(None)
		self.Collections_Outliner_treeView = IblSetsCollections_QTreeView(self,
																		self.__model,
																		self.__engine.parameters.databaseReadOnly)
		self.Collections_Outliner_treeView.setObjectName("Collections_Outliner_treeView")
		self.Collections_Outliner_dockWidgetContents_gridLayout.addWidget(self.Collections_Outliner_treeView, 0, 0)
		self.__view = self.Collections_Outliner_treeView
		self.__view.setContextMenuPolicy(Qt.ActionsContextMenu)
		self.__view_addActions()

		# Signals / Slots.
		self.__engine.imagesCaches.QIcon.contentAdded.connect(self.__view.viewport().update)
		self.__view.selectionModel().selectionChanged.connect(self.__view_selectionModel__selectionChanged)
		self.refreshNodes.connect(self.__model__refreshNodes)
		if not self.__engine.parameters.databaseReadOnly:
			self.__model.dataChanged.connect(self.__model__dataChanged)

		self.initializedUi = True
		return True
class CollectionsOutliner(QWidgetComponentFactory(uiFile=COMPONENT_UI_FILE)):
	"""
	| Defines the :mod:`sibl_gui.components.core.collectionsOutliner.collectionsOutliner` Component Interface class.
	| It defines methods for Database Collections management.
	"""

	# Custom signals definitions.
	refreshNodes = pyqtSignal()
	"""
	This signal is emited by the :class:`CollectionsOutliner` class when :obj:`CollectionsOutliner.model` class
	property Model Nodes needs to be refreshed. ( pyqtSignal )
	"""

	def __init__(self, parent=None, name=None, *args, **kwargs):
		"""
		Initializes the class.

		:param parent: Object parent.
		:type parent: QObject
		:param name: Component name.
		:type name: unicode
		:param \*args: Arguments.
		:type \*args: \*
		:param \*\*kwargs: Keywords arguments.
		:type \*\*kwargs: \*\*
		"""

		LOGGER.debug("> Initializing '{0}()' class.".format(self.__class__.__name__))

		super(CollectionsOutliner, self).__init__(parent, name, *args, **kwargs)

		# --- Setting class attributes. ---
		self.deactivatable = False

		self.__uiResourcesDirectory = "resources"
		self.__uiDefaultCollectionImage = "Default_Collection.png"
		self.__uiUserCollectionImage = "User_Collection.png"
		self.__dockArea = 1

		self.__engine = None
		self.__settings = None
		self.__settingsSection = None
		self.__settingsSeparator = ","

		self.__iblSetsOutliner = None

		self.__model = None
		self.__view = None
		self.__overallCollection = "Overall"
		self.__defaultCollection = "Default"
		self.__iblSetsCountLabel = "Ibl Sets"
		self.__headers = OrderedDict([("Collections", "name"),
										(self.__iblSetsCountLabel, "count"),
										("Comment", "comment")])

	#******************************************************************************************************************
	#***	Attributes properties.
	#******************************************************************************************************************
	@property
	def uiResourcesDirectory(self):
		"""
		Property for **self.__uiResourcesDirectory** attribute.

		:return: self.__uiResourcesDirectory.
		:rtype: unicode
		"""

		return self.__uiResourcesDirectory

	@uiResourcesDirectory.setter
	@foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
	def uiResourcesDirectory(self, value):
		"""
		Setter for **self.__uiResourcesDirectory** attribute.

		:param value: Attribute value.
		:type value: unicode
		"""

		raise foundations.exceptions.ProgrammingError(
		"{0} | '{1}' attribute is read only!".format(self.__class__.__name__, "uiResourcesDirectory"))

	@uiResourcesDirectory.deleter
	@foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
	def uiResourcesDirectory(self):
		"""
		Deleter for **self.__uiResourcesDirectory** attribute.
		"""

		raise foundations.exceptions.ProgrammingError(
		"{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "uiResourcesDirectory"))

	@property
	def uiDefaultCollectionImage(self):
		"""
		Property for **self.__uiDefaultCollectionImage** attribute.

		:return: self.__uiDefaultCollectionImage.
		:rtype: unicode
		"""

		return self.__uiDefaultCollectionImage

	@uiDefaultCollectionImage.setter
	@foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
	def uiDefaultCollectionImage(self, value):
		"""
		Setter for **self.__uiDefaultCollectionImage** attribute.

		:param value: Attribute value.
		:type value: unicode
		"""

		raise foundations.exceptions.ProgrammingError(
		"{0} | '{1}' attribute is read only!".format(self.__class__.__name__, "uiDefaultCollectionImage"))

	@uiDefaultCollectionImage.deleter
	@foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
	def uiDefaultCollectionImage(self):
		"""
		Deleter for **self.__uiDefaultCollectionImage** attribute.
		"""

		raise foundations.exceptions.ProgrammingError(
		"{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "uiDefaultCollectionImage"))

	@property
	def uiUserCollectionImage(self):
		"""
		Property for **self.__uiUserCollectionImage** attribute.

		:return: self.__uiUserCollectionImage.
		:rtype: unicode
		"""

		return self.__uiUserCollectionImage

	@uiUserCollectionImage.setter
	@foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
	def uiUserCollectionImage(self, value):
		"""
		Setter for **self.__uiUserCollectionImage** attribute.

		:param value: Attribute value.
		:type value: unicode
		"""

		raise foundations.exceptions.ProgrammingError(
		"{0} | '{1}' attribute is read only!".format(self.__class__.__name__, "uiUserCollectionImage"))

	@uiUserCollectionImage.deleter
	@foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
	def uiUserCollectionImage(self):
		"""
		Deleter for **self.__uiUserCollectionImage** attribute.
		"""

		raise foundations.exceptions.ProgrammingError(
		"{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "uiUserCollectionImage"))

	@property
	def dockArea(self):
		"""
		Property for **self.__dockArea** attribute.

		:return: self.__dockArea.
		:rtype: int
		"""

		return self.__dockArea

	@dockArea.setter
	@foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
	def dockArea(self, value):
		"""
		Setter for **self.__dockArea** attribute.

		:param value: Attribute value.
		:type value: int
		"""

		raise foundations.exceptions.ProgrammingError(
		"{0} | '{1}' attribute is read only!".format(self.__class__.__name__, "dockArea"))

	@dockArea.deleter
	@foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
	def dockArea(self):
		"""
		Deleter for **self.__dockArea** attribute.
		"""

		raise foundations.exceptions.ProgrammingError(
		"{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "dockArea"))

	@property
	def engine(self):
		"""
		Property for **self.__engine** attribute.

		:return: self.__engine.
		:rtype: QObject
		"""

		return self.__engine

	@engine.setter
	@foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
	def engine(self, value):
		"""
		Setter for **self.__engine** attribute.

		:param value: Attribute value.
		:type value: QObject
		"""

		raise foundations.exceptions.ProgrammingError(
		"{0} | '{1}' attribute is read only!".format(self.__class__.__name__, "engine"))

	@engine.deleter
	@foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
	def engine(self):
		"""
		Deleter for **self.__engine** attribute.
		"""

		raise foundations.exceptions.ProgrammingError(
		"{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "engine"))

	@property
	def settings(self):
		"""
		Property for **self.__settings** attribute.

		:return: self.__settings.
		:rtype: QSettings
		"""

		return self.__settings

	@settings.setter
	@foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
	def settings(self, value):
		"""
		Setter for **self.__settings** attribute.

		:param value: Attribute value.
		:type value: QSettings
		"""

		raise foundations.exceptions.ProgrammingError(
		"{0} | '{1}' attribute is read only!".format(self.__class__.__name__, "settings"))

	@settings.deleter
	@foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
	def settings(self):
		"""
		Deleter for **self.__settings** attribute.
		"""

		raise foundations.exceptions.ProgrammingError(
		"{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "settings"))

	@property
	def settingsSection(self):
		"""
		Property for **self.__settingsSection** attribute.

		:return: self.__settingsSection.
		:rtype: unicode
		"""

		return self.__settingsSection

	@settingsSection.setter
	@foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
	def settingsSection(self, value):
		"""
		Setter for **self.__settingsSection** attribute.

		:param value: Attribute value.
		:type value: unicode
		"""

		raise foundations.exceptions.ProgrammingError(
		"{0} | '{1}' attribute is read only!".format(self.__class__.__name__, "settingsSection"))

	@settingsSection.deleter
	@foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
	def settingsSection(self):
		"""
		Deleter for **self.__settingsSection** attribute.
		"""

		raise foundations.exceptions.ProgrammingError(
		"{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "settingsSection"))

	@property
	def settingsSeparator(self):
		"""
		Property for **self.__settingsSeparator** attribute.

		:return: self.__settingsSeparator.
		:rtype: unicode
		"""

		return self.__settingsSeparator

	@settingsSeparator.setter
	@foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
	def settingsSeparator(self, value):
		"""
		Setter for **self.__settingsSeparator** attribute.

		:param value: Attribute value.
		:type value: unicode
		"""

		raise foundations.exceptions.ProgrammingError(
		"{0} | '{1}' attribute is read only!".format(self.__class__.__name__, "settingsSeparator"))

	@settingsSeparator.deleter
	@foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
	def settingsSeparator(self):
		"""
		Deleter for **self.__settingsSeparator** attribute.
		"""

		raise foundations.exceptions.ProgrammingError(
		"{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "settingsSeparator"))

	@property
	def iblSetsOutliner(self):
		"""
		Property for **self.__iblSetsOutliner** attribute.

		:return: self.__iblSetsOutliner.
		:rtype: QWidget
		"""

		return self.__iblSetsOutliner

	@iblSetsOutliner.setter
	@foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
	def iblSetsOutliner(self, value):
		"""
		Setter for **self.__iblSetsOutliner** attribute.

		:param value: Attribute value.
		:type value: QWidget
		"""

		raise foundations.exceptions.ProgrammingError(
		"{0} | '{1}' attribute is read only!".format(self.__class__.__name__, "iblSetsOutliner"))

	@iblSetsOutliner.deleter
	@foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
	def iblSetsOutliner(self):
		"""
		Deleter for **self.__iblSetsOutliner** attribute.
		"""

		raise foundations.exceptions.ProgrammingError(
		"{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "iblSetsOutliner"))

	@property
	def model(self):
		"""
		Property for **self.__model** attribute.

		:return: self.__model.
		:rtype: CollectionsModel
		"""

		return self.__model

	@model.setter
	@foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
	def model(self, value):
		"""
		Setter for **self.__model** attribute.

		:param value: Attribute value.
		:type value: CollectionsModel
		"""

		raise foundations.exceptions.ProgrammingError(
		"{0} | '{1}' attribute is read only!".format(self.__class__.__name__, "model"))

	@model.deleter
	@foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
	def model(self):
		"""
		Deleter for **self.__model** attribute.
		"""

		raise foundations.exceptions.ProgrammingError(
		"{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "model"))

	@property
	def view(self):
		"""
		Property for **self.__view** attribute.

		:return: self.__view.
		:rtype: QWidget
		"""

		return self.__view

	@view.setter
	@foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
	def view(self, value):
		"""
		Setter for **self.__view** attribute.

		:param value: Attribute value.
		:type value: QWidget
		"""

		raise foundations.exceptions.ProgrammingError(
		"{0} | '{1}' attribute is read only!".format(self.__class__.__name__, "view"))

	@view.deleter
	@foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
	def view(self):
		"""
		Deleter for **self.__view** attribute.
		"""

		raise foundations.exceptions.ProgrammingError(
		"{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "view"))

	@property
	def overallCollection(self):
		"""
		Property for **self.__overallCollection** attribute.

		:return: self.__overallCollection.
		:rtype: unicode
		"""

		return self.__overallCollection

	@overallCollection.setter
	@foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
	def overallCollection(self, value):
		"""
		Setter for **self.__overallCollection** attribute.

		:param value: Attribute value.
		:type value: unicode
		"""

		raise foundations.exceptions.ProgrammingError(
		"{0} | '{1}' attribute is read only!".format(self.__class__.__name__, "overallCollection"))

	@overallCollection.deleter
	@foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
	def overallCollection(self):
		"""
		Deleter for **self.__overallCollection** attribute.
		"""

		raise foundations.exceptions.ProgrammingError(
		"{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "overallCollection"))

	@property
	def defaultCollection(self):
		"""
		Property for **self.__defaultCollection** attribute.

		:return: self.__defaultCollection.
		:rtype: unicode
		"""

		return self.__defaultCollection

	@defaultCollection.setter
	@foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
	def defaultCollection(self, value):
		"""
		Setter for **self.__defaultCollection** attribute.

		:param value: Attribute value.
		:type value: unicode
		"""

		raise foundations.exceptions.ProgrammingError(
		"{0} | '{1}' attribute is read only!".format(self.__class__.__name__, "defaultCollection"))

	@defaultCollection.deleter
	@foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
	def defaultCollection(self):
		"""
		Deleter for **self.__defaultCollection** attribute.
		"""

		raise foundations.exceptions.ProgrammingError(
		"{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "defaultCollection"))

	@property
	def iblSetsCountLabel(self):
		"""
		Property for **self.__iblSetsCountLabel** attribute.

		:return: self.__iblSetsCountLabel.
		:rtype: unicode
		"""

		return self.__iblSetsCountLabel

	@iblSetsCountLabel.setter
	@foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
	def iblSetsCountLabel(self, value):
		"""
		Setter for **self.__iblSetsCountLabel** attribute.

		:param value: Attribute value.
		:type value: unicode
		"""

		raise foundations.exceptions.ProgrammingError(
		"{0} | '{1}' attribute is read only!".format(self.__class__.__name__, "iblSetsCountLabel"))

	@iblSetsCountLabel.deleter
	@foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
	def iblSetsCountLabel(self):
		"""
		Deleter for **self.__iblSetsCountLabel** attribute.
		"""

		raise foundations.exceptions.ProgrammingError(
		"{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "iblSetsCountLabel"))

	@property
	def headers(self):
		"""
		Property for **self.__headers** attribute.

		:return: self.__headers.
		:rtype: OrderedDict
		"""

		return self.__headers

	@headers.setter
	@foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
	def headers(self, value):
		"""
		Setter for **self.__headers** attribute.

		:param value: Attribute value.
		:type value: OrderedDict
		"""

		raise foundations.exceptions.ProgrammingError(
		"{0} | '{1}' attribute is read only!".format(self.__class__.__name__, "headers"))

	@headers.deleter
	@foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
	def headers(self):
		"""
		Deleter for **self.__headers** attribute.
		"""

		raise foundations.exceptions.ProgrammingError(
		"{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "headers"))

	#******************************************************************************************************************
	#***	Class methods.
	#******************************************************************************************************************
	def activate(self, engine):
		"""
		Activates the Component.

		:param engine: Engine to attach the Component to.
		:type engine: QObject
		:return: Method success.
		:rtype: bool
		"""

		LOGGER.debug("> Activating '{0}' Component.".format(self.__class__.__name__))

		self.__uiResourcesDirectory = os.path.join(os.path.dirname(__file__), self.__uiResourcesDirectory)
		self.__engine = engine
		self.__settings = self.__engine.settings
		self.__settingsSection = self.name

		self.__iblSetsOutliner = self.__engine.componentsManager["core.iblSetsOutliner"]

		self.activated = True
		return True

	@foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
	def deactivate(self):
		"""
		Deactivates the Component.
		"""

		raise foundations.exceptions.ProgrammingError(
		"{0} | '{1}' Component cannot be deactivated!".format(self.__class__.__name__, self.__name))

	def initializeUi(self):
		"""
		Initializes the Component ui.
		
		:return: Method success.
		:rtype: bool
		"""

		LOGGER.debug("> Initializing '{0}' Component ui.".format(self.__class__.__name__))

		self.__engine.parameters.databaseReadOnly and \
		LOGGER.info("{0} | Model edition deactivated by '{1}' command line parameter value!".format(self.__class__.__name__,
																									"databaseReadOnly"))
		self.__model = CollectionsModel(self, horizontalHeaders=self.__headers)
		self.setCollections()

		self.Collections_Outliner_treeView.setParent(None)
		self.Collections_Outliner_treeView = IblSetsCollections_QTreeView(self,
																		self.__model,
																		self.__engine.parameters.databaseReadOnly)
		self.Collections_Outliner_treeView.setObjectName("Collections_Outliner_treeView")
		self.Collections_Outliner_dockWidgetContents_gridLayout.addWidget(self.Collections_Outliner_treeView, 0, 0)
		self.__view = self.Collections_Outliner_treeView
		self.__view.setContextMenuPolicy(Qt.ActionsContextMenu)
		self.__view_addActions()

		# Signals / Slots.
		self.__engine.imagesCaches.QIcon.contentAdded.connect(self.__view.viewport().update)
		self.__view.selectionModel().selectionChanged.connect(self.__view_selectionModel__selectionChanged)
		self.refreshNodes.connect(self.__model__refreshNodes)
		if not self.__engine.parameters.databaseReadOnly:
			self.__model.dataChanged.connect(self.__model__dataChanged)

		self.initializedUi = True
		return True

	@foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
	def uninitializeUi(self):
		"""
		Uninitializes the Component ui.
		"""

		raise foundations.exceptions.ProgrammingError(
		"{0} | '{1}' Component ui cannot be uninitialized!".format(self.__class__.__name__, self.name))

	def addWidget(self):
		"""
		Adds the Component Widget to the engine.

		:return: Method success.
		:rtype: bool
		"""

		LOGGER.debug("> Adding '{0}' Component Widget.".format(self.__class__.__name__))

		self.__engine.addDockWidget(Qt.DockWidgetArea(self.__dockArea), self)

		return True

	@foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError)
	def removeWidget(self):
		"""
		Removes the Component Widget from the engine.
		"""

		raise foundations.exceptions.ProgrammingError(
		"{0} | '{1}' Component Widget cannot be removed!".format(self.__class__.__name__, self.name))

	def onStartup(self):
		"""
		Defines the slot triggered on Framework startup.

		:return: Method success.
		:rtype: bool
		"""

		LOGGER.debug("> Calling '{0}' Component Framework 'onStartup' method.".format(self.__class__.__name__))

		if not self.__engine.parameters.databaseReadOnly:
			not self.getCollections() and self.addCollection(self.__defaultCollection, "Default Collection")
		else:
			LOGGER.info("{0} | Database default Collection wizard deactivated by '{1}' command line parameter value!".format(
			self.__class__.__name__, "databaseReadOnly"))

		activeCollectionsIdentities = foundations.strings.toString(
		self.__settings.getKey(self.__settingsSection, "activeCollections").toString())
		LOGGER.debug("> '{0}' View stored selected Collections identities '{1}'.".format(self.__class__.__name__,
																						activeCollectionsIdentities))
		self.__view.modelSelection["Collections"] = activeCollectionsIdentities and \
													[int(identity) for identity in activeCollectionsIdentities.split(
													self.__settingsSeparator)] or []

		activeOverallCollection = foundations.strings.toString(
		self.__settings.getKey(self.__settingsSection, "activeOverallCollection").toString())
		LOGGER.debug("> '{0}' View stored 'Overall' Collection: '{1}'.".format(self.__class__.__name__,
																				activeOverallCollection))
		self.__view.modelSelection[self.__overallCollection] = activeCollectionsIdentities and \
																[activeOverallCollection] or []
		self.__view.restoreModelSelection()
		return True

	def onClose(self):
		"""
		Defines the slot triggered on Framework close.

		:return: Method success.
		:rtype: bool
		"""

		LOGGER.debug("> Calling '{0}' Component Framework 'onClose' method.".format(self.__class__.__name__))

		self.__view.storeModelSelection()
		self.__settings.setKey(self.__settingsSection,
								"activeCollections",
								self.__settingsSeparator.join((foundations.strings.toString(
								identity) for identity in self.__view.modelSelection[
								"Collections"])))
		self.__settings.setKey(self.__settingsSection,
								"activeOverallCollection",
								self.__settingsSeparator.join((foundations.strings.toString(name)
								for name in self.__view.modelSelection[self.__overallCollection])))
		return True

	def __model__refreshNodes(self):
		"""
		Defines the slot triggered by the Model when Nodes need refresh.
		"""

		self.setCollections()

	def __model__refreshAttributes(self):
		"""
		Refreshes the Model Nodes attributes.
		"""

		for node in foundations.walkers.nodesWalker(self.__model.rootNode):
			if not node.family == "Collection":
				continue

			node.updateNodeAttributes()

		overallCollectionNode = \
		foundations.common.getFirstItem(self.__model.findChildren("^{0}$".format(self.__overallCollection)))
		overallCollectionNode.updateNodeAttributes()

	@foundations.exceptions.handleExceptions(umbra.exceptions.notifyExceptionHandler,
											foundations.exceptions.UserError)
	def __model__dataChanged(self, startIndex, endIndex):
		"""
		Defines the slot triggered by the Model when data has changed.
		
		:param startIndex: Edited item starting QModelIndex.
		:type startIndex: QModelIndex
		:param endIndex: Edited item ending QModelIndex.
		:type endIndex: QModelIndex
		"""

		collectionNode = self.__model.getNode(startIndex)
		if collectionNode.family != "Collection":
			return

		if startIndex.column() == 0:
			if self.collectionExists(collectionNode.name):
				self.__engine.notificationsManager.warnify(
				"{0} | '{1}' Collection name already exists in Database!".format(self.__class__.__name__,
																				collectionNode.name))
				return

			if not collectionNode.name:
				collectionNode.updateNode()
				raise foundations.exceptions.UserError(
				"{0} | Exception while editing a Collection field: Cannot use an empty value!".format(
				self.__class__.__name__))

		collectionNode.updateDatabaseItem()
		collectionNode.updateToolTip()

		sibl_gui.components.core.database.operations.commit()

	def __view_addActions(self):
		"""
		Sets the View actions.
		"""

		if not self.__engine.parameters.databaseReadOnly:
			self.__view.addAction(self.__engine.actionsManager.registerAction(
			"Actions|Umbra|Components|core.collectionsOutliner|Add Content ...",
			slot=self.__view_addContentAction__triggered))
			self.__view.addAction(self.__engine.actionsManager.registerAction(
			"Actions|Umbra|Components|core.collectionsOutliner|Add Collection ...",
			slot=self.__view_addCollectionAction__triggered))
			self.__view.addAction(self.__engine.actionsManager.registerAction(
			"Actions|Umbra|Components|core.collectionsOutliner|Remove Collection(s) ...",
			slot=self.__view_removeCollectionsAction__triggered))
		else:
			LOGGER.info(
			"{0} | Collections Database alteration capabilities deactivated by '{1}' command line parameter value!".format(
			self.__class__.__name__, "databaseReadOnly"))

	def __view_addContentAction__triggered(self, checked):
		"""
		Defines the slot triggered by **'Actions|Umbra|Components|core.collectionsOutliner|Add Content ...'** action.

		:param checked: Action checked state.
		:type checked: bool
		:return: Method success.
		:rtype: bool
		"""

		return self.addContentUi()

	def __view_addCollectionAction__triggered(self, checked):
		"""
		Defines the slot triggered by **'Actions|Umbra|Components|core.collectionsOutliner|Add Collection ...'** action.

		:param checked: Action checked state.
		:type checked: bool
		:return: Method success.
		:rtype: bool
		"""

		return self.addCollectionUi()

	def __view_removeCollectionsAction__triggered(self, checked):
		"""
		Defines the slot triggered by 
		**'Actions|Umbra|Components|core.collectionsOutliner|Remove Collection(s) ...'** action.

		:param checked: Action checked state.
		:type checked: bool
		:return: Method success.
		:rtype: bool
		"""

		return self.removeCollectionsUi()

	def __view_selectionModel__selectionChanged(self, selectedItems, deselectedItems):
		"""
		Defines the slot triggered by the View **selectionModel** when selection changed.

		:param selectedItems: Selected items.
		:type selectedItems: QItemSelection
		:param deselectedItems: Deselected items.
		:type deselectedItems: QItemSelection
		"""

		self.__iblSetsOutliner.refreshNodes.emit()

	@foundations.exceptions.handleExceptions(umbra.exceptions.notifyExceptionHandler, Exception)
	@umbra.engine.showProcessing("Adding Content ...")
	def addContentUi(self):
		"""
		Adds user defined content to the Database.

		:return: Method success.
		:rtype: bool

		:note: May require user interaction.
		"""

		collection = self.addCollectionUi()
		if not collection:
			return False

		directory = umbra.ui.common.storeLastBrowsedPath((QFileDialog.getExistingDirectory(self,
																						"Add Content:",
																						RuntimeGlobals.lastBrowsedPath)))
		if not directory:
			return False

		LOGGER.debug("> Chosen directory path: '{0}'.".format(directory))
		if self.__iblSetsOutliner.addDirectory(directory, self.getCollectionId(collection)):
			return True
		else:
			raise Exception("{0} | Exception raised while adding '{1}' directory content to the Database!".format(
			self.__class__.__name__, directory))

	@foundations.exceptions.handleExceptions(umbra.exceptions.notifyExceptionHandler,
											foundations.exceptions.UserError,
											Exception)
	@umbra.engine.showProcessing("Adding Collection ...")
	def addCollectionUi(self):
		"""
		Adds an user defined Collection to the Database.

		:return: Collection name.
		:rtype: unicode

		:note: May require user interaction.
		"""

		collectionInformations, state = QInputDialog.getText(self, "Add Collection", "Enter your Collection name:")
		if not state:
			return False

		if collectionInformations:
			collectionInformations = foundations.strings.toString(collectionInformations).split(",")
			name = collectionInformations[0].strip()
			if name != self.__overallCollection:
				if not self.collectionExists(name):
					comment = len(collectionInformations) == 1 and "Double click to set a comment!" or \
					collectionInformations[1].strip()
					if self.addCollection(name, comment):
						self.__view.selectionModel().setCurrentIndex(self.__model.getNodeIndex(
						foundations.common.getFirstItem(self.__model.findChildren(r"^{0}$".format(name)))),
						QItemSelectionModel.Current | QItemSelectionModel.Select | QItemSelectionModel.Rows)
						return name
					else:
						raise Exception("{0} | Exception raised while adding '{1}' Collection to the Database!".format(
						self.__class__.__name__, name))
				else:
					self.__engine.notificationsManager.warnify(
					"{0} | '{1}' Collection already exists in Database!".format(self.__class__.__name__, name))
			else:
				raise foundations.exceptions.UserError(
				"{0} | Exception while adding a Collection to the Database: Cannot use '{1}' as Collection name!".format(
				self.__class__.__name__, self.__model.overallCollection))
		else:
			raise foundations.exceptions.UserError(
			"{0} | Exception while adding a Collection to the Database: Cannot use an empty name!".format(
			self.__class__.__name__))

	@foundations.exceptions.handleExceptions(umbra.exceptions.notifyExceptionHandler, Exception)
	@umbra.engine.encapsulateProcessing
	def removeCollectionsUi(self):
		"""
		Removes user selected Collections from the Database.

		:return: Method success.
		:rtype: bool

		:note: May require user interaction.
		"""

		selectedNodes = self.getSelectedNodes().keys()
		if self.__overallCollection in (node.name for node in selectedNodes) or \
		self.__defaultCollection in (node.name for node in selectedNodes):
			self.__engine.notificationsManager.warnify(
			"{0} | '{1}' and '{2}' Collections cannot be removed!".format(self.__class__.__name__,
																	self.__overallCollection,
																	self.__defaultCollection))

		selectedCollections = [collection
								for collection in self.getSelectedCollections()
								if collection.name != self.__defaultCollection]
		if not selectedCollections:
			return False

		if messageBox.messageBox("Question", "Question",
		"Are you sure you want to remove '{0}' Collection(s)?".format(", ".join((foundations.strings.toString(collection.name)
																	for collection in selectedCollections))),
		buttons=QMessageBox.Yes | QMessageBox.No) == QMessageBox.Yes:
			self.__engine.startProcessing("Removing Collections ...", len(selectedCollections))
			success = True
			for collection in selectedCollections:
				success *= self.removeCollection(collection) or False
				self.__engine.stepProcessing()
			self.__engine.stopProcessing()
			self.__view.selectionModel().setCurrentIndex(self.__model.index(0, 0),
			QItemSelectionModel.Current | QItemSelectionModel.Select | QItemSelectionModel.Rows)
			if success:
				return True
			else:
				raise Exception("{0} | Exception raised while removing '{1}' Collections from the Database!".format(
				self.__class__.__name__, ", ". join((collection.name for collection in selectedCollections))))

	@foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError,
											sibl_gui.components.core.database.exceptions.DatabaseOperationError)
	def addCollection(self, name, comment="Double click to set a comment!"):
		"""
		Adds a Collection to the Database.

		:param name: Collection name.
		:type name: unicode
		:param collection: Collection name.
		:type collection: unicode
		:return: Method success.
		:rtype: bool
		"""

		if name != self.__overallCollection:
			if not self.collectionExists(name):
				LOGGER.info("{0} | Adding '{1}' Collection to the Database!".format(self.__class__.__name__, name))
				if sibl_gui.components.core.database.operations.addCollection(name, "IblSets", comment):
					self.refreshNodes.emit()
					return True
				else:
					raise sibl_gui.components.core.database.exceptions.DatabaseOperationError(
					"{0} | Exception raised while adding '{1}' Collection to the Database!".format(self.__class__.__name__,
																									name))
			else:
				raise foundations.exceptions.ProgrammingError(
		"{0} | '{1}' Collection already exists in Database!".format(self.__class__.__name__, name))
		else:
			raise foundations.exceptions.ProgrammingError(
		"{0} | Cannot use '{1}' as Collection name!".format(self.__class__.__name__, self.__model.overallCollection))

	@foundations.exceptions.handleExceptions(sibl_gui.components.core.database.exceptions.DatabaseOperationError)
	def removeCollection(self, collection):
		"""
		Removes given Collection from the Database.

		:param collection: Collection to remove.
		:type collection: Collection
		:return: Method success.
		:rtype: bool
		"""

		iblSets = sibl_gui.components.core.database.operations.getCollectionsIblSets((collection.id,))
		for iblSet in iblSets:
			LOGGER.info("{0} | Moving '{1}' Ibl Set to default Collection!".format(self.__class__.__name__, iblSet.title))
			iblSet.collection = self.getCollectionId(self.__defaultCollection)

		LOGGER.info("{0} | Removing '{1}' Collection from the Database!".format(self.__class__.__name__, collection.name))
		if sibl_gui.components.core.database.operations.removeCollection(foundations.strings.toString(collection.id)):
			self.refreshNodes.emit()
			self.__iblSetsOutliner.refreshNodes.emit()
			return True
		else:
			raise sibl_gui.components.core.database.exceptions.DatabaseOperationError(
			"{0} | Exception raised while removing '{1}' Collection from the Database!".format(self.__class__.__name__,
																								collection.name))
	def getCollections(self):
		"""
		Returns Database Ibl Sets Collections.

		:return: Database Ibl Sets Collections.
		:rtype: list
		"""

		return sibl_gui.components.core.database.operations.getCollectionsByType("IblSets")

	def filterCollections(self, pattern, attribute, flags=re.IGNORECASE):
		"""
		Filters the Database Ibl Sets Collections on given attribute using given pattern.
		
		:param pattern: Filter pattern.
		:type pattern: unicode
		:param attribute: Attribute to filter on.
		:type attribute: unicode
		:param flags: Regex filtering flags.
		:type flags: int

		:return: Filtered Database Ibl Sets Collections.
		:rtype: list
		"""

		try:
			pattern = re.compile(pattern, flags)
		except Exception:
			return list()

		return sibl_gui.components.core.database.operations.filterIblSetsCollections(
		"{0}".format(foundations.strings.toString(pattern.pattern)), attribute, flags)

	def collectionExists(self, name):
		"""
		Returns if given Collection name exists in the Database.

		:param name: Collection name.
		:type name: unicode
		:return: Collection exists.
		:rtype: bool
		"""

		return sibl_gui.components.core.database.operations.collectionExists(name)

	def listCollections(self):
		"""
		Lists Database Ibl Sets Collections names.

		:return: Database Ibl Sets Collections names.
		:rtype: list
		"""

		return [collection.name for collection in self.getCollections()]

	def setCollections(self):
		"""
		Sets the Collections Model nodes.
		"""

		nodeFlags = attributesFlags = self.__engine.parameters.databaseReadOnly and \
		int(Qt.ItemIsSelectable | Qt.ItemIsEnabled) or int(Qt.ItemIsSelectable | Qt.ItemIsEditable | Qt.ItemIsEnabled)
		collections = self.getCollections()

		rootNode = umbra.ui.nodes.DefaultNode(name="InvisibleRootNode")

		overallCollectionNode = OverallCollectionNode(name="Overall",
													parent=rootNode,
													nodeFlags=int(Qt.ItemIsSelectable | Qt.ItemIsEnabled),
													attributesFlags=int(Qt.ItemIsSelectable | Qt.ItemIsEnabled))

		for collection in collections:
			decorationRole = os.path.join(self.__uiResourcesDirectory, self.__uiUserCollectionImage)
			if collection.name == self.__defaultCollection:
				collectionNode = CollectionNode(collection,
												name=collection.name,
												parent=overallCollectionNode,
												nodeFlags=int(Qt.ItemIsSelectable | Qt.ItemIsEnabled),
												attributesFlags=int(Qt.ItemIsSelectable | Qt.ItemIsEnabled))
				decorationRole = os.path.join(self.__uiResourcesDirectory, self.__uiDefaultCollectionImage)
			else:
				collectionNode = CollectionNode(collection,
												name=collection.name,
												parent=overallCollectionNode,
												nodeFlags=nodeFlags,
												attributesFlags=attributesFlags)
			collectionNode.roles[Qt.DecorationRole] = foundations.common.filterPath(decorationRole)
		overallCollectionNode.updateNodeAttributes()
		rootNode.sortChildren()

		self.__model.initializeModel(rootNode)
		return True

	def getCollectionByName(self, name):
		"""
		Returns Database Ibl Sets Collection with given name.

		:param name: Collection name.
		:type name: unicode
		:return: Database Ibl Sets Collection.
		:rtype: Collection
		"""

		collections = self.filterCollections(r"^{0}$".format(name), "name")
		return foundations.common.getFirstItem(collections)

	def getCollectionsIblSets(self, collections):
		"""
		Gets given Collections Ibl Sets.

		:param collections: Collections to get Ibl Sets from.
		:type collections: list
		:return: Ibl Sets list.
		:rtype: list
		"""

		return [iblSet for iblSet in \
		sibl_gui.components.core.database.operations.getCollectionsIblSets([collection.id for collection in collections])]

	def getCollectionId(self, collection):
		"""
		Returns given Collection id.

		:param collection: Collection to get the id from.
		:type collection: unicode
		:return: Provided Collection id.
		:rtype: int
		"""

		children = self.__model.findChildren(r"^{0}$".format(collection))
		child = foundations.common.getFirstItem(children)
		return child and child.databaseItem.id or None

	def getSelectedNodes(self):
		"""
		Returns the View selected nodes.

		:return: View selected nodes.
		:rtype: dict
		"""

		return self.__view.getSelectedNodes()

	def getSelectedCollectionsNodes(self):
		"""
		Returns the View selected Collections nodes.

		:return: View selected Collections nodes.
		:rtype: list
		"""

		return [node for node in self.getSelectedNodes() if node.family == "Collection"]

	def getSelectedCollections(self):
		"""
		Gets the View selected Collections.

		:return: View selected Collections.
		:rtype: list
		"""

		return [node.databaseItem for node in self.getSelectedCollectionsNodes()]
Example #4
0
class CollectionsOutliner(QWidgetComponentFactory(uiFile=COMPONENT_UI_FILE)):
    """
	| Defines the :mod:`sibl_gui.components.core.collectionsOutliner.collectionsOutliner` Component Interface class.
	| It defines methods for Database Collections management.
	"""

    # Custom signals definitions.
    refreshNodes = pyqtSignal()
    """
	This signal is emited by the :class:`CollectionsOutliner` class when :obj:`CollectionsOutliner.model` class
	property Model Nodes needs to be refreshed. ( pyqtSignal )
	"""
    def __init__(self, parent=None, name=None, *args, **kwargs):
        """
		Initializes the class.

		:param parent: Object parent.
		:type parent: QObject
		:param name: Component name.
		:type name: unicode
		:param \*args: Arguments.
		:type \*args: \*
		:param \*\*kwargs: Keywords arguments.
		:type \*\*kwargs: \*\*
		"""

        LOGGER.debug("> Initializing '{0}()' class.".format(
            self.__class__.__name__))

        super(CollectionsOutliner, self).__init__(parent, name, *args,
                                                  **kwargs)

        # --- Setting class attributes. ---
        self.deactivatable = False

        self.__uiResourcesDirectory = "resources"
        self.__uiDefaultCollectionImage = "Default_Collection.png"
        self.__uiUserCollectionImage = "User_Collection.png"
        self.__dockArea = 1

        self.__engine = None
        self.__settings = None
        self.__settingsSection = None
        self.__settingsSeparator = ","

        self.__iblSetsOutliner = None

        self.__model = None
        self.__view = None
        self.__overallCollection = "Overall"
        self.__defaultCollection = "Default"
        self.__iblSetsCountLabel = "Ibl Sets"
        self.__headers = OrderedDict([("Collections", "name"),
                                      (self.__iblSetsCountLabel, "count"),
                                      ("Comment", "comment")])

    #******************************************************************************************************************
    #***	Attributes properties.
    #******************************************************************************************************************
    @property
    def uiResourcesDirectory(self):
        """
		Property for **self.__uiResourcesDirectory** attribute.

		:return: self.__uiResourcesDirectory.
		:rtype: unicode
		"""

        return self.__uiResourcesDirectory

    @uiResourcesDirectory.setter
    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def uiResourcesDirectory(self, value):
        """
		Setter for **self.__uiResourcesDirectory** attribute.

		:param value: Attribute value.
		:type value: unicode
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' attribute is read only!".format(
                self.__class__.__name__, "uiResourcesDirectory"))

    @uiResourcesDirectory.deleter
    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def uiResourcesDirectory(self):
        """
		Deleter for **self.__uiResourcesDirectory** attribute.
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' attribute is not deletable!".format(
                self.__class__.__name__, "uiResourcesDirectory"))

    @property
    def uiDefaultCollectionImage(self):
        """
		Property for **self.__uiDefaultCollectionImage** attribute.

		:return: self.__uiDefaultCollectionImage.
		:rtype: unicode
		"""

        return self.__uiDefaultCollectionImage

    @uiDefaultCollectionImage.setter
    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def uiDefaultCollectionImage(self, value):
        """
		Setter for **self.__uiDefaultCollectionImage** attribute.

		:param value: Attribute value.
		:type value: unicode
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' attribute is read only!".format(
                self.__class__.__name__, "uiDefaultCollectionImage"))

    @uiDefaultCollectionImage.deleter
    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def uiDefaultCollectionImage(self):
        """
		Deleter for **self.__uiDefaultCollectionImage** attribute.
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' attribute is not deletable!".format(
                self.__class__.__name__, "uiDefaultCollectionImage"))

    @property
    def uiUserCollectionImage(self):
        """
		Property for **self.__uiUserCollectionImage** attribute.

		:return: self.__uiUserCollectionImage.
		:rtype: unicode
		"""

        return self.__uiUserCollectionImage

    @uiUserCollectionImage.setter
    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def uiUserCollectionImage(self, value):
        """
		Setter for **self.__uiUserCollectionImage** attribute.

		:param value: Attribute value.
		:type value: unicode
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' attribute is read only!".format(
                self.__class__.__name__, "uiUserCollectionImage"))

    @uiUserCollectionImage.deleter
    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def uiUserCollectionImage(self):
        """
		Deleter for **self.__uiUserCollectionImage** attribute.
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' attribute is not deletable!".format(
                self.__class__.__name__, "uiUserCollectionImage"))

    @property
    def dockArea(self):
        """
		Property for **self.__dockArea** attribute.

		:return: self.__dockArea.
		:rtype: int
		"""

        return self.__dockArea

    @dockArea.setter
    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def dockArea(self, value):
        """
		Setter for **self.__dockArea** attribute.

		:param value: Attribute value.
		:type value: int
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' attribute is read only!".format(
                self.__class__.__name__, "dockArea"))

    @dockArea.deleter
    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def dockArea(self):
        """
		Deleter for **self.__dockArea** attribute.
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' attribute is not deletable!".format(
                self.__class__.__name__, "dockArea"))

    @property
    def engine(self):
        """
		Property for **self.__engine** attribute.

		:return: self.__engine.
		:rtype: QObject
		"""

        return self.__engine

    @engine.setter
    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def engine(self, value):
        """
		Setter for **self.__engine** attribute.

		:param value: Attribute value.
		:type value: QObject
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' attribute is read only!".format(
                self.__class__.__name__, "engine"))

    @engine.deleter
    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def engine(self):
        """
		Deleter for **self.__engine** attribute.
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' attribute is not deletable!".format(
                self.__class__.__name__, "engine"))

    @property
    def settings(self):
        """
		Property for **self.__settings** attribute.

		:return: self.__settings.
		:rtype: QSettings
		"""

        return self.__settings

    @settings.setter
    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def settings(self, value):
        """
		Setter for **self.__settings** attribute.

		:param value: Attribute value.
		:type value: QSettings
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' attribute is read only!".format(
                self.__class__.__name__, "settings"))

    @settings.deleter
    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def settings(self):
        """
		Deleter for **self.__settings** attribute.
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' attribute is not deletable!".format(
                self.__class__.__name__, "settings"))

    @property
    def settingsSection(self):
        """
		Property for **self.__settingsSection** attribute.

		:return: self.__settingsSection.
		:rtype: unicode
		"""

        return self.__settingsSection

    @settingsSection.setter
    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def settingsSection(self, value):
        """
		Setter for **self.__settingsSection** attribute.

		:param value: Attribute value.
		:type value: unicode
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' attribute is read only!".format(
                self.__class__.__name__, "settingsSection"))

    @settingsSection.deleter
    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def settingsSection(self):
        """
		Deleter for **self.__settingsSection** attribute.
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' attribute is not deletable!".format(
                self.__class__.__name__, "settingsSection"))

    @property
    def settingsSeparator(self):
        """
		Property for **self.__settingsSeparator** attribute.

		:return: self.__settingsSeparator.
		:rtype: unicode
		"""

        return self.__settingsSeparator

    @settingsSeparator.setter
    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def settingsSeparator(self, value):
        """
		Setter for **self.__settingsSeparator** attribute.

		:param value: Attribute value.
		:type value: unicode
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' attribute is read only!".format(
                self.__class__.__name__, "settingsSeparator"))

    @settingsSeparator.deleter
    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def settingsSeparator(self):
        """
		Deleter for **self.__settingsSeparator** attribute.
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' attribute is not deletable!".format(
                self.__class__.__name__, "settingsSeparator"))

    @property
    def iblSetsOutliner(self):
        """
		Property for **self.__iblSetsOutliner** attribute.

		:return: self.__iblSetsOutliner.
		:rtype: QWidget
		"""

        return self.__iblSetsOutliner

    @iblSetsOutliner.setter
    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def iblSetsOutliner(self, value):
        """
		Setter for **self.__iblSetsOutliner** attribute.

		:param value: Attribute value.
		:type value: QWidget
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' attribute is read only!".format(
                self.__class__.__name__, "iblSetsOutliner"))

    @iblSetsOutliner.deleter
    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def iblSetsOutliner(self):
        """
		Deleter for **self.__iblSetsOutliner** attribute.
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' attribute is not deletable!".format(
                self.__class__.__name__, "iblSetsOutliner"))

    @property
    def model(self):
        """
		Property for **self.__model** attribute.

		:return: self.__model.
		:rtype: CollectionsModel
		"""

        return self.__model

    @model.setter
    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def model(self, value):
        """
		Setter for **self.__model** attribute.

		:param value: Attribute value.
		:type value: CollectionsModel
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' attribute is read only!".format(
                self.__class__.__name__, "model"))

    @model.deleter
    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def model(self):
        """
		Deleter for **self.__model** attribute.
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' attribute is not deletable!".format(
                self.__class__.__name__, "model"))

    @property
    def view(self):
        """
		Property for **self.__view** attribute.

		:return: self.__view.
		:rtype: QWidget
		"""

        return self.__view

    @view.setter
    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def view(self, value):
        """
		Setter for **self.__view** attribute.

		:param value: Attribute value.
		:type value: QWidget
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' attribute is read only!".format(
                self.__class__.__name__, "view"))

    @view.deleter
    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def view(self):
        """
		Deleter for **self.__view** attribute.
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' attribute is not deletable!".format(
                self.__class__.__name__, "view"))

    @property
    def overallCollection(self):
        """
		Property for **self.__overallCollection** attribute.

		:return: self.__overallCollection.
		:rtype: unicode
		"""

        return self.__overallCollection

    @overallCollection.setter
    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def overallCollection(self, value):
        """
		Setter for **self.__overallCollection** attribute.

		:param value: Attribute value.
		:type value: unicode
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' attribute is read only!".format(
                self.__class__.__name__, "overallCollection"))

    @overallCollection.deleter
    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def overallCollection(self):
        """
		Deleter for **self.__overallCollection** attribute.
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' attribute is not deletable!".format(
                self.__class__.__name__, "overallCollection"))

    @property
    def defaultCollection(self):
        """
		Property for **self.__defaultCollection** attribute.

		:return: self.__defaultCollection.
		:rtype: unicode
		"""

        return self.__defaultCollection

    @defaultCollection.setter
    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def defaultCollection(self, value):
        """
		Setter for **self.__defaultCollection** attribute.

		:param value: Attribute value.
		:type value: unicode
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' attribute is read only!".format(
                self.__class__.__name__, "defaultCollection"))

    @defaultCollection.deleter
    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def defaultCollection(self):
        """
		Deleter for **self.__defaultCollection** attribute.
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' attribute is not deletable!".format(
                self.__class__.__name__, "defaultCollection"))

    @property
    def iblSetsCountLabel(self):
        """
		Property for **self.__iblSetsCountLabel** attribute.

		:return: self.__iblSetsCountLabel.
		:rtype: unicode
		"""

        return self.__iblSetsCountLabel

    @iblSetsCountLabel.setter
    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def iblSetsCountLabel(self, value):
        """
		Setter for **self.__iblSetsCountLabel** attribute.

		:param value: Attribute value.
		:type value: unicode
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' attribute is read only!".format(
                self.__class__.__name__, "iblSetsCountLabel"))

    @iblSetsCountLabel.deleter
    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def iblSetsCountLabel(self):
        """
		Deleter for **self.__iblSetsCountLabel** attribute.
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' attribute is not deletable!".format(
                self.__class__.__name__, "iblSetsCountLabel"))

    @property
    def headers(self):
        """
		Property for **self.__headers** attribute.

		:return: self.__headers.
		:rtype: OrderedDict
		"""

        return self.__headers

    @headers.setter
    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def headers(self, value):
        """
		Setter for **self.__headers** attribute.

		:param value: Attribute value.
		:type value: OrderedDict
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' attribute is read only!".format(
                self.__class__.__name__, "headers"))

    @headers.deleter
    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def headers(self):
        """
		Deleter for **self.__headers** attribute.
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' attribute is not deletable!".format(
                self.__class__.__name__, "headers"))

    #******************************************************************************************************************
    #***	Class methods.
    #******************************************************************************************************************
    def activate(self, engine):
        """
		Activates the Component.

		:param engine: Engine to attach the Component to.
		:type engine: QObject
		:return: Method success.
		:rtype: bool
		"""

        LOGGER.debug("> Activating '{0}' Component.".format(
            self.__class__.__name__))

        self.__uiResourcesDirectory = os.path.join(os.path.dirname(__file__),
                                                   self.__uiResourcesDirectory)
        self.__engine = engine
        self.__settings = self.__engine.settings
        self.__settingsSection = self.name

        self.__iblSetsOutliner = self.__engine.componentsManager[
            "core.iblSetsOutliner"]

        self.activated = True
        return True

    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def deactivate(self):
        """
		Deactivates the Component.
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' Component cannot be deactivated!".format(
                self.__class__.__name__, self.__name))

    def initializeUi(self):
        """
		Initializes the Component ui.
		
		:return: Method success.
		:rtype: bool
		"""

        LOGGER.debug("> Initializing '{0}' Component ui.".format(
            self.__class__.__name__))

        self.__engine.parameters.databaseReadOnly and \
        LOGGER.info("{0} | Model edition deactivated by '{1}' command line parameter value!".format(self.__class__.__name__,
                               "databaseReadOnly"))
        self.__model = CollectionsModel(self, horizontalHeaders=self.__headers)
        self.setCollections()

        self.Collections_Outliner_treeView.setParent(None)
        self.Collections_Outliner_treeView = IblSetsCollections_QTreeView(
            self, self.__model, self.__engine.parameters.databaseReadOnly)
        self.Collections_Outliner_treeView.setObjectName(
            "Collections_Outliner_treeView")
        self.Collections_Outliner_dockWidgetContents_gridLayout.addWidget(
            self.Collections_Outliner_treeView, 0, 0)
        self.__view = self.Collections_Outliner_treeView
        self.__view.setContextMenuPolicy(Qt.ActionsContextMenu)
        self.__view_addActions()

        # Signals / Slots.
        self.__engine.imagesCaches.QIcon.contentAdded.connect(
            self.__view.viewport().update)
        self.__view.selectionModel().selectionChanged.connect(
            self.__view_selectionModel__selectionChanged)
        self.refreshNodes.connect(self.__model__refreshNodes)
        if not self.__engine.parameters.databaseReadOnly:
            self.__model.dataChanged.connect(self.__model__dataChanged)

        self.initializedUi = True
        return True

    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def uninitializeUi(self):
        """
		Uninitializes the Component ui.
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' Component ui cannot be uninitialized!".format(
                self.__class__.__name__, self.name))

    def addWidget(self):
        """
		Adds the Component Widget to the engine.

		:return: Method success.
		:rtype: bool
		"""

        LOGGER.debug("> Adding '{0}' Component Widget.".format(
            self.__class__.__name__))

        self.__engine.addDockWidget(Qt.DockWidgetArea(self.__dockArea), self)

        return True

    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError)
    def removeWidget(self):
        """
		Removes the Component Widget from the engine.
		"""

        raise foundations.exceptions.ProgrammingError(
            "{0} | '{1}' Component Widget cannot be removed!".format(
                self.__class__.__name__, self.name))

    def onStartup(self):
        """
		Defines the slot triggered on Framework startup.

		:return: Method success.
		:rtype: bool
		"""

        LOGGER.debug(
            "> Calling '{0}' Component Framework 'onStartup' method.".format(
                self.__class__.__name__))

        if not self.__engine.parameters.databaseReadOnly:
            not self.getCollections() and self.addCollection(
                self.__defaultCollection, "Default Collection")
        else:
            LOGGER.info(
                "{0} | Database default Collection wizard deactivated by '{1}' command line parameter value!"
                .format(self.__class__.__name__, "databaseReadOnly"))

        activeCollectionsIdentities = foundations.strings.toString(
            self.__settings.getKey(self.__settingsSection,
                                   "activeCollections").toString())
        LOGGER.debug(
            "> '{0}' View stored selected Collections identities '{1}'.".
            format(self.__class__.__name__, activeCollectionsIdentities))
        self.__view.modelSelection["Collections"] = activeCollectionsIdentities and \
                   [int(identity) for identity in activeCollectionsIdentities.split(
                   self.__settingsSeparator)] or []

        activeOverallCollection = foundations.strings.toString(
            self.__settings.getKey(self.__settingsSection,
                                   "activeOverallCollection").toString())
        LOGGER.debug("> '{0}' View stored 'Overall' Collection: '{1}'.".format(
            self.__class__.__name__, activeOverallCollection))
        self.__view.modelSelection[self.__overallCollection] = activeCollectionsIdentities and \
                      [activeOverallCollection] or []
        self.__view.restoreModelSelection()
        return True

    def onClose(self):
        """
		Defines the slot triggered on Framework close.

		:return: Method success.
		:rtype: bool
		"""

        LOGGER.debug(
            "> Calling '{0}' Component Framework 'onClose' method.".format(
                self.__class__.__name__))

        self.__view.storeModelSelection()
        self.__settings.setKey(
            self.__settingsSection, "activeCollections",
            self.__settingsSeparator.join(
                (foundations.strings.toString(identity)
                 for identity in self.__view.modelSelection["Collections"])))
        self.__settings.setKey(
            self.__settingsSection, "activeOverallCollection",
            self.__settingsSeparator.join(
                (foundations.strings.toString(name) for name in
                 self.__view.modelSelection[self.__overallCollection])))
        return True

    def __model__refreshNodes(self):
        """
		Defines the slot triggered by the Model when Nodes need refresh.
		"""

        self.setCollections()

    def __model__refreshAttributes(self):
        """
		Refreshes the Model Nodes attributes.
		"""

        for node in foundations.walkers.nodesWalker(self.__model.rootNode):
            if not node.family == "Collection":
                continue

            node.updateNodeAttributes()

        overallCollectionNode = \
        foundations.common.getFirstItem(self.__model.findChildren("^{0}$".format(self.__overallCollection)))
        overallCollectionNode.updateNodeAttributes()

    @foundations.exceptions.handleExceptions(
        umbra.exceptions.notifyExceptionHandler,
        foundations.exceptions.UserError)
    def __model__dataChanged(self, startIndex, endIndex):
        """
		Defines the slot triggered by the Model when data has changed.
		
		:param startIndex: Edited item starting QModelIndex.
		:type startIndex: QModelIndex
		:param endIndex: Edited item ending QModelIndex.
		:type endIndex: QModelIndex
		"""

        collectionNode = self.__model.getNode(startIndex)
        if collectionNode.family != "Collection":
            return

        if startIndex.column() == 0:
            if self.collectionExists(collectionNode.name):
                self.__engine.notificationsManager.warnify(
                    "{0} | '{1}' Collection name already exists in Database!".
                    format(self.__class__.__name__, collectionNode.name))
                return

            if not collectionNode.name:
                collectionNode.updateNode()
                raise foundations.exceptions.UserError(
                    "{0} | Exception while editing a Collection field: Cannot use an empty value!"
                    .format(self.__class__.__name__))

        collectionNode.updateDatabaseItem()
        collectionNode.updateToolTip()

        sibl_gui.components.core.database.operations.commit()

    def __view_addActions(self):
        """
		Sets the View actions.
		"""

        if not self.__engine.parameters.databaseReadOnly:
            self.__view.addAction(
                self.__engine.actionsManager.registerAction(
                    "Actions|Umbra|Components|core.collectionsOutliner|Add Content ...",
                    slot=self.__view_addContentAction__triggered))
            self.__view.addAction(
                self.__engine.actionsManager.registerAction(
                    "Actions|Umbra|Components|core.collectionsOutliner|Add Collection ...",
                    slot=self.__view_addCollectionAction__triggered))
            self.__view.addAction(
                self.__engine.actionsManager.registerAction(
                    "Actions|Umbra|Components|core.collectionsOutliner|Remove Collection(s) ...",
                    slot=self.__view_removeCollectionsAction__triggered))
        else:
            LOGGER.info(
                "{0} | Collections Database alteration capabilities deactivated by '{1}' command line parameter value!"
                .format(self.__class__.__name__, "databaseReadOnly"))

    def __view_addContentAction__triggered(self, checked):
        """
		Defines the slot triggered by **'Actions|Umbra|Components|core.collectionsOutliner|Add Content ...'** action.

		:param checked: Action checked state.
		:type checked: bool
		:return: Method success.
		:rtype: bool
		"""

        return self.addContentUi()

    def __view_addCollectionAction__triggered(self, checked):
        """
		Defines the slot triggered by **'Actions|Umbra|Components|core.collectionsOutliner|Add Collection ...'** action.

		:param checked: Action checked state.
		:type checked: bool
		:return: Method success.
		:rtype: bool
		"""

        return self.addCollectionUi()

    def __view_removeCollectionsAction__triggered(self, checked):
        """
		Defines the slot triggered by 
		**'Actions|Umbra|Components|core.collectionsOutliner|Remove Collection(s) ...'** action.

		:param checked: Action checked state.
		:type checked: bool
		:return: Method success.
		:rtype: bool
		"""

        return self.removeCollectionsUi()

    def __view_selectionModel__selectionChanged(self, selectedItems,
                                                deselectedItems):
        """
		Defines the slot triggered by the View **selectionModel** when selection changed.

		:param selectedItems: Selected items.
		:type selectedItems: QItemSelection
		:param deselectedItems: Deselected items.
		:type deselectedItems: QItemSelection
		"""

        self.__iblSetsOutliner.refreshNodes.emit()

    @foundations.exceptions.handleExceptions(
        umbra.exceptions.notifyExceptionHandler, Exception)
    @umbra.engine.showProcessing("Adding Content ...")
    def addContentUi(self):
        """
		Adds user defined content to the Database.

		:return: Method success.
		:rtype: bool

		:note: May require user interaction.
		"""

        collection = self.addCollectionUi()
        if not collection:
            return False

        directory = umbra.ui.common.storeLastBrowsedPath(
            (QFileDialog.getExistingDirectory(self, "Add Content:",
                                              RuntimeGlobals.lastBrowsedPath)))
        if not directory:
            return False

        LOGGER.debug("> Chosen directory path: '{0}'.".format(directory))
        if self.__iblSetsOutliner.addDirectory(
                directory, self.getCollectionId(collection)):
            return True
        else:
            raise Exception(
                "{0} | Exception raised while adding '{1}' directory content to the Database!"
                .format(self.__class__.__name__, directory))

    @foundations.exceptions.handleExceptions(
        umbra.exceptions.notifyExceptionHandler,
        foundations.exceptions.UserError, Exception)
    @umbra.engine.showProcessing("Adding Collection ...")
    def addCollectionUi(self):
        """
		Adds an user defined Collection to the Database.

		:return: Collection name.
		:rtype: unicode

		:note: May require user interaction.
		"""

        collectionInformations, state = QInputDialog.getText(
            self, "Add Collection", "Enter your Collection name:")
        if not state:
            return False

        if collectionInformations:
            collectionInformations = foundations.strings.toString(
                collectionInformations).split(",")
            name = collectionInformations[0].strip()
            if name != self.__overallCollection:
                if not self.collectionExists(name):
                    comment = len(collectionInformations) == 1 and "Double click to set a comment!" or \
                    collectionInformations[1].strip()
                    if self.addCollection(name, comment):
                        self.__view.selectionModel().setCurrentIndex(
                            self.__model.getNodeIndex(
                                foundations.common.getFirstItem(
                                    self.__model.findChildren(
                                        r"^{0}$".format(name)))),
                            QItemSelectionModel.Current
                            | QItemSelectionModel.Select
                            | QItemSelectionModel.Rows)
                        return name
                    else:
                        raise Exception(
                            "{0} | Exception raised while adding '{1}' Collection to the Database!"
                            .format(self.__class__.__name__, name))
                else:
                    self.__engine.notificationsManager.warnify(
                        "{0} | '{1}' Collection already exists in Database!".
                        format(self.__class__.__name__, name))
            else:
                raise foundations.exceptions.UserError(
                    "{0} | Exception while adding a Collection to the Database: Cannot use '{1}' as Collection name!"
                    .format(self.__class__.__name__,
                            self.__model.overallCollection))
        else:
            raise foundations.exceptions.UserError(
                "{0} | Exception while adding a Collection to the Database: Cannot use an empty name!"
                .format(self.__class__.__name__))

    @foundations.exceptions.handleExceptions(
        umbra.exceptions.notifyExceptionHandler, Exception)
    @umbra.engine.encapsulateProcessing
    def removeCollectionsUi(self):
        """
		Removes user selected Collections from the Database.

		:return: Method success.
		:rtype: bool

		:note: May require user interaction.
		"""

        selectedNodes = self.getSelectedNodes().keys()
        if self.__overallCollection in (node.name for node in selectedNodes) or \
        self.__defaultCollection in (node.name for node in selectedNodes):
            self.__engine.notificationsManager.warnify(
                "{0} | '{1}' and '{2}' Collections cannot be removed!".format(
                    self.__class__.__name__, self.__overallCollection,
                    self.__defaultCollection))

        selectedCollections = [
            collection for collection in self.getSelectedCollections()
            if collection.name != self.__defaultCollection
        ]
        if not selectedCollections:
            return False

        if messageBox.messageBox(
                "Question",
                "Question",
                "Are you sure you want to remove '{0}' Collection(s)?".format(
                    ", ".join((foundations.strings.toString(collection.name)
                               for collection in selectedCollections))),
                buttons=QMessageBox.Yes | QMessageBox.No) == QMessageBox.Yes:
            self.__engine.startProcessing("Removing Collections ...",
                                          len(selectedCollections))
            success = True
            for collection in selectedCollections:
                success *= self.removeCollection(collection) or False
                self.__engine.stepProcessing()
            self.__engine.stopProcessing()
            self.__view.selectionModel().setCurrentIndex(
                self.__model.index(0, 0), QItemSelectionModel.Current
                | QItemSelectionModel.Select | QItemSelectionModel.Rows)
            if success:
                return True
            else:
                raise Exception(
                    "{0} | Exception raised while removing '{1}' Collections from the Database!"
                    .format(
                        self.__class__.__name__, ", ".join(
                            (collection.name
                             for collection in selectedCollections))))

    @foundations.exceptions.handleExceptions(
        foundations.exceptions.ProgrammingError,
        sibl_gui.components.core.database.exceptions.DatabaseOperationError)
    def addCollection(self, name, comment="Double click to set a comment!"):
        """
		Adds a Collection to the Database.

		:param name: Collection name.
		:type name: unicode
		:param collection: Collection name.
		:type collection: unicode
		:return: Method success.
		:rtype: bool
		"""

        if name != self.__overallCollection:
            if not self.collectionExists(name):
                LOGGER.info(
                    "{0} | Adding '{1}' Collection to the Database!".format(
                        self.__class__.__name__, name))
                if sibl_gui.components.core.database.operations.addCollection(
                        name, "IblSets", comment):
                    self.refreshNodes.emit()
                    return True
                else:
                    raise sibl_gui.components.core.database.exceptions.DatabaseOperationError(
                        "{0} | Exception raised while adding '{1}' Collection to the Database!"
                        .format(self.__class__.__name__, name))
            else:
                raise foundations.exceptions.ProgrammingError(
                    "{0} | '{1}' Collection already exists in Database!".
                    format(self.__class__.__name__, name))
        else:
            raise foundations.exceptions.ProgrammingError(
                "{0} | Cannot use '{1}' as Collection name!".format(
                    self.__class__.__name__, self.__model.overallCollection))

    @foundations.exceptions.handleExceptions(
        sibl_gui.components.core.database.exceptions.DatabaseOperationError)
    def removeCollection(self, collection):
        """
		Removes given Collection from the Database.

		:param collection: Collection to remove.
		:type collection: Collection
		:return: Method success.
		:rtype: bool
		"""

        iblSets = sibl_gui.components.core.database.operations.getCollectionsIblSets(
            (collection.id, ))
        for iblSet in iblSets:
            LOGGER.info(
                "{0} | Moving '{1}' Ibl Set to default Collection!".format(
                    self.__class__.__name__, iblSet.title))
            iblSet.collection = self.getCollectionId(self.__defaultCollection)

        LOGGER.info(
            "{0} | Removing '{1}' Collection from the Database!".format(
                self.__class__.__name__, collection.name))
        if sibl_gui.components.core.database.operations.removeCollection(
                foundations.strings.toString(collection.id)):
            self.refreshNodes.emit()
            self.__iblSetsOutliner.refreshNodes.emit()
            return True
        else:
            raise sibl_gui.components.core.database.exceptions.DatabaseOperationError(
                "{0} | Exception raised while removing '{1}' Collection from the Database!"
                .format(self.__class__.__name__, collection.name))

    def getCollections(self):
        """
		Returns Database Ibl Sets Collections.

		:return: Database Ibl Sets Collections.
		:rtype: list
		"""

        return sibl_gui.components.core.database.operations.getCollectionsByType(
            "IblSets")

    def filterCollections(self, pattern, attribute, flags=re.IGNORECASE):
        """
		Filters the Database Ibl Sets Collections on given attribute using given pattern.
		
		:param pattern: Filter pattern.
		:type pattern: unicode
		:param attribute: Attribute to filter on.
		:type attribute: unicode
		:param flags: Regex filtering flags.
		:type flags: int

		:return: Filtered Database Ibl Sets Collections.
		:rtype: list
		"""

        try:
            pattern = re.compile(pattern, flags)
        except Exception:
            return list()

        return sibl_gui.components.core.database.operations.filterIblSetsCollections(
            "{0}".format(foundations.strings.toString(pattern.pattern)),
            attribute, flags)

    def collectionExists(self, name):
        """
		Returns if given Collection name exists in the Database.

		:param name: Collection name.
		:type name: unicode
		:return: Collection exists.
		:rtype: bool
		"""

        return sibl_gui.components.core.database.operations.collectionExists(
            name)

    def listCollections(self):
        """
		Lists Database Ibl Sets Collections names.

		:return: Database Ibl Sets Collections names.
		:rtype: list
		"""

        return [collection.name for collection in self.getCollections()]

    def setCollections(self):
        """
		Sets the Collections Model nodes.
		"""

        nodeFlags = attributesFlags = self.__engine.parameters.databaseReadOnly and \
        int(Qt.ItemIsSelectable | Qt.ItemIsEnabled) or int(Qt.ItemIsSelectable | Qt.ItemIsEditable | Qt.ItemIsEnabled)
        collections = self.getCollections()

        rootNode = umbra.ui.nodes.DefaultNode(name="InvisibleRootNode")

        overallCollectionNode = OverallCollectionNode(
            name="Overall",
            parent=rootNode,
            nodeFlags=int(Qt.ItemIsSelectable | Qt.ItemIsEnabled),
            attributesFlags=int(Qt.ItemIsSelectable | Qt.ItemIsEnabled))

        for collection in collections:
            decorationRole = os.path.join(self.__uiResourcesDirectory,
                                          self.__uiUserCollectionImage)
            if collection.name == self.__defaultCollection:
                collectionNode = CollectionNode(
                    collection,
                    name=collection.name,
                    parent=overallCollectionNode,
                    nodeFlags=int(Qt.ItemIsSelectable | Qt.ItemIsEnabled),
                    attributesFlags=int(Qt.ItemIsSelectable
                                        | Qt.ItemIsEnabled))
                decorationRole = os.path.join(self.__uiResourcesDirectory,
                                              self.__uiDefaultCollectionImage)
            else:
                collectionNode = CollectionNode(
                    collection,
                    name=collection.name,
                    parent=overallCollectionNode,
                    nodeFlags=nodeFlags,
                    attributesFlags=attributesFlags)
            collectionNode.roles[
                Qt.DecorationRole] = foundations.common.filterPath(
                    decorationRole)
        overallCollectionNode.updateNodeAttributes()
        rootNode.sortChildren()

        self.__model.initializeModel(rootNode)
        return True

    def getCollectionByName(self, name):
        """
		Returns Database Ibl Sets Collection with given name.

		:param name: Collection name.
		:type name: unicode
		:return: Database Ibl Sets Collection.
		:rtype: Collection
		"""

        collections = self.filterCollections(r"^{0}$".format(name), "name")
        return foundations.common.getFirstItem(collections)

    def getCollectionsIblSets(self, collections):
        """
		Gets given Collections Ibl Sets.

		:param collections: Collections to get Ibl Sets from.
		:type collections: list
		:return: Ibl Sets list.
		:rtype: list
		"""

        return [iblSet for iblSet in \
        sibl_gui.components.core.database.operations.getCollectionsIblSets([collection.id for collection in collections])]

    def getCollectionId(self, collection):
        """
		Returns given Collection id.

		:param collection: Collection to get the id from.
		:type collection: unicode
		:return: Provided Collection id.
		:rtype: int
		"""

        children = self.__model.findChildren(r"^{0}$".format(collection))
        child = foundations.common.getFirstItem(children)
        return child and child.databaseItem.id or None

    def getSelectedNodes(self):
        """
		Returns the View selected nodes.

		:return: View selected nodes.
		:rtype: dict
		"""

        return self.__view.getSelectedNodes()

    def getSelectedCollectionsNodes(self):
        """
		Returns the View selected Collections nodes.

		:return: View selected Collections nodes.
		:rtype: list
		"""

        return [
            node for node in self.getSelectedNodes()
            if node.family == "Collection"
        ]

    def getSelectedCollections(self):
        """
		Gets the View selected Collections.

		:return: View selected Collections.
		:rtype: list
		"""

        return [
            node.databaseItem for node in self.getSelectedCollectionsNodes()
        ]