MauiKit Controls

handy.cpp
1/*
2 * Copyright 2018 Camilo Higuita <milo.h@aol.com>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Library General Public License as
6 * published by the Free Software Foundation; either version 2, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this program; if not, write to the
16 * Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 */
19
20#include "handy.h"
21#include "fmh.h"
22
23#include <QDateTime>
24#include <QClipboard>
25#include <QDebug>
26#include <QIcon>
27#include <QMimeData>
28#include <QOperatingSystemVersion>
29#include <QStandardPaths>
30#include <QWindow>
31#include <QMouseEvent>
32#include <QRegularExpression>
33#include <QInputDevice>
34#include <QFileInfo>
35
36#ifdef Q_OS_ANDROID
37#include <QGuiApplication>
38#else
39#include <QApplication>
40#endif
41
42#include <MauiMan4/formfactormanager.h>
43#include <MauiMan4/accessibilitymanager.h>
44#include <MauiMan4/mauimanutils.h>
45
46Q_GLOBAL_STATIC(Handy, handyInstance)
47
48Handy::Handy(QObject *parent)
49 : QObject(parent)
50 ,m_formFactor(new MauiMan::FormFactorManager(this))
51 ,m_accessibility(new MauiMan::AccessibilityManager(this))
52 ,m_hasTransientTouchInput(false)
53{
54 qDebug() << "CREATING INSTANCE OF MAUI HANDY";
55
56 connect(m_accessibility, &MauiMan::AccessibilityManager::singleClickChanged, [&](bool value)
57 {
58 m_singleClick = value;
59 Q_EMIT singleClickChanged();
60 });
61
62 m_singleClick = m_accessibility->singleClick();
63
64 // #ifdef FORMFACTOR_FOUND //TODO check here for Cask desktop enviroment
65
66 connect(m_formFactor, &MauiMan::FormFactorManager::preferredModeChanged, [this](uint value)
67 {
68 m_ffactor = static_cast<FFactor>(value);
69 m_mobile = m_ffactor == FFactor::Phone || m_ffactor == FFactor::Tablet;
70 Q_EMIT formFactorChanged();
71 Q_EMIT isMobileChanged();
72 });
73
74 connect(m_formFactor, &MauiMan::FormFactorManager::hasTouchscreenChanged, [this](bool value)
75 {
76 m_isTouch = value || m_formFactor->forceTouchScreen();
77 Q_EMIT isTouchChanged();
78 });
79
80 connect(m_formFactor, &MauiMan::FormFactorManager::hasKeyboardChanged, [this](bool value)
81 {
82 Q_EMIT hasKeyboardChanged();
83 });
84
85
86 m_ffactor = static_cast<FFactor>(m_formFactor->preferredMode());
87
89 {
90 m_mobile = m_ffactor == FFactor::Phone || m_ffactor == FFactor::Tablet;
91 }
92 else
93 {
94#if defined(Q_OS_ANDROID) || defined(Q_OS_IOS) || defined(UBUNTU_TOUCH)
95 m_mobile = true;
96#else
97 // Mostly for debug purposes and for platforms which are always mobile,
98 // such as Plasma Mobile
99 if (qEnvironmentVariableIsSet("QT_QUICK_CONTROLS_MOBILE")) {
100 m_mobile = QByteArrayList{"1", "true"}.contains(qgetenv("QT_QUICK_CONTROLS_MOBILE"));
101 } else {
102 m_mobile = false;
103 }
104#endif
105 }
106
107#ifdef Q_OS_ANDROID
108 m_isTouch = true;
109#else
110 m_isTouch = m_formFactor->hasTouchscreen() || m_formFactor->forceTouchScreen();
111#endif
112
113 if (m_isTouch)
114 {
115 connect(qApp, &QGuiApplication::focusWindowChanged, this, [this](QWindow *win)
116 {
117 if (win)
118 {
119 win->installEventFilter(this);
120 }
121 });
122 }
123 qDebug() << "DONE CREATING INSTANCE OF MAUI HANDY";
124}
125
126Handy *Handy::instance()
127{
128 return handyInstance();
129}
130
131bool Handy::isTouch()
132{
133 return m_isTouch;
134}
135
137{
138 return m_ffactor;
139}
140
142{
143 return m_hasTransientTouchInput;
144}
145
146void Handy::setTransientTouchInput(bool touch)
147{
148 if (touch == m_hasTransientTouchInput) {
149 return;
150 }
151
152 m_hasTransientTouchInput = touch;
153 Q_EMIT hasTransientTouchInputChanged();
154}
155
156bool Handy::eventFilter(QObject *watched, QEvent *event)
157{
158 Q_UNUSED(watched)
159 switch (event->type())
160 {
162 setTransientTouchInput(true);
163 break;
165 case QEvent::MouseMove: {
166 QMouseEvent *me = static_cast<QMouseEvent *>(event);
168 {
169 setTransientTouchInput(false);
170 }
171 break;
172 }
173 case QEvent::Wheel:
174 setTransientTouchInput(false);
175 default:
176 break;
177 }
178
179 return false;
180}
181
182#ifdef Q_OS_ANDROID
183static inline struct {
184 QList<QUrl> urls;
185 QString text;
186 bool cut = false;
187
188 bool hasUrls()
189 {
190 return !urls.isEmpty();
191 }
192 bool hasText()
193 {
194 return !text.isEmpty();
195 }
196
197} _clipboard;
198#endif
199
200QVariantMap Handy::userInfo()
201{
202 QString name = qgetenv("USER");
203 if (name.isEmpty())
204 name = qgetenv("USERNAME");
205
206 return QVariantMap({{FMH::MODEL_NAME[FMH::MODEL_KEY::NAME], name}});
207}
208
210{
211#ifdef Q_OS_ANDROID
212 auto clipboard = QGuiApplication::clipboard();
213#else
214 auto clipboard = QApplication::clipboard();
215#endif
216
217 auto mime = clipboard->mimeData();
218 if (mime->hasText())
219 return clipboard->text();
220
221 return QString();
222}
223
225{
226 QVariantMap res;
227#ifdef Q_OS_ANDROID
228 if (_clipboard.hasUrls())
229 res.insert("urls", QUrl::toStringList(_clipboard.urls));
230
231 if (_clipboard.hasText())
232 res.insert("text", _clipboard.text);
233
234 res.insert("cut", _clipboard.cut);
235#else
236 auto clipboard = QApplication::clipboard();
237
238 auto mime = clipboard->mimeData();
239
240 if(!mime)
241 return res;
242
243 if (mime->hasUrls())
244 res.insert("urls", QUrl::toStringList(mime->urls()));
245
246 if (mime->hasText())
247 res.insert("text", mime->text());
248
249 if(mime->hasImage())
250 res.insert("image", mime->imageData());
251
252 const QByteArray a = mime->data(QStringLiteral("application/x-kde-cutselection"));
253
254 res.insert("cut", !a.isEmpty() && a.at(0) == '1');
255#endif
256 return res;
257}
258
259bool Handy::copyToClipboard(const QVariantMap &value, const bool &cut)
260{
261#ifdef Q_OS_ANDROID
262 if (value.contains("urls"))
263 _clipboard.urls = QUrl::fromStringList(value["urls"].toStringList());
264
265 if (value.contains("text"))
266 _clipboard.text = value["text"].toString();
267
268 _clipboard.cut = cut;
269
270 return true;
271#else
272 auto clipboard = QApplication::clipboard();
273 QMimeData *mimeData = new QMimeData();
274
275 if (value.contains("urls"))
276 mimeData->setUrls(QUrl::fromStringList(value["urls"].toStringList()));
277
278 if (value.contains("text"))
279 mimeData->setText(value["text"].toString());
280
281 mimeData->setData(QStringLiteral("application/x-kde-cutselection"), cut ? "1" : "0");
282 clipboard->setMimeData(mimeData);
283
284 return true;
285#endif
286
287 return false;
288}
289
291{
292#ifdef Q_OS_ANDROID
293 Handy::copyToClipboard({{"text", text}});
294#else
296#endif
297 return true;
298}
299
304
305bool Handy::isAndroid()
306{
307 return FMH::isAndroid();
308}
309
310bool Handy::isLinux()
311{
312 return FMH::isLinux();
313}
314
315bool Handy::isIOS()
316{
317 return FMH::isIOS();
318}
319
321{
322 return m_formFactor->hasKeyboard();
323}
324
325bool Handy::hasMouse()
326{
327 return m_formFactor->hasMouse();
328}
329
330bool Handy::isWindows()
331{
332 return FMH::isWindows();
333}
334
335bool Handy::isMac()
336{
337 return FMH::isMac();
338}
339
340
342{
343 const QLocale locale;
344 return locale.formattedDataSize(size);
345}
346
347QString Handy::formatDate(const QString &dateStr, const QString &format, const QString &initFormat)
348{
349 if (initFormat.isEmpty())
350 return QDateTime::fromString(dateStr, Qt::TextDate).toString(format);
351 else
352 return QDateTime::fromString(dateStr, initFormat).toString(format);
353}
354
355QString Handy::formatTime(const qint64 &value)
356{
357 QString tStr;
358 if (value) {
359 QTime time((value / 3600) % 60, (value / 60) % 60, value % 60, (value * 1000) % 1000);
360 QString format = "mm:ss";
361 if (value > 3600)
362 {
363 format = "hh:mm:ss";
364 }
365 tStr = time.toString(format);
366 }
367
368 return tStr.isEmpty() ? "00:00" : tStr;
369}
370
371bool Handy::isMobile() const
372{
373 return m_mobile;
374}
375
376bool Handy::isEmail(const QString &text)
377{
378 QRegularExpression reg(R"(^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$)", QRegularExpression::CaseInsensitiveOption);
379
380 auto res = reg.match(text);
381
382 return res.hasMatch();
383}
384
385bool Handy::isPhoneNumber(const QString &text)
386{
387 QRegularExpression reg(R"(^[\+]?[(]?[0-9]{3}[)]?[-\s\.]?[0-9]{3}[-\s\.]?[0-9]{4,6}$)", QRegularExpression::CaseInsensitiveOption);
388
389 auto res = reg.match(text);
390
391 return res.hasMatch();
392}
393
394bool Handy::isWebLink(const QString &text)
395{
396 QRegularExpression reg(R"(^(https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|www\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9]\.[^\s]{2,}|www\.[a-zA-Z0-9]\.[^\s]{2,})$)", QRegularExpression::CaseInsensitiveOption);
397
398 auto res = reg.match(text);
399
400 return res.hasMatch();
401}
402
403bool Handy::isFileLink(const QString &text)
404{
405 QUrl url = QUrl::fromUserInput(text);
406
407 if(url.isValid())
408 {
409 QFileInfo file(url.toLocalFile());
410 return file.exists();
411 }
412
413 return false;
414}
415
416bool Handy::isTimeDate(const QString &text)
417{
418 QDateTime dat = QDateTime::fromString(text);
419 return dat.isValid();
420}
The Handy class.
Definition handy.h:41
FFactor formFactor
The current preferred from factor the user has selected.
Definition handy.h:109
bool isTouch
Whether the target device has a touch screen.
Definition handy.h:55
static int version()
Returns the major version of the current OS.
Definition handy.cpp:300
QML_SINGLETONbool isMobile
Whether the host platform is set as mobile.
Definition handy.h:50
static QVariantMap getClipboard()
Retrieves the data in the clipboard into a key-value map.
Definition handy.cpp:224
static QString formatTime(const qint64 &value)
Format a milliseconds value to a readable format.
Definition handy.cpp:355
FFactor
The different form factor options.
Definition handy.h:118
bool isLinux
Whether the host platform is a GNU/Linux distribution.
Definition handy.h:80
bool isMac
Whether the host platform is running MacOS.
Definition handy.h:90
bool hasMouse
Whether the target device has a physical mouse attached.
Definition handy.h:60
bool isWindows
Whether the host platform is running Windows OS.
Definition handy.h:85
static QString getClipboardText()
Returns the text contained in the clipboard.
Definition handy.cpp:209
bool hasKeyboard
Whether the target device has a physical keyboard attached.
Definition handy.h:65
static bool copyToClipboard(const QVariantMap &value, const bool &cut=false)
Adds a key-value map to the clipboard.
Definition handy.cpp:259
bool isIOS
Whether the host platform is running IOS.
Definition handy.h:95
static QString formatDate(const QString &dateStr, const QString &format=QString("dd/MM/yyyy"), const QString &initFormat=QString())
Given a date string, its original format and an intended format, return a readable string.
Definition handy.cpp:347
static QVariantMap userInfo()
Returns a key-value map containing basic information about the current user.
Definition handy.cpp:200
bool hasTransientTouchInput
Whether the current press input has been received from a touch screen.
Definition handy.h:70
bool isAndroid
Whether the host platform is an Android device.
Definition handy.h:75
static bool copyTextToClipboard(const QString &text)
Copies a text string to the clipboard.
Definition handy.cpp:290
static QString formatSize(quint64 size)
Format a size value to the a readable locale size format.
Definition handy.cpp:341
static bool isMauiSession()
bool isLinux()
Whether the platform running is GNU/Linux.
Definition fmh.cpp:104
bool isIOS()
Whether the platform running is IOS.
Definition fmh.cpp:124
static const QHash< MODEL_KEY, QString > MODEL_NAME
The mapping of the FMH::MODEL_KEY enum values to its string representation.
Definition fmh.h:219
bool isWindows()
Whether the platform running is Window.
Definition fmh.cpp:93
bool isMac()
Whether the platform running is Mac.
Definition fmh.cpp:113
bool isAndroid()
Whether the platform running is Android.
Definition fmh.cpp:84
const QList< QKeySequence > & cut()
char at(qsizetype i) const const
char * data()
bool isEmpty() const const
void setText(const QString &text, Mode mode)
QDateTime fromString(QStringView string, QStringView format, QCalendar cal)
bool isValid() const const
QString toString(QStringView format, QCalendar cal) const const
QClipboard * clipboard()
void focusWindowChanged(QWindow *focusWindow)
bool contains(const AT &value) const const
bool isEmpty() const const
QString formattedDataSize(qint64 bytes, int precision, DataSizeFormats format) const const
void setData(const QString &mimeType, const QByteArray &data)
void setText(const QString &text)
void setUrls(const QList< QUrl > &urls)
Qt::MouseEventSource source() const const
Q_EMITQ_EMIT
virtual bool event(QEvent *e)
void installEventFilter(QObject *filterObj)
QOperatingSystemVersion current()
int majorVersion() const const
bool isEmpty() const const
TextDate
MouseEventNotSynthesized
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
QString toString(QStringView format) const const
QList< QUrl > fromStringList(const QStringList &urls, ParsingMode mode)
QUrl fromUserInput(const QString &userInput, const QString &workingDirectory, UserInputResolutionOptions options)
bool isValid() const const
QString toLocalFile() const const
QStringList toStringList(const QList< QUrl > &urls, FormattingOptions options)
This file is part of the KDE documentation.
Documentation copyright © 1996-2025 The KDE developers.
Generated on Fri May 2 2025 11:57:11 by doxygen 1.13.2 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.