/**
 * @brief Changes the id of a dialog.
 *
 * The index of multiple dialogs may change, since they are sorted alphabetically.
 * In this case, emits rowsAboutToBeRemoved(), removes the dialog,
 * emits rowsRemoved() and rowsAboutToBeInserted(), adds the new dialog
 * and then emits rowsInserted(), as required by QAbstractItemModel.
 *
 * Then, emits dialog_id_changed(), no matter if the index has also changed.
 *
 * The selection is preserved, though the index of many dialogs can change.
 * The selection is cleared before the operations and restored after,
 * updated with the new indexes.
 *
 * @param id Id of an existing dialog.
 * @param new_id The new id to set.
 * @return The new id of the dialog.
 * @throws EditorException in case of error.
 */
QString DialogsModel::set_dialog_id(const QString& id, const QString& new_id) {

  if (new_id == id) {
    // Nothing to do.
    return id;
  }

  // Make some checks first.
  if (!dialog_exists(id)) {
    throw EditorException(tr("Dialog '%1' no exists").arg(id));
  }

  if (dialog_exists(new_id)) {
    throw EditorException(tr("Dialog '%1' already exists").arg(new_id));
  }

  if (!is_valid_id(new_id)) {
    throw EditorException(tr("Invalid dialog id: %1").arg(new_id));
  }

  // Save and clear the selection since a lot of indexes may change.
  QString old_selection = get_selected_id();
  clear_selection();

  // Change in to the strings file.
  resources.set_dialog_id(id.toStdString(), new_id.toStdString());

  // Remove from the indexed tree.
  QString parent_id;
  int index;
  if (dialog_tree.can_remove_key(id, parent_id, index)) {

    // Call beginRemoveRows() as requested by QAbstractItemModel.
    beginRemoveRows(id_to_index(parent_id), index, index);
    dialog_tree.remove_key(id);
    endRemoveRows();
  } else if (dialog_tree.remove_key(id)) {
    QModelIndex model_index = id_to_index(id);
    dataChanged(model_index, model_index);
  }

  // Add to the indexed tree.
  if (dialog_tree.add_key(new_id, parent_id, index)) {

    // Call beginInsertRows() as requested by QAbstractItemModel.
    beginInsertRows(id_to_index(parent_id), index, index);
    endInsertRows();
  } else {
    QModelIndex model_index = id_to_index(id);
    dataChanged(model_index, model_index);
  }

  // Notify people.
  emit dialog_id_changed(id, new_id);

  // Restore the selection.
  set_selected_id(old_selection);
  return new_id;
}
/**
 * @brief Returns whether dialog or sub dialog has translation and don't exists.
 * @param id The id of the dialog.
 * @return @c true if the dialog or sub dialog has tanslation and don't exists.
 */
bool DialogsModel::has_missing_translation(const QString& id) const {

  if (!dialog_exists(id) && translated_dialog_exists(id)) {
    return true;
  }

  for (QString sub_id : get_translated_ids(id + ".")) {
    if (!dialog_exists(sub_id)) {
      return true;
    }
  }

  return false;
}
/**
 * @brief Returns the data of a dialog id in the indexed tree for a given role.
 * @param index Index of the dialog id to get.
 * @param role The wanted role.
 * @return The data.
 */
QVariant DialogsModel::data(const QModelIndex& model_index, int role) const {

  if (model_index.column() != 0 || !model_index.isValid()) {
    return QVariant();
  }

  QString id = index_to_id(model_index);
  if (dialog_tree.key_exists(id)) {
    switch (role) {
      case Qt::DisplayRole: return id.split(".").back(); break;

      case Qt::DecorationRole:
        if (dialog_exists(id)) {
          if (has_missing_translation(id)) {
            return QIcon(":/images/icon_dialogs_missing.png");
          } else if (dialog_tree.get_row_count(id) == 0) {
            return QIcon(":/images/icon_dialog.png");
          }
          return QIcon(":/images/icon_dialogs.png");
        }
        else if (has_missing_translation(id)) {
          if (dialog_tree.get_row_count(id) == 0) {
            return QIcon(":/images/icon_dialog_missing.png");
          } if (translated_dialog_exists(id)) {
            return QIcon(":/images/icon_dialogs_missing.png");
          }
          return QIcon(":/images/icon_folder_open_missing.png");
        }
        return QIcon(":/images/icon_folder_open.png");
    }
  }

  return QVariant();
}
/**
 * @brief Returns the text of a dialog with the specified id.
 * @param id The id to test.
 * @return the text of the specified dialog or an empty string if no exists.
 */
QString DialogsModel::get_dialog_text(const QString& id) const {

  if (!dialog_exists(id)) {
    return "";
  }
  return QString::fromStdString(
        resources.get_dialog(id.toStdString()).get_text());
}
/**
 * @brief Returns the data of a dialog with the specified id.
 * @param id The id to test.
 * @return the data of the specified dialog.
 */
DialogData DialogsModel::get_dialog_data(const QString& id) const {

  DialogData data;
  if (dialog_exists(id)) {
    data = resources.get_dialog(id.toStdString());
  }
  return data;
}
/**
 * @brief Returns whether there exists a dialog property with the specified id.
 * @param id The id to test.
 * @param key The key of the property.
 * @return @c true if such the specified property dialog exists.
 */
bool DialogsModel::dialog_property_exists(
    const QString& id, const QString& key) const {

  if (!dialog_exists(id)) {
    return false;
  }
  return resources.get_dialog(id.toStdString()).has_property(key.toStdString());
}
/**
 * @brief Removes all translated dialogs from the indexed tree.
 */
void DialogsModel::clear_translation_from_tree() {

  for (const auto& kvp : translation_resources.get_dialogs()) {
    QString id = QString::fromStdString(kvp.first);
    QString parent_id;
    int index;
    if (dialog_tree.can_remove_ref(id, parent_id, index)) {
      if (!dialog_exists(id)) {
        beginRemoveRows(id_to_index(parent_id), index, index);
        dialog_tree.remove_ref(id, false);
        endRemoveRows();
      } else {
        dialog_tree.remove_ref(id, true);
      }
    } else {
      dialog_tree.remove_ref(id, dialog_exists(id));
    }
  }
}
/**
 * @brief Returns whether the prefix of dialog ids can be changed.
 * @param old_prefix[in] The prefix key of strings to change.
 * @param new_prefix[in] The new prefix to set.
 * @param id[out] The id that already exists in case of error.
 * @return @c true if the prefix can be changed.
 */
bool DialogsModel::can_set_dialog_id_prefix(
    const QString& old_prefix, const QString& new_prefix, QString& id) {

  for (QString prefixed_id : get_ids(old_prefix)) {

    prefixed_id.replace(QRegExp(QString("^") + old_prefix), new_prefix);
    if (dialog_exists(prefixed_id)) {
      id = prefixed_id;
      return false;
    }
  }
  return true;
}
/**
 * @brief Returns the properties of a dialog with the specified id.
 * @param id The id to test.
 * @return the properties of the specified dialog.
 */
QMap<QString, QString> DialogsModel::get_dialog_properties(
    const QString& id) const {

  QMap<QString, QString> map;
  if (!dialog_exists(id)) {
    return map;
  }

  for (auto kvp : resources.get_dialog(id.toStdString()).get_properties()) {
    map.insert(
          QString::fromStdString(kvp.first),
          QString::fromStdString(kvp.second));
  }
  return map;
}
/**
 * @brief Deletes a dialog.
 *
 * The index of multiple dialogs may change, since they are sorted alphabetically.
 * Emits rowsAboutToBeRemoved(), removes the dialog
 * and then emits rowsRemoved(), as required by QAbstractItemModel.
 *
 * Then, emits dialog_deleted().
 *
 * Except for the deleted dialog, the existing selection is preserved,
 * though the index of many dialogs can change.
 * The selection is cleared before the operations and restored after,
 * updated with the new indexes.
 *
 * @param id Id of the dialog to delete.
 * @throws EditorException in case of error.
 */
void DialogsModel::delete_dialog(const QString& id) {

  // Make some checks first.
  if (!dialog_exists(id)) {
    throw EditorException(tr("Invalid dialog id: %1").arg(id));
  }

  // Save and clear the selection since a lot of indexes may change.
  QString old_selection = get_selected_id();
  clear_selection();

  // Delete from the strings file
  resources.remove_dialog(id.toStdString());

  // Remove from the indexed tree.
  QString parent_id;
  int index;
  if (dialog_tree.can_remove_key(id, parent_id, index)) {

    // Call beginRemoveRows() as requested by QAbstractItemModel.
    beginRemoveRows(id_to_index(parent_id), index, index);

    dialog_tree.remove_key(id);

    // Notify people before restoring the selection, so that they have a
    // chance to know new indexes before receiving selection signals.
    endRemoveRows();
  } else if (dialog_tree.remove_key(id)) {
    QModelIndex model_index = id_to_index(id);
    dataChanged(model_index, model_index);
  }

  // Notify people.
  emit dialog_deleted(id);

  // Restore the selection.
  set_selected_id(old_selection);
}
/**
 * @brief Creates a new dialog.
 *
 * The index of the selection may change, since dialog are sorted
 * alphabetically.
 * Emits rowsAboutToBeInserted(), adds the new dialog
 * and then emits rowsInserted(), as required by QAbstractItemModel.
 *
 * Then, emits dialog_created().
 *
 * The newly created dialog is not initially selected.
 * The existing selection is preserved, though the index of many
 * dialogs can change.
 * The selection is cleared before the operations and restored after,
 * updated with the new index.
 *
 * @param id Id of the dialog to create.
 * @param data Data of the dialog to create.
 * @throws EditorException in case of error.
 */
void DialogsModel::create_dialog(const QString& id, const DialogData& data) {

  // Make some checks first.
  if (!is_valid_id(id)) {
      throw EditorException(tr("Invalid dialog id: %1").arg(id));
  }

  if (dialog_exists(id)) {
      throw EditorException(tr("Dialog '%1' already exists").arg(id));
  }

  // Save and clear the selection since a lot of indexes may change.
  QString old_selection = get_selected_id();
  clear_selection();

  // Add to the strings file.
  resources.add_dialog(id.toStdString(), data);

  // Update the indexed tree.
  QString parent_id;
  int index;
  if (dialog_tree.add_key(id, parent_id, index)) {
    // Notify people before restoring the selection, so that they have a
    // chance to know new indexes before receiving selection signals.
    beginInsertRows(id_to_index(parent_id), index, index);
    endInsertRows();
  } else {
    QModelIndex model_index = id_to_index(id);
    dataChanged(model_index, model_index);
  }

  // Notify people.
  emit dialog_created(id);

  // Restore the selection.
  set_selected_id(old_selection);
}
Пример #12
0
gint anim_next_frame(struct model_pak *model)
{
    gulong time;
    gchar *text, *name;

    g_assert(model != NULL);

    /* increment and test if should we return to the start */
    model->cur_frame += model->anim_step;
    if (model->cur_frame >= model->num_frames)
        if (model->anim_loop)
            model->cur_frame = 1;

    /* continue until we run out of frames (or a stop is flagged) */
    if (model->cur_frame < model->num_frames && model->animating)
    {
#if DEBUG_DISPLAY_NEXT_FRAME
        printf("displaying [%d]\n", model->cur_frame);
#endif

        time = mytimer();

        /* if a dialog exists - update via the current frame spinner */
        if (dialog_exists(ANIM, model))
            gui_relation_update(model);
        else
        {
            /* otherwise, update manually */
            read_frame(model->afp, model->cur_frame, model);
            meas_graft_model(model);
            gui_active_refresh();
            redraw_canvas(SINGLE);
        }

        /* animation adjusted redraw time */
        time = mytimer() - time;
        model->redraw_cumulative += time;

        /* NEW - render to file */
        if (sysenv.render.animate)
        {
            text = g_strdup_printf("%s_%06d.pov", sysenv.render.animate_file, model->cur_frame);
            name = g_build_filename(sysenv.cwd, text, NULL);

            write_povray(name, model);

            /* NB: added this as jago keeps locking up on multi-frame renders */
            if (!sysenv.render.no_povray_exec)
                povray_exec(name);

            g_free(text);
            g_free(name);
        }

        return(TRUE);
    }

    /* FIXME - find a better way to do this... */
    if (!model->transform_list)
        fclose(model->afp);

    /* done animation */
    model->animating = FALSE;
    model->cur_frame--;

    /* create movie? */
    if (sysenv.render.animate && !sysenv.render.no_povray_exec)
    {
        text = NULL;
        switch (sysenv.render.animate_type)
        {
        case ANIM_GIF:
            text = g_strdup_printf("%s -delay %d %s_*.tga %s.gif",
                                   sysenv.convert_path,
                                   (gint) sysenv.render.delay,
                                   sysenv.render.animate_file, sysenv.render.animate_file);
            break;

        case ANIM_MPEG:
            text = g_strdup_printf("%s -quality %d -delay %d %s_*.tga %s.mpg",
                                   sysenv.convert_path, (gint) sysenv.render.mpeg_quality,
                                   (gint) sysenv.render.delay,
                                   sysenv.render.animate_file, sysenv.render.animate_file);
            break;
        }

        if (text)
        {
            system(text);
            g_free(text);
            gui_text_show(DEFAULT, "Completed movie creation.\n");
        }
    }

    /* cleanup */
    if (sysenv.render.no_keep_tempfiles)
    {
#ifndef __WIN32
        text = g_strdup_printf("rm -rf %s_*.pov", sysenv.render.animate_file);
        system(text);
        g_free(text);
        text = g_strdup_printf("rm -rf %s_*.tga", sysenv.render.animate_file);
        system(text);
        g_free(text);
#endif
        /* TODO - windows equivalents */
    }

    /* done - return FALSE to terminate the timer */
    return(FALSE);
}