Documentation for OpenFLUID 2.2.1
UIHelpers.hpp
Go to the documentation of this file.
1 /*
2 
3  This file is part of OpenFLUID software
4  Copyright(c) 2021-2026, INRAE
5 
6 
7  == GNU General Public License Usage ==
8 
9  OpenFLUID is free software: you can redistribute it and/or modify
10  it under the terms of the GNU General Public License as published by
11  the Free Software Foundation, either version 3 of the License, or
12  (at your option) any later version.
13 
14  OpenFLUID is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  GNU General Public License for more details.
18 
19  You should have received a copy of the GNU General Public License
20  along with OpenFLUID. If not, see <http://www.gnu.org/licenses/>.
21 
22 
23  == Other Usage ==
24 
25  Other Usage means a use of OpenFLUID that is inconsistent with the GPL
26  license, and requires a written agreement between You and INRA.
27  Licensees for Other Usage of OpenFLUID may use this file in accordance
28  with the terms contained in the written agreement between You and INRA.
29 
30 */
31 
32 /**
33  @file UIHelpers.hpp
34 
35  @author Jean-Christophe FABRE <jean-christophe.fabre@inra.fr>
36  @author Armel THÖNI <armel.thoni@inrae.fr>
37 */
38 
39 
40 #ifndef __OPENFLUID_UICOMMON_UIHELPERS_HPP__
41 #define __OPENFLUID_UICOMMON_UIHELPERS_HPP__
42 
43 
44 #include <cmath>
45 #include <random>
46 
47 #include <QInputDialog>
48 #include <QColor>
49 #if (QT_VERSION_MAJOR < 6)
50 #include <QRegExp>
51 #else
52 #include <QRegularExpression>
53 #endif
54 #include <QLineEdit>
55 #include <QIcon>
56 #include <QApplication>
57 #include <QFile>
58 #include <QFileDialog>
59 #include <QMessageBox>
60 #include <QDesktopServices>
61 
65 
66 
67 namespace openfluid { namespace ui { namespace common {
68 
69 
70 inline QColor getRandomColor()
71 {
72  static std::random_device RD;
73  static std::mt19937 G(RD());
74  static std::uniform_int_distribution<> Distri255(0, 255);
75 
76  return QColor(Distri255(G),Distri255(G),Distri255(G));
77 }
78 
79 
80 // =====================================================================
81 // =====================================================================
82 
83 
84 inline double computeLuminance(const QColor& Color)
85 {
86  // Reference: https://www.w3.org/WAI/GL/wiki/Relative_luminance
87  auto adjustColor = [](const double ChannelValue)
88  {
89  double RelValue = ChannelValue/255;
90  if (RelValue <= 0.03928)
91  {
92  return RelValue/12.92;
93  }
94  else
95  {
96  // low-gamma adjust coefficient
97  return std::pow((RelValue + 0.055) / 1.055, 2.4);
98  }
99  };
100  return adjustColor(Color.red())*0.2126 + adjustColor(Color.green())*0.7152 + adjustColor(Color.blue())*0.0722;
101 }
102 
103 
104 // =====================================================================
105 // =====================================================================
106 
107 
108 #if (QT_VERSION_MAJOR < 6)
109 inline void fixLineEdit(QLineEdit* LineEdit,QRegExp SearchRegExp = QRegExp("[^\\w]"),QString NewStr = "_")
110 #else
111 inline void fixLineEdit(QLineEdit* LineEdit,QRegularExpression SearchRegExp = QRegularExpression("[^\\w]"),
112  QString NewStr = "_")
113 #endif
114 {
115  int CPos = LineEdit->cursorPosition();
116  LineEdit->setText(LineEdit->text().replace(SearchRegExp,NewStr));
117  LineEdit->setCursorPosition(CPos);
118 }
119 
120 
121 // =====================================================================
122 // =====================================================================
123 
124 
125 inline bool isHiDPIDevice()
126 {
127  return (qApp->devicePixelRatio() >= 2.0);
128 }
129 
130 
131 // =====================================================================
132 // =====================================================================
133 
134 
135 inline QIcon getIcon(const QString& IconName,const QString& ResourcePath,
136  bool IsLight = false,bool AutoHiDPI = true)
137 {
138  QString IconSuffix = "dark";
139 
140  if (IsLight)
141  {
142  IconSuffix = "light";
143  }
144 
145  QString TmpPath = QString(":%1/icons/%2_%3.png").arg(ResourcePath).arg(IconName).arg(IconSuffix);
146 
147  if (AutoHiDPI && isHiDPIDevice())
148  {
149  QString TmpHiDPIPath = QString(":%1/icons/%2_%3@2x.png").arg(ResourcePath).arg(IconName).arg(IconSuffix);
150 
151  if (QFile::exists(TmpHiDPIPath))
152  {
153  TmpPath = TmpHiDPIPath;
154  }
155  }
156 
157  QIcon TmpIcon(TmpPath);
158 
159  if (IsLight)
160  {
161  QString TmpLightPath = QString(":%1/icons/%2_grayed.png").arg(ResourcePath).arg(IconName);
162 
163  if (AutoHiDPI && isHiDPIDevice())
164  {
165  QString TmpLightHiDPIPath = QString(":%1/icons/%2_grayed@2x.png").arg(ResourcePath).arg(IconName);
166 
167  if (QFile::exists(TmpLightHiDPIPath))
168  {
169  TmpLightPath = TmpLightHiDPIPath;
170  }
171  }
172  TmpIcon.addPixmap(QPixmap(TmpLightPath),QIcon::Disabled);
173  }
174 
175  return TmpIcon;
176 }
177 
178 
179 // =====================================================================
180 // =====================================================================
181 
182 
183 inline QPixmap getImage(const QString& ImageName,const QString& ResourcePath,bool AutoHiDPI = true)
184 {
185  QString TmpPath = QString(":%1/images/%2.png").arg(ResourcePath).arg(ImageName);
186 
187  if (AutoHiDPI && isHiDPIDevice())
188  {
189  QString TmpHiDPIPath = QString(":%1/images/%2@2x.png").arg(ResourcePath).arg(ImageName);
190 
191  if (QFile::exists(TmpHiDPIPath))
192  {
193  TmpPath = TmpHiDPIPath;
194  }
195  }
196 
197  return QPixmap(TmpPath);
198 }
199 
200 
201 // =====================================================================
202 // =====================================================================
203 
204 
205 inline QString createNewFile(QWidget* Parent, const QString& PathString)
206 {
207  if (PathString.isEmpty())
208  {
209  return "";
210  }
211 
212  QString FileToCreate = "";
213  QString FileName = QFileDialog::getSaveFileName(Parent,
214  QApplication::translate("openfluid::ui::common","Create file"),
215  PathString,
216  QApplication::translate("openfluid::ui::common","All files"));
217  if (!FileName.isEmpty() && !FileName.isNull())
218  {
219  FileToCreate = FileName;
220  }
221 
222  if (!FileToCreate.isEmpty())
223  {
224  auto NewFilePath = openfluid::tools::Path(FileToCreate.toStdString());
225 
226  if (NewFilePath.isDirectory())
227  {
228  QMessageBox::critical(Parent,QApplication::translate("openfluid::ui::common","Error creating file"),
229  QApplication::translate("openfluid::ui::common","\"%1\" is an existing directory")
230  .arg(QString::fromStdString(NewFilePath.toNative())));
231  }
232  // Checks if new path included in ref path
233  else if (!openfluid::tools::Path(PathString.toStdString()).contains(FileToCreate.toStdString()))
234  {
235  QMessageBox::critical(Parent,QApplication::translate("openfluid::ui::common","Error creating file"),
236  QApplication::translate("openfluid::ui::common",
237  "\"%1\" is not in the current ware main directory")
238  .arg(QString::fromStdString(NewFilePath.toNative())));
239  return "";
240  }
241  else
242  {
243  NewFilePath.makeFile();
244  }
245  return FileToCreate;
246  }
247  return "";
248 }
249 
250 
251 // =====================================================================
252 // =====================================================================
253 
254 
255 inline void openPath(std::string CurrentPath, bool IsRemote=false)
256 {
257 #if OPENFLUID_OS_ISWSL_FLAG == 1
258  std::string FullLocation = CurrentPath;
259  if (!IsRemote)
260  {
261  openfluid::utils::Process P("wslpath",{"-m", CurrentPath});
262  P.run();
263  const auto OutLines = P.stdOutLines();
264  CurrentPath = OutLines[0];
265  FullLocation = "file://"+CurrentPath;
266  }
267  openfluid::utils::Process PR("cmd.exe",{"/C", "start", FullLocation});
268  bool Success = PR.run();
269  if (!Success)
270  {
271  openfluid::base::log::info("Path opening", "WSL context, path: "+CurrentPath);
272  openfluid::base::log::info("Path opening", "status: "+std::to_string(Success));
273  for (const auto& L : PR.stdOutLines())
274  {
275  openfluid::base::log::debug("Path opening", L);
276  }
277  for (const auto& L : PR.stdErrLines())
278  {
279  openfluid::base::log::error("Path opening", L);
280  }
281  }
282 #else
283  QUrl CurrentURL;
284  if (IsRemote)
285  {
286  CurrentURL = QUrl(QString::fromStdString(CurrentPath), QUrl::TolerantMode);
287  }
288  else
289  {
290  CurrentURL = QUrl::fromLocalFile(QString::fromStdString(CurrentPath));
291  }
292  QDesktopServices::openUrl(CurrentURL);
293 #endif
294 }
295 
296 
297 } } } // namespaces
298 
299 
300 #endif /* __OPENFLUID_UICOMMON_UIHELPERS_HPP__ */
Definition: FilesystemPath.hpp:62
bool contains(const std::string &Path) const
Definition: Process.hpp:68
void OPENFLUID_API info(const std::string &Context, const std::string &Msg)
void OPENFLUID_API error(const std::string &Context, const std::string &Msg)
void OPENFLUID_API debug(const std::string &Context, const std::string &Msg)
FilesystemPath Path
Definition: FilesystemPath.hpp:308
QString createNewFile(QWidget *Parent, const QString &PathString)
Definition: UIHelpers.hpp:205
void openPath(std::string CurrentPath, bool IsRemote=false)
Definition: UIHelpers.hpp:255
QPixmap getImage(const QString &ImageName, const QString &ResourcePath, bool AutoHiDPI=true)
Definition: UIHelpers.hpp:183
void fixLineEdit(QLineEdit *LineEdit, QRegExp SearchRegExp=QRegExp("[^\\w]"), QString NewStr="_")
Definition: UIHelpers.hpp:109
QIcon getIcon(const QString &IconName, const QString &ResourcePath, bool IsLight=false, bool AutoHiDPI=true)
Definition: UIHelpers.hpp:135
double computeLuminance(const QColor &Color)
Definition: UIHelpers.hpp:84
QColor getRandomColor()
Definition: UIHelpers.hpp:70
bool isHiDPIDevice()
Definition: UIHelpers.hpp:125
Definition: ApplicationException.hpp:47