#include "selfdrive/ui/qt/util.h" #include #include #include #include #include #include #include #include "common/params.h" #include "common/swaglog.h" #include "system/hardware/hw.h" QString getVersion() { static QString version = QString::fromStdString(Params().get("Version")); return version; } QString getBrand() { return Params().getBool("Passive") ? QObject::tr("dashcam") : QObject::tr("openpilot"); } QString getBrandVersion() { return getBrand() + " v" + getVersion().left(14).trimmed(); } QString getUserAgent() { return "openpilot-" + getVersion(); } std::optional getDongleId() { std::string id = Params().get("DongleId"); if (!id.empty() && (id != "UnregisteredDevice")) { return QString::fromStdString(id); } else { return {}; } } QMap getSupportedLanguages() { QFile f("translations/languages.json"); f.open(QIODevice::ReadOnly | QIODevice::Text); QString val = f.readAll(); QJsonObject obj = QJsonDocument::fromJson(val.toUtf8()).object(); QMap map; for (auto key : obj.keys()) { map[key] = obj[key].toString(); } return map; } void configFont(QPainter &p, const QString &family, int size, const QString &style) { QFont f(family); f.setPixelSize(size); f.setStyleName(style); p.setFont(f); } void clearLayout(QLayout* layout) { while (QLayoutItem* item = layout->takeAt(0)) { if (QWidget* widget = item->widget()) { widget->deleteLater(); } if (QLayout* childLayout = item->layout()) { clearLayout(childLayout); } delete item; } } QString timeAgo(const QDateTime &date) { int diff = date.secsTo(QDateTime::currentDateTimeUtc()); QString s; if (diff < 60) { s = "now"; } else if (diff < 60 * 60) { int minutes = diff / 60; s = QObject::tr("%1 minute%2 ago").arg(minutes).arg(minutes > 1 ? "s" : ""); } else if (diff < 60 * 60 * 24) { int hours = diff / (60 * 60); s = QObject::tr("%1 hour%2 ago").arg(hours).arg(hours > 1 ? "s" : ""); } else if (diff < 3600 * 24 * 7) { int days = diff / (60 * 60 * 24); s = QObject::tr("%1 day%2 ago").arg(days).arg(days > 1 ? "s" : ""); // %2 "s" show In other languages, this is not normal } else { s = date.date().toString(); } return s; } void setQtSurfaceFormat() { QSurfaceFormat fmt; #ifdef __APPLE__ fmt.setVersion(3, 2); fmt.setProfile(QSurfaceFormat::OpenGLContextProfile::CoreProfile); fmt.setRenderableType(QSurfaceFormat::OpenGL); #else fmt.setRenderableType(QSurfaceFormat::OpenGLES); #endif fmt.setSamples(16); QSurfaceFormat::setDefaultFormat(fmt); } void initApp(int argc, char *argv[]) { Hardware::set_display_power(true); Hardware::set_brightness(65); #ifdef __APPLE__ { // Get the devicePixelRatio, and scale accordingly to maintain 1:1 rendering QApplication tmp(argc, argv); qputenv("QT_SCALE_FACTOR", QString::number(1.0 / tmp.devicePixelRatio() ).toLocal8Bit()); } #endif setQtSurfaceFormat(); } void swagLogMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg) { static std::map levels = { {QtMsgType::QtDebugMsg, CLOUDLOG_DEBUG}, {QtMsgType::QtInfoMsg, CLOUDLOG_INFO}, {QtMsgType::QtWarningMsg, CLOUDLOG_WARNING}, {QtMsgType::QtCriticalMsg, CLOUDLOG_ERROR}, {QtMsgType::QtSystemMsg, CLOUDLOG_ERROR}, {QtMsgType::QtFatalMsg, CLOUDLOG_CRITICAL}, }; std::string file, function; if (context.file != nullptr) file = context.file; if (context.function != nullptr) function = context.function; auto bts = msg.toUtf8(); cloudlog_e(levels[type], file.c_str(), context.line, function.c_str(), "%s", bts.constData()); } QWidget* topWidget (QWidget* widget) { while (widget->parentWidget() != nullptr) widget=widget->parentWidget(); return widget; } QPixmap loadPixmap(const QString &fileName, const QSize &size, Qt::AspectRatioMode aspectRatioMode) { if (size.isEmpty()) { return QPixmap(fileName); } else { return QPixmap(fileName).scaled(size, aspectRatioMode, Qt::SmoothTransformation); } } QRect getTextRect(QPainter &p, int flags, QString text) { QFontMetrics fm(p.font()); QRect init_rect = fm.boundingRect(text); return fm.boundingRect(init_rect, flags, text); } void drawRoundedRect(QPainter &painter, const QRectF &rect, qreal xRadiusTop, qreal yRadiusTop, qreal xRadiusBottom, qreal yRadiusBottom){ qreal w_2 = rect.width() / 2; qreal h_2 = rect.height() / 2; xRadiusTop = 100 * qMin(xRadiusTop, w_2) / w_2; yRadiusTop = 100 * qMin(yRadiusTop, h_2) / h_2; xRadiusBottom = 100 * qMin(xRadiusBottom, w_2) / w_2; yRadiusBottom = 100 * qMin(yRadiusBottom, h_2) / h_2; qreal x = rect.x(); qreal y = rect.y(); qreal w = rect.width(); qreal h = rect.height(); qreal rxx2Top = w*xRadiusTop/100; qreal ryy2Top = h*yRadiusTop/100; qreal rxx2Bottom = w*xRadiusBottom/100; qreal ryy2Bottom = h*yRadiusBottom/100; QPainterPath path; path.arcMoveTo(x, y, rxx2Top, ryy2Top, 180); path.arcTo(x, y, rxx2Top, ryy2Top, 180, -90); path.arcTo(x+w-rxx2Top, y, rxx2Top, ryy2Top, 90, -90); path.arcTo(x+w-rxx2Bottom, y+h-ryy2Bottom, rxx2Bottom, ryy2Bottom, 0, -90); path.arcTo(x, y+h-ryy2Bottom, rxx2Bottom, ryy2Bottom, 270, -90); path.closeSubpath(); painter.drawPath(path); } QColor interpColor(float xv, std::vector xp, std::vector fp) { assert(xp.size() == fp.size()); int N = xp.size(); int hi = 0; while (hi < N and xv > xp[hi]) hi++; int low = hi - 1; if (hi == N && xv > xp[low]) { return fp[fp.size() - 1]; } else if (hi == 0){ return fp[0]; } else { return QColor( (xv - xp[low]) * (fp[hi].red() - fp[low].red()) / (xp[hi] - xp[low]) + fp[low].red(), (xv - xp[low]) * (fp[hi].green() - fp[low].green()) / (xp[hi] - xp[low]) + fp[low].green(), (xv - xp[low]) * (fp[hi].blue() - fp[low].blue()) / (xp[hi] - xp[low]) + fp[low].blue(), (xv - xp[low]) * (fp[hi].alpha() - fp[low].alpha()) / (xp[hi] - xp[low]) + fp[low].alpha() ); } }