mirror of
https://github.com/iDescriptor/iDescriptor.git
synced 2026-06-22 03:45:51 +08:00
refactor: remove ensureConnection method and update MediaPreviewDialog for image loading
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user