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 
20 
22 {
23 
25  {
26  _latestDirectory = QString::fromStdString("/tmp/MemoryExport");
27 
28  _loadFromDiskButton = new QPushButton(" Load Query from Disk into WM", this);
29  _loadFromDiskButton->setIcon(QIcon(":/icons/document-open.svg"));
30  _storeOnDiskButton = new QPushButton(" Store shown Data on Disk", this);
31  _storeOnDiskButton->setIcon(QIcon(":/icons/document-save.svg"));
32 
33  // Allow horizontal shrinking of buttons
34  std::vector<QPushButton*> buttons{_storeOnDiskButton, _loadFromDiskButton};
35  for (QPushButton* button : buttons)
36  {
37  button->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Fixed);
38  }
39 
40  this->setSizePolicy(QSizePolicy::Policy::Preferred, QSizePolicy::Policy::Fixed);
41 
42  QHBoxLayout* layout = new QHBoxLayout();
43  this->setLayout(layout);
44 
45  const int margin = 0;
46  layout->setContentsMargins(margin, margin, margin, margin);
47 
48  layout->addWidget(_loadFromDiskButton);
49  layout->addWidget(_storeOnDiskButton);
50 
51 
52  // Connections
53 
54  connect(_loadFromDiskButton,
55  &QPushButton::pressed,
56  [this]()
57  {
58  QString directory = chooseDirectoryDialog();
59  if (directory.size() > 0)
60  {
61  emit requestedLoadFromDisk(directory);
62  }
63  });
64  connect(_storeOnDiskButton,
65  &QPushButton::pressed,
66  [this]()
67  {
68  QString directory = chooseDirectoryDialog();
69  if (directory.size() > 0)
70  {
71  emit requestedStoreOnDisk(directory);
72  }
73  });
74  }
75 
76  static const std::string&
77  handleSingular(int num, const std::string& singular, const std::string& plural)
78  {
79  return num == 1 ? singular : plural;
80  }
81 
82  void
83  ControlWidget::storeOnDisk(QString directory,
84  const std::vector<wm::Memory> memoryData,
85  std::string* outStatus)
86  {
87  std::filesystem::path path(directory.toUtf8().constData());
88  ARMARX_CHECK_POSITIVE(path.string().size()); // An empty path indicates an error.
89 
90  std::stringstream status;
91  if (std::filesystem::is_regular_file(path))
92  {
93  status << "Could not export memories contents to " << path
94  << ": Cannot overwrite existing file.";
95  }
96  else
97  {
98  int numStored = 0;
99  for (const auto& data : memoryData)
100  {
101  std::string name = data.id().memoryName;
102  if (std::filesystem::is_regular_file(path / name))
103  {
104  status << "Could not export memory '" << name << "' to " << path
105  << ": Cannot overwrite existing file.\n";
106  }
107  else
108  {
109  std::string defaultIdent = "DefaultDisk";
110  std::string exportName = "MemoryExport";
111  std::shared_ptr<armem::server::ltm::persistence::DiskPersistence> diskPersistence = std::make_shared<armem::server::ltm::persistence::DiskPersistence>(defaultIdent, exportName, path);
112 
113  armem::server::ltm::Memory memory(exportName, name);
114 
115  if (memory.getPersistenceStrategy())
116  {
117  memory.getPersistenceStrategy()->addStrategy(diskPersistence);
118  }
119  else
120  {
121  std::shared_ptr<armem::server::ltm::persistence::RedundantPersistenceStrategy> redundantPersistence = std::make_shared<armem::server::ltm::persistence::RedundantPersistenceStrategy>();
122 
123  memory.setPersistenceStrategy(redundantPersistence);
124  memory.getPersistenceStrategy()->addStrategy(diskPersistence);
125  }
126 
127  memory.directlyStore(data);
128 
129  numStored++;
130  }
131  }
132  status << "Exported " << numStored << " "
133  << handleSingular(numStored, "memory", "memories") << " to " << path << ".";
134  }
135 
136  if (outStatus)
137  {
138  *outStatus = status.str();
139  }
140  }
141 
142  std::map<std::filesystem::path, wm::Memory>
143  ControlWidget::loadFromDisk(QString directory,
144  const armem::client::QueryInput& _queryInput,
145  std::string* outStatus)
146  {
147  std::filesystem::path path(directory.toUtf8().constData());
148 
149  std::map<std::filesystem::path, wm::Memory> memoryData;
150 
151  auto setStatus = [&](const std::string& s)
152  {
153  if (outStatus)
154  {
155  *outStatus = s;
156  }
157  };
158 
159  if (not std::filesystem::is_directory(path))
160  {
161  setStatus("Could not import a memory from " + path.string() +
162  ". It is not a directory. Skipping import.");
163  return memoryData;
164  }
165 
166  // Find out whether this is a single memory or a collection of memories by searching
167  // for a data.aron.* or metadata.aron.* file at depth 5 (if 6 then it is collection of memories)
168  bool isSingleMemory = false;
169  for (auto i = std::filesystem::recursive_directory_iterator(path);
170  i != std::filesystem::recursive_directory_iterator();
171  ++i)
172  {
174  {
175  // After some depth we stop searching to not freeze GUI too long
176  setStatus("Could not import a memory from " + path.string() +
177  ". Data files were not found until max-depth 7. Skipping import.");
178  return memoryData;
179  }
180 
181  auto& dir = *i;
182 
183  // if one matches it is enough to check
184  if (std::filesystem::is_regular_file(dir.path()) &&
185  simox::alg::starts_with(dir.path().filename(), "data.aron"))
186  {
188  break;
189  }
190  }
191 
192  // TODO: Only add data that matches query?
193  // We use LTM as query target for the disk
194  // armem::client::QueryInput queryInput = _queryInput;
195  // queryInput.addQueryTargetToAll(armem::query::data::QueryTarget::LTM);
196  // const query::data::Input queryIce = queryInput.toIce();
197 
198  int numLoaded = 0;
199  auto loadMemory = [&](const std::filesystem::path& p)
200  {
201  if (std::filesystem::is_directory(p))
202  {
203  std::string defaultIdent = "DefaultDisk";
204  std::string exportName = "MemoryExport";
205  std::shared_ptr<armem::server::ltm::persistence::DiskPersistence> diskPersistence = std::make_shared<armem::server::ltm::persistence::DiskPersistence>(defaultIdent, exportName, p.parent_path().parent_path());
206 
207  armem::server::ltm::Memory ltm(exportName, p.filename());
208  if (ltm.getPersistenceStrategy())
209  {
210  ltm.getPersistenceStrategy()->addStrategy(diskPersistence);
211  }
212  else
213  {
214  std::shared_ptr<armem::server::ltm::persistence::RedundantPersistenceStrategy> redundantPersistence = std::make_shared<armem::server::ltm::persistence::RedundantPersistenceStrategy>();
215 
216  ltm.setPersistenceStrategy(redundantPersistence);
217  ltm.getPersistenceStrategy()->addStrategy(diskPersistence);
218  }
219 
221  ltm.loadAllAndResolve(); // load list of references and load data
222  memoryData[p] = std::move(memory);
223 
224  numLoaded++;
225  }
226  };
227 
228  if (isSingleMemory)
229  {
230  loadMemory(path);
231  }
232  else
233  {
234  // we have to load multiple memories (each subfolder)
235  for (const auto& dir : std::filesystem::directory_iterator(path))
236  {
237  loadMemory(dir.path());
238  }
239  }
240 
241  setStatus("Loaded " + std::to_string(numLoaded) + " " +
242  handleSingular(numLoaded, "memory", "memories") + " from " + path.string() + ".");
243  return memoryData;
244  }
245 
246  QString
247  ControlWidget::chooseDirectoryDialog()
248  {
249  _latestDirectory = QFileDialog::getExistingDirectory(this,
250  "Open query result",
251  _latestDirectory,
252  QFileDialog::ShowDirsOnly |
253  QFileDialog::DontResolveSymlinks);
254 
255  return _latestDirectory;
256  }
257 
258 } // 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:83
MemoryPersistenceStrategy.h
armarx::armem::server::ltm::Memory::setPersistenceStrategy
void setPersistenceStrategy(std::shared_ptr< persistence::RedundantPersistenceStrategy > persistenceStrategy)
Definition: Memory.h:59
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::getPersistenceStrategy
std::shared_ptr< persistence::RedundantPersistenceStrategy > getPersistenceStrategy() const
Definition: Memory.h:66
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:20
armarx::status
status
Definition: FiniteStateMachine.h:244
armarx::armem::gui::disk::ControlWidget::ControlWidget
ControlWidget()
Definition: ControlWidget.cpp:24
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::persistence::MemoryPersistenceStrategy::DEPTH_TO_DATA_FILES
static const int DEPTH_TO_DATA_FILES
Definition: MemoryPersistenceStrategy.h:189
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:143
armarx::armem::gui::disk::ControlWidget::requestedLoadFromDisk
void requestedLoadFromDisk(QString directory)
DiskPersistence.h
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:21