/** * @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); }
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); }