mirror of
https://github.com/cmclark00/retro-imager.git
synced 2025-05-18 07:55:21 +01:00
parent
6069e8f441
commit
755d7dc6ab
8 changed files with 115 additions and 23 deletions
|
@ -19,7 +19,7 @@ set(CMAKE_AUTOMOC ON)
|
||||||
set(CMAKE_AUTORCC ON)
|
set(CMAKE_AUTORCC ON)
|
||||||
|
|
||||||
# Adding headers explicity so they are displayed in Qt Creator
|
# Adding headers explicity so they are displayed in Qt Creator
|
||||||
set(HEADERS config.h imagewriter.h networkaccessmanagerfactory.h nan.h drivelistitem.h drivelistmodel.h driveformatthread.h powersaveblocker.h
|
set(HEADERS config.h imagewriter.h networkaccessmanagerfactory.h nan.h drivelistitem.h drivelistmodel.h drivelistmodelpollthread.h driveformatthread.h powersaveblocker.h
|
||||||
downloadthread.h downloadextractthread.h localfileextractthread.h dependencies/mountutils/src/mountutils.hpp)
|
downloadthread.h downloadextractthread.h localfileextractthread.h dependencies/mountutils/src/mountutils.hpp)
|
||||||
|
|
||||||
# Add dependencies
|
# Add dependencies
|
||||||
|
@ -67,7 +67,7 @@ if (NOT atomicbuiltin)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(SOURCES "main.cpp" "imagewriter.cpp" "networkaccessmanagerfactory.cpp"
|
set(SOURCES "main.cpp" "imagewriter.cpp" "networkaccessmanagerfactory.cpp"
|
||||||
"drivelistitem.cpp" "drivelistmodel.cpp" "downloadthread.cpp" "downloadextractthread.cpp"
|
"drivelistitem.cpp" "drivelistmodel.cpp" "drivelistmodelpollthread.cpp" "downloadthread.cpp" "downloadextractthread.cpp"
|
||||||
"driveformatthread.cpp" "localfileextractthread.cpp" "powersaveblocker.cpp" "qml.qrc")
|
"driveformatthread.cpp" "localfileextractthread.cpp" "powersaveblocker.cpp" "qml.qrc")
|
||||||
|
|
||||||
find_package(Qt5 COMPONENTS Core Quick LinguistTools Svg OPTIONAL_COMPONENTS Widgets)
|
find_package(Qt5 COMPONENTS Core Quick LinguistTools Svg OPTIONAL_COMPONENTS Widgets)
|
||||||
|
|
|
@ -20,6 +20,9 @@ DriveListModel::DriveListModel(QObject *parent)
|
||||||
{isScsiRole, "isScsi"},
|
{isScsiRole, "isScsi"},
|
||||||
{mountpointsRole, "mountpoints"}
|
{mountpointsRole, "mountpoints"}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Enumerate drives in seperate thread, but process results in UI thread
|
||||||
|
connect(&_thread, SIGNAL(newDriveList(std::vector<Drivelist::DeviceDescriptor>)), SLOT(processDriveList(std::vector<Drivelist::DeviceDescriptor>)));
|
||||||
}
|
}
|
||||||
|
|
||||||
int DriveListModel::rowCount(const QModelIndex &) const
|
int DriveListModel::rowCount(const QModelIndex &) const
|
||||||
|
@ -45,11 +48,10 @@ QVariant DriveListModel::data(const QModelIndex &index, int role) const
|
||||||
return _drivelist.values().at(row)->property(propertyName);
|
return _drivelist.values().at(row)->property(propertyName);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DriveListModel::refreshDriveList()
|
void DriveListModel::processDriveList(std::vector<Drivelist::DeviceDescriptor> l)
|
||||||
{
|
{
|
||||||
bool changes = false;
|
bool changes = false;
|
||||||
bool filterSystemDrives = DRIVELIST_FILTER_SYSTEM_DRIVES;
|
bool filterSystemDrives = DRIVELIST_FILTER_SYSTEM_DRIVES;
|
||||||
auto l = Drivelist::ListStorageDevices();
|
|
||||||
QSet<QString> drivesInNewList;
|
QSet<QString> drivesInNewList;
|
||||||
|
|
||||||
for (auto &i: l)
|
for (auto &i: l)
|
||||||
|
@ -117,3 +119,13 @@ void DriveListModel::refreshDriveList()
|
||||||
if (changes)
|
if (changes)
|
||||||
endResetModel();
|
endResetModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DriveListModel::startPolling()
|
||||||
|
{
|
||||||
|
_thread.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DriveListModel::stopPolling()
|
||||||
|
{
|
||||||
|
_thread.stop();
|
||||||
|
}
|
||||||
|
|
|
@ -10,25 +10,30 @@
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
#include <QHash>
|
#include <QHash>
|
||||||
#include "drivelistitem.h"
|
#include "drivelistitem.h"
|
||||||
|
#include "drivelistmodelpollthread.h"
|
||||||
|
|
||||||
class DriveListModel : public QAbstractListModel
|
class DriveListModel : public QAbstractListModel
|
||||||
{
|
{
|
||||||
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
DriveListModel(QObject *parent = nullptr);
|
DriveListModel(QObject *parent = nullptr);
|
||||||
virtual int rowCount(const QModelIndex &) const;
|
virtual int rowCount(const QModelIndex &) const;
|
||||||
virtual QHash<int, QByteArray> roleNames() const;
|
virtual QHash<int, QByteArray> roleNames() const;
|
||||||
virtual QVariant data(const QModelIndex &index, int role) const;
|
virtual QVariant data(const QModelIndex &index, int role) const;
|
||||||
|
void startPolling();
|
||||||
|
void stopPolling();
|
||||||
|
|
||||||
enum driveListRoles {
|
enum driveListRoles {
|
||||||
deviceRole = Qt::UserRole + 1, descriptionRole, sizeRole, isUsbRole, isScsiRole, mountpointsRole
|
deviceRole = Qt::UserRole + 1, descriptionRole, sizeRole, isUsbRole, isScsiRole, mountpointsRole
|
||||||
};
|
};
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void refreshDriveList();
|
void processDriveList(std::vector<Drivelist::DeviceDescriptor> l);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QMap<QString,DriveListItem *> _drivelist;
|
QMap<QString,DriveListItem *> _drivelist;
|
||||||
QHash<int, QByteArray> _rolenames;
|
QHash<int, QByteArray> _rolenames;
|
||||||
|
DriveListModelPollThread _thread;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // DRIVELISTMODEL_H
|
#endif // DRIVELISTMODEL_H
|
||||||
|
|
47
drivelistmodelpollthread.cpp
Normal file
47
drivelistmodelpollthread.cpp
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
#include "drivelistmodelpollthread.h"
|
||||||
|
#include <QElapsedTimer>
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
* Copyright (C) 2020 Raspberry Pi (Trading) Limited
|
||||||
|
*/
|
||||||
|
|
||||||
|
DriveListModelPollThread::DriveListModelPollThread(QObject *parent)
|
||||||
|
: QThread(parent), _terminate(false)
|
||||||
|
{
|
||||||
|
qRegisterMetaType< std::vector<Drivelist::DeviceDescriptor> >( "std::vector<Drivelist::DeviceDescriptor>" );
|
||||||
|
}
|
||||||
|
|
||||||
|
DriveListModelPollThread::~DriveListModelPollThread()
|
||||||
|
{
|
||||||
|
_terminate = true;
|
||||||
|
if (!wait(2000)) {
|
||||||
|
terminate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DriveListModelPollThread::stop()
|
||||||
|
{
|
||||||
|
_terminate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DriveListModelPollThread::start()
|
||||||
|
{
|
||||||
|
_terminate = false;
|
||||||
|
QThread::start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DriveListModelPollThread::run()
|
||||||
|
{
|
||||||
|
QElapsedTimer t1;
|
||||||
|
|
||||||
|
while (!_terminate)
|
||||||
|
{
|
||||||
|
t1.start();
|
||||||
|
emit newDriveList( Drivelist::ListStorageDevices() );
|
||||||
|
if (t1.elapsed() > 1000)
|
||||||
|
qDebug() << "Enumerating drives took a long time:" << t1.elapsed()/1000.0 << "seconds";
|
||||||
|
QThread::sleep(1);
|
||||||
|
}
|
||||||
|
}
|
29
drivelistmodelpollthread.h
Normal file
29
drivelistmodelpollthread.h
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
#ifndef DRIVELISTMODELPOLLTHREAD_H
|
||||||
|
#define DRIVELISTMODELPOLLTHREAD_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
* Copyright (C) 2020 Raspberry Pi (Trading) Limited
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <QThread>
|
||||||
|
#include "dependencies/drivelist/src/drivelist.hpp"
|
||||||
|
|
||||||
|
class DriveListModelPollThread : public QThread
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
DriveListModelPollThread(QObject *parent = nullptr);
|
||||||
|
~DriveListModelPollThread();
|
||||||
|
void start();
|
||||||
|
void stop();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool _terminate;
|
||||||
|
virtual void run() override;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void newDriveList(std::vector<Drivelist::DeviceDescriptor> list);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // DRIVELISTMODELPOLLTHREAD_H
|
|
@ -323,10 +323,16 @@ void ImageWriter::setCustomOsListUrl(const QUrl &url)
|
||||||
_repo = url;
|
_repo = url;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Refresh the list of available drives */
|
/* Start polling the list of available drives */
|
||||||
void ImageWriter::refreshDriveList()
|
void ImageWriter::startDriveListPolling()
|
||||||
{
|
{
|
||||||
_drivelist.refreshDriveList();
|
_drivelist.startPolling();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Stop polling the list of available drives */
|
||||||
|
void ImageWriter::stopDriveListPolling()
|
||||||
|
{
|
||||||
|
_drivelist.stopPolling();
|
||||||
}
|
}
|
||||||
|
|
||||||
DriveListModel *ImageWriter::getDriveList()
|
DriveListModel *ImageWriter::getDriveList()
|
||||||
|
|
|
@ -48,10 +48,13 @@ public:
|
||||||
/* Return true if url is in our local disk cache */
|
/* Return true if url is in our local disk cache */
|
||||||
Q_INVOKABLE bool isCached(const QUrl &url, const QByteArray &sha256);
|
Q_INVOKABLE bool isCached(const QUrl &url, const QByteArray &sha256);
|
||||||
|
|
||||||
/* Refresh the list of available drives */
|
/* Start polling the list of available drives */
|
||||||
Q_INVOKABLE void refreshDriveList();
|
Q_INVOKABLE void startDriveListPolling();
|
||||||
|
|
||||||
/* Return list of available drives. Call refreshDriveList() first */
|
/* Stop polling the list of available drives */
|
||||||
|
Q_INVOKABLE void stopDriveListPolling();
|
||||||
|
|
||||||
|
/* Return list of available drives. Call startDriveListPolling() first */
|
||||||
DriveListModel *getDriveList();
|
DriveListModel *getDriveList();
|
||||||
|
|
||||||
/* Utility function to return filename part from URL */
|
/* Utility function to return filename part from URL */
|
||||||
|
|
14
main.qml
14
main.qml
|
@ -149,8 +149,7 @@ ApplicationWindow {
|
||||||
Layout.preferredWidth: 100
|
Layout.preferredWidth: 100
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
onClicked: {
|
onClicked: {
|
||||||
imageWriter.refreshDriveList()
|
imageWriter.startDriveListPolling()
|
||||||
drivePollTimer.start()
|
|
||||||
dstpopup.open()
|
dstpopup.open()
|
||||||
dstlist.forceActiveFocus()
|
dstlist.forceActiveFocus()
|
||||||
}
|
}
|
||||||
|
@ -546,6 +545,7 @@ ApplicationWindow {
|
||||||
height: parent.height-50
|
height: parent.height-50
|
||||||
padding: 0
|
padding: 0
|
||||||
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
|
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
|
||||||
|
onClosed: imageWriter.stopDriveListPolling()
|
||||||
|
|
||||||
// background of title
|
// background of title
|
||||||
Rectangle {
|
Rectangle {
|
||||||
|
@ -616,7 +616,6 @@ ApplicationWindow {
|
||||||
if (currentIndex == -1)
|
if (currentIndex == -1)
|
||||||
return
|
return
|
||||||
|
|
||||||
drivePollTimer.stop()
|
|
||||||
dstpopup.close()
|
dstpopup.close()
|
||||||
imageWriter.setDst(currentItem.device, currentItem.size)
|
imageWriter.setDst(currentItem.device, currentItem.size)
|
||||||
dstbutton.text = currentItem.description
|
dstbutton.text = currentItem.description
|
||||||
|
@ -628,7 +627,6 @@ ApplicationWindow {
|
||||||
if (currentIndex == -1)
|
if (currentIndex == -1)
|
||||||
return
|
return
|
||||||
|
|
||||||
drivePollTimer.stop()
|
|
||||||
dstpopup.close()
|
dstpopup.close()
|
||||||
imageWriter.setDst(currentItem.device, currentItem.size)
|
imageWriter.setDst(currentItem.device, currentItem.size)
|
||||||
dstbutton.text = currentItem.description
|
dstbutton.text = currentItem.description
|
||||||
|
@ -720,7 +718,6 @@ ApplicationWindow {
|
||||||
}
|
}
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
drivePollTimer.stop()
|
|
||||||
dstpopup.close()
|
dstpopup.close()
|
||||||
imageWriter.setDst(device, size)
|
imageWriter.setDst(device, size)
|
||||||
dstbutton.text = description
|
dstbutton.text = description
|
||||||
|
@ -784,13 +781,6 @@ ApplicationWindow {
|
||||||
property alias y: window.y
|
property alias y: window.y
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Timer for polling drivelist changes */
|
|
||||||
Timer {
|
|
||||||
id: drivePollTimer
|
|
||||||
repeat: true
|
|
||||||
onTriggered: imageWriter.refreshDriveList()
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Utility functions */
|
/* Utility functions */
|
||||||
function httpRequest(url, callback) {
|
function httpRequest(url, callback) {
|
||||||
var xhr = new XMLHttpRequest();
|
var xhr = new XMLHttpRequest();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue