Force pre-select definitions specified in [Definitions] section of editor template c4s (#1898)

alut-include-path
Sven Eberhardt 2017-03-11 00:13:13 -05:00
parent 2c3a770415
commit 6937969175
5 changed files with 181 additions and 21 deletions

View File

@ -25,7 +25,7 @@
/* Definition file list model for new scenario definition selection */
C4ConsoleQtDefinitionFileListModel::DefFileInfo::DefFileInfo(C4ConsoleQtDefinitionFileListModel::DefFileInfo *parent, const char *filename, const char *root_path)
: parent(parent), filename(filename), root_path(root_path), was_opened(false), is_root(false), selected(parent->IsSelected()), disabled(parent->IsSelected() /*not a bug*/)
: parent(parent), filename(filename), root_path(root_path), was_opened(false), is_root(false), user_selected(parent->IsUserSelected()), force_selected(parent->IsForceSelected())
{
// Delay opening of groups until information is actually requested
// Full names into child groups in C4S always delimeted with backslashes
@ -36,14 +36,12 @@ C4ConsoleQtDefinitionFileListModel::DefFileInfo::DefFileInfo(C4ConsoleQtDefiniti
}
C4ConsoleQtDefinitionFileListModel::DefFileInfo::DefFileInfo()
: parent(nullptr), was_opened(true), is_root(true), selected(false), disabled(false)
: parent(nullptr), was_opened(true), is_root(true), user_selected(false), force_selected(false)
{
// Init as root: List definitions in root paths
// Objects.ocd is always there (even if not actually found) and always first
DefFileInfo *main_objects_def = new DefFileInfo(this, C4CFN_Objects, "");
children.emplace_back(main_objects_def);
main_objects_def->SetSelected(true);
main_objects_def->SetDisabled(true);
bool has_default_objects_found = false;
for (auto & root_iter : ::Reloc)
{
@ -73,14 +71,16 @@ C4ConsoleQtDefinitionFileListModel::DefFileInfo::DefFileInfo()
}
}
void C4ConsoleQtDefinitionFileListModel::DefFileInfo::SetSelected(bool to_val)
void C4ConsoleQtDefinitionFileListModel::DefFileInfo::SetSelected(bool to_val, bool forced)
{
selected = to_val;
// Selection propagates to children; children of selected are disabled because they cannot be un-selected
if (forced)
force_selected = to_val;
else
user_selected = to_val;
// Selection propagates to children
for (auto & child : children)
{
child->SetSelected(selected);
child->SetDisabled(selected);
child->SetSelected(to_val, forced);
}
}
@ -126,6 +126,20 @@ int32_t C4ConsoleQtDefinitionFileListModel::DefFileInfo::GetChildIndex(const Def
return int32_t(iter - children.begin());
}
void C4ConsoleQtDefinitionFileListModel::DefFileInfo::AddUserSelectedDefinitions(std::list<const char *> *result) const
{
// Add parent-most selected
// Ignore any forced selection even if also selected by user.
// It may have been selected first and then forced by the scenario preset after the template has been switched)
if (!IsForceSelected())
{
if (IsUserSelected())
result->push_back(full_filename.getData());
else
for (auto &iter : children) iter->AddUserSelectedDefinitions(result);
}
}
void C4ConsoleQtDefinitionFileListModel::DefFileInfo::AddSelectedDefinitions(std::list<const char *> *result) const
{
// Add parent-most selected
@ -135,6 +149,41 @@ void C4ConsoleQtDefinitionFileListModel::DefFileInfo::AddSelectedDefinitions(std
for (auto &iter : children) iter->AddSelectedDefinitions(result);
}
void C4ConsoleQtDefinitionFileListModel::DefFileInfo::SetForcedSelection(const char *selected_def_filepath)
{
// Filenames are assumed to be case insensitive for the Windows client
if (SEqualNoCase(selected_def_filepath, full_filename.getData()))
{
// This is the def to be force-selected
SetSelected(true, true);
}
else if (is_root || (SEqual2NoCase(selected_def_filepath, full_filename.getData()) && selected_def_filepath[full_filename.getLength()] == '\\'))
{
// One of the child definitions should be force-selected
if (!was_opened) OpenGroup();
for (auto &iter : children) iter->SetForcedSelection(selected_def_filepath);
}
}
void C4ConsoleQtDefinitionFileListModel::DefFileInfo::AddExtraDef(const char *def)
{
assert(is_root);
// Ignore if it was already added
// Could also avoid adding child definitions if they are already in the list.
// E.g. do not add both foo.ocs\bar.ocd and foo.ocs\bar.ocd\baz.ocd, but keep only the parent path.
// But it's overkill for a case that will probably never happen and would pose just a minor nuisance if it does.
for (auto &iter : children)
{
if (SEqualNoCase(iter->full_filename.getData(), def))
{
return;
}
}
// Add using user path as root (extra defs will always be in the user path because they are not used by our main system templates)
children.emplace_back(new DefFileInfo(this, def, ::Config.General.UserDataPath));
}
C4ConsoleQtDefinitionFileListModel::C4ConsoleQtDefinitionFileListModel()
{
}
@ -143,6 +192,18 @@ C4ConsoleQtDefinitionFileListModel::~C4ConsoleQtDefinitionFileListModel()
{
}
void C4ConsoleQtDefinitionFileListModel::AddExtraDef(const char *def)
{
root.AddExtraDef(def);
}
std::list<const char *> C4ConsoleQtDefinitionFileListModel::GetUserSelectedDefinitions() const
{
std::list<const char *> result;
root.AddUserSelectedDefinitions(&result);
return result;
}
std::list<const char *> C4ConsoleQtDefinitionFileListModel::GetSelectedDefinitions() const
{
std::list<const char *> result;
@ -150,6 +211,17 @@ std::list<const char *> C4ConsoleQtDefinitionFileListModel::GetSelectedDefinitio
return result;
}
void C4ConsoleQtDefinitionFileListModel::SetForcedSelection(std::list<const char *> &defs)
{
// Unselect previous
root.SetSelected(false, true);
// Force new selection
for (const char *def : defs)
{
root.SetForcedSelection(def);
}
}
int C4ConsoleQtDefinitionFileListModel::rowCount(const QModelIndex & parent) const
{
if (!parent.isValid()) return root.GetChildCount();
@ -216,7 +288,7 @@ bool C4ConsoleQtDefinitionFileListModel::setData(const QModelIndex& index, const
DefFileInfo *def = static_cast<DefFileInfo *>(index.internalPointer());
if (def && !def->IsDisabled())
{
def->SetSelected(value.toBool());
def->SetSelected(value.toBool(), false);
// Update changed index and all children
int32_t child_count = def->GetChildCount();
QModelIndex end_changed = index;
@ -287,6 +359,28 @@ void C4ConsoleQtNewScenarioDlg::AddScenarioTemplate(C4Group &parent, const char
// Add it; remember full path as user data
StdStrBuf template_path(grp.GetFullName());
ui.templateComboBox->addItem(QString(title.getData()), QString(template_path.getData()));
all_template_c4s.push_back(template_c4s);
// Add any extra definition (e.g. pointing into a scenario) to selection model
// "extra" definitions are those that use non-ocd-files anywhere in their path
auto c4s_defs = template_c4s.Definitions.GetModulesAsList();
for (const char *c4s_def : c4s_defs)
{
char c4s_def_component[_MAX_PATH + 1];
int32_t i = 0;
bool is_extra_def = false;
while (SCopySegment(c4s_def, i++, c4s_def_component, '\\', _MAX_PATH))
{
if (!WildcardMatch(C4CFN_DefFiles, c4s_def_component))
{
is_extra_def = true;
break;
}
}
if (is_extra_def)
{
def_file_model.AddExtraDef(c4s_def);
}
}
// Default selection
if (is_default) ui.templateComboBox->setCurrentIndex(ui.templateComboBox->count()-1);
}
@ -296,6 +390,20 @@ bool C4ConsoleQtNewScenarioDlg::IsHostAsNetwork() const
return ui.startInNetworkCheckbox->isChecked();
}
void C4ConsoleQtNewScenarioDlg::SelectedTemplateChanged(int new_selection)
{
// Update forced definition selection for template
if (new_selection >= 0 && new_selection < all_template_c4s.size())
{
const C4Scenario &template_c4s = all_template_c4s[new_selection];
def_file_model.SetForcedSelection(template_c4s.Definitions.GetModulesAsList());
}
else
{
def_file_model.SetForcedSelection(std::list<const char *>());
}
}
bool C4ConsoleQtNewScenarioDlg::CreateScenario()
{
// Try to create scenario from template. Unpack if necessery.
@ -339,11 +447,19 @@ bool C4ConsoleQtNewScenarioDlg::CreateScenario()
c4s.Game.Mode.Copy(ui.gameModeComboBox->currentText().toUtf8());
if (c4s.Game.Mode == "Undefined") c4s.Game.Mode.Clear();
filename.Copy(ui.filenameEdit->text().toUtf8());
std::list<const char *> definitions = def_file_model.GetSelectedDefinitions();
std::ostringstream definitions_join("");
std::list<const char *> definitions = def_file_model.GetUserSelectedDefinitions();
StdStrBuf forced_definitions;
c4s.Definitions.GetModules(&forced_definitions);
const char *forced_definitions_c = forced_definitions.getData();
std::ostringstream definitions_join(forced_definitions_c ? forced_definitions_c : nullptr, std::ostringstream::ate);
if (definitions.size())
{
// definitions_join = definitions.join(";")
if (forced_definitions.getLength())
{
// Combine both forced and user-selected definitions
definitions_join << ";";
}
auto iter_end = definitions.end();
std::copy(definitions.begin(), --iter_end, std::ostream_iterator<std::string>(definitions_join, ";"));
definitions_join << *iter_end;

View File

@ -34,7 +34,10 @@ class C4ConsoleQtDefinitionFileListModel : public QAbstractItemModel
public:
C4ConsoleQtDefinitionFileListModel();
~C4ConsoleQtDefinitionFileListModel();
void AddExtraDef(const char *def);
std::list<const char *> GetUserSelectedDefinitions() const;
std::list<const char *> GetSelectedDefinitions() const;
void SetForcedSelection(std::list<const char *> &defs);
private:
@ -46,7 +49,7 @@ private:
std::vector< std::unique_ptr<DefFileInfo> > children;
StdCopyStrBuf filename, root_path, full_filename;
bool was_opened, is_root;
bool selected, disabled;
bool user_selected, force_selected;
bool OpenGroup();
public:
@ -58,11 +61,15 @@ private:
int32_t GetChildIndex(const DefFileInfo *child);
const char *GetName() const { return filename.getData(); }
bool IsRoot() const { return is_root; }
void SetSelected(bool to_val);
bool IsSelected() const { return selected; }
void SetDisabled(bool to_val) { disabled = to_val; }
bool IsDisabled() const { return disabled; }
void SetSelected(bool to_val, bool forced);
bool IsUserSelected() const { return user_selected; }
bool IsForceSelected() const { return force_selected; }
bool IsSelected() const { return user_selected || force_selected; }
bool IsDisabled() const { return force_selected || (parent && parent->IsSelected()); }
void AddUserSelectedDefinitions(std::list<const char *> *result) const;
void AddSelectedDefinitions(std::list<const char *> *result) const;
void SetForcedSelection(const char *selected_def_filepath);
void AddExtraDef(const char *def);
};
mutable DefFileInfo root;
@ -85,6 +92,7 @@ class C4ConsoleQtNewScenarioDlg : public QDialog
StdCopyStrBuf filename;
bool has_custom_filename;
C4ConsoleQtDefinitionFileListModel def_file_model;
std::vector<C4Scenario> all_template_c4s;
public:
C4ConsoleQtNewScenarioDlg(class QMainWindow *parent_window);
@ -101,6 +109,7 @@ protected slots:
void CreatePressed();
void BrowsePressed();
void TitleChanged(const QString &new_title);
void SelectedTemplateChanged(int new_selection);
};
#endif // WITH_QT_EDITOR

View File

@ -419,7 +419,7 @@
<slot>CreatePressed()</slot>
<hints>
<hint type="sourcelabel">
<x>596</x>
<x>535</x>
<y>262</y>
</hint>
<hint type="destinationlabel">
@ -435,7 +435,7 @@
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>701</x>
<x>640</x>
<y>262</y>
</hint>
<hint type="destinationlabel">
@ -467,8 +467,8 @@
<slot>BrowsePressed()</slot>
<hints>
<hint type="sourcelabel">
<x>638</x>
<y>73</y>
<x>629</x>
<y>85</y>
</hint>
<hint type="destinationlabel">
<x>356</x>
@ -476,10 +476,27 @@
</hint>
</hints>
</connection>
<connection>
<sender>templateComboBox</sender>
<signal>currentIndexChanged(int)</signal>
<receiver>NewScenarioDialog</receiver>
<slot>SelectedTemplateChanged(int)</slot>
<hints>
<hint type="sourcelabel">
<x>486</x>
<y>131</y>
</hint>
<hint type="destinationlabel">
<x>325</x>
<y>138</y>
</hint>
</hints>
</connection>
</connections>
<slots>
<slot>CreatePressed()</slot>
<slot>TitleChanged(QString)</slot>
<slot>BrowsePressed()</slot>
<slot>SelectedTemplateChanged(int)</slot>
</slots>
</ui>

View File

@ -434,6 +434,23 @@ bool C4SDefinitions::GetModules(StdStrBuf *psOutModules) const
return true;
}
std::list<const char *> C4SDefinitions::GetModulesAsList() const
{
// get definitions as string pointers into this structure
std::list<const char *> result;
if (!LocalOnly)
{
for (const char *def : Definition)
{
if (*def)
{
result.push_back(def);
}
}
}
return result;
}
void C4SDefinitions::SetModules(const char *szList, const char *szRelativeToPath, const char *szRelativeToPath2)
{

View File

@ -94,6 +94,7 @@ public:
C4IDList SkipDefs;
void SetModules(const char *szList, const char *szRelativeToPath=nullptr, const char *szRelativeToPath2=nullptr);
bool GetModules(StdStrBuf *psOutModules) const;
std::list<const char *> GetModulesAsList() const; // get definitions as string pointers into this structure
void Default();
void CompileFunc(StdCompiler *pComp);