diff --git a/src/m64py/archive.py b/src/m64py/archive.py
index c54b9ea..e305fc1 100644
--- a/src/m64py/archive.py
+++ b/src/m64py/archive.py
@@ -15,7 +15,6 @@
# along with this program. If not, see .
import os
-import sys
import bz2
import gzip
import zipfile
@@ -23,12 +22,7 @@ import shutil
import tempfile
from subprocess import Popen, PIPE
-try:
- from m64py.utils import which
-except ImportError, err:
- sys.stderr.write("Error: Can't import m64py modules%s%s%s" % (
- os.linesep, str(err), os.linesep))
- sys.exit(1)
+from m64py.utils import which
try:
import UnRAR2
@@ -64,12 +58,11 @@ class Archive():
def __init__(self, filename):
"""Opens archive."""
self.file = os.path.realpath(filename)
- if not os.path.isfile(self.file) \
- or not os.access(self.file, os.R_OK):
- raise IOError("Cannot open %s. No such file." % (
- self.file))
+ if not os.path.isfile(self.file) or not os.access(self.file, os.R_OK):
+ raise IOError("Cannot open %s. No such file." % (self.file))
self.filetype = self.get_filetype()
+
if self.filetype == ZIP:
self.fd = zipfile.ZipFile(self.file, 'r')
elif self.filetype == GZIP:
@@ -84,41 +77,39 @@ class Archive():
elif RAR_CMD:
self.fd = RarCmd(self.file)
else:
- raise IOError("UnRAR2 module or rar/unrar is needed for %s." % (
- self.file))
+ raise IOError("UnRAR2 module or rar/unrar is needed for %s." % (self.file))
elif self.filetype == LZMA:
if HAS_7Z:
self.fd = Archive7z(open(self.file, 'rb'))
elif LZMA_CMD:
self.fd = LzmaCmd(self.file)
else:
- raise IOError("lzma module or 7z is needed for %s." % (
- self.file))
+ raise IOError("lzma module or 7z is needed for %s." % (self.file))
else:
- raise IOError("File %s is not a N64 ROM file." % (
- self.file))
+ raise IOError("File %s is not a N64 ROM file." % (self.file))
- def read(self):
- """Reads data. If archive has more then one
- file the first one is used."""
+ self.namelist = self.get_namelist()
+
+ def read(self, filename=None):
+ """Reads data."""
data = None
+ fname = self.namelist[0] if not filename else filename
if self.filetype == ZIP:
- data = self.fd.read(self.fd.infolist()[0])
+ data = self.fd.read(fname)
elif self.filetype == GZIP:
data = self.fd.read()
elif self.filetype == BZIP:
data = self.fd.read()
elif self.filetype == RAR:
if HAS_RAR:
- data = self.fd.read_files()[0][1]
+ data = self.fd.read_files(fname)[0][1]
elif RAR_CMD:
- data = self.fd.read()
+ data = self.fd.read(fname)
elif self.filetype == LZMA:
if HAS_7Z:
- data = self.fd.getmember(
- self.fd.getnames()[0]).read()
+ data = self.fd.getmember(fname).read()
elif LZMA_CMD:
- data = self.fd.read()
+ data = self.fd.read(fname)
elif self.filetype == ROM:
data = self.fd.read()
return data
@@ -131,6 +122,29 @@ class Archive():
else:
self.fd.close()
+ def get_namelist(self):
+ """Gets list of files in archive."""
+ if self.filetype == ZIP:
+ namelist = [name.filename for name in self.fd.infolist()]
+ elif self.filetype == GZIP:
+ namelist = [os.path.basename(self.file)]
+ elif self.filetype == BZIP:
+ namelist = [os.path.basename(self.file)]
+ elif self.filetype == RAR:
+ if HAS_RAR:
+ for filename in self.fd.infoiter():
+ namelist.append(filename.filename)
+ elif RAR_CMD:
+ namelist = self.fd.namelist
+ elif self.filetype == LZMA:
+ if HAS_7Z:
+ namelist = self.fd.getnames()
+ elif LZMA_CMD:
+ namelist = self.fd.namelist
+ elif self.filetype == ROM:
+ namelist = [os.path.basename(self.file)]
+ return namelist
+
def get_filetype(self):
"""Gets archive type."""
fd = open(self.file, 'rb')
@@ -155,13 +169,10 @@ class RarCmd:
def __init__(self, archive):
"""Opens archive."""
+ self.fd = None
self.file = archive
self.namelist = self.namelist()
- self.filename = self.namelist[0]
- self.tempdir = tempfile.mkdtemp(self.file)
- self.extract()
- self.fd = open(os.path.join(
- self.tempdir, self.filename), "rb")
+ self.tempdir = tempfile.mkdtemp()
def namelist(self):
"""Returns list of filenames in archive."""
@@ -170,21 +181,24 @@ class RarCmd:
def extract(self):
"""Extracts archive to temp dir."""
- proc = Popen([RAR_CMD, 'x', '-kb', '-p-', '-o-', '-inul', '--',
- self.file, self.filename, self.tempdir],
- stdin=PIPE, stdout=PIPE, stderr=PIPE)
+ cmd = [RAR_CMD, 'x', '-kb', '-p-', '-o-', '-inul', '--',
+ self.file, self.filename, self.tempdir]
+ proc = Popen(cmd, stdout=PIPE, stderr=PIPE)
out = proc.communicate()
if out[1] != '':
- raise IOError("Error extracting file %s: %s." % (
- self.file, out[1]))
+ raise IOError("Error extracting file %s: %s." % (self.file, out[1]))
- def read(self):
+ def read(self, filename=None):
"""Reads data."""
+ self.filename = self.namelist[0] if not filename else filename
+ self.extract()
+ self.fd = open(os.path.join(self.tempdir, self.filename), "rb")
return self.fd.read()
def close(self):
"""Closes file descriptor and clean resources."""
- self.fd.close()
+ if self.fd:
+ self.fd.close()
shutil.rmtree(self.tempdir)
class LzmaCmd:
@@ -192,35 +206,35 @@ class LzmaCmd:
def __init__(self, archive):
"""Opens archive."""
+ self.fd = None
self.file = archive
self.namelist = self.namelist()
- self.filename = self.namelist[0]
- self.tempdir = tempfile.mkdtemp(self.filename)
- self.extract()
- self.fd = open(os.path.join(
- self.tempdir, self.filename), "rb")
+ self.tempdir = tempfile.mkdtemp()
def namelist(self):
"""Returns list of filenames in archive."""
- proc1 = Popen([LZMA_CMD, 'l', self.file], stdout=PIPE)
- proc2 = Popen(['grep', '-F', '...A'], stdin=proc1.stdout, stdout=PIPE)
- lines = [name.rstrip(os.linesep) for name in proc2.stdout.readlines()]
+ proc = Popen([LZMA_CMD, 'l', self.file], stdout=PIPE)
+ lines = [name.rstrip(os.linesep) for name in proc.stdout.readlines() if '...A' in name]
return [name[53:] for name in lines]
def extract(self):
"""Extracts archive to temp dir."""
- proc = Popen([LZMA_CMD, 'x', '-o'+self.tempdir, self.file, self.filename],
- stdin=PIPE, stdout=PIPE, stderr=PIPE)
+ cmd = [LZMA_CMD, 'x', '-o'+self.tempdir, self.file, self.filename]
+ proc = Popen(cmd, stdout=PIPE, stderr=PIPE)
out = proc.communicate()
if "Error" in out[0]:
raise IOError("Error extracting file %s: %s." % (
self.file, out[0]))
- def read(self):
+ def read(self, filename=None):
"""Reads data."""
+ self.filename = self.namelist[0] if not filename else filename
+ self.extract()
+ self.fd = open(os.path.join(self.tempdir, self.filename), "rb")
return self.fd.read()
def close(self):
"""Closes file descriptor and clean resources."""
- self.fd.close()
+ if self.fd:
+ self.fd.close()
shutil.rmtree(self.tempdir)
diff --git a/src/m64py/frontend/dialogs.py b/src/m64py/frontend/dialogs.py
index bc473a5..f4b2850 100644
--- a/src/m64py/frontend/dialogs.py
+++ b/src/m64py/frontend/dialogs.py
@@ -14,28 +14,23 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-import os
-import sys
+from PyQt4.QtCore import *
+from PyQt4.QtGui import QDialog, QMessageBox, QListWidgetItem
-from PyQt4.QtGui import QDialog, QMessageBox
-
-try:
- from m64py.core.defs import FRONTEND_VERSION
- from m64py.ui.about_ui import Ui_AboutDialog
- from m64py.ui.license_ui import Ui_LicenseDialog
-except ImportError, err:
- sys.stderr.write("Error: Can't import m64py modules%s%s%s" % (
- os.linesep, str(err), os.linesep))
- sys.exit(1)
+from m64py.utils import version_split
+from m64py.core.defs import FRONTEND_VERSION
+from m64py.ui.about_ui import Ui_AboutDialog
+from m64py.ui.license_ui import Ui_LicenseDialog
+from m64py.ui.archive_ui import Ui_ArchiveDialog
class AboutDialog(QDialog, Ui_AboutDialog):
def __init__(self, parent):
QDialog.__init__(self, parent)
self.setupUi(self)
text = self.labelAbout.text()
- text.replace("FRONTEND_VERSION", FRONTEND_VERSION)
- text.replace("CORE_VERSION",
- str(parent.worker.m64p.core_version))
+ text = text.replace("FRONTEND_VERSION", FRONTEND_VERSION)
+ text = text.replace("CORE_VERSION",
+ version_split(parent.worker.m64p.core_version))
self.labelAbout.setText(text)
self.show()
@@ -51,3 +46,17 @@ class InfoDialog(QMessageBox):
self.setText(text)
self.setWindowTitle("Info")
self.show()
+
+class ArchiveDialog(QDialog, Ui_ArchiveDialog):
+ def __init__(self, parent, files):
+ QDialog.__init__(self, parent)
+ self.setupUi(self)
+ self.build_list(files)
+
+ def build_list(self, files):
+ self.listWidget.clear()
+ for fname in files:
+ item = QListWidgetItem(fname)
+ item.setData(Qt.UserRole, fname)
+ self.listWidget.addItem(item)
+ self.listWidget.setCurrentRow(0)
diff --git a/src/m64py/frontend/romlist.py b/src/m64py/frontend/romlist.py
index 15bb459..752c356 100644
--- a/src/m64py/frontend/romlist.py
+++ b/src/m64py/frontend/romlist.py
@@ -15,21 +15,15 @@
# along with this program. If not, see .
import os
-import sys
import fnmatch
import ConfigParser
from PyQt4.QtGui import *
from PyQt4.QtCore import *
-try:
- from m64py.utils import log, md5sum
- from m64py.archive import Archive, EXT_FILTER
- from m64py.ui.romlist_ui import Ui_ROMList
-except ImportError, err:
- sys.stderr.write("Error: Can't import m64py modules%s%s%s" % (
- os.linesep, str(err), os.linesep))
- sys.exit(1)
+from m64py.utils import log, md5sum
+from m64py.archive import Archive, EXT_FILTER
+from m64py.ui.romlist_ui import Ui_ROMList
try:
from m64py.ui import title_rc
@@ -75,8 +69,8 @@ class ROMList(QMainWindow, Ui_ROMList):
def init(self):
self.read_rom_list()
- self.roms = self.qset.value("rom_list", []).toPyObject()
- if self.qset.value("show_available", 0).toInt()[0]:
+ self.roms = self.qset.value("rom_list", [])
+ if bool(self.qset.value("show_available", 0)):
self.add_available_items(self.roms)
else:
self.add_items()
@@ -119,7 +113,7 @@ class ROMList(QMainWindow, Ui_ROMList):
except KeyError:
md5 = key
list_item = QListWidgetItem(rom['goodname'])
- list_item.setData(Qt.UserRole, (md5, None))
+ list_item.setData(Qt.UserRole, (md5, None, None))
list_item.setFlags(Qt.ItemIsEnabled)
self.listWidget.addItem(list_item)
self.pushOpen.setEnabled(False)
@@ -135,11 +129,11 @@ class ROMList(QMainWindow, Ui_ROMList):
self.qset.setValue("rom_list", self.roms)
self.qset.sync()
self.listWidget.clear()
- for md5, path in self.roms:
+ for md5, path, fname in self.roms:
if md5 in self.romlist:
goodname = self.romlist[md5]['goodname']
list_item = QListWidgetItem(goodname)
- list_item.setData(Qt.UserRole, (md5, path))
+ list_item.setData(Qt.UserRole, (md5, path, fname))
self.listWidget.addItem(list_item)
self.progressBar.setValue(0)
self.progressBar.hide()
@@ -150,7 +144,7 @@ class ROMList(QMainWindow, Ui_ROMList):
def refresh_items(self):
"""Refreshes available ROMs list"""
- path_roms = self.qset.value("Paths/ROM").toString()
+ path_roms = self.qset.value("Paths/ROM")
if not path_roms:
self.parent.emit(SIGNAL(
"info_dialog(PyQt_PyObject)"),
@@ -162,31 +156,31 @@ class ROMList(QMainWindow, Ui_ROMList):
self.reader.set_path(path_roms)
self.reader.start()
- def file_open(self, path):
+ def file_open(self, path, fname):
"""Opens ROM file."""
self.close()
if self.parent.isMinimized():
self.parent.activateWindow()
self.parent.emit(SIGNAL(
- "file_open(PyQt_PyObject)"), str(path))
+ "file_open(PyQt_PyObject, PyQt_PyObject)"), path, fname)
def on_progress_bar_changed(self, value):
self.progressBar.setValue(value)
def on_item_open(self):
item = self.listWidget.currentItem()
- md5, path = item.data(Qt.UserRole).toPyObject()
+ md5, path, fname = item.data(Qt.UserRole)
if path:
- self.file_open(path)
+ self.file_open(path, fname)
def on_item_activated(self, item):
- md5, path = item.data(Qt.UserRole).toPyObject()
+ md5, path, fname = item.data(Qt.UserRole)
if path:
- self.file_open(path)
+ self.file_open(path, fname)
def on_item_changed(self, current, previous):
if not current: return
- md5, path = current.data(Qt.UserRole).toPyObject()
+ md5, path, fname = current.data(Qt.UserRole)
title = QPixmap(os.path.join(
self.user_data_path, "title", "%s.png") % md5)
@@ -241,7 +235,7 @@ class ROMReader(QThread):
def set_path(self, path):
"""Sets ROM directory path."""
- self.rom_path = str(path)
+ self.rom_path = path
def get_roms(self):
"""Returns ROM list."""
@@ -265,13 +259,14 @@ class ROMReader(QThread):
fullpath = os.path.join(self.rom_path, filename)
try:
archive = Archive(fullpath)
- romfile = archive.read()
- archive.close()
+ for fname in archive.namelist:
+ romfile = archive.read(fname)
+ archive.close()
+ rom_md5 = md5sum(filedata=romfile)
+ self.roms.append((rom_md5.upper(), fullpath, fname))
except Exception, err:
log.warn(str(err))
continue
- rom_md5 = md5sum(filedata=romfile)
- self.roms.append((rom_md5.upper(), fullpath))
percent = float(filenum) / float(num_files) * 100
self.parent.progressBar.emit(
SIGNAL("valueChanged(int)"), percent)