def canInsertFromMimeData(self, source: QMimeData): if source.hasImage(): return True elif source.hasUrls(): return True elif source.hasHtml(): return True else: return super().canInsertFromMimeData(source)
def dropMimeData(self, mime: QMimeData, action, row: int, column: int, parent: QModelIndex): LOG.debug('dropMimeData at row {}'.format(row)) if action == Qt.IgnoreAction: return True if mime.hasFormat('text/uri-list'): if mime.hasUrls(): LOG.debug('found urls in drop!') paths = [ qurl.path() for qurl in mime.urls() if qurl.isLocalFile() ] self.doc.import_files(paths) # FIXME: replace with a signal return True elif mime.hasFormat(self._mimetype): # unpickle the presentation information and re-insert it # b = base64.decodebytes(mime.text()) b = mime.data(self._mimetype) layer_set_len, insertion_info = pkl.loads(b) LOG.debug('dropped: {0!r:s}'.format(insertion_info)) count = len(insertion_info) if row == -1: row = len(self.doc) # append # FIXME: row=col=-1 implies drop-on-parent # which may mean replace or may mean append for composite layers # self.insertRows(row, count) # for i, presentation in enumerate(l): # self.setData(self.index(row+i, 0), presentation) order = list(range(layer_set_len)) inserted_row_numbers = [] # inserted_presentations = [] # delete_these_rows = [] insertion_point = row uuids = [] for old_row, presentation in reversed(sorted(insertion_info)): del order[old_row] if old_row < insertion_point: insertion_point -= 1 inserted_row_numbers.insert(0, old_row) uuids.append(presentation.uuid) # delete_these_rows.append(old_row if old_row<row else old_row+count) # inserted_presentations.append(presentation) order = order[:insertion_point] + inserted_row_numbers + order[ insertion_point:] LOG.debug('new order after drop {0!r:s}'.format(order)) self.select([]) self.doc.reorder_by_indices(order) # self.doc.insert_layer_prez(row, inserted_presentations) # LOG.debug('after insertion removing rows {0!r:s}'.format(delete_these_rows)) # for exrow in delete_these_rows: # self.doc.remove_layer_prez(exrow) # self.doc.didReorderLayers.emit(order) # FUTURE: not our business to be emitting on behalf of the document assert (count == len(insertion_info)) return True return False
def insertFromMimeData(self, source: QMimeData, disable_richtext: bool = False): ''' ..todo: Add support for embedded content when inserting html mime from clipboard ''' if source.hasImage(): temporary_file = os.path.join( Environment.get_base_path(), Configuration().get_setting( 'oxnote', 'application.directories.temporary', default='.oxnote/tmp'), '{}.png'.format( (str(uuid.uuid4())))) source.imageData().save(temporary_file) with open(temporary_file, 'rb') as f: encoded = base64.b64encode(f.read()) self.textCursor().insertImage('data:image/png;base64,{}'.format( encoded.decode("utf-8"))) if os.path.isfile(temporary_file): os.remove(temporary_file) elif source.hasUrls(): for url in source.urls(): if pathlib.Path(url.fileName()).suffix.lower( )[1:] not in self.supported_image_formats: super().insertFromMimeData(source) continue file_extension = pathlib.Path( url.fileName()).suffix.lower()[1:] if url.isLocalFile(): if not os.path.isfile(url.toLocalFile()): continue with open(url.toLocalFile(), 'rb') as f: self.textCursor().insertImage( 'data:image/png;base64,{}'.format( base64.b64encode(f.read()).decode("utf-8"))) else: response = requests.get(url.toString(), stream=True) if response.status_code == 200: self.textCursor().insertImage( 'data:image/{};base64,{}'.format( file_extension, base64.b64encode( response.content).decode("utf-8"))) elif source.hasHtml() and disable_richtext: self.textCursor().insertText(source.text()) else: super().insertFromMimeData(source)
def show_menu(self, clickPos): index = self.tree.indexAt(clickPos) selected_path = self.tree.model().filePath(index) enclosing_dir = self.find_enclosing_dir(selected_path) menu = QMenu(self) openAction = menu.addAction("Open") newFolderAction = menu.addAction("New Folder") newFileAction = menu.addAction("New File") copyAction = menu.addAction("Copy") pasteAction = menu.addAction("Paste") renameAction = menu.addAction("Rename") fileInfo = menu.addAction("Properties") menuPos = QPoint(clickPos.x() + 15, clickPos.y() + 15) action = menu.exec_(self.mapToGlobal(menuPos)) if action == openAction: self.open_file(index) elif action == newFolderAction: path = self.get_dialog_str("New Folder", "Enter name for new folder:") if path: self.mkdir(os.path.join(enclosing_dir, path)) elif action == newFileAction: path = self.get_dialog_str("New File", "Enter name for new file:") if path: self.touch(os.path.join(enclosing_dir, path)) elif action == renameAction: path = self.get_dialog_str("Rename File", "Enter new name:") # Naive validation if "/" in path: msg = QMessageBox() msg.setIcon(QMessageBox.Critical) msg.setText("Filename cannot contain '/'") msg.setWindowTitle("Error") msg.exec_() return new_path = os.path.join(enclosing_dir, path) self.move(selected_path, new_path) elif action == copyAction: mime_data = QMimeData() # TODO: support multiple selections mime_data.setUrls([QUrl(Path(selected_path).as_uri())]) self.clipboard.setMimeData(mime_data) elif action == pasteAction: mime_data = self.clipboard.mimeData() if not mime_data: return if mime_data.hasUrls(): for src_url in mime_data.urls(): self.copy(src_url.path(), enclosing_dir)