#include "fsp_gui_plugin.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace FreeSpace { std::shared_ptr GuiPlugin::createGuiInterface(LtsSession::LtsSession *session) { return std::make_shared(session); } InterfaceImpl::InterfaceImpl(LtsSession::LtsSession *session) : GuiPluginBase::Interface(session, NGL::NGLLoggerBootstrap::getNGLRootLogger().getNGLLogger("FreeSpaceGui")) { connect(m_session, &LtsSession::LtsSession::signalDoneInitializingSession, this, &InterfaceImpl::onInitDone); } void InterfaceImpl::onInitDone() { disconnect(m_session, &LtsSession::LtsSession::signalDoneInitializingSession, this, nullptr); } QVector InterfaceImpl::getActions() { QVector ret; LtsWidgets::PluginData plData; unsigned long dummy1; double dummy2; if (onStatusRAM(dummy1, dummy2)) { plData.identifier = QLatin1String("CreateFreeRamNoti"); plData.createInstant = LtsWidgets::CreateInstantType::CreateInstantAndDiscardAction; plData.directFunc = [this](const LtsWidgets::PluginData &) { m_notiStatusRam = m_session->createNotification(QStringLiteral("FreeRamMonitor")); m_notiStatusRam->setIcon(QIcon(QStringLiteral("icon:usedspace-100.svg"))); slotCheckFreeRamStatus(); QTimer *t = new QTimer(this); t->setInterval(5000); connect(t, &QTimer::timeout, this, &InterfaceImpl::slotCheckFreeRamStatus); t->start(); }; ret.append(plData); } bool fakeMba = (LtsSessionData::LtsSessionData::getInstance()->debugFlagValue(QStringLiteral("MBA.Fake")) == QVariant(true)); if (!fakeMba) { std::shared_ptr asmDtc; if (!m_session->getDtc(asmDtc)) { WARNING_LOG(m_logger) << "getDtc for AssetManagement::DataInterface failed."; return {}; } bool isAAR = asmDtc->isAARWorkstation(LtsSession::LtsSession::workstationName()); if (!isAAR) { DEBUG_LOG(m_logger) << "not a mba ws - no free space noti"; return ret; } } else WARNING_LOG(m_logger) << "fake mba"; plData.identifier = QLatin1String("CreateFreeSpaceNoti"); plData.createInstant = LtsWidgets::CreateInstantType::CreateInstantAndDiscardAction; plData.directFunc = [this](const LtsWidgets::PluginData &) { m_notiStatusHdd = m_session->createNotification(QStringLiteral("FreeSpaceMonitor")); m_notiStatusHdd->setIcon(QIcon(QStringLiteral("icon:usedspace-100.svg"))); m_notiStatusHdd->setAction([this]() { new LtsWidgets::LtsMessageDialogNew(m_session->baseLayout(), m_notiStatusHdd->tooltip(), tr("Current free disk space")); }); slotCheckFreeSpaceStatus(); QTimer *t = new QTimer(this); t->setInterval(10000); connect(t, &QTimer::timeout, this, &InterfaceImpl::slotCheckFreeSpaceStatus); t->start(); }; ret.append(plData); return ret; } bool InterfaceImpl::onStatusHDD(quint64 &freeSpaceBytes, double &usedSpacePercent) { QStorageInfo storage(QCoreApplication::applicationFilePath()); if (storage.isValid() && storage.isReady()) { quint64 freeBytesAvailable = storage.bytesAvailable(); quint64 bytesAvailable = storage.bytesTotal(); double percent = bytesAvailable ? 100.0 * freeBytesAvailable / bytesAvailable : 0; freeSpaceBytes = freeBytesAvailable; usedSpacePercent = 100.0 - percent; return true; } else return false; } bool InterfaceImpl::onStatusRAM(unsigned long &freeRamKbytes, double &usedRamPercent) { freeRamKbytes = 0; usedRamPercent = 0.0; std::string key; std::ifstream meminfo("/proc/meminfo"); if (!meminfo.is_open()) { qWarning() << "cannot open /proc/meminfo"; return false; } unsigned long memTotal = 0; unsigned long memAvailable = 0; while (meminfo >> key) { if (key == "MemTotal:") meminfo >> memTotal; else if (key == "MemAvailable:") meminfo >> memAvailable; meminfo.ignore(std::numeric_limits::max(), '\n'); } qDebug() << "MemTotal" << memTotal << "MemAvailable" << memAvailable; freeRamKbytes = memAvailable; usedRamPercent = static_cast(memTotal - memAvailable) / static_cast(memTotal) * 100.0; return true; } QImage renderRamImage(double usedRamPercent) { int size = 100; QImage image(size, size, QImage::Format_ARGB32); image.fill(Qt::transparent); QPainter painter(&image); painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform); QColor color{Qt::darkRed}; if (usedRamPercent < 70.0) color = Qt::green; else if (usedRamPercent < 80.0) color = Qt::yellow; else if (usedRamPercent < 85.0) color = qRgb(213, 200, 0); else if (usedRamPercent < 90.0) color = qRgb(255, 165, 0); else if (usedRamPercent < 95.0) color = Qt::red; QRadialGradient arcGradient(image.rect().center(), size * 0.6); arcGradient.setColorAt(1.0, Qt::transparent); arcGradient.setColorAt(0.0, color); painter.setBrush(QBrush(arcGradient)); painter.setPen(QPen(Qt::NoPen)); painter.drawEllipse(image.rect()); painter.end(); return image; } void InterfaceImpl::slotCheckFreeRamStatus() { if (!m_notiStatusRam) return; unsigned long freeRamKbytes; double usedRamPercent; if (!onStatusRAM(freeRamKbytes, usedRamPercent)) return; m_notiStatusRam->setIcon(QPixmap::fromImage(renderRamImage(usedRamPercent))); QString statusText(tr("Free memory: %1 (%2% used)").arg(readableSize(freeRamKbytes * 1024)).arg(std::round(usedRamPercent))); m_notiStatusRam->setToolTip(statusText); } void InterfaceImpl::slotCheckFreeSpaceStatus() { if (!m_notiStatusHdd) return; double usedSpacePercent = 0.0; quint64 freeSpaceBytes = 0.0; bool success = onStatusHDD(freeSpaceBytes, usedSpacePercent); QString statusText; QString filename; if (!success) { statusText = tr("Error while reading disk space"); filename = QStringLiteral("icon:usedspace-100.svg"); } else { int usedDiskSpaceFile = 0; if (usedSpacePercent < 11) usedDiskSpaceFile = 0; else if (usedSpacePercent < 21) usedDiskSpaceFile = 20; else if (usedSpacePercent < 41) usedDiskSpaceFile = 40; else if (usedSpacePercent < 61) usedDiskSpaceFile = 60; else if (usedSpacePercent < 81) usedDiskSpaceFile = 80; else usedDiskSpaceFile = 100; filename = QStringLiteral("icon:usedspace-%1.svg").arg(usedDiskSpaceFile); statusText = tr("Free disk space: %1 (%2% used)").arg(readableSize(freeSpaceBytes)).arg(std::round(usedSpacePercent)); } QString tooltip(statusText); m_notiStatusHdd->setIcon(QIcon(filename)); m_notiStatusHdd->setToolTip(tooltip); } QString InterfaceImpl::readableSize(quint64 bytes) const { if (bytes > TB) return QStringLiteral("%1 TB").arg((double) bytes / TB, 0, 'f', 2); else if (bytes > GB) return QStringLiteral("%1 GB").arg((double) bytes / GB, 0, 'f', 2); else if (bytes > MB) return QStringLiteral("%1 MB").arg((double) bytes / MB, 0, 'f', 2); else if (bytes > KB) return QStringLiteral("%1 KB").arg((double) bytes / KB, 0, 'f', 2); else return QStringLiteral("%1 Bytes").arg(bytes); } }