| 167 | QString Backend::getAccountId() const { return m_accountId; } |
| 168 | |
| 169 | void Backend::scanStorageForApps() |
| 170 | { |
| 171 | m_apps.clear(); |
| 172 | |
| 173 | if (m_accountId.isEmpty() || m_storagePath.isEmpty()) return; |
| 174 | |
| 175 | QString accountDir = m_storagePath + "/" + m_accountId; |
| 176 | QDir dir(accountDir); |
| 177 | if (!dir.exists()) return; |
| 178 | |
| 179 | static const QSet<QString> metadataFiles = {"cn.dat", "root_token.dat", "file_tokens.dat", "deleted.dat"}; |
| 180 | |
| 181 | QStringList appDirs = dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot); |
| 182 | for (const auto &appIdStr : appDirs) { |
| 183 | bool ok; |
| 184 | uint appId = appIdStr.toUInt(&ok); |
| 185 | if (!ok || appId == 0) continue; |
| 186 | if (kHiddenAppIds.contains(appId)) continue; |
| 187 | |
| 188 | QString appDir = accountDir + "/" + appIdStr; |
| 189 | |
| 190 | // Read save root from root_token.dat |
| 191 | QString saveRoot; |
| 192 | QFile rootTokenFile(appDir + "/root_token.dat"); |
| 193 | if (rootTokenFile.open(QIODevice::ReadOnly | QIODevice::Text)) { |
| 194 | saveRoot = QString::fromUtf8(rootTokenFile.readAll()).trimmed(); |
| 195 | rootTokenFile.close(); |
| 196 | } |
| 197 | |
| 198 | // Count files and compute size (skip metadata) |
| 199 | QDirIterator it(appDir, QDir::Files, QDirIterator::Subdirectories); |
| 200 | int count = 0; |
| 201 | qint64 size = 0; |
| 202 | while (it.hasNext()) { |
| 203 | it.next(); |
| 204 | QString fileName = it.fileName(); |
| 205 | if (metadataFiles.contains(fileName)) continue; |
| 206 | count++; |
| 207 | size += it.fileInfo().size(); |
| 208 | } |
| 209 | |
| 210 | QString name = m_nameCache.value(appId, QString("App %1").arg(appId)); |
| 211 | m_apps.append({appId, name, QString(), saveRoot, count, size, true, false}); |
| 212 | } |
| 213 | |
| 214 | emit appsChanged(); |
| 215 | } |
| 216 | |
| 217 | void Backend::loadSLSsteamApps() |
| 218 | { |