File indexing completed on 2024-05-05 04:46:58
0001 /* 0002 * Copyright 2018 Camilo Higuita <milo.h@aol.com> 0003 * 0004 * This program is free software; you can redistribute it and/or modify 0005 * it under the terms of the GNU Library General Public License as 0006 * published by the Free Software Foundation; either version 2, or 0007 * (at your option) any later version. 0008 * 0009 * This program is distributed in the hope that it will be useful, 0010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 0012 * GNU General Public License for more details 0013 * 0014 * You should have received a copy of the GNU Library General Public 0015 * License along with this program; if not, write to the 0016 * Free Software Foundation, Inc., 0017 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 0018 */ 0019 0020 #include "handy.h" 0021 #include "fmh.h" 0022 0023 #include <QDateTime> 0024 #include <QClipboard> 0025 #include <QDebug> 0026 #include <QIcon> 0027 #include <QMimeData> 0028 #include <QOperatingSystemVersion> 0029 #include <QStandardPaths> 0030 #include <QWindow> 0031 #include <QMouseEvent> 0032 0033 #include "platforms/platform.h" 0034 0035 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 0036 #include <QTouchDevice> 0037 #else 0038 #include <QInputDevice> 0039 #endif 0040 0041 #ifdef Q_OS_ANDROID 0042 #include <QGuiApplication> 0043 #else 0044 #include <QApplication> 0045 #endif 0046 0047 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 0048 #include <MauiMan3/formfactormanager.h> 0049 #include <MauiMan3/accessibilitymanager.h> 0050 #else 0051 #include <MauiMan4/formfactormanager.h> 0052 #include <MauiMan4/accessibilitymanager.h> 0053 #endif 0054 0055 Handy *Handy::m_instance = nullptr; 0056 0057 Handy::Handy(QObject *parent) 0058 : QObject(parent) 0059 ,m_hasTransientTouchInput(false) 0060 ,m_formFactor(new MauiMan::FormFactorManager(this)) 0061 ,m_accessibility(new MauiMan::AccessibilityManager(this)) 0062 { 0063 qDebug() << "CREATING INSTANCE OF MAUI HANDY"; 0064 0065 connect(m_accessibility, &MauiMan::AccessibilityManager::singleClickChanged, [&](bool value) 0066 { 0067 m_singleClick = value; 0068 Q_EMIT singleClickChanged(); 0069 }); 0070 0071 m_singleClick = m_accessibility->singleClick(); 0072 0073 // #ifdef FORMFACTOR_FOUND //TODO check here for Cask desktop enviroment 0074 0075 connect(m_formFactor, &MauiMan::FormFactorManager::preferredModeChanged, [this](uint value) 0076 { 0077 m_ffactor = static_cast<FFactor>(value); 0078 m_mobile = m_ffactor == FFactor::Phone || m_ffactor == FFactor::Tablet; 0079 Q_EMIT formFactorChanged(); 0080 Q_EMIT isMobileChanged(); 0081 }); 0082 0083 connect(m_formFactor, &MauiMan::FormFactorManager::hasTouchscreenChanged, [this](bool value) 0084 { 0085 m_isTouch = value; 0086 Q_EMIT isTouchChanged(); 0087 }); 0088 0089 m_ffactor = static_cast<FFactor>(m_formFactor->preferredMode()); 0090 m_mobile = m_ffactor == FFactor::Phone || m_ffactor == FFactor::Tablet; 0091 m_isTouch = m_formFactor->hasTouchscreen(); 0092 0093 connect(qApp, &QGuiApplication::focusWindowChanged, this, [this](QWindow *win) 0094 { 0095 if (win) 0096 { 0097 win->installEventFilter(this); 0098 } 0099 }); 0100 0101 connect(qApp, &QCoreApplication::aboutToQuit, []() 0102 { 0103 qDebug() << "Lets remove Handy singleton instance"; 0104 delete m_instance; 0105 m_instance = nullptr; 0106 }); 0107 } 0108 0109 bool Handy::isTouch() 0110 { 0111 return m_isTouch; 0112 } 0113 0114 Handy::FFactor Handy::formFactor() 0115 { 0116 return m_ffactor; 0117 } 0118 0119 bool Handy::hasTransientTouchInput() const 0120 { 0121 return m_hasTransientTouchInput; 0122 } 0123 0124 void Handy::setTransientTouchInput(bool touch) 0125 { 0126 if (touch == m_hasTransientTouchInput) { 0127 return; 0128 } 0129 0130 m_hasTransientTouchInput = touch; 0131 Q_EMIT hasTransientTouchInputChanged(); 0132 } 0133 0134 bool Handy::eventFilter(QObject *watched, QEvent *event) 0135 { 0136 Q_UNUSED(watched) 0137 switch (event->type()) 0138 { 0139 case QEvent::TouchBegin: 0140 setTransientTouchInput(true); 0141 break; 0142 case QEvent::MouseButtonPress: 0143 case QEvent::MouseMove: { 0144 QMouseEvent *me = static_cast<QMouseEvent *>(event); 0145 if (me->source() == Qt::MouseEventNotSynthesized) 0146 { 0147 setTransientTouchInput(false); 0148 } 0149 break; 0150 } 0151 case QEvent::Wheel: 0152 setTransientTouchInput(false); 0153 default: 0154 break; 0155 } 0156 0157 return false; 0158 } 0159 0160 #ifdef Q_OS_ANDROID 0161 static inline struct { 0162 QList<QUrl> urls; 0163 QString text; 0164 bool cut = false; 0165 0166 bool hasUrls() 0167 { 0168 return !urls.isEmpty(); 0169 } 0170 bool hasText() 0171 { 0172 return !text.isEmpty(); 0173 } 0174 0175 } _clipboard; 0176 #endif 0177 0178 QVariantMap Handy::userInfo() 0179 { 0180 QString name = qgetenv("USER"); 0181 if (name.isEmpty()) 0182 name = qgetenv("USERNAME"); 0183 0184 return QVariantMap({{FMH::MODEL_NAME[FMH::MODEL_KEY::NAME], name}}); 0185 } 0186 0187 QString Handy::getClipboardText() 0188 { 0189 #ifdef Q_OS_ANDROID 0190 auto clipboard = QGuiApplication::clipboard(); 0191 #else 0192 auto clipboard = QApplication::clipboard(); 0193 #endif 0194 0195 auto mime = clipboard->mimeData(); 0196 if (mime->hasText()) 0197 return clipboard->text(); 0198 0199 return QString(); 0200 } 0201 0202 QVariantMap Handy::getClipboard() 0203 { 0204 QVariantMap res; 0205 #ifdef Q_OS_ANDROID 0206 if (_clipboard.hasUrls()) 0207 res.insert("urls", QUrl::toStringList(_clipboard.urls)); 0208 0209 if (_clipboard.hasText()) 0210 res.insert("text", _clipboard.text); 0211 0212 res.insert("cut", _clipboard.cut); 0213 #else 0214 auto clipboard = QApplication::clipboard(); 0215 0216 auto mime = clipboard->mimeData(); 0217 0218 if(!mime) 0219 return res; 0220 0221 if (mime->hasUrls()) 0222 res.insert("urls", QUrl::toStringList(mime->urls())); 0223 0224 if (mime->hasText()) 0225 res.insert("text", mime->text()); 0226 0227 if(mime->hasImage()) 0228 res.insert("image", mime->imageData()); 0229 0230 const QByteArray a = mime->data(QStringLiteral("application/x-kde-cutselection")); 0231 0232 res.insert("cut", !a.isEmpty() && a.at(0) == '1'); 0233 #endif 0234 return res; 0235 } 0236 0237 bool Handy::copyToClipboard(const QVariantMap &value, const bool &cut) 0238 { 0239 #ifdef Q_OS_ANDROID 0240 if (value.contains("urls")) 0241 _clipboard.urls = QUrl::fromStringList(value["urls"].toStringList()); 0242 0243 if (value.contains("text")) 0244 _clipboard.text = value["text"].toString(); 0245 0246 _clipboard.cut = cut; 0247 0248 return true; 0249 #else 0250 auto clipboard = QApplication::clipboard(); 0251 QMimeData *mimeData = new QMimeData(); 0252 0253 if (value.contains("urls")) 0254 mimeData->setUrls(QUrl::fromStringList(value["urls"].toStringList())); 0255 0256 if (value.contains("text")) 0257 mimeData->setText(value["text"].toString()); 0258 0259 mimeData->setData(QStringLiteral("application/x-kde-cutselection"), cut ? "1" : "0"); 0260 clipboard->setMimeData(mimeData); 0261 0262 return true; 0263 #endif 0264 0265 return false; 0266 } 0267 0268 bool Handy::copyTextToClipboard(const QString &text) 0269 { 0270 #ifdef Q_OS_ANDROID 0271 Handy::copyToClipboard({{"text", text}}); 0272 #else 0273 QApplication::clipboard()->setText(text); 0274 #endif 0275 return true; 0276 } 0277 0278 int Handy::version() 0279 { 0280 return QOperatingSystemVersion::current().majorVersion(); 0281 } 0282 0283 bool Handy::isAndroid() 0284 { 0285 return FMH::isAndroid(); 0286 } 0287 0288 bool Handy::isLinux() 0289 { 0290 return FMH::isLinux(); 0291 } 0292 0293 bool Handy::isIOS() 0294 { 0295 return FMH::isIOS(); 0296 } 0297 0298 bool Handy::hasKeyboard() 0299 { 0300 return m_formFactor->hasKeyboard(); 0301 } 0302 0303 bool Handy::hasMouse() 0304 { 0305 return m_formFactor->hasMouse(); 0306 } 0307 0308 bool Handy::isWindows() 0309 { 0310 return FMH::isWindows(); 0311 } 0312 0313 bool Handy::isMac() 0314 { 0315 return FMH::isMac(); 0316 } 0317 0318 0319 QString Handy::formatSize(quint64 size) 0320 { 0321 const QLocale locale; 0322 return locale.formattedDataSize(size); 0323 } 0324 0325 QString Handy::formatDate(const QString &dateStr, const QString &format, const QString &initFormat) 0326 { 0327 if (initFormat.isEmpty()) 0328 return QDateTime::fromString(dateStr, Qt::TextDate).toString(format); 0329 else 0330 return QDateTime::fromString(dateStr, initFormat).toString(format); 0331 } 0332 0333 QString Handy::formatTime(const qint64 &value) 0334 { 0335 QString tStr; 0336 if (value) { 0337 QTime time((value / 3600) % 60, (value / 60) % 60, value % 60, (value * 1000) % 1000); 0338 QString format = "mm:ss"; 0339 if (value > 3600) 0340 { 0341 format = "hh:mm:ss"; 0342 } 0343 tStr = time.toString(format); 0344 } 0345 0346 return tStr.isEmpty() ? "00:00" : tStr; 0347 } 0348 0349 bool Handy::isMobile() const 0350 { 0351 return m_mobile; 0352 }