def store_file(self, id, file): id = id.replace('/', '_') directory = ApplicationData.get('images') filename = os.path.join(directory, id + '.png') if filename == os.path.normpath(file): return self.iconmap.get(id, None) makedirs(directory) pixmap = QPixmap() if file is not None and pixmap.load(file): if pixmap.size().width() > self.max_size or pixmap.size().height() > self.max_size: pixmap = pixmap.scaled(self.max_size, self.max_size, Qt.KeepAspectRatio, Qt.SmoothTransformation) buffer = QBuffer() pixmap.save(buffer, 'png') data = str(buffer.data()) with open(filename, 'wb') as f: f.write(data) icon = QIcon(pixmap) icon.filename = filename icon.content = data icon.content_type = 'image/png' else: unlink(filename) icon = None self.iconmap[id] = icon return icon
def _addIcon(self): filter_ = self.tr("Images (*.jpg *.jpeg *.bmp *.png *.tiff *.gif);;" "All files (*.*)") fileName, _selectedFilter = QFileDialog.getOpenFileName(self, self.tr("Open File"), self.latestDir, filter_) if fileName: file_info = QFileInfo(fileName) self.latestDir = file_info.absolutePath() image = QImage() if image.load(fileName): maxWidth = 22 maxHeight = 15 if image.width() > maxWidth or image.height() > maxHeight: scaledImage = image.scaled(maxWidth, maxHeight, Qt.KeepAspectRatio, Qt.SmoothTransformation) else: scaledImage = image ba = QByteArray() buffer = QBuffer(ba) buffer.open(QIODevice.WriteOnly) scaledImage.save(buffer, 'png') model = self.model() index = model.index(self.selectedIndex().row(), model.fieldIndex('icon')) model.setData(index, ba)
def write(self, stream, nodes, mode = MeshWriter.OutputMode.BinaryMode): archive = VirtualFile() archive.openStream(stream, "application/x-ufp", OpenMode.WriteOnly) #Store the g-code from the scene. archive.addContentType(extension = "gcode", mime_type = "text/x-gcode") gcode_textio = StringIO() #We have to convert the g-code into bytes. PluginRegistry.getInstance().getPluginObject("GCodeWriter").write(gcode_textio, None) gcode = archive.getStream("/3D/model.gcode") gcode.write(gcode_textio.getvalue().encode("UTF-8")) archive.addRelation(virtual_path = "/3D/model.gcode", relation_type = "http://schemas.ultimaker.org/package/2018/relationships/gcode") #Store the thumbnail. if self._snapshot: archive.addContentType(extension = "png", mime_type = "image/png") thumbnail = archive.getStream("/Metadata/thumbnail.png") thumbnail_buffer = QBuffer() thumbnail_buffer.open(QBuffer.ReadWrite) thumbnail_image = self._snapshot thumbnail_image.save(thumbnail_buffer, "PNG") thumbnail.write(thumbnail_buffer.data()) archive.addRelation(virtual_path = "/Metadata/thumbnail.png", relation_type = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail", origin = "/3D/model.gcode") else: Logger.log("d", "Thumbnail not created, cannot save it") archive.close() return True
def loadFromMemory(self): """ This slot function is called in the second Dialog process, when the user presses the "Load Image from Shared Memory" button. First, it attaches the process to the shared memory segment created by the first Dialog process. Then it locks the segment for exclusive access, copies the image data from the segment into a QBuffer, and streams the QBuffer into a QImage. Then it unlocks the shared memory segment, detaches from it, and finally displays the QImage in the Dialog. """ if not self.sharedMemory.attach(): self.ui.label.setText( "Unable to attach to shared memory segment.\nLoad an " "image first.") return buf = QBuffer() ins = QDataStream(buf) image = QImage() self.sharedMemory.lock() buf.setData(self.sharedMemory.constData()) buf.open(QBuffer.ReadOnly) ins >> image self.sharedMemory.unlock() self.sharedMemory.detach() self.ui.label.setPixmap(QPixmap.fromImage(image))
def mimeData(self, indexes): """ Public method to return the mime data. @param indexes list of indexes (QModelIndexList) @return mime data (QMimeData) """ from .XbelWriter import XbelWriter data = QByteArray() stream = QDataStream(data, QIODevice.WriteOnly) urls = [] for index in indexes: if index.column() != 0 or not index.isValid(): continue encodedData = QByteArray() buffer = QBuffer(encodedData) buffer.open(QIODevice.ReadWrite) writer = XbelWriter() parentNode = self.node(index) writer.write(buffer, parentNode) stream << encodedData urls.append(index.data(self.UrlRole)) mdata = QMimeData() mdata.setData(self.MIMETYPE, data) mdata.setUrls(urls) return mdata
def mouseMoveEvent(self, event): """ If the mouse moves far enough when the left mouse button is held down, start a drag and drop operation. """ if not event.buttons() & Qt.LeftButton: return if (event.pos() - self.dragStartPosition).manhattanLength() \ < QApplication.startDragDistance(): return if not self.hasImage: return drag = QDrag(self) mimeData = QMimeData() output = QByteArray() outputBuffer = QBuffer(output) outputBuffer.open(QIODevice.WriteOnly) self.imageLabel.pixmap().toImage().save(outputBuffer, 'PNG') outputBuffer.close() mimeData.setData('image/png', output) drag.setMimeData(mimeData) drag.setPixmap(self.imageLabel.pixmap().scaled(64, 64, Qt.KeepAspectRatio)) drag.setHotSpot(QPoint(drag.pixmap().width() / 2, drag.pixmap().height())) drag.start()
def dropMimeData(self, data, action, row, column, parent): """ Public method to accept the mime data of a drop action. @param data reference to the mime data (QMimeData) @param action drop action requested (Qt.DropAction) @param row row number (integer) @param column column number (integer) @param parent index of the parent node (QModelIndex) @return flag indicating successful acceptance of the data (boolean) """ if action == Qt.IgnoreAction: return True if column > 0: return False parentNode = self.node(parent) if not data.hasFormat(self.MIMETYPE): if not data.hasUrls(): return False from .BookmarkNode import BookmarkNode node = BookmarkNode(BookmarkNode.Bookmark, parentNode) node.url = bytes(data.urls()[0].toEncoded()).decode() if data.hasText(): node.title = data.text() else: node.title = node.url self.__bookmarksManager.addBookmark(parentNode, node, row) return True ba = data.data(self.MIMETYPE) stream = QDataStream(ba, QIODevice.ReadOnly) if stream.atEnd(): return False undoStack = self.__bookmarksManager.undoRedoStack() undoStack.beginMacro("Move Bookmarks") from .XbelReader import XbelReader while not stream.atEnd(): encodedData = QByteArray() stream >> encodedData buffer = QBuffer(encodedData) buffer.open(QIODevice.ReadOnly) reader = XbelReader() rootNode = reader.read(buffer) for bookmarkNode in rootNode.children(): rootNode.remove(bookmarkNode) row = max(0, row) self.__bookmarksManager.addBookmark( parentNode, bookmarkNode, row) self.__endMacro = True return True
def store_data(self, id, data): id = id.replace('/', '_') directory = ApplicationData.get('images') filename = os.path.join(directory, id + '.png') makedirs(directory) pixmap = QPixmap() if data is not None and pixmap.loadFromData(data): image_size = pixmap.size() if image_size.width() > self.max_size or image_size.height() > self.max_size: pixmap = pixmap.scaled(self.max_size, self.max_size, Qt.KeepAspectRatio, Qt.SmoothTransformation) if imghdr.what(None, data) != 'png' or pixmap.size() != image_size: buffer = QBuffer() pixmap.save(buffer, 'png') data = str(buffer.data()) with open(filename, 'wb') as f: f.write(data) icon = QIcon(pixmap) icon.filename = filename icon.content = data icon.content_type = 'image/png' else: unlink(filename) icon = None self.iconmap[id] = icon return icon
def dropEvent(self, event): mimeData = event.mimeData() if mimeData.hasUrls(): paths = mimeData.urls() # pick just one image path = paths[0].toLocalFile() fileName = os.path.basename(path) with open(path, "rb") as imgFile: data = imgFile.read() ext = os.path.splitext(path)[1][1:] # TODO: make sure we cleanup properly when replacing an image with # another if ext.lower() != "png": # convert img = QImage(path) data = QByteArray() buffer = QBuffer(data) buffer.open(QIODevice.WriteOnly) img.save(buffer, 'PNG') # format data = bytearray(data) fileName = "%s.png" % os.path.splitext(fileName)[0] imageSet = self._glyph.font.images try: imageSet[fileName] = data except Exception as e: errorReports.showCriticalException(e) return image = self._glyph.instantiateImage() image.fileName = fileName event.setAccepted(True) else: super().dropEvent(event)
def image_and_format_from_data(data): ' Create an image object from the specified data which should be a bytestring and also return the format of the image ' ba = QByteArray(data) buf = QBuffer(ba) buf.open(QBuffer.ReadOnly) r = QImageReader(buf) fmt = bytes(r.format()).decode('utf-8') return r.read(), fmt
def take_screenshot(self): byte_array = QByteArray() buffer = QBuffer(byte_array) buffer.open(QIODevice.WriteOnly) image = self.__screen.grabWindow(QApplication.desktop().winId()) image.save(buffer, "PNG") return str(byte_array.toBase64())[1:]
def requestStarted(self, job): """Handle a request for a qute: scheme. This method must be reimplemented by all custom URL scheme handlers. The request is asynchronous and does not need to be handled right away. Args: job: QWebEngineUrlRequestJob """ url = job.requestUrl() if url.scheme() in ['chrome-error', 'chrome-extension']: # WORKAROUND for https://bugreports.qt.io/browse/QTBUG-63378 job.fail(QWebEngineUrlRequestJob.UrlInvalid) return if not self._check_initiator(job): return if job.requestMethod() != b'GET': job.fail(QWebEngineUrlRequestJob.RequestDenied) return assert url.scheme() == 'qute' log.misc.debug("Got request for {}".format(url.toDisplayString())) try: mimetype, data = qutescheme.data_for_url(url) except qutescheme.Error as e: errors = { qutescheme.NotFoundError: QWebEngineUrlRequestJob.UrlNotFound, qutescheme.UrlInvalidError: QWebEngineUrlRequestJob.UrlInvalid, qutescheme.RequestDeniedError: QWebEngineUrlRequestJob.RequestDenied, qutescheme.SchemeOSError: QWebEngineUrlRequestJob.UrlNotFound, qutescheme.Error: QWebEngineUrlRequestJob.RequestFailed, } exctype = type(e) log.misc.error("{} while handling qute://* URL".format( exctype.__name__)) job.fail(errors[exctype]) except qutescheme.Redirect as e: qtutils.ensure_valid(e.url) job.redirect(e.url) else: log.misc.debug("Returning {} data".format(mimetype)) # We can't just use the QBuffer constructor taking a QByteArray, # because that somehow segfaults... # https://www.riverbankcomputing.com/pipermail/pyqt/2016-September/038075.html buf = QBuffer(parent=self) buf.open(QIODevice.WriteOnly) buf.write(data) buf.seek(0) buf.close() job.reply(mimetype.encode('ascii'), buf)
def sendMessage(self): textbuf = QBuffer() textbuf.open(QBuffer.ReadWrite) messageText = QDataStream(textbuf) messageText << self.ui.messageBox.text size = textbuf.size() if not self.shareMemory.create(size): return size = min(self.shareMemory.size(), size) self.sharedMemory.lock()
def fillImageFaster(self, begin, paint, current, image): buffer = QBuffer() buffer.open(QBuffer.ReadWrite) image.save(buffer, "PNG") pil_im = Image.open(io.BytesIO(buffer.data())) ImageDraw.floodfill(pil_im, begin, (paint.red(), paint.green(), paint.blue())) self.image().image = QtGui.QImage(pil_im.convert("RGB").tobytes("raw", "RGB"), pil_im.size[0], pil_im.size[1], QtGui.QImage.Format_RGB888) self.update()
def loadFromFile(self): """ This slot function is called when the "Load Image From File..." button is pressed on the firs Dialog process. First, it tests whether the process is already connected to a shared memory segment and, if so, detaches from that segment. This ensures that we always start the example from the beginning if we run it multiple times with the same two Dialog processes. After detaching from an existing shared memory segment, the user is prompted to select an image file. The selected file is loaded into a QImage. The QImage is displayed in the Dialog and streamed into a QBuffer with a QDataStream. Next, it gets a new shared memory segment from the system big enough to hold the image data in the QBuffer, and it locks the segment to prevent the second Dialog process from accessing it. Then it copies the image from the QBuffer into the shared memory segment. Finally, it unlocks the shared memory segment so the second Dialog process can access it. After self function runs, the user is expected to press the "Load Image from Shared Memory" button on the second Dialog process. """ if self.sharedMemory.isAttached(): self.detach() self.ui.label.setText("Select an image file") fileName, _ = QFileDialog.getOpenFileName(self, None, None, "Images (*.png *.xpm *.jpg)") image = QImage() if not image.load(fileName): self.ui.label.setText( "Selected file is not an image, please select another.") return self.ui.label.setPixmap(QPixmap.fromImage(image)) # Load into shared memory. buf = QBuffer() buf.open(QBuffer.ReadWrite) out = QDataStream(buf) out << image size = buf.size() if not self.sharedMemory.create(size): self.ui.label.setText("Unable to create shared memory segment.") return size = min(self.sharedMemory.size(), size) self.sharedMemory.lock() # Copy image data from buf into shared memory area. self.sharedMemory.data()[:] = buf.data().data() self.sharedMemory.unlock()
def encode_jpeg(file_path, quality=80): from calibre.utils.speedups import ReadOnlyFileBuffer quality = max(0, min(100, int(quality))) exe = get_exe_path('cjpeg') cmd = [exe] + '-optimize -progressive -maxmemory 100M -quality'.split() + [str(quality)] img = QImage() if not img.load(file_path): raise ValueError('%s is not a valid image file' % file_path) ba = QByteArray() buf = QBuffer(ba) buf.open(QBuffer.WriteOnly) if not img.save(buf, 'PPM'): raise ValueError('Failed to export image to PPM') return run_optimizer(file_path, cmd, as_filter=True, input_data=ReadOnlyFileBuffer(ba.data()))
def setImage(self, image): """ Public method to set the image of the engine. @param image image to be set (QImage) """ if not self._imageUrl: imageBuffer = QBuffer() imageBuffer.open(QIODevice.ReadWrite) if image.save(imageBuffer, "PNG"): self._imageUrl = "data:image/png;base64,{0}".format( bytes(imageBuffer.buffer().toBase64()).decode()) self.__image = QImage(image) self.imageChanged.emit()
def createData(self, mimeType): if mimeType != 'image/png': return image = QImage(self.imageLabel.size(), QImage.Format_RGB32) painter = QPainter() painter.begin(image) self.imageLabel.renderer().render(painter) painter.end() data = QByteArray() buffer = QBuffer(data) buffer.open(QIODevice.WriteOnly) image.save(buffer, 'PNG') buffer.close() self.mimeData.setData('image/png', data)
def capture(self, fullScreen = False, filename = ''): if fullScreen: image = QApplication.primaryScreen().grabWindow(0) else: image = QImage(self.webView.mainFrame.contentsSize(), QImage.Format_ARGB32) painter = QPainter(image) self.webView.mainFrame.render(painter) painter.end() if filename: return image.save(filename) else: data = QByteArray() buffer = QBuffer(data) buffer.open(QBuffer.WriteOnly) image.save(buffer, 'PNG') return bytes(data.toBase64()).decode()
def __getitem__(key): if key not in IconCache.icons: if not key.endswith('.svg') and not key.endswith('.svgz'): image = QImage(key).scaled(24, 24) else: svg = QSvgRenderer(key) image = QImage(24, 24, QImage.Format_ARGB32) image.fill(0) painter = QPainter(image) svg.render(painter) painter.end() bytes = QByteArray() buff = QBuffer(bytes) buff.open(QIODevice.WriteOnly) image.save(buff, 'png') IconCache.icons[key] = bytes return QIcon(QPixmap.fromImage(QImage.fromData(IconCache.icons[key])))
def _setNewImage(self, image): maxWidth = 16 maxHeight = 16 if image.width() > maxWidth or image.height() > maxHeight: scaledImage = image.scaled(maxWidth, maxHeight, Qt.KeepAspectRatio, Qt.SmoothTransformation) else: scaledImage = image ba = QByteArray() buffer = QBuffer(ba) buffer.open(QIODevice.WriteOnly) scaledImage.save(buffer, 'png') model = self.model() index = model.index(self.selectedIndex().row(), model.sourceModel().fieldIndex('icon')) model.setData(index, ba)
def sendDeleteRequest(self, endpoint, data={}, params={}, headers={}): buff = QBuffer() buff.open(QBuffer.ReadWrite) d = json.dumps(data).encode('utf-8') buff.write(d) buff.seek(0) headers.update({"Content-Type":"application/json"}) content = self.sendRequest( endpoint, params, 'delete', buff, headers=headers ) buff.close() return content
def __cssLinkClass(self, icon, size=32): """ Private method to generate a link class with an icon. @param icon icon to be included (QIcon) @param size size of the icon to be generated (integer) @return CSS class string (string) """ cssString = \ """a.{{0}} {{{{\n"""\ """ padding-left: {0}px;\n"""\ """ background: transparent url(data:image/png;base64,{1})"""\ """ no-repeat center left;\n"""\ """ font-weight: bold;\n"""\ """}}}}\n""" pixmap = icon.pixmap(size, size) imageBuffer = QBuffer() imageBuffer.open(QIODevice.ReadWrite) if not pixmap.save(imageBuffer, "PNG"): # write a blank pixmap on error pixmap = QPixmap(size, size) pixmap.fill(Qt.transparent) imageBuffer.buffer().clear() pixmap.save(imageBuffer, "PNG") return cssString.format( size + 4, str(imageBuffer.buffer().toBase64(), encoding="ascii"))
def open(self, _fname, mode): """Open an in-memory PyQIODevice instead of a real file.""" modes = { 'wb': QIODevice.WriteOnly | QIODevice.Truncate, 'w': QIODevice.WriteOnly | QIODevice.Text | QIODevice.Truncate, 'rb': QIODevice.ReadOnly, 'r': QIODevice.ReadOnly | QIODevice.Text, } try: qt_mode = modes[mode] except KeyError: raise ValueError("Invalid mode {}!".format(mode)) f = QBuffer(self._data) f.open(qt_mode) qiodev = qtutils.PyQIODevice(f) # Make sure tests using name/mode don't blow up. qiodev.name = test_file.TESTFN qiodev.mode = mode # Create empty TESTFN file because the Python tests try to unlink # it.after the test. open(test_file.TESTFN, 'w', encoding='utf-8').close() return qiodev
def __init__(self, job, engine, parent=None): """ Constructor :param job: reference to the URL request :type job: QWebEngineUrlRequestJob :param engine: reference to the help engine :type engine: QHelpEngine :param parent: reference to the parent object :type parent: QObject """ super(HelpSchemeReply, self).__init__(parent) url = job.requestUrl() strUrl = url.toString() self.__buffer = QBuffer() # For some reason the url to load maybe wrong (passed from web engine) # though the css file and the references inside should work that way. # One possible problem might be that the css is loaded at the same # level as the html, thus a path inside the css like # (../images/foo.png) might cd out of the virtual folder if not engine.findFile(url).isValid(): if strUrl.startswith(QtHelp_DOCROOT): newUrl = job.requestUrl() if not newUrl.path().startswith("/qdoc/"): newUrl.setPath("/qdoc" + newUrl.path()) url = newUrl strUrl = url.toString() self.__mimeType = mimetypes.guess_type(strUrl)[0] if self.__mimeType is None: # do our own (limited) guessing self.__mimeType = self.__mimeFromUrl(url) if engine.findFile(url).isValid(): data = engine.fileData(url) else: data = QByteArray(self.tr( """<html>""" """<head><title>Error 404...</title></head>""" """<body><div align="center"><br><br>""" """<h1>The page could not be found</h1><br>""" """<h3>'{0}'</h3></div></body>""" """</html>""").format(strUrl) .encode("utf-8")) self.__buffer.setData(data) self.__buffer.open(QIODevice.ReadOnly) self.open(QIODevice.ReadOnly)
def requestStarted(self, job): """Handle a request for a qute: scheme. This method must be reimplemented by all custom URL scheme handlers. The request is asynchronous and does not need to be handled right away. Args: job: QWebEngineUrlRequestJob """ url = job.requestUrl() assert job.requestMethod() == b'GET' assert url.scheme() == 'qute' log.misc.debug("Got request for {}".format(url.toDisplayString())) try: mimetype, data = qutescheme.data_for_url(url) except qutescheme.NoHandlerFound: log.misc.debug("No handler found for {}".format( url.toDisplayString())) job.fail(QWebEngineUrlRequestJob.UrlNotFound) except qutescheme.QuteSchemeOSError: # FIXME:qtwebengine how do we show a better error here? log.misc.exception("OSError while handling qute://* URL") job.fail(QWebEngineUrlRequestJob.UrlNotFound) except qutescheme.QuteSchemeError: # FIXME:qtwebengine how do we show a better error here? log.misc.exception("Error while handling qute://* URL") job.fail(QWebEngineUrlRequestJob.RequestFailed) except qutescheme.Redirect as e: qtutils.ensure_valid(e.url) job.redirect(e.url) else: log.misc.debug("Returning {} data".format(mimetype)) # We can't just use the QBuffer constructor taking a QByteArray, # because that somehow segfaults... # https://www.riverbankcomputing.com/pipermail/pyqt/2016-September/038075.html buf = QBuffer(parent=self) buf.open(QIODevice.WriteOnly) buf.write(data) buf.seek(0) buf.close() job.reply(mimetype.encode('ascii'), buf)
def fromqimage(im): buffer = QBuffer() buffer.open(QIODevice.ReadWrite) im.save(buffer, 'ppm') b = BytesIO() try: b.write(buffer.data()) except TypeError: # workaround for Python 2 b.write(str(buffer.data())) buffer.close() b.seek(0) return PIL.Image.open(b)
def perform_delete(self, endpoint, data, url): """ Perform an HTTP DELETE request. :param endpoint: the name of the Tribler endpoint. :param data: the data/body to send with the request. :param url: the url to send the request to. """ buf = QBuffer() buf.setData(data) buf.open(QIODevice.ReadOnly) delete_request = QNetworkRequest(QUrl(url)) reply = self.sendCustomRequest(delete_request, "DELETE", buf) buf.setParent(reply) return reply
def scale(image, width, height): edited = QImage.fromData(image.data, format_for(image.mime)) if edited.isNull(): return image scaled = edited.scaled(width, height, Qt.KeepAspectRatio, Qt.SmoothTransformation) buffer = QBuffer() buffer.open(QIODevice.WriteOnly) scaled.save(buffer, format_for(image.mime)) buffer.close() return Image(mime=image.mime, data=buffer.data(), desc=image.desc, type_=image.type)
def _resizeImage(self, virtual_path: str, width: int, height: int) -> IO[bytes]: input = self.getStream(virtual_path) try: from PyQt5.QtGui import QImage from PyQt5.QtCore import Qt, QBuffer image = QImage() image.loadFromData(input.read()) image = image.scaled(width, height, Qt.IgnoreAspectRatio, Qt.SmoothTransformation) output_buffer = QBuffer() output_buffer.open(QBuffer.ReadWrite) image.save(output_buffer, "PNG") output_buffer.seek( 0) # Reset that buffer so that the next guy can request it. return BytesIO(output_buffer.readAll()) except ImportError: # TODO: Try other image loaders. raise # Raise import error again if we find no other image loaders.
def init_ui(self): self.setMinimumWidth(320) self.setMinimumHeight(240) lb = QLabel() te = QTextEdit() layout = QBoxLayout(QBoxLayout.LeftToRight) layout.addWidget(lb) layout.addWidget(te) self.setLayout(layout) # 사용할 그림 설정 pixmap = QPixmap("apple.jpg") pixmap = pixmap.scaledToHeight(100) # 사이즈가 조정 lb.setPixmap(pixmap) # PNG 포맷 및 Base64로 변환 image: QImage = pixmap.toImage() data = QByteArray() buffer = QBuffer(data) image.save(buffer, 'PNG') te.setText(str(data.toBase64()))
def fromqimage(im): """ :param im: A PIL Image object, or a file name (given either as Python string or a PyQt string object) """ buffer = QBuffer() buffer.open(QIODevice.ReadWrite) # preserve alpha channel with png # otherwise ppm is more friendly with Image.open if im.hasAlphaChannel(): im.save(buffer, "png") else: im.save(buffer, "ppm") b = BytesIO() b.write(buffer.data()) buffer.close() b.seek(0) return Image.open(b)
def get_piclist_data_to_dict(self): for i in range(self.count()): try: item = self.item(i) if item.checkState() != Qt.Checked: continue icon = item.icon() if icon: pixmap = icon.pixmap(icon.availableSizes()[0]) array = QByteArray() buffer = QBuffer(array) buffer.open(QIODevice.WriteOnly) pixmap.save(buffer, 'JPG') buffer.close() yield array.data() except Exception: pass
def Guardar(self): # Obtener el nombre de usuario y la foto nombre = " ".join(self.lineEditNombre.text().split()).title() foto = self.labelImagen.pixmap() if foto: # Convertir la foto al tipo de dato adecuado bArray = QByteArray() bufer = QBuffer(bArray) bufer.open(QIODevice.WriteOnly) bufer.close() foto.save(bufer, "PNG") else: bArray = "" if nombre and bArray: # Establecer conexión con la base de datos conexion = connect("DB_USUARIOS.db") cursor = conexion.cursor() # Crear tabla, si no existe cursor.execute( "CREATE TABLE IF NOT EXISTS Usuarios (NOMBRE TEXT, FOTO BLOB)") conexion.commit() # Verificar que el usuario no exista if cursor.execute("SELECT * FROM Usuarios WHERE NOMBRE = ?", (nombre, )).fetchone(): print("El usaurio {} ya existe.".format(nombre)) else: # Guardar en la base de datos, el nombre de usuario y la foto cursor.execute("INSERT INTO Usuarios VALUES (?,?)", (nombre, bArray)) conexion.commit() self.labelImagen.clear() self.lineEditNombre.clear() print("Usuario guardado con éxito.") # Cerrar la conexión con la base de datos conexion.close() self.lineEditNombre.setFocus() else: self.lineEditNombre.setFocus()
def fromqimage(im): """ :param im: A PIL Image object, or a file name (given either as Python string or a PyQt string object) """ buffer = QBuffer() buffer.open(QIODevice.ReadWrite) # preserve alha channel with png # otherwise ppm is more friendly with Image.open if im.hasAlphaChannel(): im.save(buffer, 'png') else: im.save(buffer, 'ppm') b = BytesIO() try: b.write(buffer.data()) except TypeError: # workaround for Python 2 b.write(str(buffer.data())) buffer.close() b.seek(0) return Image.open(b)
def ReadText(self): # -------------------------------------------------------------- # # Alex Walker have a look below! ------------------------------- # buffer = QBuffer() buffer.open(QIODevice.ReadWrite) self.canvas.image.save(buffer, "PNG") data = BytesIO(buffer.data()) buffer.close() img = Image.open(data) # PIL image format # -------------------------------------------------------------- # thresh = 200 fn = lambda x: 255 if x > thresh else 0 mod = img.convert('L').point(fn, mode='1') text = pytesseract.image_to_string(mod, config='--psm 10') text = text.replace("~¦", "") self.pages[self.display.currentIndex()].insertPlainText(text.strip()) self.canvas.clearImage()
def generate_gif(self): img: Image imgs: List[Image] # https://pillow.readthedocs.io/en/stable/handbook/image-file-formats.html#gif select_frames_labels = self.layout_children(self.select_frames_layout) if not select_frames_labels: self.adjust_corgo() return pixmaps = [ i.original_pixmap for i in select_frames_labels if i.highlighted ] height = int(self.height.text()) img, *imgs = [ qpixmap_to_pil(i.scaledToHeight(height)) for i in pixmaps ] delay = int(self.delay.text()) bytesio = io.BytesIO() img.save(fp=bytesio, format='GIF', append_images=imgs, save_all=True, duration=delay, loop=0) self.gif_qbytearray = QByteArray(bytesio.getvalue()) bytesio.close() self.gif_qbuffer = QBuffer(self.gif_qbytearray) gif = QMovie() gif.setDevice(self.gif_qbuffer) gif.setCacheMode(QMovie.CacheAll) print(f'Movie isValid() {gif.isValid()}') self.gif_view.setMovie(gif) gif.start()
async def handleImage(self, requestId, img): scaledImage = img.scaled(self.ui.viewfinder.size(), Qt.KeepAspectRatio, Qt.SmoothTransformation) self.ui.lastImagePreviewLabel.setPixmap(QPixmap.fromImage(scaledImage)) self.displayCapturedImage() imgFormat = self.ui.captureImageFormat.currentText() array = QByteArray() buffer = QBuffer(array) buffer.open(QIODevice.WriteOnly) img.save(buffer, imgFormat) buffer.close() await self.importImageBuffer(buffer, imgFormat.lower()) QTimer.singleShot(3000, self.displayViewfinder)
def imageToSql(self, pathimage, idcd, minisize): """Write image and thunbnail to database.""" # just file #file = QFile(pathimage) #file.open(QIODevice.ReadOnly) #inByteArray = QByteArray(file.readAll()) # image big #print(path.getsize(pathimage)) inPixmap = QPixmap(pathimage) inByteArray = QByteArray() inBuffer = QBuffer(inByteArray) if not inBuffer.open(QIODevice.WriteOnly): return False inPixmap.save(inBuffer,"JPG"); # image mini # Qt.FastTransformation inPixmap = inPixmap.scaled(minisize, minisize, Qt.IgnoreAspectRatio, Qt.SmoothTransformation) inByteArraymini = QByteArray() inBuffer = QBuffer(inByteArraymini) inBuffer.open(QIODevice.WriteOnly); inPixmap.save(inBuffer,"JPG"); # mssql # https://stackoverflow.com/questions/108403/solutions-for-insert-or-update-on-sql-server # UPDATE data or INSERT : https://en.wikipedia.org/wiki/Merge_(SQL) query = QSqlQuery() request = getrequest('insertcover') query.prepare(request) query.bindValue(0, idcd) query.bindValue(1, pathimage) query.bindValue(2, inByteArray) query.bindValue(3, inByteArraymini) if not query.exec_(): qDebug(10*' '+":index "+query.lastError().text()) return False return True
def extract(self, page: Poppler.Page): from tesserocr import PyTessBaseAPI # NOQA Stupid assert on LC_* == 'C' ocr = PyTessBaseAPI(lang=settings.CAMPUSONLINE_BULLETIN_OCR_LANGUAGE) text = page.text(QRectF()).strip() if len(text) > settings.CAMPUSONLINE_BULLETIN_OCR_THRESHOLD: self.clean = True self.text = text return dpi = settings.CAMPUSONLINE_BULLETIN_OCR_DPI buf = QBuffer() buf.open(QIODevice.ReadWrite) page.renderToImage(dpi, dpi).save(buf, "PNG") bio = BytesIO() bio.write(buf.data()) buf.close() bio.seek(0) img = Image.open(bio) ocr.SetImage(img) scanned = ocr.GetUTF8Text().strip() img.close() bio.close() self.clean = False self.text = scanned
def screenshot(): app = QtWidgets.QApplication(sys.argv) image = QtWidgets.QApplication.screens()[0].grabWindow( QtWidgets.QApplication.desktop().winId(), 0, 0, QtWidgets.QApplication.desktop().screenGeometry().width(), QtWidgets.QApplication.desktop().screenGeometry().height()) size = QSize(SRC_W, SRC_H) image = image.scaled(size) buffer = QBuffer() buffer.open(QIODevice.WriteOnly) image.save(buffer, "PNG") strio = BytesIO() strio.write(buffer.data()) buffer.close() strio.seek(0) img = imread(strio) test = prepare_image(img) return test
def image_to_data(img, compression_quality=95, fmt='JPEG', png_compression_level=9, jpeg_optimized=True, jpeg_progressive=False): ''' Serialize image to bytestring in the specified format. :param compression_quality: is for JPEG and goes from 0 to 100. 100 being lowest compression, highest image quality :param png_compression_level: is for PNG and goes from 0-9. 9 being highest compression. :param jpeg_optimized: Turns on the 'optimize' option for libjpeg which losslessly reduce file size :param jpeg_progressive: Turns on the 'progressive scan' option for libjpeg which allows JPEG images to be downloaded in streaming fashion ''' fmt = fmt.upper() ba = QByteArray() buf = QBuffer(ba) buf.open(QBuffer.WriteOnly) if fmt == 'GIF': w = QImageWriter(buf, b'PNG') w.setQuality(90) if not w.write(img): raise ValueError('Failed to export image as ' + fmt + ' with error: ' + w.errorString()) from PIL import Image im = Image.open(BytesIO(ba.data())) buf = BytesIO() im.save(buf, 'gif') return buf.getvalue() is_jpeg = fmt in ('JPG', 'JPEG') w = QImageWriter(buf, fmt.encode('ascii')) if is_jpeg: if img.hasAlphaChannel(): img = blend_image(img) # QImageWriter only gained the following options in Qt 5.5 if jpeg_optimized: w.setOptimizedWrite(True) if jpeg_progressive: w.setProgressiveScanWrite(True) w.setQuality(compression_quality) elif fmt == 'PNG': cl = min(9, max(0, png_compression_level)) w.setQuality(10 * (9-cl)) if not w.write(img): raise ValueError('Failed to export image as ' + fmt + ' with error: ' + w.errorString()) return ba.data()
def to_jpeg(self, quality=None): if quality is None: quality = defaults.JPEG_QUALITY buf = QBuffer() self.img.save(buf, 'jpeg', quality) return bytes(buf.data())
def to_png(self, complevel=defaults.PNG_COMPRESSION_LEVEL): quality = 90 - (complevel * 10) buf = QBuffer() self.img.save(buf, 'png', quality) return bytes(buf.data())
class ContourRoundRectangle(): # # define your own images to describe your GCode-Generator def __init__(self, parent): path = os.getcwd() self.__imageNames = [ # left down path + "/img/contour/round-rectangle-pic1_1.jpg", path + "/img/contour/round-rectangle-pic1_2.jpg", ] self.parent = parent self.window = parent.window self.centerPos = 0 self.window.rbCPRR_1.clicked.connect( lambda clicked: self.onCenterPosChange(0)) self.window.rbCPRR_2.clicked.connect( lambda clicked: self.onCenterPosChange(1)) self.window.rbTrcRRect.clicked.connect( lambda clicked: self.onToolMoveChanged("on")) self.window.rbTrclRRect.clicked.connect( lambda clicked: self.onToolMoveChanged("left")) self.window.rbTrcrrRect.clicked.connect( lambda clicked: self.onToolMoveChanged("right")) self.window.edgeRadius.editingFinished.connect( self.onEdgeRadiusChanged) self.arcPix = False self.buffer = QBuffer() self.pixmap = QPixmap() self.painter = QPainter() for i in range(1, 3): obj = "rbCPRR_" + str(i) attr = getattr(self.window, obj) if attr.isChecked(): attr.clicked.emit() self.updateMillTool() self.drawRoundedRect(1.0) def updateMillTool(self): if self.window.rbTrcRRect.isChecked(): self.window.rbTrcRRect.clicked.emit() elif self.window.rbTrclRRect.isChecked(): self.window.rbTrclRRect.clicked.emit() elif self.window.rbTrcrrRect.isChecked(): self.window.rbTrcrrRect.clicked.emit() def updatePosForm(self, boolean): self.window.posRRX.setEnabled(boolean) self.window.posRRY.setEnabled(boolean) self.window.labelRRX.setEnabled(boolean) self.window.labelRRY.setEnabled(boolean) def onCenterPosChange(self, pos): if self.pixmap.load(self.__imageNames[pos]): self.window.imageRR.setPixmap(self.pixmap) self.drawCenterPos(pos) else: print("Image Load Error ", self.__imageNames[pos]) def onToolMoveChanged(self, pos): self.arcPix = False if pos == "on": self.drawMiller(40) elif pos == "right": self.drawMiller(20) elif pos == "left": self.drawMiller(60) def onEdgeRadiusChanged(self): value = self.window.edgeRadius.text() self.drawRoundedRect(float(value)) def drawRoundedRect(self, r): pen = QtGui.QPen() pen.setWidth(2) pen.setColor(QtGui.QColor('black')) pix = QPixmap() if self.arcPix: pix.loadFromData(self.buffer.data()) else: pix = self.window.imageRR.pixmap() self.buffer.open(QBuffer.ReadWrite) pix.save(self.buffer, "PNG") self.arcPix = True self.painter.begin(pix) self.painter.setPen(pen) self.painter.drawRoundedRect(40, 78, 220, 150, r, r) self.painter.end() self.window.imageRR.setPixmap(pix) # self.window.imageRR.update() def drawCenterPos(self, pos): pen = QtGui.QPen() pen.setWidth(3) pen.setColor(QtGui.QColor('red')) pix = QPixmap() pix = self.pixmap self.painter.begin(pix) self.painter.setPen(pen) if pos == 0: xh = 40 yh = pix.height() - 40 self.painter.drawLine(xh - 10, yh, xh + 10, yh) self.painter.drawLine(xh, yh - 10, xh, yh + 10) self.updatePosForm(True) if pos == 1: xh = pix.width() / 2 yh = pix.height() / 2 self.painter.drawLine(xh - 10, yh, xh + 10, yh) self.painter.drawLine(xh, yh - 10, xh, yh + 10) self.updatePosForm(False) self.painter.end() self.updateMillTool() def drawMiller(self, pos): pen = QtGui.QPen() pen.setWidth(30) pen.setColor(QtGui.QColor('blue')) self.window.imageRR.setPixmap(self.pixmap) pix = self.window.imageRR.pixmap() self.painter.begin(pix) self.painter.setPen(pen) self.painter.drawEllipse(pix.width() - pos, pix.height() / 2, 4, 4) self.painter.end() self.window.image.update() self.window.edgeRadius.editingFinished.emit() #------------------------------------------------------------- # here you generate your GCode. # some of this code should be used every time. # insert your code bettween marked rows #------------------------------------------------------------- def generateGCode(self, parent): ''' generate GCode for a rounded rectangle. This class is copied from pocketRoundRectangle. Some unnessesary code are removed. Some parts are new (cutter compensation) ''' print("ContourRoundRect") cPoint = (float(self.window.posRRX.text()), float(self.window.posRRY.text())) sizeAB = (float(self.window.heightRA.text()), float(self.window.heightRB.text())) radius = float(self.window.edgeRadius.text()) toolDia = float(self.window.toolDiameter.text()) zPos = { "safetyZ": float(self.window.zSafe.text()), "startZ": float(self.window.startZ.text()) } depth = (float(self.window.depthRRTotal.text()), float(self.window.depthRRStep.text())) dir = parent.commonGcode.getDir() feeds = { "XYG0": float(self.window.speedXY.text()), "XYGn": float(self.window.speedG2G3.text()), "ZG0": float(self.window.speedZ.text()), "ZGn": float(self.window.speedZg1.text()) } gc = "" gc += self.window.preamble.text() # set Unit gc += parent.commonGcode.getUnit() + CR # set Z axis gc += CR + "(set Z saftey position)" + CR gc += "G00 Z{0:08.3f} F{1:05.1f} {2}".format(zPos["safetyZ"], feeds["ZG0"], CR) # # even which center point user choosed, we start on # center point object - left down (5) if self.centerPos == 5: cPoint = (0.0 - (sizeAB[1] / 2.0), 0.0 - (sizeAB[0] / 2.0)) # set start postion X/Y gc += CR + "(set center position)" + CR gc += "G00 X{0:08.3f} Y{1:08.3f} F{2:05.1f} {3}".format( cPoint[0], cPoint[1], feeds["XYG0"], CR) # # generate as many shape steps are needed until depthtotal is reached # cut an Arc step = depth[1] # depth = float(self.__depthtotal.get()) z = step loop = "" gc += CR + "(------- start shape -------------)" + CR # start with shape gc += CR + "(move Z-axis to start postion near surface)" + CR gc += "G00 Z{0:08.3f} F{1:05.1f} {2}".format(zPos["startZ"], feeds["ZG0"], CR) spaces = "".ljust(2) #---------------------------------------------------------------------- # This loop asume, that you try to mill into your object. # if not needed for your shape, remove this part and rewrite #---------------------------------------------------------------------- # pocketMillTracks = [] x = 1 t = self.__createPocketTracks( cPoint, sizeAB, radius, feeds, 0.0 # no offset, milling only one time ! ) pocketMillTracks.append(t) #gc += self.getGCodeCutterComp(self.__cuttercompensation.get(), toolDia) gc += parent.commonGcode.getGCodeCutterComp( parent.commonGcode.getCompensation(), toolDia) # # it's time to generate the real gCode # # Every round we mill all tracks in the same detph # than we increase depth as long as we reached total depthStep gc += CR + "(-- START DEPTH Loop --)" + CR z = depth[1] while (abs(z) < abs(depth[0])): # set next Z depth print("Z: ", abs(z), " MaxD: ", abs(depth[0])) if ((abs(depth[0]) - abs(z)) < abs(depth[1])): # this happens, if a small amount is the rest z -= (abs(depth[0]) - abs(z)) print("rest Z: ", z) else: z -= abs(depth[1]) print("new Z: ", z) loop += CR gc += spaces + "(-- START Track Loop --)" + CR for t in pocketMillTracks: # every track contain a fixed number of separate gCode # commands print(t) spaces2 = spaces.ljust(2) # set new depth gc += CR + spaces2 + "(-- next depth z {0:08.3f} --){1}".format( z, CR) gc += spaces2 + "G01 Z{0:08.3f} {1}".format(z, CR) for cmd in list(t): # # combine all parameter to one command gc += spaces2 # 0 1 2 3 4 # GC, X, Y, I, J print(cmd) for p in range(len(cmd)): if p == 0: gc += cmd[p] if p == 1: f = " F{0:05.1f}".format(float(cmd[p])) if p == 2: gc += " X{0:08.3f}".format(float(cmd[p])) if p == 3: gc += " Y{0:08.3f}".format(float(cmd[p])) if p == 4: gc += " I{0:08.3f}".format(float(cmd[p])) if p == 5: gc += " J{0:08.3f}".format(float(cmd[p])) gc += f + CR gc += spaces + "(-- END Track Loop --)" + CR pass gc += "(-- END DEPTH loop --)" + CR gc += parent.commonGcode.getGCode_Homeing(cPoint[0], cPoint[1], zPos["safetyZ"], feeds["XYG0"]) gc += self.window.postGcode.text() gc += CR return gc def __createPocketTracks(self, cPoint, sizeAB, r, feeds, offset=0.0): ''' This method create for a track all needed GCode parameters and save them in a list. This list is used (afterwards) to create the real GCode commands This method is called in a loop with a new offset. The offset describes next millings position ''' # h = h1 + 2*r # w = w1 + 2*r w0 = sizeAB[1] w1 = sizeAB[1] - (2 * r) # horizontal distance between arcs h0 = sizeAB[0] h1 = sizeAB[0] - (2 * r) # vertical distance betwween arcs x = cPoint[0] y = cPoint[1] # sequence to mill a rounded rectangle seq = [] #start seq.append(("G01", feeds["XYGn"], x, y - offset)) # arc1 # G02, F X Y I J if r > 0: seq.append( ("G02", feeds["XYGn"], x - r - offset, y + r, 0.0, r + offset)) # vertical to arc2 seq.append(("G01", feeds["XYGn"], x - r - offset, y + r + h1)) # arc2 # G02, F X Y I J if r > 0: seq.append( ("G02", feeds["XYGn"], x, y + h0 + offset, r + offset, 0.0)) # horizontal to arc 3 seq.append(("G01", feeds["XYGn"], x + w1, y + h0 + offset)) # arc 3 # G02, F X Y I J if r > 0: seq.append(("G02", feeds["XYGn"], x + w1 + r + offset, y + r + h1, 0.0, -r - offset)) # vertical to arc 4 seq.append(("G01", feeds["XYGn"], x + w1 + r + offset, y + r)) # arc 4 # G02, G02, F X Y I J if r > 0: seq.append( ("G02", feeds["XYGn"], x + w1, y - offset, -r - offset, 0.0)) # go back to start position seq.append(("G01", feeds["XYGn"], x, y - offset)) #print "{1}---- offset {0} -----".format(offset,CR) #print (seq) return seq
def _close(self, request): buffer = QBuffer(self) buffer.setData( b"<html><head><script>window.close();</script></head></html>") request.reply(b"text/html", buffer) self.parent().close()
def responseComplete(self): request = self.serverInterface().requestHandler() params = request.parameterMap() # SERVICE=RENDERGEOJSON -- we are taking over if params.get('SERVICE', '').upper() == 'RENDERGEOJSON': request.clear() try: # Parse parameters geojson = params.get('GEOJSON') if not geojson: raise ParameterError('Parameter GEOJSON must be set.') style = params.get('STYLE') if not style: raise ParameterError('Parameter STYLE must be set.') try: width = int(params.get('WIDTH')) except TypeError: raise ParameterError('Parameter WIDTH must be integer.') try: height = int(params.get('HEIGHT')) except TypeError: raise ParameterError('Parameter HEIGHT must be integer.') try: dpi = int(params.get('DPI', 96)) except TypeError: raise ParameterError('Parameter DPI must be integer.') try: minx, miny, maxx, maxy = params.get('BBOX').split(',') bbox = QgsRectangle(float(minx), float(miny), float(maxx), float(maxy)) except (ValueError, AttributeError): raise ParameterError( 'Parameter BBOX must be specified in the form `min_x,min_y,max_x,max_y`.' ) url = geojson geojson_file_name = self._resolve_url(geojson) if '$type' in style: polygon_style = self._resolve_url( style.replace('$type', 'polygons')) line_style = self._resolve_url( style.replace('$type', 'lines')) point_style = self._resolve_url( style.replace('$type', 'points')) else: polygon_style = self._resolve_url(style) line_style = polygon_style point_style = polygon_style polygon_layer = QgsVectorLayer( geojson_file_name + '|geometrytype=Polygon', 'polygons', 'ogr') self._load_style(polygon_layer, polygon_style) line_layer = QgsVectorLayer( geojson_file_name + '|geometrytype=Line', 'lines', 'ogr') self._load_style(line_layer, line_style) point_layer = QgsVectorLayer( geojson_file_name + '|geometrytype=Point', 'points', 'ogr') self._load_style(point_layer, point_style) settings = QgsMapSettings() settings.setOutputSize(QSize(width, height)) settings.setOutputDpi(dpi) settings.setExtent(bbox) settings.setLayers([polygon_layer, line_layer, point_layer]) settings.setBackgroundColor(QColor(Qt.transparent)) renderer = QgsMapRendererParallelJob(settings) event_loop = QEventLoop() renderer.finished.connect(event_loop.quit) renderer.start() event_loop.exec_() img = renderer.renderedImage() img.setDotsPerMeterX(dpi * 39.37) img.setDotsPerMeterY(dpi * 39.37) image_data = QByteArray() buf = QBuffer(image_data) buf.open(QIODevice.WriteOnly) img.save(buf, 'PNG') request.setResponseHeader('Content-type', 'image/png') request.appendBody(image_data) except ParameterError as e: QgsMessageLog.logMessage( "RenderGeojson.responseComplete :: ParameterError") request.setResponseHeader('Content-type', 'text/plain') request.appendBody(str(e).encode('utf-8')) except: QgsMessageLog.logMessage( "RenderGeojson.responseComplete :: Exception") QgsMessageLog.logMessage( "RenderGeojson.responseComplete :: {}".format( traceback.format_exc())) request.setResponseHeader('Content-type', 'text/plain') request.appendBody(b'Unhandled error') request.appendBody(traceback.format_exc().encode('utf-8'))
def base64image(image): ba = QByteArray() buffer = QBuffer(ba) buffer.open(QIODevice.WriteOnly) image.save(buffer, "PNG") return "data:image/png;base64," + ba.toBase64().data().decode("ascii")
class HelpSchemeReply(QIODevice): """ Class implementing a reply for a requested qthelp: page. @signal closed emitted to signal that the web engine has read the data see: https://fossies.org/linux/eric6/eric/WebBrowser/Network/QtHelpSchemeHandler.py All credits for this class go to: Detlev Offenbach, the developer of The Eric Python IDE(https://eric-ide.python-projects.org) """ closed = pyqtSignal() def __init__(self, job, engine, parent=None): """ Constructor @param job reference to the URL request @type QWebEngineUrlRequestJob @param engine reference to the help engine @type QHelpEngine @param parent reference to the parent object @type QObject """ super(HelpSchemeReply, self).__init__(parent) url = job.requestUrl() strUrl = url.toString() self.__buffer = QBuffer() # For some reason the url to load maybe wrong (passed from web engine) # though the css file and the references inside should work that way. # One possible problem might be that the css is loaded at the same # level as the html, thus a path inside the css like # (../images/foo.png) might cd out of the virtual folder if not engine.findFile(url).isValid(): if strUrl.startswith(QtHelp_DOCROOT): newUrl = job.requestUrl() if not newUrl.path().startswith("/qdoc/"): newUrl.setPath("/qdoc" + newUrl.path()) url = newUrl strUrl = url.toString() self.__mimeType = mimetypes.guess_type(strUrl)[0] if self.__mimeType is None: # do our own (limited) guessing self.__mimeType = self.__mimeFromUrl(url) if engine.findFile(url).isValid(): data = engine.fileData(url) else: data = QByteArray(self.tr( """<html>""" """<head><title>Error 404...</title></head>""" """<body><div align="center"><br><br>""" """<h1>The page could not be found</h1><br>""" """<h3>'{0}'</h3></div></body>""" """</html>""").format(strUrl) .encode("utf-8")) self.__buffer.setData(data) self.__buffer.open(QIODevice.ReadOnly) self.open(QIODevice.ReadOnly) def bytesAvailable(self): """ Public method to get the number of available bytes. @return number of available bytes @rtype int """ return self.__buffer.bytesAvailable() def readData(self, maxlen): """ Public method to retrieve data from the reply object. @param maxlen maximum number of bytes to read (integer) @return string containing the data (bytes) """ return self.__buffer.read(maxlen) def close(self): """ Public method used to cloase the reply. """ super(HelpSchemeReply, self).close() self.closed.emit() def __mimeFromUrl(self, url): """ Private method to guess the mime type given an URL. @param url URL to guess the mime type from (QUrl) @return mime type for the given URL (string) """ path = url.path() ext = os.path.splitext(path)[1].lower() if ext in ExtensionMap: return ExtensionMap[ext] else: return "application/octet-stream" def mimeType(self): """ Public method to get the reply mime type. @return mime type of the reply @rtype bytes """ return self.__mimeType.encode("utf-8")
class MainWindow(QMainWindow): def __init__(self, wav_path): QMainWindow.__init__(self) self.resize(350, 250) self.setWindowTitle('MainWindow') self._setLayout() self.status_bar = self.statusBar() self.wav_path = wav_path self.params = utils.read_wav_info(wav_path) self.duration = self.params.nframes / self.params.framerate self.output = utils.get_audio_output(self.params) self.output.stateChanged.connect(self.state_checkpoint) self.output.setNotifyInterval(20) self.output.notify.connect(self.notified) self.loop_button.clicked.connect(self.switch_loop) self.play_button.clicked.connect(self.play_pause) self.random_button.clicked.connect(self.set_random_region) self.export_button.clicked.connect(self.export_region) self.command_edit.returnPressed.connect(self.command_entered) self.loop_enabled = False self.buffer = QBuffer() self.region = None self.set_region((0, REG_SECONDS * self.params.framerate)) # self.set_random_region() def _setLayout(self): widget = QtWidgets.QWidget() grid = QtWidgets.QGridLayout(widget) self.progressBar = QtWidgets.QProgressBar(widget) self.progressBar.setRange(0, 100) self.progressBar.setValue(0) self.progressBar.setTextVisible(True) self.loop_button = QtWidgets.QPushButton('Loop', widget) self.loop_button.setCheckable(True) self.play_button = QtWidgets.QPushButton('Play | Stop', widget) self.random_button = QtWidgets.QPushButton('Random', widget) self.command_edit = QtWidgets.QLineEdit('') self.export_button = QtWidgets.QPushButton('Export', widget) grid.addWidget(self.progressBar, 0, 0, 1, 3) grid.addWidget(self.loop_button, 1, 0) grid.addWidget(self.play_button, 1, 1) grid.addWidget(self.random_button, 1, 2) grid.addWidget(self.command_edit, 2, 1) grid.addWidget(self.export_button, 2, 2) widget.setLayout(grid) self.setCentralWidget(widget) def play(self): """ Play from the beginning. """ if self.buffer.isOpen(): state = self.output.state() if state != QAudio.StoppedState: self.output.stop() if sys.platform == 'darwin': self.buffer.close() self.buffer.open(QIODevice.ReadOnly) else: # I found this way does not works on OS X self.buffer.seek(0) else: # Load from file self.buffer.open(QIODevice.ReadOnly) self.output.start(self.buffer) def play_pause(self): """ Play or pause based on audio output state. """ state = self.output.state() if state == QAudio.ActiveState: # playing # pause playback self.output.suspend() elif state == QAudio.SuspendedState: # paused # resume playback self.output.resume() elif state == QAudio.StoppedState or state == QAudio.IdleState: self.play() def stop(self): """ Stop playback. """ state = self.output.state() if state != QAudio.StoppedState: self.output.stop() if sys.platform == 'darwin': self.buffer.close() def switch_loop(self): self.loop_enabled = not self.loop_enabled def state_checkpoint(self): """ React to AudioOutput state change. Loop if enabled. """ # Loop implementation state = self.output.state() if state == QAudio.ActiveState: print(state, '== Active') elif state == QAudio.SuspendedState: print(state, '== Suspended') elif state == QAudio.IdleState: print(state, '== Idle') if self.loop_enabled: self.play() else: self.stop() elif state == QAudio.StoppedState: print(state, '== Stopped') def notified(self): start_time = self.region[0] / self.params.framerate playing_time = self.output.processedUSecs() / 1000000 + start_time self.progressBar.setValue(playing_time * 100 / self.duration) self.status_bar.showMessage(str(timedelta(seconds=playing_time))[:-3]) def set_region(self, region): """ Put the playback start position to `position`. """ # avoid segfault if changing region during playback self.stop() position, end = region position = max(0, min(position, end)) # don't start before 0 end = min(self.params.nframes, end) # don't set end after days! self.region = position, end print('set_region -> {:,}-{:,}'.format(*self.region)) print('region times: {}-{} (duration={})'.format(*self.region_timedeltas())) frame_to_read = end - position wav = wave.open(self.wav_path) wav.setpos(position) # we need to reinit buffer since the region could be shorter than before self.buffer = QBuffer() self.buffer.writeData(wav.readframes(frame_to_read)) wav.close() start_time = position / self.params.framerate self.progressBar.setValue(start_time * 100 / self.duration) self.status_bar.showMessage(str(timedelta(seconds=start_time))[:-3]) @property def reg_nframes(self): return self.region[1] - self.region[0] def set_random_region(self): """ Choose a random position and set playback start from there. """ try: position = random.randrange(self.params.nframes - self.reg_nframes) except ValueError: print('Cannot move position randomly. Please shorten the region.') position = 0 end = position + self.reg_nframes print('Random region: {:.2f}-{:.2f}'.format( position / self.params.framerate, end / self.params.framerate) ) self.set_region((position, end)) def region_timedeltas(self): """Return start, end and duration timedeltas""" start, end = self.region start_timedelta = timedelta(seconds=start / self.params.framerate) end_timedelta = timedelta(seconds=end / self.params.framerate) return start_timedelta, end_timedelta, (end_timedelta - start_timedelta) def command_entered(self): """ Change region boundaries with Blender-like syntax. Examples: "l-0.5" ==> move start position 0.5 s before "r1" ==> move stop position 1 seconds after """ command = self.command_edit.text() try: lr, delta = utils.parse_command(command) except (IndexError, ValueError) as err: print(err) return start, end = self.region if lr == 'l': start = int(start + delta * self.params.framerate) print('New start: {}'.format(timedelta(seconds=(start / self.params.framerate)))) elif lr == 'r': end = int(end + delta * self.params.framerate) print('New end: {}'.format(timedelta(seconds=(end / self.params.framerate)))) self.set_region((start, end)) self.command_edit.setText('') # feature: restart immediately after command is entered self.play() def export_region(self): """ Export the current region. """ start, stop = self.region wav_filepath = self.wav_path[:-4] + '[{}-{}].wav'.format(start, stop) with wave.open(wav_filepath, 'wb') as wave_write: wave_write.setparams(self.params) wave_write.writeframes(self.buffer.data()) print(wav_filepath, 'created')
def saveBookInfo(self): selected_items = self.treeFileList.selectedItems() if len(selected_items) == 1: QApplication.setOverrideCursor(Qt.BusyCursor) item = selected_items[0] meta = Fb2Meta(item.text(2)) meta.get() if self.book_cover: data = QByteArray() buf = QBuffer(data) self.book_cover.save(buf, 'JPG') meta.coverdata = bytes(buf.buffer()) if not meta.coverpage: meta.coverpage = 'cover.jpg' meta.coverpage_href = '{http://www.w3.org/1999/xlink}href' else: meta.coverpage = '' meta.coverdata = None meta.set_authors(self.editAuthor.text()) meta.book_title = self.editTitle.text() meta.set_series(self.editSeries.text(), self.editSeriesNumber.text()) meta.lang = self.editBookLanguage.text() meta.write() item.setText(0, meta.book_title) item.setText(1, meta.get_autors()) QApplication.restoreOverrideCursor() elif len(selected_items) > 1: msg = QMessageBox(self) msg.setIcon(QMessageBox.Question) msg.setWindowTitle(_translate('fb2mobi', 'Save')) msg.setText( _translate('fb2mobi', 'Save changes in selected files?')) msg.setStandardButtons(QMessageBox.Save | QMessageBox.Cancel) if msg.exec_() == QMessageBox.Save: QApplication.setOverrideCursor(Qt.BusyCursor) for item in selected_items: meta = Fb2Meta(item.text(2)) meta.get() (series, series_number) = meta.get_first_series() authors = meta.get_autors() if self.editAuthor.text(): authors = self.editAuthor.text() if self.editSeries.text(): series = self.editSeries.text() meta.set_authors(authors) meta.set_series(series, series_number) if self.editBookLanguage.text(): meta.lang = self.editBookLanguage.text() meta.write() item.setText(0, meta.book_title) item.setText(1, meta.get_autors()) QApplication.restoreOverrideCursor()
def run_api(): # pdf = Poppler.Document() # page = Poppler.Page() pdf = 0 page = 0 image = QImage() byte_data = QByteArray() color_theme = 'light' #allowed color themes: 'light','dark','sepia' while True: s = input() tokens = s.split(' ') if tokens[0] == 'open': #open a pdf file pdf = Poppler.Document.load(tokens[1]) pdf.setRenderHint(Poppler.Document.TextAntialiasing) if tokens[0] == 'page': #open a page of the current pdf page = pdf.page(tokens[1]) if tokens[0] == 'pages': #returns number of pages print(pdf.numPages()) if tokens[0] == 'color': #set color theme color_theme = tokens[1] if tokens[0] == 'textlist': #outputs textlist as a json file textlist = page.textList() textlist_json = [] for text in textlist: bb = text.boundingBox() d = {'text': text.text(), 'x': bb.x(), 'y': bb.y(), 'width': bb.width(), 'height': bb.height()} textlist_json.append(d) print(json.dumps(textlist_json)) if tokens[0] == 'render': #output pixel data to stdout image = page.renderToImage(3 * 72, 3 * 72, -1, -1, -1, -1) print(image.format()) if color_theme == 'dark': for x in range(image.width()): for y in range(image.height()): rgb = image.pixelColor(x, y) rgb.setRed(int(linear_interpolation(234, 68, rgb.red() / 255))) rgb.setGreen(int(linear_interpolation(234, 68, rgb.green() / 255))) rgb.setBlue(int(linear_interpolation(234, 68, rgb.blue() / 255))) image.setPixelColor(x, y, rgb) # print(image.data) # bits = image.bits() # byte_data.fromRawData(image.data) # print(byte_data) ba = QByteArray() buffer = QBuffer(ba) buffer.open(QIODevice.WriteOnly) image.save(buffer, "PNG") # writes image into ba in PNG format ba2 = buffer.data() for i in ba. bits = image.constBits() bits.setsize(image.width() * image.height() * 4) print(str(bits)) print(dir(bits)) print(bits.asarray()) print(str(bits.asarray())) imgPtr = c_void_p(bits.__int__()) print(dir(imgPtr)) # for i in range(len(bits)): # print(bits[i]) # print(image.constBits()[0]) # print(bits) # print(type(bits)) # for i in range(image.width()): # for j in range(image.height()): # # print(image.pixel(i, j)) # print(bits[i]) # # color = QColor(image.pixel(i,j)) # # print(image.pixel(i,j).red(), image.pixel(i,j).green(), image.pixel(i,j).blue()) if tokens[0] == 'toc': toc = pdf.toc()
def perform_request(self, endpoint, read_callback, data="", method='GET', capture_errors=True): """ Perform a HTTP request. :param endpoint: the endpoint to call (i.e. "statistics") :param read_callback: the callback to be called with result info when we have the data :param data: optional POST data to be sent with the request :param method: the HTTP verb (GET/POST/PUT/PATCH) :param capture_errors: whether errors should be handled by this class (defaults to True) """ performed_requests[self.request_id] = [endpoint, method, data, time(), -1] performed_requests_ids.append(self.request_id) if len(performed_requests_ids) > 200: del performed_requests[performed_requests_ids.pop(0)] url = self.base_url + endpoint if method == 'GET': buf = QBuffer() buf.setData(data) buf.open(QIODevice.ReadOnly) get_request = QNetworkRequest(QUrl(url)) self.reply = self.sendCustomRequest(get_request, "GET", buf) buf.setParent(self.reply) elif method == 'PATCH': buf = QBuffer() buf.setData(data) buf.open(QIODevice.ReadOnly) patch_request = QNetworkRequest(QUrl(url)) self.reply = self.sendCustomRequest(patch_request, "PATCH", buf) buf.setParent(self.reply) elif method == 'PUT': request = QNetworkRequest(QUrl(url)) request.setHeader(QNetworkRequest.ContentTypeHeader, "application/x-www-form-urlencoded") self.reply = self.put(request, data) elif method == 'DELETE': buf = QBuffer() buf.setData(data) buf.open(QIODevice.ReadOnly) delete_request = QNetworkRequest(QUrl(url)) self.reply = self.sendCustomRequest(delete_request, "DELETE", buf) buf.setParent(self.reply) elif method == 'POST': request = QNetworkRequest(QUrl(url)) request.setHeader(QNetworkRequest.ContentTypeHeader, "application/x-www-form-urlencoded") self.reply = self.post(request, data) if read_callback: self.received_json.connect(read_callback) self.finished.connect(lambda reply: self.on_finished(reply, capture_errors))
def write(self, stream, nodes, mode=MeshWriter.OutputMode.TextMode): """Writes the g-code for the entire scene to a stream. Note that even though the function accepts a collection of nodes, the entire scene is always written to the file since it is not possible to separate the g-code for just specific nodes. :param stream: The stream to write the g-code to. :param nodes: This is ignored. :param mode: Additional information on how to format the g-code in the file. This must always be text mode. """ if mode != MeshWriter.OutputMode.TextMode: Logger.log("e", "SnapmakerGCodeWriter does not support non-text mode.") self.setInformation( catalog.i18nc( "@error:not supported", "SnapmakerGCodeWriter does not support non-text mode.")) return False active_build_plate = Application.getInstance().getMultiBuildPlateModel( ).activeBuildPlate scene = Application.getInstance().getController().getScene() if not hasattr(scene, "gcode_dict"): self.setInformation( catalog.i18nc("@warning:status", "Please prepare G-code before exporting.")) return False gcode_dict = getattr(scene, "gcode_dict") gcode_list = gcode_dict.get(active_build_plate, None) # Get some vars (I cannot find the correct value) printTemp = None bedTemp = None for x in gcode_list: if ("M190" in x or "M140" in x) and bedTemp is None: for y in re.findall(r"(M140|M190) S(\d+)", x): #Logger.log("d","Bed:" + y[1]) bedTemp = y[1] break if ("M109" in x or "M104" in x) and printTemp is None: for y in re.findall(r"(M109|M104) S(\d+)", x): #Logger.log("d","Extruder:" + y[1]) printTemp = y[1] break if printTemp is not None and bedTemp is not None: break print_info = Application.getInstance().getPrintInformation() feature_times = print_info.getFeaturePrintTimes() estiTime = 0 #in Seconds for x in feature_times: #Logger.log("d",x+":"+str(int(feature_times[x])) + " Seconds") estiTime += int(feature_times[x]) # Generate snapshot self.snapshot = self._createSnapshot() Logger.log("d", "Snapshot created.") thumbnail_buffer = QBuffer() thumbnail_buffer.open(QBuffer.ReadWrite) thumbnail_image = self._snapshot thumbnail_image.save(thumbnail_buffer, "PNG") base64_bytes = base64.b64encode(thumbnail_buffer.data()) base64_message = base64_bytes.decode('ascii') thumbnail_buffer.close() # Start header stream.write(";Header Start\n\n") gcode_buffer = "" header_buffer = False model_line_count = 0 if gcode_list is not None: has_settings = False for gcode in gcode_list: if gcode[:len(self._setting_keyword)] == self._setting_keyword: has_settings = True # Move FLAVOR/TIME/... block to top if "FLAVOR" not in gcode: model_line_count += len(gcode.splitlines( )) # Add lines to model_line_count for header gcode_buffer += gcode + '\n' # Add extra newline for each layer, for readability of gcode else: # Split header lines and write to buffer header_buffer = gcode.splitlines(keepends=True) # Combine everything stream.write(header_buffer[0]) # FLAVOR stream.write(header_buffer[1]) # TIME stream.write(header_buffer[2]) # Filament used stream.write(header_buffer[3]) # Layer height stream.write("\n\n;header_type: 3dp\n") stream.write(";thumbnail: data:image/png;base64," + base64_message + "\n") stream.write(";file_total_lines: " + str(model_line_count) + "\n") stream.write(";estimated_time(s): " + str(estiTime) + "\n") stream.write(";nozzle_temperature(°C): " + str(printTemp) + "\n") stream.write(";build_plate_temperature(°C): " + str(bedTemp) + "\n") stream.write(header_buffer[7].replace('MAXX:', 'max_x(mm): ')) # max_x stream.write(header_buffer[8].replace('MAXY:', 'max_y(mm): ')) # max_y stream.write(header_buffer[9].replace('MAXZ:', 'max_z(mm): ')) # max_z stream.write(header_buffer[4].replace('MINX:', 'min_x(mm): ')) # min_x stream.write(header_buffer[5].replace('MINY:', 'min_y(mm): ')) # min_y stream.write(header_buffer[6].replace('MINZ:', 'min_z(mm): ')) # min_z stream.write("\n;Header End\n\n") # Add some useful comments, conform Luban generated code, and/or what I deem usefull gcode_buffer = re.sub(r"(M109 S\d+)", r"\1 ;Wait for Hotend Temperature", gcode_buffer) gcode_buffer = re.sub(r"(M190 S\d+)", r"\1 ;Wait for Bed Temperature", gcode_buffer) gcode_buffer = re.sub(r"(G92 E0)", r"\1 ;Reset the extruder's origin/length", gcode_buffer) stream.write(gcode_buffer) # Serialise the current container stack and put it at the end of the file. if not has_settings: settings = self._serialiseSettings( Application.getInstance().getGlobalContainerStack()) stream.write(settings) return True self.setInformation( catalog.i18nc("@warning:status", "Please prepare G-code before exporting.")) return False
def __init__(self, view): self.view = view self.buffer = QBuffer() self.network_manager = QNetworkAccessManager(self.view) self.network_manager.finished.connect(self.on_received_response)
def html(self): QApplication.setOverrideCursor(QCursor(Qt.WaitCursor)) # create start to basic html format html = """ <!DOCTYPE html> <html> <head> </head> <style> * { font-size: 75%; font-family: "Times New Roman", Times, serif; } th { text-align: left; } </style> <body> """ # add title information html = html + ("<H1>" + self.lblLocation.text() + "</H1>") html = html + ("<H3>" + self.lblDateRange.text() + "</H3>") html = html + ("<H3>" + self.lblDetails.text() + "</H3>") html = html + ("<H3>" + self.lblLocationsVisited.text() + "</H3>") html = html + ("<H3>" + self.lblTopSpeciesSeen.text() + "</H3>") # grab the map image from the map tap # process it into a byte array and encode it # so we can insert it inline into the html myPixmap = self.webMap.grab() myPixmap = myPixmap.scaledToWidth(600, Qt.SmoothTransformation) myByteArray = QByteArray() myBuffer = QBuffer(myByteArray) myBuffer.open(QIODevice.WriteOnly) myPixmap.save(myBuffer, "PNG") encodedImage = base64.b64encode(myByteArray) html = html + (""" <img src="data:image/png;base64, """) html = html + str(encodedImage)[1:] html = html + (""" " /> """) html = html + ("<H4>" + "Species" + "</H4>") html = html + ("<font size='2'>" + "<table width='100%'>" + " <tr>") html = html + ("<th>" + "Species" + "</th>" + "<th>" + "First" + "</th> " + "<th></th> " + "<th>" + "Latest" + "</th>" + "</tr>") for r in range(self.tblSpecies.rowCount()): html = html + ( "<tr>" + "<td>" + self.tblSpecies.item(r, 1).text() + "</td>" + "<td>" + self.tblSpecies.item(r, 2).text() + "</td>" + "<td>" + " " + "</td>" + "<td>" + self.tblSpecies.item(r, 3).text() + "</td>" + "</tr>") html = html + "</table>" html = html + ("<H4>" + "Dates" + "</H4>") html = html + ("<font size='2'>" + "<p>") # loopthrough the dates listed in lstDates # create a filter unique to each date # and get species for that date for r in range(self.lstDates.count()): html = html + ("<b>" + self.lstDates.item(r).text() + "</b>") # create filter set to our current location filter = deepcopy(self.filter) filter.setStartDate(self.lstDates.item(r).text()) filter.setEndDate(self.lstDates.item(r).text()) species = self.mdiParent.db.GetSpecies(filter) html = html + ("<br>" + "<table width='100%'>" + "<tr>") # set up counter R to start a new row after listing each 3 species R = 1 for s in species: html = html + ("<td>" + s + "</td>") if R == 3: html = html + ("</tr>" + "<tr>") R = 0 R = R + 1 html = html + ("<br>" + "<br>" + "</table>") html = html + ( "<H4>" + "Locations" + "</H4>" + "<p>" + "Asterisks indicate species seen only at listed location.") # loopthrough the locations listed in lstLocations # create a filter unique to each location # and get species for that date for r in range(self.lstLocations.count()): html = html + ("<b>" + self.lstLocations.item(r).text() + "</b>") # create filter set to our current location filter = deepcopy(self.filter) filter.setLocationType("Location") filter.setLocationName(self.lstLocations.item(r).text()) species = self.mdiParent.db.GetSpecies(filter) uniqueSpecies = self.mdiParent.db.GetUniqueSpeciesForLocation( self.filter, self.lstLocations.item(r).text(), species, self.filteredSightingList) html = html + ("<br>" + "<table width='100%'>" + "<tr>") # set up counter R to start a new row after listing each 3 species R = 1 for s in species: if s in uniqueSpecies: s = s + "*" html = html + ("<td>" + s + "</td>") if R == 3: html = html + ("</tr>" + "<tr>") R = 0 R = R + 1 html = html + ("<br>" + "<br>" + "</table>") html = html + ("<p>" + "<H4>" + "New Life Species" + "</H4>" + "<p>" + "<table width='100%'>" "<tr>") # set up counter R to start a new row after listing each 3 species R = 1 if self.lstNewLifeSpecies.count() == 0: html = html + ("<td>" + "None" + "</td>") else: # loopthrough the species listed in lstNewLifeSpecies for r in range(self.lstNewLifeSpecies.count()): html = html + ("<td>" + self.lstNewLifeSpecies.item(r).text() + "</td>") if R == 3: html = html + ("</tr>" + "<tr>") R = 0 R = R + 1 html = html + ("<br>" + "<br>" + "</table>") # set up New Year Species html = html + ("<p>" + "<H4>" + "New Year Species" + "</H4>" + "<p>" + "<table width='100%'>" + "<tr>") # set up counter R to start a new row after listing each 3 species R = 1 if self.tblNewYearSpecies.rowCount() == 0: html = html + ("<td>" + "None" + "</td>") else: # loopthrough the species listed in lstNewLifeSpecies for r in range(self.tblNewYearSpecies.rowCount()): html = html + ( "<td>" + self.tblNewYearSpecies.item(r, 1).text() + " (" + self.tblNewYearSpecies.item(r, 0).text() + ")" + "</td>") if R == 3: html = html + ("</tr>" "<tr>") R = 0 R = R + 1 html = html + ("</tr>" + "</table>") # set up New Month Species html = html + ("<p>" + "<H4>" + "New Month Species" + "</H4>" + "<p>" + "<table width='100%'>" + "<tr>") # set up counter R to start a new row after listing each 3 species R = 1 if self.tblNewMonthSpecies.rowCount() == 0: html = html + ("<td>" + "None" + "</td>") else: # loopthrough the species listed in lstNewLifeSpecies for r in range(self.tblNewMonthSpecies.rowCount()): html = html + ( "<td>" + self.tblNewMonthSpecies.item(r, 1).text() + " (" + self.tblNewMonthSpecies.item(r, 0).text() + ")" + "</td>") if R == 3: html = html + ("</tr>" "<tr>") R = 0 R = R + 1 html = html + ("</tr>" + "</table>") # set up New Country Species html = html + ("<p>" + "<H4>" + "New Country Species" + "</H4>" + "<p>" + "<table width='100%'>" + "<tr>") # set up counter R to start a new row after listing each 3 species R = 1 if self.tblNewCountrySpecies.rowCount() == 0: html = html + ("<td>" + "None" + "</td>") else: # loopthrough the species listed in lstNewLifeSpecies for r in range(self.tblNewCountrySpecies.rowCount()): html = html + ("<td>" + self.tblNewCountrySpecies.item( r, 1).text() + " (" + self.tblNewCountrySpecies.item( r, 0).text() + ")" + "</td>") if R == 2: html = html + ("</tr>" "<tr>") R = 0 R = R + 1 html = html + ("</tr>" + "</table>") html = html + ("<font size>" + "</body>" + "</html>") # set up New State Species html = html + ("<p>" + "<H4>" + "New State Species" + "</H4>" + "<p>" + "<table width='100%'>" + "<tr>") # set up counter R to start a new row after listing each 3 species R = 1 if self.tblNewStateSpecies.rowCount() == 0: html = html + ("<td>" + "None" + "</td>") else: # loopthrough the species listed in lstNewLifeSpecies for r in range(self.tblNewStateSpecies.rowCount()): html = html + ( "<td>" + self.tblNewStateSpecies.item(r, 1).text() + " (" + self.tblNewStateSpecies.item(r, 0).text() + ")" + "</td>") if R == 2: html = html + ("</tr>" "<tr>") R = 0 R = R + 1 html = html + ("</tr>" + "</table>") # set up New County Species html = html + ("<p>" + "<H4>" + "New County Species" + "</H4>" + "<p>" + "<table width='100%'>" + "<tr>") # set up counter R to start a new row after listing each 3 species R = 1 if self.tblNewCountySpecies.rowCount() == 0: html = html + ("<td>" + "None" + "</td>") else: # loopthrough the species listed in lstNewLifeSpecies for r in range(self.tblNewCountySpecies.rowCount()): html = html + ("<td>" + self.tblNewCountySpecies.item( r, 1).text() + " (" + self.tblNewCountySpecies.item( r, 0).text() + ")" + "</td>") if R == 2: html = html + ("</tr>" "<tr>") R = 0 R = R + 1 html = html + ("</tr>" + "</table>") # set up New Location Species html = html + ("<p>" + "<H4>" + "New Location Species" + "</H4>" + "<p>" + "<table width='100%'>" + "<tr>") # set up counter R to start a new row after listing each 3 species R = 1 if self.tblNewLocationSpecies.rowCount() == 0: html = html + ("<td>" + "None" + "</td>") else: # loopthrough the species listed in lstNewLifeSpecies for r in range(self.tblNewLocationSpecies.rowCount()): html = html + ("<td>" + self.tblNewLocationSpecies.item( r, 1).text() + " (" + self.tblNewLocationSpecies.item( r, 0).text() + ")" + "</td>") if R == 2: html = html + ("</tr>" "<tr>") R = 0 R = R + 1 html = html + ("</tr>" + "</table>") html = html + ("<font size>" + "</body>" + "</html>") QApplication.restoreOverrideCursor() return (html)
def write(self, stream, nodes, mode=MeshWriter.OutputMode.BinaryMode): archive = VirtualFile() archive.openStream(stream, "application/x-ufp", OpenMode.WriteOnly) #Store the g-code from the scene. archive.addContentType(extension="gcode", mime_type="text/x-gcode") gcode_textio = StringIO() #We have to convert the g-code into bytes. gcode_writer = cast( MeshWriter, PluginRegistry.getInstance().getPluginObject("GCodeWriter")) success = gcode_writer.write(gcode_textio, None) if not success: #Writing the g-code failed. Then I can also not write the gzipped g-code. self.setInformation(gcode_writer.getInformation()) return False gcode = archive.getStream("/3D/model.gcode") gcode.write(gcode_textio.getvalue().encode("UTF-8")) archive.addRelation( virtual_path="/3D/model.gcode", relation_type= "http://schemas.ultimaker.org/package/2018/relationships/gcode") self._createSnapshot() #Store the thumbnail. if self._snapshot: archive.addContentType(extension="png", mime_type="image/png") thumbnail = archive.getStream("/Metadata/thumbnail.png") thumbnail_buffer = QBuffer() thumbnail_buffer.open(QBuffer.ReadWrite) thumbnail_image = self._snapshot thumbnail_image.save(thumbnail_buffer, "PNG") thumbnail.write(thumbnail_buffer.data()) archive.addRelation( virtual_path="/Metadata/thumbnail.png", relation_type= "http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail", origin="/3D/model.gcode") else: Logger.log("d", "Thumbnail not created, cannot save it") # Store the material. application = Application.getInstance() machine_manager = application.getMachineManager() material_manager = application.getMaterialManager() global_stack = machine_manager.activeMachine material_extension = "xml.fdm_material" material_mime_type = "application/x-ultimaker-material-profile" try: archive.addContentType(extension=material_extension, mime_type=material_mime_type) except: Logger.log("w", "The material extension: %s was already added", material_extension) added_materials = [] for extruder_stack in global_stack.extruders.values(): material = extruder_stack.material try: material_file_name = material.getMetaData( )["base_file"] + ".xml.fdm_material" except KeyError: Logger.log("w", "Unable to get base_file for the material %s", material.getId()) continue material_file_name = "/Materials/" + material_file_name # The same material should not be added again. if material_file_name in added_materials: continue material_root_id = material.getMetaDataEntry("base_file") material_group = material_manager.getMaterialGroup( material_root_id) if material_group is None: Logger.log("e", "Cannot find material container with root id [%s]", material_root_id) return False material_container = material_group.root_material_node.getContainer( ) try: serialized_material = material_container.serialize() except NotImplementedError: Logger.log( "e", "Unable serialize material container with root id: %s", material_root_id) return False material_file = archive.getStream(material_file_name) material_file.write(serialized_material.encode("UTF-8")) archive.addRelation( virtual_path=material_file_name, relation_type= "http://schemas.ultimaker.org/package/2018/relationships/material", origin="/3D/model.gcode") added_materials.append(material_file_name) archive.close() return True
def export_video(self): if not imageio: return QMessageBox( QMessageBox.Information, 'Export not available', 'imageio and ffmpeg must be installed to export videos').exec( ) location = QFileDialog.getSaveFileName(self, 'Choose export location', filter='Video (*.mp4)')[0] if not location: return if not location.endswith('.mp4'): location += '.mp4' frame_count = int(self.duration * FPS) progress_box = QProgressDialog('Recording and exporting video...', 'Cancel', 1, frame_count, self) progress_box.setWindowModality(Qt.WindowModal) with imageio.get_writer(location, format='mp4', mode='I', fps=FPS, quality=6) as writer: frame = 0 stopped = False def new_event(*args): nonlocal frame, stopped try: self.callback( AniState(self, frame=frame, time=frame / FPS, dt=1 / FPS)) frame += 1 except StopIteration: stopped = True old = self.paintEvent self.paintEvent = new_event self.start() self.frame_no = 0 for i in range(frame_count): progress_box.setValue(i) if progress_box.wasCanceled(): os.remove(location) return im_bytes = QByteArray() buf = QBuffer(im_bytes) buf.open(QIODevice.WriteOnly) self.grab().save(buf, 'PNG', 100) # Triggers paintEvent self.frame_no += 1 writer.append_data(imageio.imread(im_bytes.data(), 'png')) if stopped: break progress_box.setValue(progress_box.maximum()) self.paintEvent = old return QMessageBox( QMessageBox.Information, 'Completed', 'Export finished! Saved to {}'.format(location)).exec()
def qImgToPilRGBA(qimg): buf = QBuffer() buf.open(QBuffer.ReadWrite) qimg.save(buf, "PNG") return Image.open(io.BytesIO(buf.data().data())).convert('RGBA')