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