diff --git a/CMakeLists.txt b/CMakeLists.txt index 2c5534c..b4614b4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,7 +22,7 @@ pkg_check_modules(Xcursor REQUIRED IMPORTED_TARGET xcursor) find_package(Libcrypt REQUIRED) -find_package(CutefishFramework REQUIRED COMPONENTS Application Appearance IO) +find_package(CutefishFramework REQUIRED COMPONENTS Application Appearance IO Power) pkg_search_module(FontConfig REQUIRED fontconfig IMPORTED_TARGET) pkg_search_module(ICU REQUIRED icu-i18n) @@ -56,7 +56,6 @@ set(SRCS src/shortcuts/shortcutsmodel.cpp src/networkproxy.cpp src/defaultapplications.cpp - src/mimeapps.cpp src/inputmethod.cpp src/keyboard.cpp src/mock/networkmockmodel.cpp @@ -77,6 +76,7 @@ target_link_libraries(${PROJECT_NAME} Cutefish::Application Cutefish::Appearance Cutefish::IO + Cutefish::Power Qt6::Core Qt6::Widgets Qt6::Quick diff --git a/src/battery.cpp b/src/battery.cpp index f927643..80d3649 100644 --- a/src/battery.cpp +++ b/src/battery.cpp @@ -3,11 +3,11 @@ #include "battery.h" #include -#include +#include +#include #include #include #include -#include #include #include #include @@ -15,52 +15,19 @@ #include #include +#include #include -static const QString s_sServer = "com.cutefish.Services"; -static const QString s_sPath = "/com/cutefish/Services/Battery"; -static const QString s_sInterface = "com.cutefish.Services.Battery"; - static bool mockBatteryEnabled() { return QCoreApplication::arguments().contains(QStringLiteral("--mock-battery")); } -// DBus Battery Info Structure -struct BatteryInfo { - uint time, state; - double value; -}; -Q_DECLARE_METATYPE(BatteryInfo) - -const QDBusArgument &operator<<(QDBusArgument &argument, const BatteryInfo &info) -{ - argument.beginStructure(); - argument << info.time << info.value << info.state; - argument.endStructure(); - return argument; -} - -const QDBusArgument &operator>>(const QDBusArgument &argument, BatteryInfo &info) -{ - argument.beginStructure(); - argument >> info.time >> info.value >> info.state; - argument.endStructure(); - return argument; -} - Battery::Battery(QObject *parent) : QObject(parent) - , m_upowerInterface("org.freedesktop.UPower", "/org/freedesktop/UPower", - "org.freedesktop.UPower", QDBusConnection::systemBus()) - , m_interface("com.cutefish.Services", "/com/cutefish/Services/Battery", - "com.cutefish.Services.Battery", QDBusConnection::sessionBus()) - , m_available(false) - , m_onBattery(false) + , m_status(BatteryStatus::instance()) { if (mockBatteryEnabled()) { - m_available = true; - m_onBattery = true; m_udi = QStringLiteral("mock-battery"); m_chargeLimitSupported = true; m_chargeLimitStart = 75; @@ -68,100 +35,56 @@ Battery::Battery(QObject *parent) return; } - m_available = m_interface.isValid() && !m_interface.lastError().isValid(); - - if (m_available) { - QDBusConnection::sessionBus().connect(s_sServer, s_sPath, s_sInterface, - "chargeStateChanged", this, - SLOT(chargeStateChanged(int))); - QDBusConnection::sessionBus().connect(s_sServer, s_sPath, s_sInterface, - "chargePercentChanged", this, - SLOT(chargePercentChanged(int))); - QDBusConnection::sessionBus().connect(s_sServer, s_sPath, s_sInterface, - "lastChargedPercentChanged", this, - SLOT(lastChargedPercentChanged())); - QDBusConnection::sessionBus().connect(s_sServer, s_sPath, s_sInterface, "capacityChanged", - this, SLOT(capacityChanged(int))); - QDBusConnection::sessionBus().connect(s_sServer, s_sPath, s_sInterface, - "remainingTimeChanged", this, - SLOT(remainingTimeChanged(qlonglong))); - - QDBusInterface interface("org.freedesktop.UPower", "/org/freedesktop/UPower", - "org.freedesktop.UPower", QDBusConnection::systemBus()); - - QDBusConnection::systemBus().connect( - "org.freedesktop.UPower", "/org/freedesktop/UPower", - "org.freedesktop.DBus.Properties", "PropertiesChanged", this, - SLOT(onPropertiesChanged(QString, QVariantMap, QStringList))); - - if (interface.isValid()) { - m_onBattery = interface.property("OnBattery").toBool(); - } + connect(m_status, &BatteryStatus::readyChanged, this, &Battery::readyChanged); + connect(m_status, &BatteryStatus::availableChanged, this, &Battery::validChanged); + connect(m_status, &BatteryStatus::onBatteryChanged, this, &Battery::onBatteryChanged); + connect(m_status, &BatteryStatus::chargeStateChanged, this, &Battery::chargeStateChanged); + connect(m_status, &BatteryStatus::chargePercentChanged, this, &Battery::chargePercentChanged); + connect(m_status, &BatteryStatus::capacityChanged, this, &Battery::capacityChanged); + connect(m_status, &BatteryStatus::statusStringChanged, this, &Battery::remainingTimeChanged); + connect(m_status, &BatteryStatus::lastChargedChanged, this, + &Battery::lastChargedPercentChanged); + connect(m_status, &BatteryStatus::udiChanged, this, &Battery::watchDevice); + + watchDevice(); +} + +void Battery::watchDevice() +{ + if (m_status->udi() == m_udi) + return; - m_udi = m_interface.property("udi").toString(); + QDBusConnection bus = QDBusConnection::systemBus(); + if (!m_udi.isEmpty()) + bus.disconnect("org.freedesktop.UPower", m_udi, "org.freedesktop.DBus.Properties", + "PropertiesChanged", this, + SLOT(onDevicePropertiesChanged(QString, QVariantMap, QStringList))); - if (!m_udi.isEmpty()) { - QDBusConnection::systemBus().connect( - "org.freedesktop.UPower", m_udi, "org.freedesktop.DBus.Properties", + m_udi = m_status->udi(); + + if (!m_udi.isEmpty()) { + bus.connect("org.freedesktop.UPower", m_udi, "org.freedesktop.DBus.Properties", "PropertiesChanged", this, SLOT(onDevicePropertiesChanged(QString, QVariantMap, QStringList))); - loadChargeLimit(); - } - - emit udiChanged(); - emit validChanged(); + loadChargeLimit(); } -} -bool Battery::available() const -{ - return m_available; + emit udiChanged(); } -bool Battery::onBattery() const +bool Battery::ready() const { - return m_onBattery; + return mockBatteryEnabled() || m_status->ready(); } -void Battery::refresh() +bool Battery::available() const { - if (mockBatteryEnabled()) - return; - - m_interface.call("refresh"); + return mockBatteryEnabled() || m_status->available(); } -QVariantList Battery::getHistory(const int timespan, const int resolution) +bool Battery::onBattery() const { - QVariantList listValues; - QVariantMap listItem; - - QDBusMessage historyMessage = QDBusMessage::createMethodCall( - "org.freedesktop.UPower", m_udi, "org.freedesktop.UPower.Device", "GetHistory"); - QVariantList historyMessageArguments; - historyMessageArguments.append("charge"); - historyMessageArguments.append((uint)timespan); - historyMessageArguments.append((uint)resolution); - historyMessage.setArguments(historyMessageArguments); - - quint64 offset = QDateTime::currentDateTime().toSecsSinceEpoch(); - - QDBusReply historyArgument = QDBusConnection::systemBus().call(historyMessage); - if (historyArgument.isValid()) { - QDBusArgument arrayArgument = historyArgument.value(); - arrayArgument.beginArray(); - while (!arrayArgument.atEnd()) { - BatteryInfo info; - arrayArgument >> info; - listItem.insert("time", offset - info.time); - listItem.insert("value", info.value); - - if (info.value > 0) - listValues += listItem; - } - } - - return listValues; + return mockBatteryEnabled() || m_status->onBattery(); } int Battery::chargeState() const @@ -169,7 +92,7 @@ int Battery::chargeState() const if (mockBatteryEnabled()) return 2; - return m_interface.property("chargeState").toInt(); + return m_status->chargeState(); } int Battery::chargePercent() const @@ -177,7 +100,7 @@ int Battery::chargePercent() const if (mockBatteryEnabled()) return 78; - return m_interface.property("chargePercent").toInt(); + return m_status->chargePercent(); } int Battery::lastChargedPercent() const @@ -185,7 +108,7 @@ int Battery::lastChargedPercent() const if (mockBatteryEnabled()) return 100; - return m_interface.property("lastChargedPercent").toInt(); + return m_status->lastChargedPercent(); } int Battery::capacity() const @@ -193,7 +116,7 @@ int Battery::capacity() const if (mockBatteryEnabled()) return 94; - return m_interface.property("capacity").toInt(); + return m_status->capacity(); } QString Battery::statusString() const @@ -201,13 +124,13 @@ QString Battery::statusString() const if (mockBatteryEnabled()) return tr("Discharging ยท 3 hours 24 minutes remaining"); - return m_interface.property("statusString").toString(); + return m_status->statusString(); } QString Battery::lastChargedTime() const { const qint64 secs = mockBatteryEnabled() ? QDateTime::currentSecsSinceEpoch() - 2 * 3600 - : m_interface.property("lastChargedSecs").toLongLong(); + : m_status->lastChargedSecs(); if (secs <= 0) return QString(); @@ -369,21 +292,6 @@ void Battery::updateChargeLimit(const QVariantMap &props) QTimer::singleShot(5000, this, &Battery::readKernelChargeLimit); } -void Battery::onPropertiesChanged(const QString &ifaceName, const QVariantMap &changedProps, - const QStringList &invalidatedProps) -{ - Q_UNUSED(ifaceName); - Q_UNUSED(changedProps); - Q_UNUSED(invalidatedProps); - - bool onBattery = m_upowerInterface.property("OnBattery").toBool(); - if (onBattery != m_onBattery) { - m_onBattery = onBattery; - m_interface.call("refresh"); - emit onBatteryChanged(); - } -} - void Battery::onDevicePropertiesChanged(const QString &ifaceName, const QVariantMap &changedProps, const QStringList &invalidatedProps) { diff --git a/src/battery.h b/src/battery.h index 69ab4e3..85b569a 100644 --- a/src/battery.h +++ b/src/battery.h @@ -5,11 +5,15 @@ #define BATTERY_H #include -#include +#include +class BatteryStatus; + +// The battery page's view of cutefish-services' battery, plus UPower's charge limit. class Battery : public QObject { Q_OBJECT + Q_PROPERTY(bool ready READ ready NOTIFY readyChanged) Q_PROPERTY(bool available READ available NOTIFY validChanged) Q_PROPERTY(int chargeState READ chargeState NOTIFY chargeStateChanged) Q_PROPERTY(int chargePercent READ chargePercent NOTIFY chargePercentChanged) @@ -29,12 +33,10 @@ class Battery : public QObject public: explicit Battery(QObject *parent = nullptr); + bool ready() const; bool available() const; bool onBattery() const; - Q_INVOKABLE void refresh(); - Q_INVOKABLE QVariantList getHistory(const int timespan, const int resolution); - int chargeState() const; int chargePercent() const; int lastChargedPercent() const; @@ -58,25 +60,24 @@ public: QString udi() const; signals: + void readyChanged(); void validChanged(); - void chargeStateChanged(int); - void chargePercentChanged(int); - void capacityChanged(int); - void remainingTimeChanged(qlonglong time); + void chargeStateChanged(); + void chargePercentChanged(); + void capacityChanged(); + void remainingTimeChanged(); void onBatteryChanged(); void lastChargedPercentChanged(); void udiChanged(); void chargeLimitChanged(); private slots: - void onPropertiesChanged(const QString &ifaceName, const QVariantMap &changedProps, const QStringList &invalidatedProps); void onDevicePropertiesChanged(const QString &ifaceName, const QVariantMap &changedProps, const QStringList &invalidatedProps); private: - QDBusInterface m_upowerInterface; - QDBusInterface m_interface; - bool m_available; - bool m_onBattery; + void watchDevice(); + + BatteryStatus *m_status; QString m_udi; bool m_chargeLimitSupported = false; diff --git a/src/defaultapplications.cpp b/src/defaultapplications.cpp index 4fc15ef..40813c5 100644 --- a/src/defaultapplications.cpp +++ b/src/defaultapplications.cpp @@ -8,7 +8,6 @@ #include #include -#include DefaultApplications::DefaultApplications(QObject *parent) : QObject(parent) @@ -50,12 +49,12 @@ void DefaultApplications::loadApps() } const QString defaultBrowser = - MimeApps::associations(mimeAppsListFilePath(), "Default Applications", + MimeApps::associations(MimeApps::userListPath(), "Default Applications", "x-scheme-handler/http").value(0); const QString defaultEMail = - MimeApps::associations(mimeAppsListFilePath(), "Default Applications", + MimeApps::associations(MimeApps::userListPath(), "Default Applications", "x-scheme-handler/mailto").value(0); - const QString defaultTerminal = MimeApps::defaultTerminal(terminalsListFilePath()); + const QString defaultTerminal = MimeApps::defaultTerminal(MimeApps::userTerminalsListPath()); // Init indexes. for (int i = 0; i < m_browserList.size(); ++i) { @@ -168,7 +167,8 @@ void DefaultApplications::setDefaultTerminal(int index) if (index < 0 || index >= m_terminalList.size()) return; - if (!MimeApps::setDefaultTerminal(terminalsListFilePath(), m_terminalList.at(index).fileName)) { + if (!MimeApps::setDefaultTerminal(MimeApps::userTerminalsListPath(), + m_terminalList.at(index).fileName)) { qWarning() << "Failed to save the default terminal"; return; } @@ -177,21 +177,9 @@ void DefaultApplications::setDefaultTerminal(int index) void DefaultApplications::setDefaultApp(const QString &mimeType, const QString &path) { - if (!MimeApps::setDefault(mimeAppsListFilePath(), mimeType, path)) { + if (!MimeApps::setDefault(MimeApps::userListPath(), mimeType, path)) { qWarning() << "Failed to save default application for" << mimeType; return; } loadApps(); } - -QString DefaultApplications::mimeAppsListFilePath() const -{ - return QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) - + QLatin1String("/mimeapps.list"); -} - -QString DefaultApplications::terminalsListFilePath() const -{ - return QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) - + QLatin1String("/xdg-terminals.list"); -} diff --git a/src/defaultapplications.h b/src/defaultapplications.h index 020db15..6f0c84b 100644 --- a/src/defaultapplications.h +++ b/src/defaultapplications.h @@ -46,8 +46,6 @@ public: private: void setDefaultApp(const QString &mimeType, const QString &path); - QString mimeAppsListFilePath() const; - QString terminalsListFilePath() const; signals: void loadFinished(); diff --git a/src/mimeapps.cpp b/src/mimeapps.cpp deleted file mode 100644 index 511e50f..0000000 --- a/src/mimeapps.cpp +++ /dev/null @@ -1,148 +0,0 @@ -#include "mimeapps.h" - -#include -#include -#include -#include -#include - -namespace { -QStringList readEntries(const QStringList &lines, const QString &group, const QString &key) -{ - QString current; - for (const QString &line : lines) { - const QString trimmed = line.trimmed(); - if (trimmed.startsWith('[') && trimmed.endsWith(']')) - current = trimmed.mid(1, trimmed.size() - 2); - else if (current == group && !trimmed.startsWith('#')) { - const auto equals = line.indexOf('='); - if (equals >= 0 && line.left(equals).trimmed() == key) - return line.mid(equals + 1).trimmed().split(';', Qt::SkipEmptyParts); - } - } - return {}; -} - -void writeEntry(QStringList &lines, const QString &group, const QString &key, - const QStringList &values) -{ - const QString entry = key + '=' + values.join(';') + ';'; - QString current; - int insertion = -1; - for (int i = 0; i < lines.size(); ++i) { - const QString trimmed = lines.at(i).trimmed(); - if (trimmed.startsWith('[') && trimmed.endsWith(']')) { - if (current == group) - break; - current = trimmed.mid(1, trimmed.size() - 2); - if (current == group) - insertion = i + 1; - } else if (current == group) { - const auto equals = lines.at(i).indexOf('='); - if (equals >= 0 && lines.at(i).left(equals).trimmed() == key) { - lines.removeAt(i--); - } else { - insertion = i + 1; - } - } - } - if (insertion < 0) { - lines.append('[' + group + ']'); - insertion = lines.size(); - } - lines.insert(insertion, entry); -} - -// An entry may carry a "+" (include) or "-" (exclude) prefix and an ":action" suffix. -QString terminalId(const QString &line) -{ - QString entry = line.trimmed(); - if (entry.startsWith('+') || entry.startsWith('-')) - entry.remove(0, 1); - return entry.section(':', 0, 0); -} -} // namespace - -QStringList MimeApps::associations(const QString &path, const QString &group, - const QString &mimeType) -{ - QFile file(path); - if (!file.open(QIODevice::ReadOnly)) - return {}; - return readEntries(QString::fromUtf8(file.readAll()).split('\n'), group, mimeType); -} - -bool MimeApps::setDefault(const QString &path, const QString &mimeType, const QString &desktopId) -{ - if (mimeType.isEmpty() || mimeType.contains('\n') || mimeType.contains('\r') - || mimeType.contains('=') || desktopId.isEmpty() || desktopId.contains('\n') - || desktopId.contains('\r') || desktopId.contains(';')) - return false; - if (!QDir().mkpath(QFileInfo(path).absolutePath())) - return false; - QLockFile lock(path + ".lock"); - if (!lock.tryLock()) - return false; - QFile input(path); - QStringList lines; - if (input.exists()) { - if (!input.open(QIODevice::ReadOnly)) - return false; - lines = QString::fromUtf8(input.readAll()).split('\n'); - input.close(); - } - auto added = readEntries(lines, "Added Associations", mimeType); - added.removeAll(desktopId); - added.prepend(desktopId); - writeEntry(lines, "Default Applications", mimeType, {desktopId}); - writeEntry(lines, "Added Associations", mimeType, added); - auto removed = readEntries(lines, "Removed Associations", mimeType); - if (removed.removeAll(desktopId)) - writeEntry(lines, "Removed Associations", mimeType, removed); - QSaveFile output(path); - if (!output.open(QIODevice::WriteOnly)) - return false; - const auto data = (lines.join('\n') + '\n').toUtf8(); - return output.write(data) == data.size() && output.commit(); -} - -QString MimeApps::defaultTerminal(const QString &path) -{ - QFile file(path); - if (!file.open(QIODevice::ReadOnly)) - return {}; - for (const QString &line : QString::fromUtf8(file.readAll()).split('\n')) { - const QString entry = line.trimmed(); - if (!entry.isEmpty() && !entry.startsWith('#') && !entry.startsWith('-')) - return terminalId(entry); - } - return {}; -} - -bool MimeApps::setDefaultTerminal(const QString &path, const QString &desktopId) -{ - if (desktopId.isEmpty() || desktopId.contains('\n') || desktopId.contains('\r')) - return false; - if (!QDir().mkpath(QFileInfo(path).absolutePath())) - return false; - QLockFile lock(path + ".lock"); - if (!lock.tryLock()) - return false; - QFile input(path); - QStringList lines; - if (input.exists()) { - if (!input.open(QIODevice::ReadOnly)) - return false; - lines = QString::fromUtf8(input.readAll()).split('\n', Qt::SkipEmptyParts); - input.close(); - } - lines.removeIf([&desktopId](const QString &line) { - return !line.trimmed().startsWith('#') && terminalId(line) == desktopId; - }); - lines.prepend(desktopId); - QSaveFile output(path); - if (!output.open(QIODevice::WriteOnly)) - return false; - const auto data = (lines.join('\n') + '\n').toUtf8(); - return output.write(data) == data.size() && output.commit(); -} diff --git a/src/mimeapps.h b/src/mimeapps.h deleted file mode 100644 index 8e12b88..0000000 --- a/src/mimeapps.h +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once -#include -#include - -namespace MimeApps { -QStringList associations(const QString &path, const QString &group, const QString &mimeType); -bool setDefault(const QString &path, const QString &mimeType, const QString &desktopId); - -// xdg-terminals.list of the xdg-terminal-exec spec: desktop entry IDs, most preferred first. -QString defaultTerminal(const QString &path); -bool setDefaultTerminal(const QString &path, const QString &desktopId); -} // namespace MimeApps diff --git a/src/qml/SideBar.qml b/src/qml/SideBar.qml index 1c3711d..4443d3c 100644 --- a/src/qml/SideBar.qml +++ b/src/qml/SideBar.qml @@ -896,10 +896,14 @@ Item { Battery { id: _battery - Component.onCompleted: { - if (!_battery.available) + // The service is read in the background; until then there is no battery either way. + function syncBattery() { + if (ready && !available) removeItem("battery") } + + onReadyChanged: syncBattery() + Component.onCompleted: syncBattery() } Touchpad { diff --git a/tests/defaultapplications/CMakeLists.txt b/tests/defaultapplications/CMakeLists.txt index dc7ebc0..acb2300 100644 --- a/tests/defaultapplications/CMakeLists.txt +++ b/tests/defaultapplications/CMakeLists.txt @@ -4,7 +4,7 @@ set(CMAKE_AUTOMOC ON) set(CMAKE_CXX_STANDARD 17) find_package(Qt6 REQUIRED COMPONENTS Core Test) find_package(CutefishFramework REQUIRED COMPONENTS Application) -add_executable(tst_mimeapps tst_mimeapps.cpp ../../src/mimeapps.cpp ../../src/defaultapplications.cpp) +add_executable(tst_mimeapps tst_mimeapps.cpp ../../src/defaultapplications.cpp) target_include_directories(tst_mimeapps PRIVATE ../../src) target_link_libraries(tst_mimeapps PRIVATE Qt6::Core Qt6::Test Cutefish::Application) enable_testing() diff --git a/tests/defaultapplications/tst_mimeapps.cpp b/tests/defaultapplications/tst_mimeapps.cpp index e0db3a7..497cba6 100644 --- a/tests/defaultapplications/tst_mimeapps.cpp +++ b/tests/defaultapplications/tst_mimeapps.cpp @@ -68,52 +68,6 @@ private slots: QCOMPARE(reopened.emailIndex(), 0); QCOMPARE(reopened.terminalIndex(), 0); } - - void preservesAssociations() - { - QTemporaryDir dir; - const QString path = dir.filePath("mimeapps.list"); - QFile file(path); - QVERIFY(file.open(QIODevice::WriteOnly)); - file.write("# Keep this comment\n[Default Applications]\nimage/png=image.desktop;\n" - "[Added Associations]\ntext/plain=old.desktop;new.desktop;\n" - "[Removed Associations]\ntext/plain=new.desktop;blocked.desktop;\n"); - file.close(); - QVERIFY(MimeApps::setDefault(path, "text/plain", "new.desktop")); - QVERIFY(MimeApps::setDefault(path, "text/plain", "new.desktop")); - QCOMPARE(MimeApps::associations(path, "Default Applications", "text/plain"), - QStringList {"new.desktop"}); - QCOMPARE(MimeApps::associations(path, "Default Applications", "image/png"), - QStringList {"image.desktop"}); - QCOMPARE(MimeApps::associations(path, "Added Associations", "text/plain"), - QStringList({"new.desktop", "old.desktop"})); - QCOMPARE(MimeApps::associations(path, "Removed Associations", "text/plain"), - QStringList {"blocked.desktop"}); - QVERIFY(file.open(QIODevice::ReadOnly)); - const auto contents = file.readAll(); - QVERIFY(contents.contains("# Keep this comment")); - QVERIFY(contents.contains("text/plain=new.desktop;")); - QVERIFY(!contents.contains("text%2Fplain")); - QVERIFY(!MimeApps::setDefault(path, "text/plain", "bad;entry.desktop")); - QVERIFY(!MimeApps::setDefault(dir.path(), "text/plain", "new.desktop")); - } - - void terminalListPrependsTheDefault() - { - QTemporaryDir dir; - const QString path = dir.filePath("xdg-terminals.list"); - QFile file(path); - QVERIFY(file.open(QIODevice::WriteOnly)); - file.write("# Keep this comment\n-blocked.desktop\nfirst.desktop\n+new.desktop:new-window\n"); - file.close(); - QCOMPARE(MimeApps::defaultTerminal(path), QStringLiteral("first.desktop")); - QVERIFY(MimeApps::setDefaultTerminal(path, "new.desktop")); - QCOMPARE(MimeApps::defaultTerminal(path), QStringLiteral("new.desktop")); - QVERIFY(file.open(QIODevice::ReadOnly)); - QCOMPARE(file.readAll(), QByteArray("new.desktop\n# Keep this comment\n-blocked.desktop\n" - "first.desktop\n")); - QVERIFY(!MimeApps::setDefaultTerminal(path, "bad\nentry.desktop")); - } }; QTEST_GUILESS_MAIN(MimeAppsTest) #include "tst_mimeapps.moc"