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