[glom] utils: Move some functions into layout_utils.



commit d136618ecd51e99a18e1635fbd52683f753dd8e3
Author: Murray Cumming <murrayc murrayc com>
Date:   Thu Mar 17 11:36:16 2016 +0100

    utils: Move some functions into layout_utils.

 CMakeLists.txt                                     |    2 +
 glom/libglom/db_utils_export.cc                    |    1 +
 glom/libglom/filelist.am                           |    3 +
 glom/libglom/layout_utils.cc                       |  328 ++++++++++++++++++++
 glom/libglom/layout_utils.h                        |   95 ++++++
 glom/libglom/utils.cc                              |  279 -----------------
 glom/libglom/utils.h                               |   59 ----
 glom/mode_data/box_data.cc                         |    1 +
 glom/mode_data/box_data_details.cc                 |    1 +
 glom/mode_data/box_data_list.cc                    |    1 +
 glom/mode_data/box_data_portal.cc                  |    1 +
 .../datawidget/combochoiceswithtreemodel.cc        |    2 +-
 .../layout/layout_item_dialogs/box_formatting.cc   |    1 +
 .../layout/layout_item_dialogs/dialog_group_by.cc  |    2 +-
 glom/print_layout/canvas_print_layout.cc           |    1 +
 15 files changed, 437 insertions(+), 340 deletions(-)
---
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5b7682a..0a76d74 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -252,6 +252,8 @@ set(SOURCE_FILES
         glom/libglom/standard_table_prefs_fields.h
         glom/libglom/translations_po.cc
         glom/libglom/translations_po.h
+        glom/libglom/layout_utils.cc
+        glom/libglom/layout_utils.h
         glom/libglom/file_utils.cc
         glom/libglom/file_utils.h
         glom/libglom/sql_utils.cc
diff --git a/glom/libglom/db_utils_export.cc b/glom/libglom/db_utils_export.cc
index 16d09d1..8afc023 100644
--- a/glom/libglom/db_utils_export.cc
+++ b/glom/libglom/db_utils_export.cc
@@ -21,6 +21,7 @@
 
 #include <libglom/db_utils_export.h>
 #include <libglom/db_utils.h>
+#include <libglom/layout_utils.h>
 #include <libglom/utils.h>
 #include <libglom/sql_utils.h>
 #include <libglom/algorithms_utils.h>
diff --git a/glom/libglom/filelist.am b/glom/libglom/filelist.am
index c19dc82..6243b49 100644
--- a/glom/libglom/filelist.am
+++ b/glom/libglom/filelist.am
@@ -27,6 +27,7 @@ libglom_toplevel_headers =                            \
        glom/libglom/utils.h                            \
        glom/libglom/db_utils.h \
        glom/libglom/db_utils_export.h \
+       glom/libglom/layout_utils.h \
        glom/libglom/sql_utils.h \
        glom/libglom/report_builder.h \
        glom/libglom/translations_po.h
@@ -111,6 +112,8 @@ libglom_sources =                                                   \
        glom/libglom/db_utils_export.h                                          \
        glom/libglom/file_utils.cc \
        glom/libglom/file_utils.h \
+       glom/libglom/layout_utils.cc \
+       glom/libglom/layout_utils.h \
        glom/libglom/glom_postgres.cc                                   \
        glom/libglom/glom_postgres.h                                    \
        glom/libglom/init.cc                                            \
diff --git a/glom/libglom/layout_utils.cc b/glom/libglom/layout_utils.cc
new file mode 100644
index 0000000..5933120
--- /dev/null
+++ b/glom/libglom/layout_utils.cc
@@ -0,0 +1,328 @@
+/* Glom
+ *
+ * Copyright (C) 2001-2016 Murray Cumming
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ */
+
+#include <libglom/layout_utils.h>
+#include <libglom/db_utils.h>
+#include <libglom/layout_utils.h>
+#include <libglom/privs.h>
+#include <libglom/connectionpool.h>
+#include <libglom/data_structure/layout/report_parts/layoutitem_fieldsummary.h>
+#include <libglom/data_structure/glomconversions.h>
+#include <libglom/string_utils.h>
+
+#include <giomm/file.h>
+#include <giomm/resource.h>
+#include <glibmm/convert.h>
+#include <glibmm/fileutils.h>
+#include <glibmm/miscutils.h>
+#include <glibmm/i18n.h>
+
+
+#include <string.h> // for strchr
+#include <sstream> //For stringstream
+
+#include <iostream>
+#include "utils.h"
+
+
+namespace Glom
+{
+
+Glib::ustring Utils::get_list_of_layout_items_for_display(const LayoutGroup::type_list_items& 
list_layout_fields)
+{
+  Glib::ustring result;
+  for(const auto& item : list_layout_fields)
+  {
+    if(item)
+    {
+      if(!result.empty())
+       result += ", ";
+
+      result += item->get_layout_display_name();
+    }
+  }
+
+  return result;
+}
+
+Glib::ustring Utils::get_list_of_layout_items_for_display(const std::shared_ptr<const LayoutGroup>& 
layout_group)
+{
+  if(layout_group)
+    return get_list_of_layout_items_for_display(layout_group->m_list_items);
+  else
+    return Glib::ustring();
+}
+
+Glib::ustring Utils::get_list_of_sort_fields_for_display(const Formatting::type_list_sort_fields& 
sort_fields)
+{
+  Glib::ustring text;
+  for(const auto& the_pair : sort_fields)
+  {
+    const auto item = the_pair.first;
+    if(!item)
+      continue;
+    
+    if(!text.empty())
+      text += ", ";
+
+    text += item->get_layout_display_name();
+    //TODO: Show Ascending/Descending?
+  }
+
+  return text;
+}
+
+LayoutGroup::type_list_const_items Utils::get_layout_items_plus_primary_key(const 
LayoutGroup::type_list_const_items& items, const std::shared_ptr<const Document>& document, const 
Glib::ustring& table_name)
+{
+  if(!document)
+  {
+    std::cerr << G_STRFUNC << ": document was null.\n";
+    return items;
+  }
+
+  const auto field_primary_key = document->get_field_primary_key(table_name);
+  if(!field_primary_key)
+  {
+    std::cerr << G_STRFUNC << ": Could not find the primary key.\n";
+    return items;
+  }
+
+  auto pk_layout_item = std::make_shared<LayoutItem_Field>();
+  pk_layout_item->set_hidden();
+  pk_layout_item->set_full_field_details(field_primary_key);
+  
+  if(find_if_layout_item_field_is_same_field_exists(items, pk_layout_item))
+    return items; //It is already in the list:
+
+  LayoutGroup::type_list_const_items items_plus_pk = items;
+  items_plus_pk.emplace_back(pk_layout_item);
+  return items_plus_pk;
+}
+
+//TODO: Avoid the horrible code duplication with the const version.
+LayoutGroup::type_list_items Utils::get_layout_items_plus_primary_key(const LayoutGroup::type_list_items& 
items, const std::shared_ptr<const Document>& document, const Glib::ustring& table_name)
+{
+  if(!document)
+  {
+    std::cerr << G_STRFUNC << ": document was null.\n";
+    return items;
+  }
+
+  const auto field_primary_key = document->get_field_primary_key(table_name);
+  if(!field_primary_key)
+  {
+    std::cerr << G_STRFUNC << ": Could not find the primary key.\n";
+    return items;
+  }
+
+  auto pk_layout_item = std::make_shared<LayoutItem_Field>();
+  pk_layout_item->set_hidden();
+  pk_layout_item->set_full_field_details(field_primary_key);
+  
+  if(find_if_layout_item_field_is_same_field_exists(items, pk_layout_item))
+    return items; //It is already in the list:
+
+  LayoutGroup::type_list_items items_plus_pk = items;
+  items_plus_pk.emplace_back(pk_layout_item);
+  return items_plus_pk;
+}
+
+namespace {
+
+static bool get_field_primary_key_index_for_fields(const Utils::type_vec_fields& fields, guint& field_column)
+{
+  //Initialize input parameter:
+  field_column = 0;
+
+  //TODO_performance: Cache the primary key?
+  guint col = 0;
+  guint cols_count = fields.size();
+  while(col < cols_count)
+  {
+    if(fields[col]->get_primary_key())
+    {
+      field_column = col;
+      return true;
+    }
+    else
+    {
+      ++col;
+    }
+  }
+
+  return false; //Not found.
+}
+
+static void get_table_fields_to_show_for_sequence_add_group(const std::shared_ptr<const Document>& document, 
const Glib::ustring& table_name, const Privileges& table_privs, const Utils::type_vec_fields& all_db_fields, 
const std::shared_ptr<LayoutGroup>& group, Utils::type_vecConstLayoutFields& vecFields)
+{
+  //g_warning("Box_Data::get_table_fields_to_show_for_sequence_add_group(): table_name=%s, 
all_db_fields.size()=%d, group->name=%s", table_name.c_str(), all_db_fields.size(), 
group->get_name().c_str());
+
+  for(const auto& item : group->get_items())
+  {
+    auto item_field = std::dynamic_pointer_cast<LayoutItem_Field>(item);
+    if(item_field)
+    {
+      //Get the field info:
+      const auto field_name = item->get_name();
+
+      if(item_field->get_has_relationship_name()) //If it's a field in a related table.
+      {
+        //TODO_Performance: get_fields_for_table_one_field() is probably very inefficient
+        auto field = DbUtils::get_fields_for_table_one_field(document, 
item_field->get_table_used(table_name), item->get_name());
+        if(field)
+        {
+          auto layout_item = item_field;
+          layout_item->set_full_field_details(field); //Fill in the full field information for later.
+
+
+          //TODO_Performance: We do this once for each related field, even if there are 2 from the same 
table:
+          const auto privs_related = Privs::get_current_privs(item_field->get_table_used(table_name));
+          layout_item->m_priv_view = privs_related.m_view;
+          layout_item->m_priv_edit = privs_related.m_edit;
+
+          vecFields.emplace_back(layout_item);
+        }
+        else
+        {
+          std::cerr << G_STRFUNC << ": related field not found: field=" << item->get_layout_display_name() 
<< std::endl;
+        }
+      }
+      else //It's a regular field in the table:
+      {
+        const auto iterFind = find_if_same_name(all_db_fields, field_name);
+
+        //If the field does not exist anymore then we won't try to show it:
+        if(iterFind != all_db_fields.end() )
+        {
+          auto layout_item = item_field;
+          layout_item->set_full_field_details(*iterFind); //Fill the LayoutItem with the full field 
information.
+
+          //std::cout << "debug: " << G_STRFUNC << ": name=" << layout_item->get_name() << std::endl;
+
+          //Prevent editing of the field if the user may not edit this table:
+          layout_item->m_priv_view = table_privs.m_view;
+          layout_item->m_priv_edit = table_privs.m_edit;
+
+          vecFields.emplace_back(layout_item);
+        }
+      }
+    }
+    else
+    {
+      auto item_group = std::dynamic_pointer_cast<LayoutGroup>(item);
+      if(item_group)
+      {
+        auto item_portal = std::dynamic_pointer_cast<LayoutItem_Portal>(item);
+        if(!item_portal) //Do not recurse into portals. They are filled by means of a separate SQL query.
+        {
+          //Recurse:
+          get_table_fields_to_show_for_sequence_add_group(document, table_name, table_privs, all_db_fields, 
item_group, vecFields);
+        }
+      }
+    }
+  }
+
+  if(vecFields.empty())
+  {
+    //std::cerr << G_STRFUNC << ": Returning empty list.\n";
+  }
+}
+
+} //anonymous namespace
+
+Utils::type_vecConstLayoutFields Utils::get_table_fields_to_show_for_sequence(const std::shared_ptr<const 
Document>& document, const Glib::ustring& table_name, const Document::type_list_layout_groups& 
mapGroupSequence)
+{
+  //Get field definitions from the database, with corrections from the document:
+  auto all_fields = DbUtils::get_fields_for_table(document, table_name);
+
+  const auto table_privs = Privs::get_current_privs(table_name);
+
+  //Get fields that the document says we should show:
+  type_vecConstLayoutFields result;
+  if(document)
+  {
+    if(mapGroupSequence.empty())
+    {
+      //No field sequence has been saved in the document, so we use all fields by default, so we start with 
something visible:
+
+      //Start with the Primary Key as the first field:
+      guint iPrimaryKey = 0;
+      bool bPrimaryKeyFound = get_field_primary_key_index_for_fields(all_fields, iPrimaryKey);
+      Glib::ustring primary_key_field_name;
+      if(bPrimaryKeyFound)
+      {
+        auto layout_item = std::make_shared<LayoutItem_Field>();
+        layout_item->set_full_field_details(all_fields[iPrimaryKey]);
+
+        //Don't use thousands separators with ID numbers:
+        layout_item->m_formatting.m_numeric_format.m_use_thousands_separator = false;
+
+        layout_item->set_editable(true); //A sensible default.
+
+        //Prevent editing of the field if the user may not edit this table:
+        layout_item->m_priv_view = table_privs.m_view;
+        layout_item->m_priv_edit = table_privs.m_edit;
+
+        result.emplace_back(layout_item);
+      }
+
+      //Add the rest:
+      for(const auto& field_info : all_fields)
+      {
+        if(field_info->get_name() != primary_key_field_name) //We already added the primary key.
+        {
+          auto layout_item = std::make_shared<LayoutItem_Field>();
+          layout_item->set_full_field_details(field_info);
+
+          layout_item->set_editable(true); //A sensible default.
+
+          //Prevent editing of the field if the user may not edit this table:
+          layout_item->m_priv_view = table_privs.m_view;
+          layout_item->m_priv_edit = table_privs.m_edit;
+
+          result.emplace_back(layout_item);
+        }
+      }
+    }
+    else
+    {
+      //We will show the fields that the document says we should:
+      for(const auto& group : mapGroupSequence)
+      {
+        if(true) //!group->get_hidden())
+        {
+          //Get the fields:
+          get_table_fields_to_show_for_sequence_add_group(document, table_name, table_privs, all_fields, 
group, result);
+        }
+      }
+    }
+  }
+
+  if(result.empty())
+  {
+    //std::cerr << G_STRFUNC << ": Returning empty list.\n";
+  }
+
+  return result;
+}
+
+
+
+} //namespace Glom
diff --git a/glom/libglom/layout_utils.h b/glom/libglom/layout_utils.h
new file mode 100644
index 0000000..cd57ad6
--- /dev/null
+++ b/glom/libglom/layout_utils.h
@@ -0,0 +1,95 @@
+/* Glom
+ *
+ * Copyright (C) 2001-2016 Murray Cumming
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ */
+
+#ifndef GLOM_LAYOUT_UTILS_H
+#define GLOM_LAYOUT_UTILS_H
+
+#include <libglom/document/document.h>
+#include <libglom/data_structure/layout/layoutitem_field.h>
+#include <libglom/algorithms_utils.h>
+
+namespace Glom
+{
+
+namespace Utils
+{
+
+typedef std::vector< std::shared_ptr<const LayoutItem_Field> > type_vecConstLayoutFields;
+typedef std::vector< std::shared_ptr<Field> > type_vec_fields;
+
+/** Get a string to display to the user, as a representation of a list of layout items.
+ */
+Glib::ustring get_list_of_layout_items_for_display(const LayoutGroup::type_list_items& list_layout_fields);
+
+/** Get a string to display to the user, as a representation of a list of layout items.
+ */
+Glib::ustring get_list_of_layout_items_for_display(const std::shared_ptr<const LayoutGroup>& layout_group);
+
+/** Get a string to display to the user, as a representation of a sort order
+ */
+Glib::ustring get_list_of_sort_fields_for_display(const Formatting::type_list_sort_fields& sort_fields);
+
+/** This returns the provided list of layout items,
+ * plus the primary key, if the primary key is not already present in the list
+ */
+LayoutGroup::type_list_const_items get_layout_items_plus_primary_key(const 
LayoutGroup::type_list_const_items& items, const std::shared_ptr<const Document>& document, const 
Glib::ustring& table_name);
+
+//TODO: Avoid the overload just for constness.
+/** This returns the provided list of layout items,
+ * plus the primary key, if the primary key is not already present in the list
+ */
+LayoutGroup::type_list_items get_layout_items_plus_primary_key(const LayoutGroup::type_list_items& items, 
const std::shared_ptr<const Document>& document, const Glib::ustring& table_name);
+
+type_vecConstLayoutFields get_table_fields_to_show_for_sequence(const std::shared_ptr<const Document>& 
document, const Glib::ustring& table_name, const Document::type_list_layout_groups& mapGroupSequence);
+
+
+/**
+ * Find the element in the container which is a LayoutItem_Field which refers
+ * to the same field, without comparing irrelevant stuff such as formatting.
+ * This assumes that the element is a shared_ptr<>.
+ */
+template
+        <typename T_Container>
+bool find_if_layout_item_field_is_same_field_exists(T_Container& container, const std::shared_ptr<const 
LayoutItem_Field>& layout_item)
+{
+  return Utils::find_if_exists(container,
+                               [&layout_item](const typename T_Container::value_type& element)
+                               {
+                                 //Assume that element is a shared_ptr<>.
+
+                                 if(!layout_item && !element)
+                                   return true;
+
+                                 //Allow this to be used on a container of LayoutItems,
+                                 //as well as just of LayoutItem_Fields.
+                                 const auto element_field = std::dynamic_pointer_cast<const 
LayoutItem_Field>(element);
+                                 if(!element_field)
+                                   return false;
+
+                                 return layout_item && layout_item->is_same_field(element_field);
+                               }
+  );
+}
+
+} //namespace Utils
+
+} //namespace Glom
+
+#endif //GLOM_LAYOUT_UTILS_H
diff --git a/glom/libglom/utils.cc b/glom/libglom/utils.cc
index 702a78d..a177390 100644
--- a/glom/libglom/utils.cc
+++ b/glom/libglom/utils.cc
@@ -24,7 +24,6 @@
 #include <libglom/db_utils.h>
 #include <libglom/privs.h>
 #include <libglom/connectionpool.h>
-#include <libglom/data_structure/layout/report_parts/layoutitem_fieldsummary.h>
 #include <libglom/data_structure/glomconversions.h>
 #include <libglom/string_utils.h>
 
@@ -119,284 +118,6 @@ Glib::ustring Utils::locale_language_id(const Glib::ustring& locale_id)
   }
 }
 
-Glib::ustring Utils::get_list_of_layout_items_for_display(const LayoutGroup::type_list_items& 
list_layout_fields)
-{
-  Glib::ustring result;
-  for(const auto& item : list_layout_fields)
-  {
-    if(item)
-    {
-      if(!result.empty())
-       result += ", ";
-
-      result += item->get_layout_display_name();
-    }
-  }
-
-  return result;
-}
-
-Glib::ustring Utils::get_list_of_layout_items_for_display(const std::shared_ptr<const LayoutGroup>& 
layout_group)
-{
-  if(layout_group)
-    return get_list_of_layout_items_for_display(layout_group->m_list_items);
-  else
-    return Glib::ustring();
-}
-
-Glib::ustring Utils::get_list_of_sort_fields_for_display(const Formatting::type_list_sort_fields& 
sort_fields)
-{
-  Glib::ustring text;
-  for(const auto& the_pair : sort_fields)
-  {
-    const auto item = the_pair.first;
-    if(!item)
-      continue;
-    
-    if(!text.empty())
-      text += ", ";
-
-    text += item->get_layout_display_name();
-    //TODO: Show Ascending/Descending?
-  }
-
-  return text;
-}
-
-LayoutGroup::type_list_const_items Utils::get_layout_items_plus_primary_key(const 
LayoutGroup::type_list_const_items& items, const std::shared_ptr<const Document>& document, const 
Glib::ustring& table_name)
-{
-  if(!document)
-  {
-    std::cerr << G_STRFUNC << ": document was null.\n";
-    return items;
-  }
-
-  const auto field_primary_key = document->get_field_primary_key(table_name);
-  if(!field_primary_key)
-  {
-    std::cerr << G_STRFUNC << ": Could not find the primary key.\n";
-    return items;
-  }
-
-  auto pk_layout_item = std::make_shared<LayoutItem_Field>();
-  pk_layout_item->set_hidden();
-  pk_layout_item->set_full_field_details(field_primary_key);
-  
-  if(find_if_layout_item_field_is_same_field_exists(items, pk_layout_item))
-    return items; //It is already in the list:
-
-  LayoutGroup::type_list_const_items items_plus_pk = items;
-  items_plus_pk.emplace_back(pk_layout_item);
-  return items_plus_pk;
-}
-
-//TODO: Avoid the horrible code duplication with the const version.
-LayoutGroup::type_list_items Utils::get_layout_items_plus_primary_key(const LayoutGroup::type_list_items& 
items, const std::shared_ptr<const Document>& document, const Glib::ustring& table_name)
-{
-  if(!document)
-  {
-    std::cerr << G_STRFUNC << ": document was null.\n";
-    return items;
-  }
-
-  const auto field_primary_key = document->get_field_primary_key(table_name);
-  if(!field_primary_key)
-  {
-    std::cerr << G_STRFUNC << ": Could not find the primary key.\n";
-    return items;
-  }
-
-  auto pk_layout_item = std::make_shared<LayoutItem_Field>();
-  pk_layout_item->set_hidden();
-  pk_layout_item->set_full_field_details(field_primary_key);
-  
-  if(find_if_layout_item_field_is_same_field_exists(items, pk_layout_item))
-    return items; //It is already in the list:
-
-  LayoutGroup::type_list_items items_plus_pk = items;
-  items_plus_pk.emplace_back(pk_layout_item);
-  return items_plus_pk;
-}
-
-namespace {
-
-static bool get_field_primary_key_index_for_fields(const Utils::type_vec_fields& fields, guint& field_column)
-{
-  //Initialize input parameter:
-  field_column = 0;
-
-  //TODO_performance: Cache the primary key?
-  guint col = 0;
-  guint cols_count = fields.size();
-  while(col < cols_count)
-  {
-    if(fields[col]->get_primary_key())
-    {
-      field_column = col;
-      return true;
-    }
-    else
-    {
-      ++col;
-    }
-  }
-
-  return false; //Not found.
-}
-
-static void get_table_fields_to_show_for_sequence_add_group(const std::shared_ptr<const Document>& document, 
const Glib::ustring& table_name, const Privileges& table_privs, const Utils::type_vec_fields& all_db_fields, 
const std::shared_ptr<LayoutGroup>& group, Utils::type_vecConstLayoutFields& vecFields)
-{
-  //g_warning("Box_Data::get_table_fields_to_show_for_sequence_add_group(): table_name=%s, 
all_db_fields.size()=%d, group->name=%s", table_name.c_str(), all_db_fields.size(), 
group->get_name().c_str());
-
-  for(const auto& item : group->get_items())
-  {
-    auto item_field = std::dynamic_pointer_cast<LayoutItem_Field>(item);
-    if(item_field)
-    {
-      //Get the field info:
-      const auto field_name = item->get_name();
-
-      if(item_field->get_has_relationship_name()) //If it's a field in a related table.
-      {
-        //TODO_Performance: get_fields_for_table_one_field() is probably very inefficient
-        auto field = DbUtils::get_fields_for_table_one_field(document, 
item_field->get_table_used(table_name), item->get_name());
-        if(field)
-        {
-          auto layout_item = item_field;
-          layout_item->set_full_field_details(field); //Fill in the full field information for later.
-
-
-          //TODO_Performance: We do this once for each related field, even if there are 2 from the same 
table:
-          const auto privs_related = Privs::get_current_privs(item_field->get_table_used(table_name));
-          layout_item->m_priv_view = privs_related.m_view;
-          layout_item->m_priv_edit = privs_related.m_edit;
-
-          vecFields.emplace_back(layout_item);
-        }
-        else
-        {
-          std::cerr << G_STRFUNC << ": related field not found: field=" << item->get_layout_display_name() 
<< std::endl;
-        }
-      }
-      else //It's a regular field in the table:
-      {
-        const auto iterFind = find_if_same_name(all_db_fields, field_name);
-
-        //If the field does not exist anymore then we won't try to show it:
-        if(iterFind != all_db_fields.end() )
-        {
-          auto layout_item = item_field;
-          layout_item->set_full_field_details(*iterFind); //Fill the LayoutItem with the full field 
information.
-
-          //std::cout << "debug: " << G_STRFUNC << ": name=" << layout_item->get_name() << std::endl;
-
-          //Prevent editing of the field if the user may not edit this table:
-          layout_item->m_priv_view = table_privs.m_view;
-          layout_item->m_priv_edit = table_privs.m_edit;
-
-          vecFields.emplace_back(layout_item);
-        }
-      }
-    }
-    else
-    {
-      auto item_group = std::dynamic_pointer_cast<LayoutGroup>(item);
-      if(item_group)
-      {
-        auto item_portal = std::dynamic_pointer_cast<LayoutItem_Portal>(item);
-        if(!item_portal) //Do not recurse into portals. They are filled by means of a separate SQL query.
-        {
-          //Recurse:
-          get_table_fields_to_show_for_sequence_add_group(document, table_name, table_privs, all_db_fields, 
item_group, vecFields);
-        }
-      }
-    }
-  }
-
-  if(vecFields.empty())
-  {
-    //std::cerr << G_STRFUNC << ": Returning empty list.\n";
-  }
-}
-
-} //anonymous namespace
-
-Utils::type_vecConstLayoutFields Utils::get_table_fields_to_show_for_sequence(const std::shared_ptr<const 
Document>& document, const Glib::ustring& table_name, const Document::type_list_layout_groups& 
mapGroupSequence)
-{
-  //Get field definitions from the database, with corrections from the document:
-  auto all_fields = DbUtils::get_fields_for_table(document, table_name);
-
-  const auto table_privs = Privs::get_current_privs(table_name);
-
-  //Get fields that the document says we should show:
-  type_vecConstLayoutFields result;
-  if(document)
-  {
-    if(mapGroupSequence.empty())
-    {
-      //No field sequence has been saved in the document, so we use all fields by default, so we start with 
something visible:
-
-      //Start with the Primary Key as the first field:
-      guint iPrimaryKey = 0;
-      bool bPrimaryKeyFound = get_field_primary_key_index_for_fields(all_fields, iPrimaryKey);
-      Glib::ustring primary_key_field_name;
-      if(bPrimaryKeyFound)
-      {
-        auto layout_item = std::make_shared<LayoutItem_Field>();
-        layout_item->set_full_field_details(all_fields[iPrimaryKey]);
-
-        //Don't use thousands separators with ID numbers:
-        layout_item->m_formatting.m_numeric_format.m_use_thousands_separator = false;
-
-        layout_item->set_editable(true); //A sensible default.
-
-        //Prevent editing of the field if the user may not edit this table:
-        layout_item->m_priv_view = table_privs.m_view;
-        layout_item->m_priv_edit = table_privs.m_edit;
-
-        result.emplace_back(layout_item);
-      }
-
-      //Add the rest:
-      for(const auto& field_info : all_fields)
-      {
-        if(field_info->get_name() != primary_key_field_name) //We already added the primary key.
-        {
-          auto layout_item = std::make_shared<LayoutItem_Field>();
-          layout_item->set_full_field_details(field_info);
-
-          layout_item->set_editable(true); //A sensible default.
-
-          //Prevent editing of the field if the user may not edit this table:
-          layout_item->m_priv_view = table_privs.m_view;
-          layout_item->m_priv_edit = table_privs.m_edit;
-
-          result.emplace_back(layout_item);
-        }
-      }
-    }
-    else
-    {
-      //We will show the fields that the document says we should:
-      for(const auto& group : mapGroupSequence)
-      {
-        if(true) //!group->get_hidden())
-        {
-          //Get the fields:
-          get_table_fields_to_show_for_sequence_add_group(document, table_name, table_privs, all_fields, 
group, result);
-        }
-      }
-    }
-  }
-
-  if(result.empty())
-  {
-    //std::cerr << G_STRFUNC << ": Returning empty list.\n";
-  }
-
-  return result;
-}
-
 bool Utils::script_check_for_pygtk2(const Glib::ustring& script)
 {
   //There is probably other code that this will not catch,
diff --git a/glom/libglom/utils.h b/glom/libglom/utils.h
index f73b637..1b9101a 100644
--- a/glom/libglom/utils.h
+++ b/glom/libglom/utils.h
@@ -35,10 +35,6 @@ namespace Glom
 namespace Utils
 {
 
-typedef std::vector< std::shared_ptr<const LayoutItem_Field> > type_vecConstLayoutFields;
-typedef std::vector< std::shared_ptr<Field> > type_vec_fields;
-
-
 /** Get just the first part of a locale, such as de_DE,
  * ignoring, for instance, .UTF-8 or \ euro at the end.
  */
@@ -49,32 +45,6 @@ Glib::ustring locale_simplify(const Glib::ustring& locale_id);
 Glib::ustring locale_language_id(const Glib::ustring& locale_id);
 
 
-/** Get a string to display to the user, as a representation of a list of layout items.
- */
-Glib::ustring get_list_of_layout_items_for_display(const LayoutGroup::type_list_items& list_layout_fields);
-
-/** Get a string to display to the user, as a representation of a list of layout items.
- */
-Glib::ustring get_list_of_layout_items_for_display(const std::shared_ptr<const LayoutGroup>& layout_group);
-
-/** Get a string to display to the user, as a representation of a sort order
- */
-Glib::ustring get_list_of_sort_fields_for_display(const Formatting::type_list_sort_fields& sort_fields);
-
-/** This returns the provided list of layout items,
- * plus the primary key, if the primary key is not already present in the list
- */
-LayoutGroup::type_list_const_items get_layout_items_plus_primary_key(const 
LayoutGroup::type_list_const_items& items, const std::shared_ptr<const Document>& document, const 
Glib::ustring& table_name);
-
-//TODO: Avoid the overload just for constness.
-/** This returns the provided list of layout items,
- * plus the primary key, if the primary key is not already present in the list
- */
-LayoutGroup::type_list_items get_layout_items_plus_primary_key(const LayoutGroup::type_list_items& items, 
const std::shared_ptr<const Document>& document, const Glib::ustring& table_name);
-
-type_vecConstLayoutFields get_table_fields_to_show_for_sequence(const std::shared_ptr<const Document>& 
document, const Glib::ustring& table_name, const Document::type_list_layout_groups& mapGroupSequence);
-
-
 /** @returns true if the script is OK, or 
  * false if the script uses pygtk2, which would cause a crash,
  * because Glom itself uses GTK+ 3.
@@ -95,35 +65,6 @@ to_utype(E enumerator) noexcept
   return static_cast<typename std::underlying_type<E>::type>(enumerator);
 }
 
-
-/**
- * Find the element in the container which is a LayoutItem_Field which refers 
- * to the same field, without comparing irrelevant stuff such as formatting.
- * This assumes that the element is a shared_ptr<>.
- */
-template
-<typename T_Container>
-bool find_if_layout_item_field_is_same_field_exists(T_Container& container, const std::shared_ptr<const 
LayoutItem_Field>& layout_item)
-{
-  return Utils::find_if_exists(container,
-    [&layout_item](const typename T_Container::value_type& element)
-    {
-      //Assume that element is a shared_ptr<>.
-
-      if(!layout_item && !element)
-        return true;
-
-      //Allow this to be used on a container of LayoutItems,
-      //as well as just of LayoutItem_Fields.
-      const auto element_field = std::dynamic_pointer_cast<const LayoutItem_Field>(element);
-      if(!element_field)
-        return false;
-
-      return layout_item && layout_item->is_same_field(element_field);
-    }
-  );
-}
-
 } //namespace Utils
 
 } //namespace Glom
diff --git a/glom/mode_data/box_data.cc b/glom/mode_data/box_data.cc
index 761114b..6789bf5 100644
--- a/glom/mode_data/box_data.cc
+++ b/glom/mode_data/box_data.cc
@@ -25,6 +25,7 @@
 #include <glom/utils_ui.h>
 #include <libglom/data_structure/layout/layoutitem_field.h>
 #include <libglom/db_utils.h>
+#include <libglom/layout_utils.h>
 #include <libglom/privs.h>
 #include <glom/python_embed/glom_python.h>
 #include <glom/python_embed/python_ui_callbacks.h>
diff --git a/glom/mode_data/box_data_details.cc b/glom/mode_data/box_data_details.cc
index 2a1d1c3..2f25a51 100644
--- a/glom/mode_data/box_data_details.cc
+++ b/glom/mode_data/box_data_details.cc
@@ -26,6 +26,7 @@
 #include <libglom/data_structure/relationship.h>
 #include <libglom/data_structure/glomconversions.h>
 #include <libglom/db_utils.h>
+#include <libglom/layout_utils.h>
 #include <libglom/sql_utils.h>
 #include <libglom/utils.h>
 #include <glom/mode_design/layout/dialog_layout_details.h>
diff --git a/glom/mode_data/box_data_list.cc b/glom/mode_data/box_data_list.cc
index 8011736..8de252c 100644
--- a/glom/mode_data/box_data_list.cc
+++ b/glom/mode_data/box_data_list.cc
@@ -24,6 +24,7 @@
 #include <glom/mode_design/layout/dialog_layout_list.h>
 #include <libglom/privs.h>
 #include <libglom/db_utils.h>
+#include <libglom/layout_utils.h>
 #include <libglom/utils.h> //For bold_message()).
 #include <sstream> //For stringstream
 #include <glibmm/main.h>
diff --git a/glom/mode_data/box_data_portal.cc b/glom/mode_data/box_data_portal.cc
index cd32a2c..92e0bd8 100644
--- a/glom/mode_data/box_data_portal.cc
+++ b/glom/mode_data/box_data_portal.cc
@@ -23,6 +23,7 @@
 #include <libglom/db_utils.h>
 #include <libglom/sql_utils.h>
 #include <libglom/utils.h>
+#include <libglom/layout_utils.h>
 #include <glom/glade_utils.h>
 #include <glom/frame_glom.h> //For show_ok_dialog()
 #include <glom/utils_ui.h> //For bold_message()).
diff --git a/glom/mode_data/datawidget/combochoiceswithtreemodel.cc 
b/glom/mode_data/datawidget/combochoiceswithtreemodel.cc
index 9c67490..61bb884 100644
--- a/glom/mode_data/datawidget/combochoiceswithtreemodel.cc
+++ b/glom/mode_data/datawidget/combochoiceswithtreemodel.cc
@@ -22,6 +22,7 @@
 #include <glom/mode_data/datawidget/treemodel_db_withextratext.h>
 #include <libglom/data_structure/glomconversions.h>
 #include <libglom/privs.h>
+#include <libglom/layout_utils.h>
 #include <libglom/sql_utils.h>
 #include <libglom/utils.h>
 #include <glom/utils_ui.h>
@@ -34,7 +35,6 @@
 #include <ctime>     // for struct tm
 #include <iostream>   // for cout, endl
 
-
 namespace Glom
 {
 
diff --git a/glom/mode_design/layout/layout_item_dialogs/box_formatting.cc 
b/glom/mode_design/layout/layout_item_dialogs/box_formatting.cc
index 495b474..4d0772b 100644
--- a/glom/mode_design/layout/layout_item_dialogs/box_formatting.cc
+++ b/glom/mode_design/layout/layout_item_dialogs/box_formatting.cc
@@ -25,6 +25,7 @@
 #include <libglom/data_structure/glomconversions.h>
 #include <glom/mode_design/layout/layout_item_dialogs/dialog_fieldslist.h>
 #include <libglom/utils.h>
+#include <libglom/layout_utils.h>
 #include <glibmm/i18n.h>
 
 namespace Glom
diff --git a/glom/mode_design/layout/layout_item_dialogs/dialog_group_by.cc 
b/glom/mode_design/layout/layout_item_dialogs/dialog_group_by.cc
index 49448ea..bbd6569 100644
--- a/glom/mode_design/layout/layout_item_dialogs/dialog_group_by.cc
+++ b/glom/mode_design/layout/layout_item_dialogs/dialog_group_by.cc
@@ -21,7 +21,7 @@
 #include <glom/mode_design/layout/layout_item_dialogs/dialog_group_by.h>
 #include <glom/utils_ui.h>
 #include <glom/glade_utils.h>
-#include <libglom/utils.h>
+#include <libglom/layout_utils.h>
 #include <sstream> //For stringstream
 #include <glibmm/i18n.h>
 
diff --git a/glom/print_layout/canvas_print_layout.cc b/glom/print_layout/canvas_print_layout.cc
index bf9196e..bb2f763 100644
--- a/glom/print_layout/canvas_print_layout.cc
+++ b/glom/print_layout/canvas_print_layout.cc
@@ -33,6 +33,7 @@
 #include <glom/appwindow.h>
 #include <libglom/data_structure/glomconversions.h>
 #include <libglom/db_utils.h>
+#include <libglom/layout_utils.h>
 #include <libglom/sql_utils.h>
 #include <libglom/utils.h>
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]