Example #1
0
 def readFile(self, filename, blockbytes):
     # print("send file",filename)
     info = QtCore.QFileInfo(filename)
     fname = info.fileName()
     localfile = QtCore.QFile(filename)
     localfile.open(QtCore.QFile.ReadOnly)
     totalFBytes = localfile.size()
     filecont = QByteArray()
     # filecont = self.localfile.read(min(totalFBytes,self.blockBytes))
     fstream = QDataStream(localfile)
     fnum = math.ceil(float(totalFBytes) / self.blockBytes)
     # print("total",totalFBytes)
     # print("blockbytes",self.blockBytes)
     # print("fnum",fnum)
     i = 0
     start_time = int(time.time())
     tmp_time = start_time
     tmp_speed = ""
     tmp_total_time = ""
     while not fstream.atEnd():
         readsize = min(totalFBytes, self.blockBytes)
         totalFBytes -= readsize
         filecont = fstream.readRawData(readsize)
         # print("send",i,readsize)
         self.signThread.emit(fname, i, readsize, filecont)
         i += 1
         self.signFileBar.emit(fnum, i)
         self.flag = True
         while self.flag:
             if len(tmp_speed) > 0:
                 self.signFileSpeed.emit(time_total_time + "s",
                                         self.getRandomTime(tmp_speed))
             time.sleep(0.5)
         now_time = int(time.time())
         about_time, speed = self.getAboutTime(now_time - tmp_time + 0.1,
                                               readsize, totalFBytes)
         self.signFileSpeed.emit(about_time + "s", speed)
         tmp_time = now_time
         tmp_speed = speed
         time_total_time = about_time
     localfile.close()
     self.signFileBar.emit(fnum, fnum)
     now_time = int(time.time())
     ab_time = self.getTimeFromat(now_time - start_time) + "s"
     self.signFileSpeed.emit(ab_time, "")
     self.signConfirm.emit(fname)
Example #2
0
def switch_language(client_config, lang_key=None):
    global _current_translator
    global _current_locale_language

    QCoreApplication.translate = qt_translate

    if not lang_key:
        lang_key = client_config.gui_language
    if not lang_key:
        lang_key = get_locale_language()
        logger.info(
            f"No language in settings, trying local language '{lang_key}'")
    if lang_key not in LANGUAGES.values():
        if lang_key != "en":
            logger.info(
                f"Language '{lang_key}' unavailable, defaulting to English")
        lang_key = "en"

    _current_locale_language = lang_key

    rc_file = QFile(f":/translations/translations/guardata_{lang_key}.mo")
    if not rc_file.open(QIODevice.ReadOnly):
        logger.warning(
            f"Unable to read the translations for language '{lang_key}'")
        return None

    try:
        data_stream = QDataStream(rc_file)
        out_stream = io.BytesIO()
        content = data_stream.readRawData(rc_file.size())
        out_stream.write(content)
        out_stream.seek(0)
        _current_translator = gettext.GNUTranslations(out_stream)
        _current_translator.install()
    except OSError:
        logger.warning(
            f"Unable to load the translations for language '{lang_key}'")
        return None
    finally:
        rc_file.close()
    return lang_key
Example #3
0
    def _onReadyRead(self):
        while self._socket.bytesAvailable() >= 4:
            ds = QDataStream(self._socket)
            ds.setByteOrder(QDataStream.LittleEndian)

            # Header packet
            if self.header is None:
                size, = unpack('=l', self._socket.peek(4))

                if self._socket.bytesAvailable() < size + 4:
                    return

                # Omit size
                ds.readUInt32()

                self.header = ds.readRawData(size).decode()

            # Chunks packet
            else:
                if self.nchunks == -1:
                    self.nchunks = ds.readUInt32()
                    self.chunks = []

                while len(self.chunks) < self.nchunks:
                    chunk = self._readLuaVal(ds)

                    if chunk is None:
                        return

                    self.chunks.append(chunk)

                # Packet pair reading done.
                self._logger.info("GC >> : %s : %s", self.header, self.chunks)
                self.messageReceived.emit(self.header, self.chunks)
                self.header = None
                self.nchunks = -1
                self.chunks = None
Example #4
0
 def readMessage(self):
     # print('server read message',self.tcpSocket.bytesAvailable())
     stream = QDataStream(self)  #发送数据是以QByteArray数据类型发送过来的,所以接收数据也应该以此接收
     stream.setVersion(QDataStream.Qt_5_4)  #发送和接收数据以相同的编码形式传输
     while self.bytesAvailable() > SIZEOF_HEAD_INT:
         if self.headSize == 0:
             self.headSize = stream.readInt64()
             self.fileBytes = stream.readInt64()
         if self.bytesAvailable() >= self.headSize + self.fileBytes:
             qheader = stream.readQString()
             # print("server recv head:",self.headSize,qheader)
             # if self.bytesReceive >= self.headSize+self.fileBytes+SIZEOF_HEAD_INT:
             qfilecont = stream.readRawData(self.fileBytes)
             # if self.fileBytes > 0:
             #     qfilecont=""
             # self.bytesReceive += self.fileBytes
             # self.handlerMessage(qheader,qfilecont,self.fileBytes)
             ipaddr = self.peerAddress().toString() + ":" + str(
                 self.peerPort())
             self.handlerMessage(qheader, qfilecont, self.fileBytes)
             # self.signRecv.emit(ipaddr,qheader,qfilecont)
             self.initRecv()
         else:
             break
Example #5
0
class QmyMainWindow(QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)  #调用父类构造函数,创建窗体
        self.ui = Ui_MainWindow()  #创建UI对象
        self.ui.setupUi(self)  #构造UI界面

        self.ui.groupBox.setEnabled(False)
        self.ui.actSaveALL.setEnabled(False)
        self.ui.actReadALL.setEnabled(False)

        self.__testFileName = ""
        self.__typeSize = {
            "char": 1,
            "bool": 1,
            "int8": 1,
            "uint8": 1,
            "int16": 2,
            "uint16": 2,
            "int32": 4,
            "uint32": 4,
            "int64": 8,
            "uint64": 8,
            "int": 4,
            "uint": 4,
            "float": 4,
            "single": 4,
            "double": 8
        }

##  ==============自定义功能函数============

    def __iniWrite(self):  ##开始写文件操作
        self.fileDevice = QFile(self.__testFileName)  #创建文件对象
        if not self.fileDevice.open(QIODevice.WriteOnly):
            del self.fileDevice  #删除对象
            return False

        self.fileStream = QDataStream(self.fileDevice)

        self.fileStream.setVersion(QDataStream.Qt_5_12)  #设置流版本号,写入和读取的版本号要兼容
        if self.ui.radio_BigEndian.isChecked():
            self.fileStream.setByteOrder(QDataStream.BigEndian)
        else:
            self.fileStream.setByteOrder(QDataStream.LittleEndian)

        if self.ui.radio_Single.isChecked():  #必须要设置,float和double都按照这个精度
            self.fileStream.setFloatingPointPrecision(
                QDataStream.SinglePrecision)
        else:
            self.fileStream.setFloatingPointPrecision(
                QDataStream.DoublePrecision)
        return True

    def __delFileStream(self):  ##结束写文件操作
        self.fileDevice.close()
        del self.fileStream
        del self.fileDevice

    def __iniRead(self):  ##开始写文件操作
        if not QFile.exists(self.__testFileName):
            QMessageBox.critical(self, "错误", "文件不存在")
            return False

        self.fileDevice = QFile(self.__testFileName)  #创建文件对象
        if not self.fileDevice.open(QIODevice.ReadOnly):
            del self.fileDevice  #删除对象
            return False

        self.fileStream = QDataStream(self.fileDevice)

        self.fileStream.setVersion(QDataStream.Qt_5_12)  #设置版本号,写入和读取的版本号要兼容
        if self.ui.radio_BigEndian.isChecked():
            self.fileStream.setByteOrder(QDataStream.BigEndian)
        else:
            self.fileStream.setByteOrder(QDataStream.LittleEndian)

        if self.ui.radio_Single.isChecked():  #必须要设置,float和double都按照这个精度
            self.fileStream.setFloatingPointPrecision(
                QDataStream.SinglePrecision)
        else:
            self.fileStream.setFloatingPointPrecision(
                QDataStream.DoublePrecision)
        return True

##  ==========由connectSlotsByName() 自动连接的槽函数==================

    @pyqtSlot()
    def on_btnFile_clicked(self):
        curPath = QDir.currentPath()  #获取系统当前目录
        title = "选择文件"  #对话框标题
        filt = "原始数据文件(*.raw)"  #文件过滤器
        fileName, flt = QFileDialog.getSaveFileName(self, title, curPath, filt)
        if (fileName == ""):
            return

        self.__testFileName = fileName  #测试用文件
        self.ui.editFilename.setText(fileName)
        self.ui.groupBox.setEnabled(True)
        self.ui.actSaveALL.setEnabled(True)
        self.ui.actReadALL.setEnabled(True)

    @pyqtSlot()  ##写  int8
    def on_btnInt8_Write_clicked(self):
        Value = self.ui.spin_Int8.value()  # Python的int类型
        if self.__iniWrite():
            try:
                bts = struct.pack('b', Value)  # 'b'=signed char=int8
                ## writeRawData(self, bytes) -> int
                self.fileStream.writeRawData(bts)
            except Exception as e:
                print(e)
                QMessageBox.critical(self, "写int8过程出现错误", str(e))
            finally:
                self.__delFileStream()

    @pyqtSlot()  ##读  int8
    def on_btnInt8_Read_clicked(self):
        if self.__iniRead():
            ##readRawData(self, int) -> bytes
            try:
                bts = self.fileStream.readRawData(self.__typeSize["int8"])
                ## unpack(fmt, buffer) -> (v1, v2, ...)
                Value, = struct.unpack('b', bts)  # 'b'=signed char=int8
                self.ui.edit_Int8.setText("%d" % Value)
            except Exception as e:
                QMessageBox.critical(self, "读int8过程出现错误", str(e))
            finally:
                self.__delFileStream()

    @pyqtSlot()  ##写  uint8
    def on_btnUInt8_Write_clicked(self):
        Value = self.ui.spin_UInt8.value()
        if self.__iniWrite():
            try:
                bts = struct.pack('B', Value)  # 'B'=unsigned char=uint8
                self.fileStream.writeRawData(bts)
            except Exception as e:
                QMessageBox.critical(self, "写uint8过程出现错误", str(e))
            finally:
                self.__delFileStream()

    @pyqtSlot()  ##读  uint8
    def on_btnUInt8_Read_clicked(self):
        if self.__iniRead():
            try:
                bts = self.fileStream.readRawData(self.__typeSize["uint8"])
                Value, = struct.unpack('B', bts)  # 'B'=unsigned char=uint8
                self.ui.edit_UInt8.setText("%d" % Value)
            except Exception as e:
                QMessageBox.critical(self, "读uint8过程出现错误", str(e))
            finally:
                self.__delFileStream()

    @pyqtSlot()  ##写  int16
    def on_btnInt16_Write_clicked(self):
        Value = self.ui.spin_Int16.value()
        if self.__iniWrite():
            try:
                bts = struct.pack('h', Value)  # 'h'=short, 2字节,=int16
                self.fileStream.writeRawData(bts)
            except Exception as e:
                QMessageBox.critical(self, "写int16过程出现错误", str(e))
            finally:
                self.__delFileStream()

    @pyqtSlot()  ##读  int16
    def on_btnInt16_Read_clicked(self):
        if self.__iniRead():
            try:
                bts = self.fileStream.readRawData(self.__typeSize["int16"])
                Value, = struct.unpack('h', bts)  # 'h'=short, 2字节,=int16
                self.ui.edit_Int16.setText("%d" % Value)
            except Exception as e:
                QMessageBox.critical(self, "读int16过程出现错误", str(e))
            finally:
                self.__delFileStream()

    @pyqtSlot()  ##写  uint16
    def on_btnUInt16_Write_clicked(self):
        Value = self.ui.spin_UInt16.value()
        if self.__iniWrite():
            try:
                bts = struct.pack('H', Value)  # 'H'=unsigned short, 2字节=uint16
                self.fileStream.writeRawData(bts)
            except Exception as e:
                QMessageBox.critical(self, "写uint16过程出现错误", str(e))
            finally:
                self.__delFileStream()

    @pyqtSlot()  ##读  uint16
    def on_btnUIn16_Read_clicked(self):
        if self.__iniRead():
            try:
                bts = self.fileStream.readRawData(self.__typeSize["uint16"])
                Value, = struct.unpack('H',
                                       bts)  # 'H'=unsigned short, 2字节,=uint16
                self.ui.edit_UInt16.setText("%d" % Value)
            except Exception as e:
                QMessageBox.critical(self, "读uint16过程出现错误", str(e))
            finally:
                self.__delFileStream()

    @pyqtSlot()  ##写  int32
    def on_btnInt32_Write_clicked(self):
        Value = self.ui.spin_Int32.value()
        if self.__iniWrite():
            try:
                bts = struct.pack('>l', Value)  # '>l'=大字节序 int32
                self.fileStream.writeRawData(bts)
            except Exception as e:
                QMessageBox.critical(self, "写int32过程出现错误", str(e))
            finally:
                self.__delFileStream()

    @pyqtSlot()  ##读  int32
    def on_btnInt32_Read_clicked(self):
        if self.__iniRead():
            try:
                bts = self.fileStream.readRawData(self.__typeSize["int32"])
                Value, = struct.unpack('>l', bts)  # '>l'= 大字节序int32
                self.ui.edit_Int32.setText("%d" % Value)
            except Exception as e:
                QMessageBox.critical(self, "读int32过程出现错误", str(e))
            finally:
                self.__delFileStream()

    @pyqtSlot()  ##写 int64
    def on_btnInt64_Write_clicked(self):
        Value = self.ui.spin_Int64.value()  #Python的int类型
        if self.__iniWrite():
            try:
                bts = struct.pack('q', Value)  # 'q'= long long, 8字节=int64
                self.fileStream.writeRawData(bts)
            except Exception as e:
                QMessageBox.critical(self, "写int64过程出现错误", str(e))
            finally:
                self.__delFileStream()

    @pyqtSlot()  ##读 int64
    def on_btnInt64_Read_clicked(self):
        if self.__iniRead():
            try:
                bts = self.fileStream.readRawData(self.__typeSize["int64"])
                Value, = struct.unpack('q', bts)  # 'q'= long long, 8字节=int64
                self.ui.edit_Int64.setText("%d" % Value)
            except Exception as e:
                QMessageBox.critical(self, "读int64过程出现错误", str(e))
            finally:
                self.__delFileStream()

    @pyqtSlot()  ##写  int
    def on_btnInt_Write_clicked(self):
        Value = self.ui.spin_Int.value()
        if self.__iniWrite():
            try:
                bts = struct.pack('i', Value)  # 'i'=  int, 4字节=int
                self.fileStream.writeRawData(bts)
            except Exception as e:
                QMessageBox.critical(self, "写int过程出现错误", str(e))
            finally:
                self.__delFileStream()

    @pyqtSlot()  ##读  int
    def on_btnInt_Read_clicked(self):
        if self.__iniRead():
            try:
                bts = self.fileStream.readRawData(self.__typeSize["int"])
                Value, = struct.unpack('i', bts)  # 'i'=  int, 4字节=int
                self.ui.edit_Int.setText("%d" % Value)
            except Exception as e:
                QMessageBox.critical(self, "读int过程出现错误", str(e))
            finally:
                self.__delFileStream()

    @pyqtSlot()  ##写  bool
    def on_btnBool_Write_clicked(self):
        Value = self.ui.chkBox_In.isChecked()
        if self.__iniWrite():
            bts = struct.pack('?', Value)  # '?'=  bool, 1字节
            self.fileStream.writeRawData(bts)
            self.__delFileStream()

    @pyqtSlot()  ##读  bool
    def on_btnBool_Read_clicked(self):
        if self.__iniRead():
            bts = self.fileStream.readRawData(self.__typeSize["bool"])
            Value, = struct.unpack('?', bts)  # '?'=  bool, 1字节
            self.ui.chkBox_Out.setChecked(Value)
            self.__delFileStream()

    @pyqtSlot()  ##写  float
    def on_btnFloat_Write_clicked(self):
        Value = self.ui.spin_Float.value()  #float型
        if self.__iniWrite():
            try:
                bts = struct.pack('f', Value)  # 'f'=  float, 4字节
                self.fileStream.writeRawData(bts)
            except Exception as e:
                QMessageBox.critical(self, "写float过程出现错误", str(e))
            finally:
                self.__delFileStream()

    @pyqtSlot()  ##读  float
    def on_btnFloat_Read_clicked(self):
        if self.__iniRead():
            try:
                bts = self.fileStream.readRawData(self.__typeSize["float"])
                Value, = struct.unpack('f', bts)  # 'f'=  float, 4字节
                self.ui.edit_Float.setText("%.4f" % Value)
            except Exception as e:
                QMessageBox.critical(self, "读float过程出现错误", str(e))
            finally:
                self.__delFileStream()

    @pyqtSlot()  ##写 double
    def on_btnDouble_Write_clicked(self):
        Value = self.ui.spin_Double.value()
        if self.__iniWrite():
            try:
                bts = struct.pack('d', Value)  # 'd'=  double, 8字节=double
                self.fileStream.writeRawData(bts)
            except Exception as e:
                QMessageBox.critical(self, "写double过程出现错误", str(e))
            finally:
                self.__delFileStream()

    @pyqtSlot()  ##读 double
    def on_btnDouble_Read_clicked(self):
        if self.__iniRead():
            try:
                bts = self.fileStream.readRawData(self.__typeSize["double"])
                Value, = struct.unpack('d', bts)  # 'd'=  double, 8字节
                self.ui.edit_Double.setText("%.4f" % Value)
            except Exception as e:
                QMessageBox.critical(self, "读double过程出现错误", str(e))
            finally:
                self.__delFileStream()

## BigEndian和LittleEndian会影响字符串前面表示长度的整数的存储顺序

    @pyqtSlot()  ## writeBytes写  String
    def on_btnStr_Write_clicked(self):
        strV = self.ui.editStr_In.text()  #str类型
        if self.__iniWrite():
            bts = bytes(strV, encoding="utf-8")  #转换为bytes类型
            self.fileStream.writeBytes(
                bts)  #writeBytes(self, bytes) -> QDataStream
            self.__delFileStream()

    @pyqtSlot()  ## readBytes读  String
    def on_btnStr_Read_clicked(self):
        if self.__iniRead():
            try:
                Value = self.fileStream.readBytes()  #readBytes(self) -> bytes
                strV = Value.decode("utf-8")  #从bytes类型解码为字符串,utf-8码
                self.ui.editStr_Out.setText(strV)
            except Exception as e:
                QMessageBox.critical(self, "读String过程出现错误", str(e))
            finally:
                self.__delFileStream()

    @pyqtSlot()  ## writeRawData 写String, 未知长度无法读出
    def on_btnStr_WriteRaw_clicked(self):
        strV = self.ui.editStr_RawIn.text()  #str类型
        if self.__iniWrite():
            bts = bytes(strV, encoding="utf-8")  #转换为bytes类型
            self.fileStream.writeRawData(bts)
            self.__delFileStream()

    @pyqtSlot()  ##读出编辑框全清空
    def on_actClearOutput_triggered(self):
        self.ui.edit_Int8.clear()
        self.ui.edit_UInt8.clear()
        self.ui.edit_Int16.clear()
        self.ui.edit_UInt16.clear()
        self.ui.edit_Int32.clear()
        self.ui.edit_Int64.clear()
        self.ui.edit_Int.clear()

        self.ui.edit_Float.clear()
        self.ui.edit_Double.clear()

        self.ui.editStr_Out.clear()

    @pyqtSlot()  ##连续写入文件
    def on_actSaveALL_triggered(self):
        if not self.__iniWrite():
            QMessageBox.critical(self, "错误", "为写入打开文件时出错")
            return

    #数据写入部分
        Value = self.ui.spin_Int8.value()
        bts = struct.pack('b', Value)  # 'b'=signed char, int8
        self.fileStream.writeRawData(bts)

        Value = self.ui.spin_UInt8.value()
        bts = struct.pack('B', Value)  # 'B'=unsigned char, uint8
        self.fileStream.writeRawData(bts)

        Value = self.ui.spin_Int16.value()
        bts = struct.pack('h', Value)  # 'h'=short, int16
        self.fileStream.writeRawData(bts)

        Value = self.ui.spin_UInt16.value()
        bts = struct.pack('H', Value)  # 'H'=unsigned short, uint16
        self.fileStream.writeRawData(bts)

        Value = self.ui.spin_Int32.value()
        bts = struct.pack('l', Value)  # 'l'= long, 4字节,int32
        self.fileStream.writeRawData(bts)

        Value = self.ui.spin_Int64.value()
        bts = struct.pack('q', Value)  # 'q'= long long, 8字节int64
        self.fileStream.writeRawData(bts)

        Value = self.ui.spin_Int.value()
        bts = struct.pack('i', Value)  # 'i'=  int, 4字节int
        self.fileStream.writeRawData(bts)

        Value = self.ui.chkBox_In.isChecked()
        bts = struct.pack('?', Value)  # '?'=  bool, 1字节
        self.fileStream.writeRawData(bts)

        Value = self.ui.spin_Float.value()
        bts = struct.pack('f', Value)  # 'f'=  float, 4字节
        self.fileStream.writeRawData(bts)

        Value = self.ui.spin_Double.value()
        bts = struct.pack('d', Value)  # 'd'=  double, 8字节
        self.fileStream.writeRawData(bts)

        strV = self.ui.editStr_In.text()  #str类型
        bts = bytes(strV, encoding="utf-8")  #转换为bytes类型
        self.fileStream.writeBytes(bts)

        #数据写入完成
        self.__delFileStream()
        QMessageBox.information(self, "消息", "数据连续写入完成.")

    @pyqtSlot()  ##连续读取文件
    def on_actReadALL_triggered(self):
        if not self.__iniRead():
            QMessageBox.critical(self, "错误", "为读取打开文件时出错")
            return

    #数据读取部分
        bts = self.fileStream.readRawData(self.__typeSize["int8"])
        Value, = struct.unpack('b', bts)  # 'b'=signed char,int8
        self.ui.edit_Int8.setText("%d" % Value)

        bts = self.fileStream.readRawData(self.__typeSize["uint8"])
        Value, = struct.unpack('B', bts)  # 'B'=unsigned char
        self.ui.edit_UInt8.setText("%d" % Value)

        bts = self.fileStream.readRawData(self.__typeSize["int16"])
        Value, = struct.unpack('h', bts)  #  'h'=short, 2字节
        self.ui.edit_Int16.setText("%d" % Value)

        bts = self.fileStream.readRawData(self.__typeSize["uint16"])
        Value, = struct.unpack('H', bts)  #  'H'=unsigned short, 2字节
        self.ui.edit_UInt16.setText("%d" % Value)

        bts = self.fileStream.readRawData(self.__typeSize["int32"])
        Value, = struct.unpack('l', bts)  #  'l'= long, 4字节
        self.ui.edit_Int32.setText("%d" % Value)

        bts = self.fileStream.readRawData(self.__typeSize["int64"])
        Value, = struct.unpack('q', bts)  #  'q'= long long, 8字节
        self.ui.edit_Int64.setText("%d" % Value)

        bts = self.fileStream.readRawData(self.__typeSize["int"])
        Value, = struct.unpack('i', bts)  # 'i'=  int, 4字节
        self.ui.edit_Int.setText("%d" % Value)

        bts = self.fileStream.readRawData(self.__typeSize["bool"])
        Value, = struct.unpack('?', bts)  # '?'=  bool, 1字节
        self.ui.chkBox_Out.setChecked(Value)

        bts = self.fileStream.readRawData(self.__typeSize["float"])
        Value, = struct.unpack('f', bts)  # 'f'=  float, 4字节
        self.ui.edit_Float.setText("%.4f" % Value)

        bts = self.fileStream.readRawData(self.__typeSize["double"])
        Value, = struct.unpack('d', bts)  #  'd'=  double, 8字节
        self.ui.edit_Double.setText("%.4f" % Value)

        Value = self.fileStream.readBytes()  # bytes类型
        strV = Value.decode("utf-8")  #从bytes解码为字符串,utf-8码
        self.ui.editStr_Out.setText(strV)

        #数据写入完成
        self.__delFileStream()
        QMessageBox.information(self, "消息", "数据连续读取完成.")
    def read(self, fileName):
        # Read data.
        file = QFile(fileName)
        if (not file.open(QIODevice.ReadOnly)):
            self.mError = self.tr("Cannot open Replica Island map file!")
            return 0
        
        _in = QDataStream(file)
        _in.setByteOrder(QDataStream.LittleEndian)
        _in.setFloatingPointPrecision(QDataStream.SinglePrecision)
        # Parse file header.
        mapSignature = _in.readUInt8()
        layerCount = _in.readUInt8()
        backgroundIndex = _in.readUInt8()
        if (_in.status() == QDataStream.ReadPastEnd or mapSignature != 96):
            self.mError = self.tr("Can't parse file header!")
            return 0
        
        # Create our map, setting width and height to 0 until we load a layer.
        map = Map(Map.Orientation.Orthogonal, 0, 0, 32, 32)
        map.setProperty("background_index", QString.number(backgroundIndex))
        # Load our Tilesets.
        typeTilesets = QVector()
        tileIndexTilesets = QVector()
        
        self.loadTilesetsFromResources(map, typeTilesets, tileIndexTilesets)
        # Load each of our layers.
        for i in range(layerCount):
            # Parse layer header.
            _type = _in.readUInt8()
            tileIndex = _in.readUInt8()
            scrollSpeed = _in.readFloat()
            levelSignature = _in.readUInt8()
            width = _in.readUInt32()
            height = _in.readUInt32()
            if (_in.status() == QDataStream.ReadPastEnd or levelSignature != 42):
                self.mError = self.tr("Can't parse layer header!")
                return 0
            
            # Make sure our width and height are consistent.
            if (map.width() == 0):
                map.setWidth(width)
            if (map.height() == 0):
                map.setHeight(height)
            if (map.width() != width or map.height() != height):
                self.mError = self.tr("Inconsistent layer sizes!")
                return 0
            
            # Create a layer object.
            layer = TileLayer(self.layerTypeToName(_type), 0, 0, width, height)
            layer.setProperty("type", QString.number(_type))
            layer.setProperty("tile_index", QString.number(tileIndex))
            layer.setProperty("scroll_speed", QString.number(scrollSpeed, 'f'))
            map.addLayer(layer)
            # Look up the tileset for this layer.
            tileset = tilesetForLayer(_type, tileIndex, typeTilesets, tileIndexTilesets)
            # Read our tile data all at once.
            #tileData = QByteArray(width*height, b'\x00')
            bytesNeeded = width*height
            tileData = _in.readRawData(bytesNeeded)
            bytesRead = len(tileData)
            if (bytesRead != bytesNeeded):
                self.mError = self.tr("File ended in middle of layer!")
                return 0
            
            i = 0
            # Add the tiles to our layer.
            for y in range(0, height):
                for x in range(0, width):
                    tile_id = tileData[i]&0xff
                    i += 1
                    if (tile_id != 255):
                        tile = tileset.tileAt(tile_id)
                        layer.setCell(x, y, Cell(tile))

        # Make sure we read the entire *.bin file.
        if (_in.status() != QDataStream.Ok or not _in.atEnd()):
            self.mError = self.tr("Unexpected data at end of file!")
            return 0
        
        return map
    def read(self, fileName):
        # Read data.
        file = QFile(fileName)
        if (not file.open(QIODevice.ReadOnly)):
            self.mError = self.tr("Cannot open Replica Island map file!")
            return 0

        _in = QDataStream(file)
        _in.setByteOrder(QDataStream.LittleEndian)
        _in.setFloatingPointPrecision(QDataStream.SinglePrecision)
        # Parse file header.
        mapSignature = _in.readUInt8()
        layerCount = _in.readUInt8()
        backgroundIndex = _in.readUInt8()
        if (_in.status() == QDataStream.ReadPastEnd or mapSignature != 96):
            self.mError = self.tr("Can't parse file header!")
            return 0

        # Create our map, setting width and height to 0 until we load a layer.
        map = Map(Map.Orientation.Orthogonal, 0, 0, 32, 32)
        map.setProperty("background_index", QString.number(backgroundIndex))
        # Load our Tilesets.
        typeTilesets = QVector()
        tileIndexTilesets = QVector()

        self.loadTilesetsFromResources(map, typeTilesets, tileIndexTilesets)
        # Load each of our layers.
        for i in range(layerCount):
            # Parse layer header.
            _type = _in.readUInt8()
            tileIndex = _in.readUInt8()
            scrollSpeed = _in.readFloat()
            levelSignature = _in.readUInt8()
            width = _in.readUInt32()
            height = _in.readUInt32()
            if (_in.status() == QDataStream.ReadPastEnd
                    or levelSignature != 42):
                self.mError = self.tr("Can't parse layer header!")
                return 0

            # Make sure our width and height are consistent.
            if (map.width() == 0):
                map.setWidth(width)
            if (map.height() == 0):
                map.setHeight(height)
            if (map.width() != width or map.height() != height):
                self.mError = self.tr("Inconsistent layer sizes!")
                return 0

            # Create a layer object.
            layer = TileLayer(self.layerTypeToName(_type), 0, 0, width, height)
            layer.setProperty("type", QString.number(_type))
            layer.setProperty("tile_index", QString.number(tileIndex))
            layer.setProperty("scroll_speed", QString.number(scrollSpeed, 'f'))
            map.addLayer(layer)
            # Look up the tileset for this layer.
            tileset = tilesetForLayer(_type, tileIndex, typeTilesets,
                                      tileIndexTilesets)
            # Read our tile data all at once.
            #tileData = QByteArray(width*height, b'\x00')
            bytesNeeded = width * height
            tileData = _in.readRawData(bytesNeeded)
            bytesRead = len(tileData)
            if (bytesRead != bytesNeeded):
                self.mError = self.tr("File ended in middle of layer!")
                return 0

            i = 0
            # Add the tiles to our layer.
            for y in range(0, height):
                for x in range(0, width):
                    tile_id = tileData[i] & 0xff
                    i += 1
                    if (tile_id != 255):
                        tile = tileset.tileAt(tile_id)
                        layer.setCell(x, y, Cell(tile))

        # Make sure we read the entire *.bin file.
        if (_in.status() != QDataStream.Ok or not _in.atEnd()):
            self.mError = self.tr("Unexpected data at end of file!")
            return 0

        return map