ACloudViewer  3.9.4
A Modern Library for 3D Data Processing
ecvSettingManager.cpp
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // - CloudViewer: www.cloudViewer.org -
3 // ----------------------------------------------------------------------------
4 // Copyright (c) 2018-2024 www.cloudViewer.org
5 // SPDX-License-Identifier: MIT
6 // ----------------------------------------------------------------------------
7 
8 #include "ecvSettingManager.h"
9 
10 // CV_CORE_LIB
11 #include <CVPlatform.h>
12 
13 // CV_DB_LIB
14 #include <ecvSingleton.h>
15 
16 // QT
17 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
18 #include <QDesktopWidget>
19 #endif
20 #include <QDialog>
21 #include <QDockWidget>
22 #include <QFile>
23 #include <QGuiApplication>
24 #include <QMainWindow>
25 #include <QScreen>
26 
27 /***************
28  *** Globals ***
29  ***************/
30 
31 // unique console instance
33 
35  if (!s_manager.instance && autoInit) {
36  s_manager.instance = new ecvSettingManager();
37  }
38 
39  return s_manager.instance;
40 }
41 
43 
45 
46 //-----------------------------------------------------------------------------
47 void ecvSettingManager::saveState(const QDialog& dialog, const QString& key) {
48  this->beginGroup(key);
49  this->setValue("Position", dialog.pos());
50  this->setValue("Size", dialog.size());
51  // let's add a PID to avoid restoring dialog position across different
52  // sessions. This avoids issues reported in #18163.
53  this->setValue("PID", QCoreApplication::applicationPid());
54  this->endGroup();
55 }
56 
57 //-----------------------------------------------------------------------------
58 void ecvSettingManager::restoreState(const QString& key, QDialog& dialog) {
59  this->beginGroup(key);
60 
61  if (this->contains("Size")) {
62  dialog.resize(this->value("Size").toSize());
63  }
64 
65  // restore position only if it is the same process.
66  if (this->value("PID").value<qint64>() ==
67  QCoreApplication::applicationPid() &&
68  this->contains("Position")) {
69  dialog.move(this->value("Position").toPoint());
70  }
71  this->endGroup();
72 }
73 
74 //-----------------------------------------------------------------------------
75 void ecvSettingManager::saveState(const QMainWindow& window,
76  const QString& key) {
77  this->beginGroup(key);
78  this->setValue("Size", window.size());
79  this->setValue("Layout", window.saveState());
80  this->endGroup();
81 }
82 
83 //-----------------------------------------------------------------------------
84 void ecvSettingManager::restoreState(const QString& key, QMainWindow& window) {
85  this->beginGroup(key);
86 
87  if (this->contains("Size")) {
88  window.resize(this->value("Size").toSize());
89  }
90 
91  if (this->contains("Layout")) {
92  window.restoreState(this->value("Layout").toByteArray());
93 
94  QList<QDockWidget*> dockWidgets = window.findChildren<QDockWidget*>();
95  foreach (QDockWidget* dock_widget, dockWidgets) {
96  if (dock_widget->isFloating() == true) {
97  sanityCheckDock(dock_widget);
98  }
99  }
100  }
101 
102  this->endGroup();
103 }
104 
105 //-----------------------------------------------------------------------------
106 void ecvSettingManager::sanityCheckDock(QDockWidget* dock_widget) {
107  if (nullptr == dock_widget) {
108  return;
109  }
110 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
111  QDesktopWidget desktop;
112 #endif
113 
114  QPoint dockTopLeft = dock_widget->pos();
115  QRect dockRect(dockTopLeft, dock_widget->size());
116 
117  QRect geometry = QRect(dockTopLeft, dock_widget->frameSize());
118  int titleBarHeight = geometry.height() - dockRect.height();
119 
120  // Qt5/Qt6 Compatibility: QDesktopWidget removed in Qt6, use QScreen instead
121 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
122  QScreen* screen = dock_widget->screen();
123  if (!screen) {
124  screen = QGuiApplication::primaryScreen();
125  }
126  QRect screenRect = screen ? screen->availableGeometry() : QRect();
127 #else
128  QRect screenRect = desktop.availableGeometry(dock_widget);
129 #endif
130  QRect desktopRect =
131  QGuiApplication::primaryScreen()
132  ->availableGeometry(); // Should give us the entire Desktop
133  // geometry
134  // Ensure the top left corner of the window is on the screen
135  if (!screenRect.contains(dockTopLeft)) {
136  // Are we High?
137  if (dockTopLeft.y() < screenRect.y()) {
138  dock_widget->move(dockRect.x(), screenRect.y());
139  dockTopLeft = dock_widget->pos();
140  dockRect = QRect(dockTopLeft, dock_widget->frameSize());
141  }
142  // Are we low
143  if (dockTopLeft.y() > screenRect.y() + screenRect.height()) {
144  dock_widget->move(dockRect.x(),
145  screenRect.y() + screenRect.height() - 20);
146  dockTopLeft = dock_widget->pos();
147  dockRect = QRect(dockTopLeft, dock_widget->frameSize());
148  }
149  // Are we left
150  if (dockTopLeft.x() < screenRect.x()) {
151  dock_widget->move(screenRect.x(), dockRect.y());
152  dockTopLeft = dock_widget->pos();
153  dockRect = QRect(dockTopLeft, dock_widget->frameSize());
154  }
155  // Are we right
156  if (dockTopLeft.x() > screenRect.x() + screenRect.width()) {
157  dock_widget->move(
158  screenRect.x() + screenRect.width() - dockRect.width(),
159  dockRect.y());
160  dockTopLeft = dock_widget->pos();
161  dockRect = QRect(dockTopLeft, dock_widget->frameSize());
162  }
163 
164  dockTopLeft = dock_widget->pos();
165  dockRect = QRect(dockTopLeft, dock_widget->frameSize());
166  }
167 
168  if (!desktopRect.contains(dockRect)) {
169  // Are we too wide
170  if (dockRect.x() + dockRect.width() >
171  screenRect.x() + screenRect.width()) {
172  if (screenRect.x() + screenRect.width() - dockRect.width() >
173  screenRect.x()) {
174  // Move dock side to side
175  dockRect.setX(screenRect.x() + screenRect.width() -
176  dockRect.width());
177  dock_widget->move(dockRect.x(), dockRect.y());
178  dockTopLeft = dock_widget->pos();
179  dockRect = QRect(dockTopLeft, dock_widget->frameSize());
180  } else {
181  // Move dock side to side + resize to fit
182  dockRect.setX(screenRect.x() + screenRect.width() -
183  dockRect.width());
184  dockRect.setWidth(screenRect.width());
185  dock_widget->resize(dockRect.width(), dockRect.height());
186  dock_widget->move(dockRect.x(), dockRect.y());
187  dockTopLeft = dock_widget->pos();
188  dockRect = QRect(dockTopLeft, dock_widget->frameSize());
189  }
190  }
191 
192  dockTopLeft = dock_widget->pos();
193  dockRect = QRect(dockTopLeft, dock_widget->frameSize());
194  // Are we too Tall
195  if (dockRect.y() + dockRect.height() >
196  screenRect.y() + screenRect.height()) {
197  // See if we can move it more on screen so that the entire dock is
198  // on screen
199  if (screenRect.y() + screenRect.height() - dockRect.height() >
200  screenRect.y()) {
201  // Move dock up
202  dockRect.setY(screenRect.y() + screenRect.height() -
203  dockRect.height());
204  dock_widget->move(dockRect.x(), dockRect.y());
205  dockTopLeft = dock_widget->pos();
206  dockRect = QRect(dockTopLeft, dock_widget->frameSize());
207  } else {
208  // Move dock up + resize to fit
209  dock_widget->resize(dockRect.width(),
210  screenRect.height() - titleBarHeight);
211  dock_widget->move(dockRect.x(), screenRect.y());
212  dockTopLeft = dock_widget->pos();
213  dockRect = QRect(dockTopLeft, dock_widget->frameSize());
214  }
215  }
216  }
217 }
218 
219 //-----------------------------------------------------------------------------
220 QString ecvSettingManager::backup(const QString& argName) {
221  this->sync();
222 
223  QString fname = argName.isEmpty() ? (this->fileName() + ".bak") : argName;
224  QFile::remove(fname);
225  return QFile::copy(this->fileName(), fname) ? fname : QString();
226 }
227 
228 void ecvSettingManager::Init(const QString& fileName) {
229  // should be called only once!
230  if (s_manager.instance) {
231  assert(false);
232  return;
233  }
234 
235  s_manager.instance = new ecvSettingManager();
236 
237 #ifdef CV_WINDOWS // only support QSettings Writting in file in Windows now!
238  QString configPath;
239  configPath = QCoreApplication::applicationDirPath() + "/";
240  configPath += fileName;
241  s_manager.instance->m_iniFile = QSharedPointer<QSettings>(
242  new QSettings(configPath, QSettings::IniFormat));
243  // s_manager.instance->m_iniFile->setIniCodec(QTextCodec::codecForName("System"));
244 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
245  s_manager.instance->m_iniFile->setIniCodec("utf8"); // set coding
246 #endif
247  QFile file(configPath);
248  if (false == file.open(QIODevice::ReadOnly | QIODevice::Text)) {
249  s_manager.instance->m_iniFile->beginGroup("section");
250  s_manager.instance->m_iniFile->setValue("status", "false");
251  s_manager.instance->m_iniFile->endGroup();
252  }
253 #else
254  Q_UNUSED(fileName)
255  QSettings::setDefaultFormat(QSettings::NativeFormat);
256  s_manager.instance->m_iniFile = QSharedPointer<QSettings>(new QSettings());
257  // s_manager.instance->m_iniFile->setIniCodec(QTextCodec::codecForName("System"));
258 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
259  s_manager.instance->m_iniFile->setIniCodec("utf8"); // set coding
260 #endif
261 #endif
262 }
263 
264 void ecvSettingManager::setValue(const QString& section,
265  const QString& key,
266  const QVariant& value) {
267  s_manager.instance->m_iniFile->beginGroup(section); // set node name
268  s_manager.instance->m_iniFile->setValue(
269  key, value); // set key and value according to key
270  s_manager.instance->m_iniFile->endGroup(); // end group
271 }
272 
273 void ecvSettingManager::removeNode(const QString& section) {
274  s_manager.instance->m_iniFile->remove(section);
275 }
276 
277 void ecvSettingManager::removeKey(const QString& section, const QString& key) {
278  s_manager.instance->m_iniFile->beginGroup(section);
279  s_manager.instance->m_iniFile->remove(key);
280  s_manager.instance->m_iniFile->endGroup();
281 }
282 
283 QVariant ecvSettingManager::getValue(const QString& section,
284  const QString& key,
285  const QVariant& defaultValue) {
286  s_manager.instance->m_iniFile->beginGroup(section);
287  QVariant result = s_manager.instance->m_iniFile->value(key, defaultValue);
288  s_manager.instance->m_iniFile->endGroup();
289  return result;
290 }
291 
292 void ecvSettingManager::clear() { s_manager.instance->m_iniFile->clear(); }
293 
294 void ecvSettingManager::sync() { s_manager.instance->m_iniFile->sync(); }
295 
296 QSettings::Status ecvSettingManager::status() const {
297  return s_manager.instance->m_iniFile->status();
298 }
299 
301  return s_manager.instance->m_iniFile->isAtomicSyncRequired();
302 }
303 
305  s_manager.instance->m_iniFile->setAtomicSyncRequired(enable);
306 }
307 
308 void ecvSettingManager::beginGroup(const QString& prefix) {
309  s_manager.instance->m_iniFile->beginGroup(prefix);
310 }
311 
313  s_manager.instance->m_iniFile->endGroup();
314 }
315 
316 QString ecvSettingManager::group() const {
317  return s_manager.instance->m_iniFile->group();
318 }
319 
320 int ecvSettingManager::beginReadArray(const QString& prefix) {
321  return s_manager.instance->m_iniFile->beginReadArray(prefix);
322 }
323 
324 void ecvSettingManager::beginWriteArray(const QString& prefix, int size) {
325  s_manager.instance->m_iniFile->beginWriteArray(prefix, size);
326 }
327 
329  s_manager.instance->m_iniFile->endArray();
330 }
331 
333  s_manager.instance->m_iniFile->setArrayIndex(i);
334 }
335 
336 QStringList ecvSettingManager::allKeys() const {
337  return s_manager.instance->m_iniFile->allKeys();
338 }
339 
340 QStringList ecvSettingManager::childKeys() const {
341  return s_manager.instance->m_iniFile->childKeys();
342 }
343 
344 QStringList ecvSettingManager::childGroups() const {
345  return s_manager.instance->m_iniFile->childGroups();
346 }
347 
349  return s_manager.instance->m_iniFile->isWritable();
350 }
351 
352 void ecvSettingManager::setValue(const QString& key, const QVariant& value) {
353  s_manager.instance->m_iniFile->setValue(key, value);
354 }
355 
356 QVariant ecvSettingManager::value(const QString& key,
357  const QVariant& defaultValue) const {
358  return s_manager.instance->m_iniFile->value(key, defaultValue);
359 }
360 
361 void ecvSettingManager::remove(const QString& key) {
362  s_manager.instance->m_iniFile->remove(key);
363 }
364 
365 bool ecvSettingManager::contains(const QString& key) const {
366  return s_manager.instance->m_iniFile->contains(key);
367 }
368 
370  s_manager.instance->m_iniFile->setFallbacksEnabled(b);
371 }
372 
374  return s_manager.instance->m_iniFile->fallbacksEnabled();
375 }
376 
378  return s_manager.instance->m_iniFile->fileName();
379 }
380 
381 QSettings::Format ecvSettingManager::format() const {
382  return s_manager.instance->m_iniFile->format();
383 }
384 
385 QSettings::Scope ecvSettingManager::scope() const {
386  return s_manager.instance->m_iniFile->scope();
387 }
388 
390  return s_manager.instance->m_iniFile->organizationName();
391 }
392 
394  return s_manager.instance->m_iniFile->applicationName();
395 }
396 
397 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
398 void ecvSettingManager::setIniCodec(QTextCodec* codec) {
399  s_manager.instance->m_iniFile->setIniCodec(codec);
400 }
401 
402 void ecvSettingManager::setIniCodec(const char* codecName) {
403  s_manager.instance->m_iniFile->setIniCodec(codecName);
404 }
405 
406 QTextCodec* ecvSettingManager::iniCoxdec() const {
407  return s_manager.instance->m_iniFile->iniCodec();
408 }
409 #endif
int size
core::Tensor result
Definition: VtkUtils.cpp:76
bool copy
Definition: VtkUtils.cpp:74
virtual Format format() const
virtual void restoreState(const QString &key, QMainWindow &window)
static void setValue(const QString &section, const QString &key, const QVariant &value)
virtual Status status() const
virtual QString organizationName() const
static void ReleaseInstance()
Releases unique instance.
virtual QString applicationName() const
virtual bool fallbacksEnabled() const
virtual int beginReadArray(const QString &prefix)
virtual bool isWritable() const
virtual QStringList allKeys() const
virtual void remove(const QString &key)
virtual void setAtomicSyncRequired(bool enable)
static QVariant getValue(const QString &section, const QString &key, const QVariant &defaultValue=QVariant())
virtual QString fileName() const
virtual bool isAtomicSyncRequired() const
virtual void setArrayIndex(int i)
static void removeKey(const QString &section, const QString &key)
virtual void setFallbacksEnabled(bool b)
virtual Scope scope() const
static ecvSettingManager * TheInstance(bool autoInit=true)
Returns the (unique) static instance.
virtual void endGroup()
virtual QStringList childGroups() const
virtual QString group() const
virtual QVariant value(const QString &key, const QVariant &defaultValue=QVariant()) const
virtual void beginGroup(const QString &prefix)
QString backup(const QString &filename=QString())
virtual void saveState(const QMainWindow &window, const QString &key)
virtual void sanityCheckDock(QDockWidget *docke_widget)
virtual void beginWriteArray(const QString &prefix, int size=-1)
virtual QStringList childKeys() const
virtual bool contains(const QString &key) const
virtual void alertSettingsModified()
virtual void endArray()
static void Init(const QString &path)
static void removeNode(const QString &section)
static ecvSingleton< ecvSettingManager > s_manager
Generic singleton encapsulation structure.
Definition: ecvSingleton.h:12