/**
 * @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 source image of an animation.
 *
 * Emits animation_image_changed() if there is a change.
 *
 * @param index An animation index.
 * @param src_image The source image to set.
 */
void SpriteModel::set_animation_source_image(
    const Index& index, const QString& src_image) {

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

  SpriteAnimationData& animation = get_animation(index);
  if (animation.get_src_image() == src_image.toStdString()) {
    return;
  }

  animation.set_src_image(src_image.toStdString());
  set_animation_image_dirty(index);

  emit animation_image_changed(index, src_image);
}