refactor: remove ensureConnection method and update MediaPreviewDialog for image loading

This commit is contained in:
uncor3
2025-09-14 00:36:32 +00:00
parent 9fbe1b5f45
commit ef6ad480a0
6 changed files with 74 additions and 96 deletions
+5 -66
View File
@@ -1,5 +1,6 @@
#include "fileexplorerwidget.h"
#include "iDescriptor.h"
#include "mediapreviewdialog.h"
#include <QDebug>
#include <QDesktopServices>
#include <QFileDialog>
@@ -13,76 +14,10 @@
#include <libimobiledevice/afc.h>
#include <libimobiledevice/libimobiledevice.h>
bool FileExplorerWidget::ensureConnection()
{
// Validate all required connections
if (!device->device) {
qDebug() << "Failed to connect to device";
QMessageBox::warning(this, "Error", "Device connection lost");
return false;
}
if (device->afcClient) {
qDebug() << "AFC client is defined";
}
char **dirs = NULL;
afc_error_t err = afc_read_directory(device->afcClient, "/", &dirs);
if (err != AFC_E_SUCCESS) {
qDebug() << "Failed to read directory";
qDebug() << "AFC error code: " << err;
QMessageBox::warning(this, "Error", "Need to reinitialize AFC service");
return false;
}
return true;
// lockdownd_error_t ldret = LOCKDOWN_E_UNKNOWN_ERROR;
// if (LOCKDOWN_E_SUCCESS != (ldret = lockdownd_client_new_with_handshake(
// device->device, &client, APP_LABEL))) {
// return false; // Failed to create lockdown client
// // result.error = ldret;
// qDebug() << "In fileexplorer Failed to create lockdown client: "
// << ldret;
// // idevice_free(result.device);
// // return result;
// }
// // if (!lockdownService) {
// // qDebug() << "Failed to connect to lockdown service";
// // QMessageBox::warning(this, "Error", "Lockdown service unavailable");
// // Try to reinitialize the AFC service
// if (lockdownd_start_service(client, "com.apple.afc", &lockdownService) !=
// LOCKDOWN_E_SUCCESS) {
// qDebug() << "Failed to restart AFC service";
// QMessageBox::warning(this, "Error", "Could not restart AFC service");
// return false;
// }
// if (afc_client_new(device->device, lockdownService, &afcClient) !=
// AFC_E_SUCCESS) {
// qDebug() << "Failed to create new AFC client";
// lockdownd_service_descriptor_free(lockdownService);
// QMessageBox::warning(this, "Error", "Could not create AFC client");
// return false;
// }
// qDebug() << "Successfully reinitialized AFC service";
// // }
// return true;
}
FileExplorerWidget::FileExplorerWidget(iDescriptorDevice *device,
QWidget *parent)
: QWidget(parent), device(device)
{
// Debug: log devices vector
if (!ensureConnection()) {
qDebug() << "Failed to ensure connection in FileExplorerWidget";
return;
}
QVBoxLayout *mainLayout = new QVBoxLayout(this);
// --- New: Export/Import buttons layout ---
@@ -158,6 +93,10 @@ void FileExplorerWidget::onItemDoubleClicked(QListWidgetItem *item)
history.push(nextPath);
loadPath(nextPath);
} else {
auto *previewDialog = new MediaPreviewDialog(device, nextPath, this);
previewDialog->setAttribute(Qt::WA_DeleteOnClose);
previewDialog->show();
// TODO: we need this ?
emit fileSelected(nextPath);
}
}
-1
View File
@@ -52,7 +52,6 @@ private:
const char *local_path);
int import_file_to_device(afc_client_t afc, const char *device_path,
const char *local_path);
bool ensureConnection();
};
#endif // FILEEXPLORERWIDGET_H
+7 -1
View File
@@ -309,7 +309,7 @@ struct GetMountedImageResult {
QPair<bool, plist_t> _get_mounted_image(const char *udid);
bool restart(idevice_t device);
bool restart(std::string udid);
// TODO:move
struct ImageInfo {
@@ -371,3 +371,9 @@ bool is_product_type_newer(const std::string &productType,
*/
bool is_product_type_older(const std::string &productType,
const std::string &otherProductType);
bool query_mobile_gestalt(iDescriptorDevice *id_device, const QStringList &keys,
uint32_t &xml_size, char *&xml_data);
;
std::string safeGetXML(const char *key, pugi::xml_node dict);
+15 -19
View File
@@ -174,26 +174,22 @@ void MediaPreviewDialog::loadMedia()
void MediaPreviewDialog::loadImage()
{
// TODO
// // Load image asynchronously
// auto future = QtConcurrent::run([this]() {
// return PhotoModel::loadThumbnailFromDevice(m_device, m_filePath,
// QSize(4096, 4096), "");
// });
auto future = QtConcurrent::run(
[this]() { return PhotoModel::loadImage(m_device, m_filePath, ""); });
// auto *watcher = new QFutureWatcher<QPixmap>(this);
// connect(watcher, &QFutureWatcher<QPixmap>::finished, this,
// [this, watcher]() {
// QPixmap pixmap = watcher->result();
// if (!pixmap.isNull()) {
// m_originalPixmap = pixmap;
// onImageLoaded();
// } else {
// onImageLoadFailed();
// }
// watcher->deleteLater();
// });
// watcher->setFuture(future);
auto *watcher = new QFutureWatcher<QPixmap>(this);
connect(watcher, &QFutureWatcher<QPixmap>::finished, this,
[this, watcher]() {
QPixmap pixmap = watcher->result();
if (!pixmap.isNull()) {
m_originalPixmap = pixmap;
onImageLoaded();
} else {
onImageLoadFailed();
}
watcher->deleteLater();
});
watcher->setFuture(future);
}
void MediaPreviewDialog::loadVideo()
+39 -2
View File
@@ -30,7 +30,7 @@ PhotoModel::PhotoModel(iDescriptorDevice *device, QObject *parent)
// Configure memory cache (50MB limit - much more reasonable)
m_thumbnailCache.setMaxCost(50 * 1024 * 1024);
connect(this, &PhotoModel::thumbnailNeedsLoading, this,
connect(this, &PhotoModel::thumbnailNeedsToBeLoaded, this,
&PhotoModel::requestThumbnail, Qt::QueuedConnection);
// Populate the photo paths
@@ -153,7 +153,7 @@ QVariant PhotoModel::data(const QModelIndex &index, int role) const
// Start async loading for both images and videos
if (!m_loadingPaths.contains(info.filePath)) {
qDebug() << "Starting load for:" << info.fileName;
emit const_cast<PhotoModel *>(this)->thumbnailNeedsLoading(
emit const_cast<PhotoModel *>(this)->thumbnailNeedsToBeLoaded(
index.row());
}
@@ -360,6 +360,43 @@ QPixmap PhotoModel::loadThumbnailFromDevice(iDescriptorDevice *device,
return thumbnail;
}
QPixmap PhotoModel::loadImage(iDescriptorDevice *device,
const QString &filePath, const QString &cachePath)
{
// Check disk cache first
if (QFile::exists(cachePath)) {
QPixmap cached(cachePath);
if (!cached.isNull()) {
qDebug() << "Disk cache HIT for:" << QFileInfo(filePath).fileName();
return cached;
}
}
// Load from device using your AFC function
QByteArray imageData = read_afc_file_to_byte_array(
device->afcClient, filePath.toUtf8().constData());
if (imageData.isEmpty()) {
qDebug() << "Could not read from device:" << filePath;
return QPixmap(); // Return empty pixmap on error
}
// Load pixmap from data
QPixmap original;
if (!original.loadFromData(imageData)) {
qDebug() << "Could not decode image data for:" << filePath;
return QPixmap();
}
// Save to disk cache
QDir().mkpath(QFileInfo(cachePath).absolutePath());
if (original.save(cachePath, "JPG", 85)) {
qDebug() << "Saved to disk cache:" << QFileInfo(filePath).fileName();
}
return original;
}
void PhotoModel::populatePhotoPaths()
{
beginResetModel();
+8 -7
View File
@@ -58,8 +58,15 @@ public:
QStringList getAllFilePaths() const;
QStringList getFilteredFilePaths() const;
static QPixmap loadImage(iDescriptorDevice *device, const QString &filePath,
const QString &cachePath);
// Static helper methods
static QPixmap loadThumbnailFromDevice(iDescriptorDevice *device,
const QString &filePath,
const QSize &size,
const QString &cachePath);
signals:
void thumbnailNeedsLoading(int index);
void thumbnailNeedsToBeLoaded(int index);
void exportRequested(const QStringList &filePaths);
private slots:
@@ -94,12 +101,6 @@ private:
QDateTime extractDateTimeFromFile(const QString &filePath) const;
PhotoInfo::FileType determineFileType(const QString &fileName) const;
// Static helper methods
static QPixmap loadThumbnailFromDevice(iDescriptorDevice *device,
const QString &filePath,
const QSize &size,
const QString &cachePath);
static QPixmap generateVideoThumbnail(iDescriptorDevice *device,
const QString &filePath,
const QSize &requestedSize);