ControlWidget.cpp
Go to the documentation of this file.
1 #include "ControlWidget.h"
2 
3 #include <cmath>
4 #include <filesystem>
5 
6 #include <QFileDialog>
7 #include <QHBoxLayout>
8 #include <QPushButton>
9 #include <QSpacerItem>
10 
11 #include <SimoxUtility/algorithm/string/string_tools.h>
12 
14 
17 
19 {
20 
22  {
23  _latestDirectory = QString::fromStdString("/tmp/MemoryExport");
24 
25  _loadFromDiskButton = new QPushButton(" Load Query from Disk into WM", this);
26  _loadFromDiskButton->setIcon(QIcon(":/icons/document-open.svg"));
27  _storeOnDiskButton = new QPushButton(" Store shown Data on Disk", this);
28  _storeOnDiskButton->setIcon(QIcon(":/icons/document-save.svg"));
29 
30  // Allow horizontal shrinking of buttons
31  std::vector<QPushButton*> buttons{_storeOnDiskButton, _loadFromDiskButton};
32  for (QPushButton* button : buttons)
33  {
34  button->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Fixed);
35  }
36 
37  this->setSizePolicy(QSizePolicy::Policy::Preferred, QSizePolicy::Policy::Fixed);
38 
39  QHBoxLayout* layout = new QHBoxLayout();
40  this->setLayout(layout);
41 
42  const int margin = 0;
43  layout->setContentsMargins(margin, margin, margin, margin);
44 
45  layout->addWidget(_loadFromDiskButton);
46  layout->addWidget(_storeOnDiskButton);
47 
48 
49  // Connections
50 
51  connect(_loadFromDiskButton,
52  &QPushButton::pressed,
53  [this]()
54  {
55  QString directory = chooseDirectoryDialog();
56  if (directory.size() > 0)
57  {
58  emit requestedLoadFromDisk(directory);
59  }
60  });
61  connect(_storeOnDiskButton,
62  &QPushButton::pressed,
63  [this]()
64  {
65  QString directory = chooseDirectoryDialog();
66  if (directory.size() > 0)
67  {
68  emit requestedStoreOnDisk(directory);
69  }
70  });
71  }
72 
73  static const std::string&
74  handleSingular(int num, const std::string& singular, const std::string& plural)
75  {
76  return num == 1 ? singular : plural;
77  }
78 
79  void
80  ControlWidget::storeOnDisk(QString directory,
81  const std::vector<wm::Memory> memoryData,
82  std::string* outStatus)
83  {
84  std::filesystem::path path(directory.toUtf8().constData());
85  ARMARX_CHECK_POSITIVE(path.string().size()); // An empty path indicates an error.
86 
87  std::stringstream status;
88  if (std::filesystem::is_regular_file(path))
89  {
90  status << "Could not export memories contents to " << path
91  << ": Cannot overwrite existing file.";
92  }
93  else
94  {
95  int numStored = 0;
96  for (const auto& data : memoryData)
97  {
98  std::string name = data.id().memoryName;
99  if (std::filesystem::is_regular_file(path / name))
100  {
101  status << "Could not export memory '" << name << "' to " << path
102  << ": Cannot overwrite existing file.\n";
103  }
104  else
105  {
106  armem::server::ltm::Memory memory(path, "MemoryExport", name);
107  memory.directlyStore(data);
108 
109  numStored++;
110  }
111  }
112  status << "Exported " << numStored << " "
113  << handleSingular(numStored, "memory", "memories") << " to " << path << ".";
114  }
115 
116  if (outStatus)
117  {
118  *outStatus = status.str();
119  }
120  }
121 
122  std::map<std::filesystem::path, wm::Memory>
123  ControlWidget::loadFromDisk(QString directory,
124  const armem::client::QueryInput& _queryInput,
125  std::string* outStatus)
126  {
127  std::filesystem::path path(directory.toUtf8().constData());
128 
129  std::map<std::filesystem::path, wm::Memory> memoryData;
130 
131  auto setStatus = [&](const std::string& s)
132  {
133  if (outStatus)
134  {
135  *outStatus = s;
136  }
137  };
138 
139  if (not std::filesystem::is_directory(path))
140  {
141  setStatus("Could not import a memory from " + path.string() +
142  ". It is not a directory. Skipping import.");
143  return memoryData;
144  }
145 
146  // Find out whether this is a single memory or a collection of memories by searching
147  // for a data.aron.* or metadata.aron.* file at depth 5 (if 6 then it is collection of memories)
148  bool isSingleMemory = false;
149  for (auto i = std::filesystem::recursive_directory_iterator(path);
150  i != std::filesystem::recursive_directory_iterator();
151  ++i)
152  {
154  {
155  // After some depth we stop searching to not freeze GUI too long
156  setStatus("Could not import a memory from " + path.string() +
157  ". Data files were not found until max-depth 7. Skipping import.");
158  return memoryData;
159  }
160 
161  auto& dir = *i;
162 
163  // if one matches it is enough to check
164  if (std::filesystem::is_regular_file(dir.path()) &&
165  simox::alg::starts_with(dir.path().filename(), "data.aron"))
166  {
167  isSingleMemory = (i.depth() == armem::server::ltm::Memory::DEPTH_TO_DATA_FILES);
168  break;
169  }
170  }
171 
172  // TODO: Only add data that matches query?
173  // We use LTM as query target for the disk
174  // armem::client::QueryInput queryInput = _queryInput;
175  // queryInput.addQueryTargetToAll(armem::query::data::QueryTarget::LTM);
176  // const query::data::Input queryIce = queryInput.toIce();
177 
178  int numLoaded = 0;
179  auto loadMemory = [&](const std::filesystem::path& p)
180  {
181  if (std::filesystem::is_directory(p))
182  {
184  p.parent_path().parent_path(), "MemoryExport", p.filename());
186  ltm.loadAllAndResolve(); // load list of references and load data
187  memoryData[p] = std::move(memory);
188 
189  numLoaded++;
190  }
191  };
192 
193  if (isSingleMemory)
194  {
195  loadMemory(path);
196  }
197  else
198  {
199  // we have to load multiple memories (each subfolder)
200  for (const auto& dir : std::filesystem::directory_iterator(path))
201  {
202  loadMemory(dir.path());
203  }
204  }
205 
206  setStatus("Loaded " + std::to_string(numLoaded) + " " +
207  handleSingular(numLoaded, "memory", "memories") + " from " + path.string() + ".");
208  return memoryData;
209  }
210 
211  QString
212  ControlWidget::chooseDirectoryDialog()
213  {
214  _latestDirectory = QFileDialog::getExistingDirectory(this,
215  "Open query result",
216  _latestDirectory,
217  QFileDialog::ShowDirsOnly |
218  QFileDialog::DontResolveSymlinks);
219 
220  return _latestDirectory;
221  }
222 
223 } // namespace armarx::armem::gui::disk
armarx::armem::gui::disk::ControlWidget::storeOnDisk
void storeOnDisk(QString directory, const std::vector< wm::Memory > memoryData, std::string *outStatus=nullptr)
Definition: ControlWidget.cpp:80
armarx::armem::server::ltm::detail::mixin::DiskMemoryItemMixin::DEPTH_TO_DATA_FILES
static const int DEPTH_TO_DATA_FILES
Definition: DiskStorageMixin.h:63
armarx::armem::gui::disk::ControlWidget::requestedStoreOnDisk
void requestedStoreOnDisk(QString directory)
ltm.h
armarx::starts_with
bool starts_with(const std::string &haystack, const std::string &needle)
Definition: StringHelpers.cpp:47
ControlWidget.h
armarx::memory
Brief description of class memory.
Definition: memory.h:38
armarx::armem::server::ltm::Memory
A memory storing data on the hard drive and in mongodb (needs 'armarx memory start' to start the mong...
Definition: Memory.h:19
armarx::status
status
Definition: FiniteStateMachine.h:244
armarx::armem::gui::disk::ControlWidget::ControlWidget
ControlWidget()
Definition: ControlWidget.cpp:21
data
uint8_t data[1]
Definition: EtherCATFrame.h:68
armarx::armem::client::QueryInput
A query for parts of a memory.
Definition: Query.h:23
armarx::armem::wm::Memory
Client-side working memory.
Definition: memory_definitions.h:133
armarx::armem::server::ltm::detail::MemoryBase::loadAllAndResolve
armem::wm::Memory loadAllAndResolve()
return the full ltm as a wm::Memory and resolves the references the ltm may be huge,...
Definition: MemoryBase.h:213
ARMARX_CHECK_POSITIVE
#define ARMARX_CHECK_POSITIVE(number)
This macro evaluates whether number is positive (> 0) and if it turns out to be false it will throw a...
Definition: ExpressionException.h:145
armarx::to_string
const std::string & to_string(const std::string &s)
Definition: StringHelpers.h:41
ExpressionException.h
Memory.h
armarx::armem::gui::disk::ControlWidget::loadFromDisk
std::map< std::filesystem::path, wm::Memory > loadFromDisk(QString directory, const armem::client::QueryInput &queryInput, std::string *outStatus=nullptr)
Definition: ControlWidget.cpp:123
armarx::armem::gui::disk::ControlWidget::requestedLoadFromDisk
void requestedLoadFromDisk(QString directory)
armarx::ctrlutil::s
double s(double t, double s0, double v0, double a0, double j)
Definition: CtrlUtil.h:33
armarx::armem::gui::disk
Definition: ControlWidget.cpp:18