Changeset - 8f2355969e7e
[Not reviewed]
tip default
0 3 0
Silverwing - 3 years ago 2020-11-12 23:23:24

Editing labels; Fix inability to format images without initial device change; a little bit of refactoring
3 files changed with 77 insertions and 27 deletions:
0 comments (0 inline, 0 general)
floppyemu/__init__.py
Show inline comments
 
@@ -4,6 +4,8 @@ import os
 

	
 
SINGLE_DISK_OFFSET = 1572864
 
MAX_IMAGES_ON_DRIVE = 1000
 
LABEL_START_OFFSET = 0x2B
 
LABEL_LENGTH = 11
 

	
 

	
 
def get_or_create_empty_image(index, temp_path, size=1440):
 
@@ -15,6 +17,8 @@ def get_or_create_empty_image(index, tem
 
    proc = subprocess.Popen(['mkfs.msdos', '-C', filename, str(size)])
 
    rval = proc.wait()
 
    if rval != 0:
 
        print(proc.stdout.read())
 
        print(proc.stderr.read())
 
        raise Exception('Not created')
 

	
 
    return filename
 
@@ -98,10 +102,21 @@ def list_images(device):
 
                    # As an additional precaution check fs type.
 
                    # If it's valid, then get label, otherwise consider disk unlabeled
 
                    if bootsector[0x36:0x3E] in (b'FAT12   ', b'FAT16   ', b'FAT     '):
 
                        label = bootsector[0x2B:0x36].decode(encoding='cp1251')
 
                        label = bootsector[LABEL_START_OFFSET:LABEL_START_OFFSET + LABEL_LENGTH].decode(
 
                            encoding='cp1251'
 
                        )
 
                dfile.seek(SINGLE_DISK_OFFSET - 512, 1)
 
            else:
 
                disksize = 0
 
                dfile.seek(SINGLE_DISK_OFFSET - 512, 1)
 
            rval.append((label, disksize))
 
    return rval
 

	
 

	
 
def update_label(device, index, label):
 
    offset = SINGLE_DISK_OFFSET * index
 
    label = label[0:11]
 
    label = label + ' ' * (LABEL_LENGTH - len(label))
 
    with open(device, 'wb') as dfile:
 
        dfile.seek(offset + LABEL_START_OFFSET, 0)
 
        dfile.write(label.encode(encoding='cp1251'))
forms/mainwindow.py
Show inline comments
 
@@ -26,6 +26,7 @@ class CustomListModel(QtCore.QStringList
 

	
 
class CustomTableModel(QtCore.QAbstractTableModel):
 
    headers = ['Label', 'Size']
 
    edited = QtCore.pyqtSignal(int, str)
 

	
 
    def __init__(self, placeholder):
 
        super().__init__()
 
@@ -37,8 +38,31 @@ class CustomTableModel(QtCore.QAbstractT
 
        self.model = model
 
        self.endResetModel()
 

	
 
    def flags(self, index):
 
        if not index.isValid():
 
            return QtCore.Qt.ItemIsEnabled
 

	
 
        if index.column() == 0:
 
            return int(super().flags(index)) | QtCore.Qt.ItemIsEditable
 

	
 
        return super().flags(index)
 

	
 
    def setData(self, index, value, role):
 
        if index.isValid() and role == QtCore.Qt.EditRole:
 
            self.edited.emit(index.row(), value)
 
            return True
 

	
 
        return False
 

	
 

	
 
    def data(self, index, role=QtCore.Qt.DisplayRole):
 
        model = self.model[index.row()]
 
        if role == QtCore.Qt.EditRole:
 
            if QtCore.QVariant(model[index.column()]):
 
                if index.column() == 0:
 
                    return QtCore.QVariant(model[index.column()])
 

	
 
            return QtCore.QVariant(None)
 
        if role == QtCore.Qt.DisplayRole:
 
            if QtCore.QVariant(model[index.column()]):
 
                if index.column() == 1:
 
@@ -72,12 +96,14 @@ class MainWindow(Ui_MainWindow, QtWidget
 

	
 
        self.devices_model = CustomListModel()
 
        self.table_model = CustomTableModel('(Not set)')
 
        self.table_model.edited.connect(self.table_edited)
 

	
 
        self.devices_combobox.setModel(self.devices_model)
 
        self.refresh_disk_drives()
 

	
 
        self.tableView.setModel(self.table_model)
 
        self.refresh_image_list()
 
        self.tableView.doubleClicked.connect(self.table_double_click)
 
        self.on_device_change()
 

	
 
        self.action_refresh_devices.triggered.connect(self.refresh_disk_drives)
 
        self.devices_combobox.currentIndexChanged.connect(self.on_device_change)
 
@@ -89,20 +115,34 @@ class MainWindow(Ui_MainWindow, QtWidget
 
        self.action_format_usb.triggered.connect(self.format_many)
 
        self.action_about.triggered.connect(self.show_about_dialog)
 

	
 
    @property
 
    def current_device(self):
 
        if self.devices_combobox.currentIndex() != -1:
 
            return '/dev/{}'.format(self.devices_model.getItem(self.devices_combobox.currentIndex())[0])
 
        else:
 
            return None
 

	
 
    def table_edited(self, index, value):
 
        if self.current_device:
 
            floppyemu.update_label(self.current_device, index, value)
 
            self.refresh_image_list()
 

	
 

	
 
    def table_double_click(self, index):
 
        self.tableView.edit(index)
 

	
 
    def show_about_dialog(self):
 
        AboutWidget().exec_()
 

	
 
    def format_one(self):
 
        if self.devices_combobox.currentIndex() != -1:
 
        if self.current_device:
 
            indexes = self.tableView.selectedIndexes()
 
            device = '/dev/{}'.format(self.devices_model.getItem(self.devices_combobox.currentIndex())[0])
 
            FormatOneDialog.show_dialog(indexes[0].row(), device, os.path.join(self.root, 'temp'))
 
            FormatOneDialog.show_dialog(indexes[0].row(), self.current_device, os.path.join(self.root, 'temp'))
 
            self.refresh_image_list()
 

	
 
    def format_many(self):
 
        if self.devices_combobox.currentIndex() != -1:
 
            device = '/dev/{}'.format(self.devices_model.getItem(self.devices_combobox.currentIndex())[0])
 
            FormatManyDialog.show_dialog(device, os.path.join(self.root, 'temp'))
 
        if self.current_device:
 
            FormatManyDialog.show_dialog(self.current_device, os.path.join(self.root, 'temp'))
 
            self.refresh_image_list()
 

	
 
    def refresh_disk_drives(self):
 
@@ -129,21 +169,19 @@ class MainWindow(Ui_MainWindow, QtWidget
 

	
 
    def refresh_image_list(self):
 
        try:
 
            if self.devices_combobox.currentIndex() != -1:
 
                device = '/dev/{}'.format(self.devices_model.getItem(self.devices_combobox.currentIndex())[0])
 
                m = floppyemu.list_images(device)
 
            if self.current_device:
 
                m = floppyemu.list_images(self.current_device)
 
                self.table_model.setModel(m)
 
        except PermissionError:
 
            device = '/dev/{}'.format(self.devices_model.getItem(self.devices_combobox.currentIndex())[0])
 
            QtWidgets.QMessageBox.critical(
 
                self, 'Permission error',
 
                'You have no access to the device %s. Please restart program as user with proper rights' % device
 
                'You have no access to the device %s. '
 
                'Please restart program as user with proper rights' % self.current_device
 
            )
 

	
 
    def open_directory(self):
 
        try:
 
            if self.devices_combobox.currentIndex() != -1:
 
                device = '/dev/{}'.format(self.devices_model.getItem(self.devices_combobox.currentIndex())[0])
 
            if self.current_device:
 
                indexes = self.tableView.selectedIndexes()
 
                for index in indexes:
 
                    image = os.path.join(self.root, 'temp/image{}.img'.format(index.row()))
 
@@ -151,7 +189,7 @@ class MainWindow(Ui_MainWindow, QtWidget
 
                        MountManager.get().unmount(image)
 
                    if os.path.exists(image):
 
                        os.remove(image)
 
                    floppyemu.read_image(device, image, index.row())
 
                    floppyemu.read_image(self.current_device, image, index.row())
 
                    os.makedirs(os.path.join(self.root, 'folders/{}'.format(index.row())), exist_ok=True)
 
                    os.chmod(os.path.join(self.root, 'folders/{}'.format(index.row())),
 
                             stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO)
 
@@ -163,14 +201,13 @@ class MainWindow(Ui_MainWindow, QtWidget
 
            traceback.print_exc()
 

	
 
    def save_directory(self):
 
        if self.devices_combobox.currentIndex() != -1:
 
            device = '/dev/{}'.format(self.devices_model.getItem(self.devices_combobox.currentIndex())[0])
 
        if self.current_device:
 
            indexes = self.tableView.selectedIndexes()
 
            for index in indexes:
 
                image = os.path.join(self.root, 'temp/image{}.img'.format(index.row()))
 
                if MountManager.get().is_mounted(image):
 
                    MountManager.get().unmount(image)
 
                    floppyemu.write_image(device, image, index.row())
 
                    floppyemu.write_image(self.current_device, image, index.row())
 
                    shutil.rmtree(os.path.join(self.root, 'folders/{}'.format(index.row())))
 
                else:
 
                    QtWidgets.QMessageBox.critical(
 
@@ -181,8 +218,7 @@ class MainWindow(Ui_MainWindow, QtWidget
 
        self.refresh_image_list()
 

	
 
    def write_image(self):
 
        if self.devices_combobox.currentIndex() != -1:
 
            device = '/dev/{}'.format(self.devices_model.getItem(self.devices_combobox.currentIndex())[0])
 
        if self.current_device:
 
            indexes = self.tableView.selectedIndexes()
 
            for index in indexes:
 
                fd = QtWidgets.QFileDialog(self)
 
@@ -190,15 +226,14 @@ class MainWindow(Ui_MainWindow, QtWidget
 
                fd.setWindowTitle('Select file for image {}'.format(index.row()))
 
                if fd.exec() == QtWidgets.QDialog.Accepted:
 
                    image = fd.selectedFiles()[0]
 
                    floppyemu.write_image(device, image, index.row())
 
                    floppyemu.write_image(self.current_device, image, index.row())
 
                else:
 
                    return
 

	
 
        self.refresh_image_list()
 

	
 
    def read_image(self):
 
        if self.devices_combobox.currentIndex() != -1:
 
            device = '/dev/{}'.format(self.devices_model.getItem(self.devices_combobox.currentIndex())[0])
 
        if self.current_device:
 
            indexes = self.tableView.selectedIndexes()
 
            for index in indexes:
 
                fd = QtWidgets.QFileDialog(self)
 
@@ -206,7 +241,7 @@ class MainWindow(Ui_MainWindow, QtWidget
 
                fd.setWindowTitle('Select file for image {}'.format(index.row()))
 
                if fd.exec() == QtWidgets.QDialog.Accepted:
 
                    image = fd.selectedFiles()[0]
 
                    floppyemu.read_image(device, image, index.row())
 
                    floppyemu.read_image(self.current_device, image, index.row())
 
                else:
 
                    return
 

	
 
@@ -218,4 +253,4 @@ class MainWindow(Ui_MainWindow, QtWidget
 
            QtWidgets.QMessageBox.critical(
 
                self, 'Error',
 
                'Unable to clean up. Some resources are in use: {}'.format(e)
 
            )
 
\ No newline at end of file
 
            )
ui/about.py
Show inline comments
 
@@ -27,4 +27,4 @@ class Ui_Form(object):
 
    def retranslateUi(self, Form):
 
        _translate = QtCore.QCoreApplication.translate
 
        Form.setWindowTitle(_translate("Form", "About KUSBFloppyFormatter"))
 
        self.label.setText(_translate("Form", "<html><head/><body><p align=\"center\"><img src=\":/floppy_multiple.png\"/><img src=\":/arrow_right.png\"/><img src=\":/flashdisk_logo.png\"/></p><p align=\"center\"><span style=\" font-size:22pt;\">USB Floppy Formatter</span></p><p align=\"center\">Version 1.0</p><p align=\"center\">By: Khaelenmore Thaal</p><p><br/></p><p><span style=\" font-family:\'DejaVu Sans Mono\'; font-size:9.1pt; color:#000000;\">GUI utility for formatting thumb drives for usage with hardware usb emulators<br/>Uses Qt5 </span><a href=\"https://www.qt.io/\"><span style=\" text-decoration: underline; color:#0000ee;\">https://www.qt.io/</span></a><span style=\" font-family:\'DejaVu Sans Mono\'; font-size:9.1pt;\"><br/>Uses PyQt5 </span><a href=\"https://www.riverbankcomputing.com/software/pyqt/intro\"><span style=\" text-decoration: underline; color:#0000ee;\">https://www.riverbankcomputing.com/software/pyqt/intro</span></a><span style=\" font-family:\'DejaVu Sans Mono\'; font-size:9.1pt;\"><br/>Built-in icons by </span><a href=\"http://www.fatcow.com/free-icons\"><span style=\" text-decoration: underline; color:#0000ee;\">http://www.fatcow.com/free-icons</span></a><span style=\" font-family:\'DejaVu Sans Mono\'; font-size:9.1pt;\"><br/>This program is licensed with GNU GPL v3<br/>This program is available on </span><a href=\"http://silverwing.one/pages/kusbff\"><span style=\" text-decoration: underline; color:#0000ee;\">http://silverwing.one/pages/kusbff</span></a></p></body></html>"))
 
        self.label.setText(_translate("Form", "<html><head/><body><p align=\"center\"><img src=\":/floppy_multiple.png\"/><img src=\":/arrow_right.png\"/><img src=\":/flashdisk_logo.png\"/></p><p align=\"center\"><span style=\" font-size:22pt;\">USB Floppy Formatter</span></p><p align=\"center\">Version 1.0.2</p><p align=\"center\">By: Khaelenmore Thaal</p><p><br/></p><p><span style=\" font-family:\'DejaVu Sans Mono\'; font-size:9.1pt; color:#000000;\">GUI utility for formatting thumb drives for usage with hardware usb emulators<br/>Uses Qt5 </span><a href=\"https://www.qt.io/\"><span style=\" text-decoration: underline; color:#0000ee;\">https://www.qt.io/</span></a><span style=\" font-family:\'DejaVu Sans Mono\'; font-size:9.1pt;\"><br/>Uses PyQt5 </span><a href=\"https://www.riverbankcomputing.com/software/pyqt/intro\"><span style=\" text-decoration: underline; color:#0000ee;\">https://www.riverbankcomputing.com/software/pyqt/intro</span></a><span style=\" font-family:\'DejaVu Sans Mono\'; font-size:9.1pt;\"><br/>Built-in icons by </span><a href=\"http://www.fatcow.com/free-icons\"><span style=\" text-decoration: underline; color:#0000ee;\">http://www.fatcow.com/free-icons</span></a><span style=\" font-family:\'DejaVu Sans Mono\'; font-size:9.1pt;\"><br/>This program is licensed with GNU GPL v3<br/>This program is available on </span><a href=\"http://silverwing.one/pages/kusbff\"><span style=\" text-decoration: underline; color:#0000ee;\">http://silverwing.one/pages/kusbff</span></a></p></body></html>"))
0 comments (0 inline, 0 general)