def select_file(self): """Open a file selection dialog box""" fname = self.item.from_string(to_text_string(self.edit.text())) if isinstance(fname, list): fname = osp.dirname(fname[0]) parent = self.parent_layout.parent _temp = sys.stdout sys.stdout = None if len(fname) == 0: fname = self.basedir _formats = self.item.get_prop_value("data", "formats") formats = [to_text_string(format).lower() for format in _formats] filter_lines = [(_("%s files")+" (*.%s)") % (format.upper(), format) for format in formats] all_filter = _("All supported files")+" (*.%s)" % " *.".join(formats) if len(formats) > 1: if self.all_files_first: filter_lines.insert(0, all_filter) else: filter_lines.append(all_filter) if fname is None: fname = "" child_title = _get_child_title_func(parent) fname, _filter = self.filedialog(parent, child_title(self.item), fname, "\n".join(filter_lines)) sys.stdout = _temp if fname: if isinstance(fname, list): fname = to_text_string(fname) self.edit.setText(fname)
def _qfiledialog_wrapper(attr, parent=None, caption='', basedir='', filters='', selectedfilter='', options=None): if options is None: options = QFileDialog.Options(0) try: # PyQt <v4.6 (API #1) from guidata.qt.QtCore import QString except ImportError: # PySide or PyQt >=v4.6 QString = None # analysis:ignore tuple_returned = True try: # PyQt >=v4.6 func = getattr(QFileDialog, attr+'AndFilter') except AttributeError: # PySide or PyQt <v4.6 func = getattr(QFileDialog, attr) if QString is not None: selectedfilter = QString() tuple_returned = False # Calling QFileDialog static method if sys.platform == "win32": # On Windows platforms: redirect standard outputs _temp1, _temp2 = sys.stdout, sys.stderr sys.stdout, sys.stderr = None, None try: result = func(parent, caption, basedir, filters, selectedfilter, options) except TypeError: # The selectedfilter option (`initialFilter` in Qt) has only been # introduced in Jan. 2010 for PyQt v4.7, that's why we handle here # the TypeError exception which will be raised with PyQt v4.6 # (see Issue 960 for more details) result = func(parent, caption, basedir, filters, options) finally: if sys.platform == "win32": # On Windows platforms: restore standard outputs sys.stdout, sys.stderr = _temp1, _temp2 # Processing output if tuple_returned: # PySide or PyQt >=v4.6 output, selectedfilter = result else: # PyQt <v4.6 (API #1) output = result if QString is not None: # PyQt API #1: conversions needed from QString/QStringList selectedfilter = to_text_string(selectedfilter) if isinstance(output, QString): # Single filename output = to_text_string(output) else: # List of filenames output = [to_text_string(fname) for fname in output] # Always returns the tuple (output, selectedfilter) return output, selectedfilter
def utf8_to_unicode(string): """Convert UTF-8 string to Unicode""" if not is_text_string(string): string = to_text_string(string) if not is_unicode(string): try: string = to_text_string(string, "utf-8") except UnicodeDecodeError: # This is border line... but we admit here string which has been # erroneously encoded in file system charset instead of UTF-8 string = decode_fs_string(string) return string
def exec_image_open_dialog(parent, basedir='', app_name=None, to_grayscale=True, dtype=None): """ Executes an image open dialog box (QFileDialog.getOpenFileName) * parent: parent widget (None means no parent) * basedir: base directory ('' means current directory) * app_name (opt.): application name (used as a title for an eventual error message box in case something goes wrong when saving image) * to_grayscale (default=True): convert image to grayscale Returns (filename, data) tuple if dialog is accepted, None otherwise """ saved_in, saved_out, saved_err = sys.stdin, sys.stdout, sys.stderr sys.stdout = None filename, _filter = getopenfilename(parent, _("Open"), basedir, io.iohandler.get_filters('load', dtype=dtype)) sys.stdin, sys.stdout, sys.stderr = saved_in, saved_out, saved_err filename = to_text_string(filename) try: data = io.imread(filename, to_grayscale=to_grayscale) except Exception as msg: import traceback traceback.print_exc() QMessageBox.critical(parent, _('Error') if app_name is None else app_name, (_("%s could not be opened:") % osp.basename(filename))+\ "\n"+str(msg)) return return filename, data
def __init__(self, label, curve, xrangeselection, function=None): self.label = to_text_string(label) self.curve = curve self.range = xrangeselection if function is None: function = lambda x, dx: (x, dx) self.func = function
def setup(self): title = to_text_string(self.toolbar.windowTitle()) self.plotwidget.add_toolbar(self.toolbar, title) if isinstance(self.plotwidget, ImageWidget): self.plotwidget.register_all_image_tools() else: self.plotwidget.register_all_curve_tools()
def exec_image_save_dialog(parent, data, template=None, basedir='', app_name=None): """ Executes an image save dialog box (QFileDialog.getSaveFileName) * parent: parent widget (None means no parent) * data: image pixel array data * template: image template (pydicom dataset) for DICOM files * basedir: base directory ('' means current directory) * app_name (opt.): application name (used as a title for an eventual error message box in case something goes wrong when saving image) Returns filename if dialog is accepted, None otherwise """ saved_in, saved_out, saved_err = sys.stdin, sys.stdout, sys.stderr sys.stdout = None filename, _filter = getsavefilename(parent, _("Save as"), basedir, io.iohandler.get_filters('save', dtype=data.dtype, template=template)) sys.stdin, sys.stdout, sys.stderr = saved_in, saved_out, saved_err if filename: filename = to_text_string(filename) kwargs = {} if osp.splitext(filename)[1].lower() == '.dcm': kwargs['template'] = template try: io.imwrite(filename, data, **kwargs) return filename except Exception as msg: import traceback traceback.print_exc() QMessageBox.critical(parent, _('Error') if app_name is None else app_name, (_("%s could not be written:") % osp.basename(filename))+\ "\n"+str(msg)) return
def exec_image_open_dialog(parent, basedir='', app_name=None, to_grayscale=True, dtype=None): """ Executes an image open dialog box (QFileDialog.getOpenFileName) * parent: parent widget (None means no parent) * basedir: base directory ('' means current directory) * app_name (opt.): application name (used as a title for an eventual error message box in case something goes wrong when saving image) * to_grayscale (default=True): convert image to grayscale Returns (filename, data) tuple if dialog is accepted, None otherwise """ saved_in, saved_out, saved_err = sys.stdin, sys.stdout, sys.stderr sys.stdout = None filename, _filter = getopenfilename( parent, _("Open"), basedir, io.iohandler.get_filters('load', dtype=dtype)) sys.stdin, sys.stdout, sys.stderr = saved_in, saved_out, saved_err filename = to_text_string(filename) try: data = io.imread(filename, to_grayscale=to_grayscale) except Exception as msg: import traceback traceback.print_exc() QMessageBox.critical(parent, _('Error') if app_name is None else app_name, (_("%s could not be opened:") % osp.basename(filename))+\ "\n"+str(msg)) return return filename, data
def select_directory(self): """Open a directory selection dialog box""" value = self.item.from_string(to_text_string(self.edit.text())) parent = self.parent_layout.parent child_title = _get_child_title_func(parent) dname = getexistingdirectory(parent, child_title(self.item), value) if dname: self.edit.setText(dname)
def translate_gettext(x): if not PY3 and is_unicode(x): x = x.encode("utf-8") y = lgettext(x) if is_text_string(y) and PY3: return y else: return to_text_string(y, "utf-8")
def from_string(self, value): """Override DataItem method""" value = to_text_string(value) if value.endswith("']") or value.endswith('"]'): value = eval(value) else: value = [value] return [add_extension(self, path) for path in value]
def from_string(self, value): """Override DataItem method""" value = to_text_string(value) if value.endswith("']"): value = eval(value) else: value = [value] return [add_extension(self, path) for path in value]
def from_string(self, value): """Override DataItem method""" value = to_text_string(value) # necessary if value is a QString # String may contains numerical operands: if re.match(r'^([\d\(\)\+/\-\*.]|e)+$', value): try: return self.type(eval(value)) except: pass return None
def add_extension(item, value): """Add extension to filename `item`: data item representing a file path `value`: possible value for data item""" value = to_text_string(value) formats = item.get_prop("data", "formats") if len(formats) == 1 and formats[0] != '*': if not value.endswith('.' + formats[0]) and len(value) > 0: return value + '.' + formats[0] return value
def get_string_value(self, instance): """Override DataItem method""" value = self.get_value(instance) choices = self.get_prop_value("data", instance, "choices") #print "ShowChoiceWidget:", choices, value for choice in choices: if choice[0] == value: return to_text_string(choice[1]) else: return DataItem.get_string_value(self, instance)
def closeEvent(self, event): global _figures, _current_fig, _current_axes figure_title = to_text_string(self.windowTitle()) if _figures.pop(figure_title) == _current_fig: _current_fig = None _current_axes = None self.itemlist.close() self.contrast.close() self.xcsw.close() self.ycsw.close() event.accept()
def get(self): """Override AbstractDataSetWidget method""" value = self.item.get() old_value = to_text_string(self.value()) if value is not None: if isinstance(value, QColor): # if item is a ColorItem object value = value.name() uvalue = utf8_to_unicode(value) if uvalue != old_value: self.edit.setText(utf8_to_unicode(value)) else: self.line_edit_changed(value)
def save_widget(self, fname): """Grab widget's window and save it to filename (*.png, *.pdf)""" fname = to_text_string(fname) if fname.lower().endswith('.pdf'): printer = QPrinter() printer.setOutputFormat(QPrinter.PdfFormat) printer.setOrientation(QPrinter.Landscape) printer.setOutputFileName(fname) printer.setCreator('guidata') self.print_(printer) elif fname.lower().endswith('.png'): pixmap = QPixmap.grabWidget(self) pixmap.save(fname, 'PNG') else: raise RuntimeError(_("Unknown file extension"))
def line_edit_changed(self, qvalue): """QLineEdit validator""" value = self.item.from_string(to_text_string(qvalue)) if not self.item.check_value(value): self.edit.setStyleSheet("background-color:rgb(255, 175, 90);") else: self.edit.setStyleSheet("") cb = self.item.get_prop_value("display", "callback", None) if cb is not None: if self.build_mode: self.set() else: self.parent_layout.update_dataitems() cb(self.item.instance, self.item.item, value) self.parent_layout.update_widgets(except_this_one=self) self.update(value)
def imwrite(fname, arr, ext=None, dtype=None, max_range=None, **kwargs): """Save a NumPy array to an image filename `fname`. If `to_grayscale` is True, convert RGB images to grayscale The `ext` (optional) argument is a string that specifies the file extension which defines the input format: when not specified, the input format is guessed from filename. If `max_range` is True, array data is scaled to fit the `dtype` (or data type itself if `dtype` is None) dynamic range Warning: option `max_range` changes data in place""" if not is_text_string(fname): fname = to_text_string(fname) # in case filename is a QString instance if ext is None: _base, ext = osp.splitext(fname) if max_range: arr = scale_data_to_dtype(arr, arr.dtype if dtype is None else dtype) iohandler.get_writefunc(ext)(fname, arr, **kwargs)
def imread(fname, ext=None, to_grayscale=False): """Return a NumPy array from an image filename `fname`. If `to_grayscale` is True, convert RGB images to grayscale The `ext` (optional) argument is a string that specifies the file extension which defines the input format: when not specified, the input format is guessed from filename.""" if not is_text_string(fname): fname = to_text_string(fname) # in case filename is a QString instance if ext is None: _base, ext = osp.splitext(fname) arr = iohandler.get_readfunc(ext)(fname) if to_grayscale and arr.ndim == 3: # Converting to grayscale return arr[..., :4].mean(axis=2) else: return arr
def format_string(self, instance, value, fmt, func): """Override DataItem method""" larg = self.get_prop_value("display", instance, "large", False) fmt = self.get_prop_value("display", instance, "format", "%s") unit = self.get_prop_value("display", instance, "unit", "") v = func(value) if larg: text = "= [" for flt in v[:-1]: text += fmt % flt + "; " text += fmt % v[-1] + "]" else: text = "~= " + fmt % v.mean() text += " [" + fmt % v.min() text += " .. " + fmt % v.max() text += "]" text += " %s" % unit return to_text_string(text)
def save_widget(self, fname): """Grab widget's window and save it to filename (\*.png, \*.pdf)""" fname = to_text_string(fname) if fname.lower().endswith('.pdf'): printer = QPrinter() printer.setOutputFormat(QPrinter.PdfFormat) printer.setOrientation(QPrinter.Landscape) printer.setOutputFileName(fname) printer.setCreator('guidata') self.print_(printer) elif fname.lower().endswith('.png'): if PYQT5: pixmap = self.grab() else: pixmap = QPixmap.grabWidget(self) pixmap.save(fname, 'PNG') else: raise RuntimeError(_("Unknown file extension"))
def getexistingdirectory(parent=None, caption='', basedir='', options=QFileDialog.ShowDirsOnly): """Wrapper around QtGui.QFileDialog.getExistingDirectory static method Compatible with PyQt >=v4.4 (API #1 and #2) and PySide >=v1.0""" # Calling QFileDialog static method if sys.platform == "win32": # On Windows platforms: redirect standard outputs _temp1, _temp2 = sys.stdout, sys.stderr sys.stdout, sys.stderr = None, None try: result = QFileDialog.getExistingDirectory(parent, caption, basedir, options) finally: if sys.platform == "win32": # On Windows platforms: restore standard outputs sys.stdout, sys.stderr = _temp1, _temp2 if not is_text_string(result): # PyQt API #1 result = to_text_string(result) return result
def exec_image_save_dialog(parent, data, template=None, basedir='', app_name=None): """ Executes an image save dialog box (QFileDialog.getSaveFileName) * parent: parent widget (None means no parent) * data: image pixel array data * template: image template (pydicom dataset) for DICOM files * basedir: base directory ('' means current directory) * app_name (opt.): application name (used as a title for an eventual error message box in case something goes wrong when saving image) Returns filename if dialog is accepted, None otherwise """ saved_in, saved_out, saved_err = sys.stdin, sys.stdout, sys.stderr sys.stdout = None filename, _filter = getsavefilename( parent, _("Save as"), basedir, io.iohandler.get_filters('save', dtype=data.dtype, template=template)) sys.stdin, sys.stdout, sys.stderr = saved_in, saved_out, saved_err if filename: filename = to_text_string(filename) kwargs = {} if osp.splitext(filename)[1].lower() == '.dcm': kwargs['template'] = template try: io.imwrite(filename, data, **kwargs) return filename except Exception as msg: import traceback traceback.print_exc() QMessageBox.critical(parent, _('Error') if app_name is None else app_name, (_("%s could not be written:") % osp.basename(filename))+\ "\n"+str(msg)) return
def get_string_value(self, instance): """ Return a formatted unicode representation of the item's value obeying 'display' or 'repr' properties """ value = self.get_value(instance) repval = self.get_prop_value("display", instance, "repr", None) if repval is not None: return repval else: fmt = self.get_prop_value("display", instance, "format", "%s") func = self.get_prop_value("display", instance, "func", lambda x:x) if isinstance(fmt, collections.Callable) and value is not None: return fmt(func(value)) elif is_text_string(fmt): # This is only necessary with Python 2: converting to unicode fmt = to_text_string(fmt) if value is not None: text = self.format_string(instance, value, fmt, func) else: text = "" return text
def get_string_value(self, instance): """ Return a formatted unicode representation of the item's value obeying 'display' or 'repr' properties """ value = self.get_value(instance) repval = self.get_prop_value("display", instance, "repr", None) if repval is not None: return repval else: fmt = self.get_prop_value("display", instance, "format", "%s") func = self.get_prop_value("display", instance, "func", lambda x: x) if isinstance(fmt, collections.Callable) and value is not None: return fmt(func(value)) elif is_text_string(fmt): # This is only necessary with Python 2: converting to unicode fmt = to_text_string(fmt) if value is not None: text = self.format_string(instance, value, fmt, func) else: text = "" return text
def __init__(self, label, image, rect, function): self.label = to_text_string(label) self.image = image self.rect = rect self.func = function
def __get_text(self): """Get QTextEdit text, replacing UTF-8 EOL chars by os.linesep""" return to_text_string(self.edit.toPlainText()).replace('\u2029', os.linesep)
def check(self): """Override AbstractDataSetWidget method""" value = self.item.from_string(to_text_string(self.edit.text())) return self.item.check_value(value)
def value(self): return to_text_string(self.edit.text())
def add_image_from_file(self, filename): image = ImageParam() image.title = to_text_string(filename) image.data = io.imread(filename, to_grayscale=True) image.height, image.width = image.data.shape self.add_image(image)
def child_title(self, item): """Return data item title combined with QApplication title""" app_name = QApplication.applicationName() if not app_name: app_name = to_text_string(self.title()) return "%s - %s" % ( app_name, item.label() )
def get_plain_text(self): return to_text_string(self.text.toPlainText())
def from_string(self, value): """Override DataItem method""" # QString -> str return to_text_string(value)
def _qfiledialog_wrapper(attr, parent=None, caption='', basedir='', filters='', selectedfilter='', options=None): if options is None: options = QFileDialog.Options(0) try: # PyQt <v4.6 (API #1) from guidata.qt.QtCore import QString except ImportError: # PySide or PyQt >=v4.6 QString = None # analysis:ignore tuple_returned = True try: # PyQt >=v4.6 func = getattr(QFileDialog, attr + 'AndFilter') except AttributeError: # PySide or PyQt <v4.6 func = getattr(QFileDialog, attr) if QString is not None: selectedfilter = QString() tuple_returned = False # Calling QFileDialog static method if sys.platform == "win32": # On Windows platforms: redirect standard outputs _temp1, _temp2 = sys.stdout, sys.stderr sys.stdout, sys.stderr = None, None try: result = func(parent, caption, basedir, filters, selectedfilter, options) except TypeError: # The selectedfilter option (`initialFilter` in Qt) has only been # introduced in Jan. 2010 for PyQt v4.7, that's why we handle here # the TypeError exception which will be raised with PyQt v4.6 # (see Issue 960 for more details) result = func(parent, caption, basedir, filters, options) finally: if sys.platform == "win32": # On Windows platforms: restore standard outputs sys.stdout, sys.stderr = _temp1, _temp2 # Processing output if tuple_returned: # PySide or PyQt >=v4.6 output, selectedfilter = result else: # PyQt <v4.6 (API #1) output = result if QString is not None: # PyQt API #1: conversions needed from QString/QStringList selectedfilter = to_text_string(selectedfilter) if isinstance(output, QString): # Single filename output = to_text_string(output) else: # List of filenames output = [to_text_string(fname) for fname in output] # Always returns the tuple (output, selectedfilter) return output, selectedfilter
def get_value_from_reader(self, reader): """Reads value from the reader object, inside the try...except statement defined in the base item `deserialize` method""" return [to_text_string(fname, "utf-8") for fname in reader.read_sequence()]
def get_value_from_reader(self, reader): """Reads value from the reader object, inside the try...except statement defined in the base item `deserialize` method""" return [ to_text_string(fname, "utf-8") for fname in reader.read_sequence() ]