text: # -*- coding: utf-8 -*-
  # Copyright (c) 2017-2020, Erkan Ozgur Yilmaz
  #
  # This module is part of anima and is released under the MIT
  # License: http://www.opensource.org/licenses/MIT
  
  from anima.ui.base import AnimaDialogBase, ui_caller
  from anima.ui.lib import QtCore, QtWidgets
  
  
  def UI(app_in=None, executor=None, **kwargs):
      """
      :param app_in: A Qt Application instance, which you can pass to let the UI
        be attached to the given applications event process.
  
      :param executor: Instead of calling app.exec_ the UI will call this given
        function. It also passes the created app instance to this executor.
  
      """
      return ui_caller(app_in, executor, MainDialog, **kwargs)
  
  
  class MainDialog(QtWidgets.QDialog, AnimaDialogBase):
      """The Project Users Dialog
      """
  
      def __init__(self, parent=None, project=None):
          super(MainDialog, self).__init__(parent)
  
          self.project = project
  
          self._setup_ui()
          self._setup_signals()
          self._set_defaults()
  
          if self.project:
              self.fill_ui_with_project(self.project)
  
      def _setup_ui(self):
          """create UI elements
          """
          self.resize(520, 550)
          self.vertical_layout = QtWidgets.QVBoxLayout(self)
  
          # -------------------------
          # Dialog Label
          self.dialog_label = QtWidgets.QLabel(self)
          self.dialog_label.setText('Set Project Users')
          self.dialog_label.setStyleSheet(
              "color: rgb(71, 143, 202);\nfont: 18pt;"
          )
          self.vertical_layout.addWidget(self.dialog_label)
          self.line = QtWidgets.QFrame(self)
          self.line.setFrameShape(QtWidgets.QFrame.HLine)
          self.line.setFrameShadow(QtWidgets.QFrame.Sunken)
          self.vertical_layout.addWidget(self.line)
  
          self.form_layout = QtWidgets.QFormLayout()
          self.form_layout.setLabelAlignment(
              QtCore.Qt.AlignRight |
              QtCore.Qt.AlignTrailing |
              QtCore.Qt.AlignVCenter
          )
          self.vertical_layout.addLayout(self.form_layout)
  
          i = -1
  
          # create Project Combo box
          i += 1
          self.projects_label = QtWidgets.QLabel(self)
          self.projects_label.setText('Projects')
          self.form_layout.setWidget(
              i,
              QtWidgets.QFormLayout.LabelRole,
              self.projects_label
          )
  
          self.projects_combo_box = QtWidgets.QComboBox(self)
          self.form_layout.setWidget(
              i,
              QtWidgets.QFormLayout.FieldRole,
              self.projects_combo_box
          )
  
          # create DoubleListWidget
          i += 1
          self.users_label = QtWidgets.QLabel(self)
          self.users_label.setText('Users')
          self.form_layout.setWidget(
              i,
              QtWidgets.QFormLayout.LabelRole,
              self.users_label
          )
  
          self.users_fields_vertical_layout = QtWidgets.QVBoxLayout()
          self.form_layout.setLayout(
              i,
              QtWidgets.QFormLayout.FieldRole,
              self.users_fields_vertical_layout
          )
  
          from anima.ui.widgets import DoubleListWidget
          self.users_double_list_widget = DoubleListWidget(
              dialog=self,
              parent_layout=self.users_fields_vertical_layout,
              primary_label_text='Users From DB',
              secondary_label_text='Selected Users'
          )
          # set the tooltip
          self.users_double_list_widget\
              .primary_list_widget.setToolTip(
                  "Right Click to Create/Update FilenameTemplates"
              )
          self.users_double_list_widget\
              .secondary_list_widget.setToolTip(
                  "Right Click to Create/Update FilenameTemplates"
              )
  
          # Button Box
          self.button_box = QtWidgets.QDialogButtonBox(self)
          self.button_box.setOrientation(QtCore.Qt.Horizontal)
          self.button_box.setStandardButtons(
              QtWidgets.QDialogButtonBox.Cancel | QtWidgets.QDialogButtonBox.Ok
          )
          self.vertical_layout.addWidget(self.button_box)
          self.vertical_layout.setStretch(2, 1)
  
      def _setup_signals(self):
          """setup ui signals
          """
          QtCore.QObject.connect(
              self.projects_combo_box,
              QtCore.SIGNAL("currentIndexChanged(QString)"),
              self.project_changed
          )
  
          QtCore.QObject.connect(
              self.button_box,
              QtCore.SIGNAL("accepted()"),
              self.accept
          )
          QtCore.QObject.connect(
              self.button_box,
              QtCore.SIGNAL("rejected()"),
              self.reject
          )
  
      def _set_defaults(self):
          """set defaults
          """
          # fill with projects
          from stalker.db.session import DBSession
          from stalker import Project
          projects_data = \
              DBSession\
                  .query(Project.id, Project.name)\
                  .order_by(Project.name)\
                  .all()
  
          self.projects_combo_box.clear()
          for p_data in projects_data:
              self.projects_combo_box.addItem(p_data.name, p_data.id)
  
      def fill_ui_with_project(self, project):
          """
  
          :param project: A Stalker Project instance
          :return:
          """
          # no project no gain
          if project is None:
              return
  
          # select the given project in the UI
          index = self.projects_combo_box.findData(project.id)
          if index:
              self.projects_combo_box.setCurrentIndex(index)
  
      def project_changed(self, project_name):
          """runs when the project in the combo box changed
          """
          try:
              project_id = self.projects_combo_box.currentData()
          except AttributeError:
              index = self.projects_combo_box.currentIndex()
              project_id = self.projects_combo_box.itemData(index)
  
          # refresh the items on the double list widget
          self.users_double_list_widget.clear()
  
          # get users not in the project
          from stalker.db.session import DBSession
          from stalker import User
          from stalker.models.project import ProjectUser
  
          project_users = DBSession.query(User.id, User.name).join(ProjectUser)\
              .filter(ProjectUser.project_id == project_id)\
              .filter(User.id == ProjectUser.user_id)\
              .all()
  
          project_user_ids = [u.id for u in project_users]
  
          if project_user_ids:
              users_not_in_project = [
                  u.name
                  for u in DBSession.query(User.name)
                      .filter(~User.id.in_(project_user_ids)).all()
              ]
          else:
              users_not_in_project = [
                  u.name
                  for u in DBSession.query(User.name).all()
              ]
  
          self.users_double_list_widget.add_primary_items(
              users_not_in_project
          )
  
          users_in_project = \
              [u.name for u in project_users]
  
          self.users_double_list_widget.add_secondary_items(
              users_in_project
          )
  
      def accept(self):
          """overridden accept method
          """
          # get the project
          try:
              project_id = self.projects_combo_box.currentData()
          except AttributeError:
              index = self.projects_combo_box.currentIndex()
              project_id = self.projects_combo_box.itemData(index)
  
          from stalker import Project
          project = Project.query.get(project_id)
  
          # get the users
          user_names = [
              item.text() for item in
              self.users_double_list_widget.secondary_items()
          ]
  
          from stalker import User
          if user_names:
              users = User.query.filter(User.name.in_(user_names))
          else:
              users = []
  
          # set the project users
          project.users = users
          from stalker.db.session import DBSession
          DBSession.commit()
  
          super(MainDialog, self).accept()
  