/**
 * @brief Sets the sprite model.
 * @param model The sprite model, or nullptr to remove any model.
 * This class does not take ownership on the model.
 * The model can be deleted safely.
 */
void SpritePreviewer::set_model(SpriteModel* model) {

  if (this->model != nullptr) {
    this->model->disconnect(this);
    this->model = nullptr;
  }

  this->model = model;

  if (model != nullptr) {
    connect(&model->get_selection_model(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
            this, SLOT(update_selection()));
    update_selection();

    connect(model, SIGNAL(animation_frame_delay_changed(Index,uint32_t)),
            this, SLOT(update_frame_delay()));
    connect(model, SIGNAL(animation_image_changed(Index,QString)),
            this, SLOT(update_frames()));

    connect(model, SIGNAL(direction_position_changed(Index,QPoint)),
            this, SLOT(update_frames()));
    connect(model, SIGNAL(direction_size_changed(Index,QSize)),
            this, SLOT(update_frames()));
    connect(model, SIGNAL(direction_num_frames_changed(Index,int)),
            this, SLOT(update_frames()));
    connect(model, SIGNAL(direction_num_columns_changed(Index,int)),
            this, SLOT(update_frames()));

    connect(model, SIGNAL(direction_origin_changed(Index,QPoint)),
            this, SLOT(update_origin()));
  }
/**
 * @brief Sets the frame delay of an animation.
 *
 * Emits animation_frame_delay_changed() if there is a change.
 *
 * @param index An animation index.
 * @param frame_delay The frame delay to set.
 */
void SpriteModel::set_animation_frame_delay(
    const Index& index, uint32_t frame_delay) {

  if (!animation_exists(index)) {
    return;
  }

  SpriteAnimationData& animation = get_animation(index);
  if (animation.get_frame_delay() == frame_delay) {
    return;
  }

  animation.set_frame_delay(frame_delay);
  emit animation_frame_delay_changed(index, frame_delay);
}