Source code for samsifter.gui.composites

# -*- coding: utf-8 -*-
"""
Composed widgets used to visualize filter parameters in a form layout.

.. moduleauthor:: Florian Aldehoff <faldehoff@student.uni-tuebingen.de>
"""

import os
from os.path import expanduser, isfile

""" Qt4 imports """
from PyQt4.QtGui import (
    QWidget, QSlider, QHBoxLayout, QLineEdit, QPushButton, QFileDialog, QIcon,
    QRadioButton, QButtonGroup, QLabel, QDoubleSpinBox
)
from PyQt4.QtCore import Qt


[docs]class SliderSpinboxCombo(QWidget): """ Slider coupled with Spinbox for setting numerical values between a minimum and maximum. """ def __init__(self, parent=None, minimum=0.0, maximum=100.0, default=0.0, precision=2): super(QWidget, self).__init__(parent) self.minimum = minimum self.maximum = maximum self.default = default if default < minimum: self.value = minimum elif default > maximum: self.value = maximum else: self.value = default self.precision = precision self.slider = QSlider(self) self.slider.setOrientation(Qt.Horizontal) self.slider.setTickPosition(QSlider.TicksBelow) self.slider.setObjectName("slider") self.slider.setMinimum(0) self.slider.setMaximum(10000) self.slider.setSingleStep(1) self.slider.setTickInterval(max(1000, 10000 / (self.maximum - self.minimum))) self.slider.setValue(self.normalize(self.value)) self.spinner = QDoubleSpinBox() self.spinner.setDecimals(self.precision) self.spinner.setSingleStep(10 ** (-1 * self.precision)) self.spinner.setMinimum(self.minimum) self.spinner.setMaximum(self.maximum) self.spinner.setValue(self.value) self.spinner.setObjectName("spinner") self.spinner.valueChanged.connect(self.on_spinner_value_change) self.slider.valueChanged.connect(self.on_slider_value_change) layout = QHBoxLayout(self) layout.setMargin(0) layout.addWidget(self.slider) layout.addWidget(self.spinner) self.setLayout(layout)
[docs] def on_spinner_value_change(self, value): self.value = value self.slider.setValue(self.normalize(value))
[docs] def on_slider_value_change(self, value): self.spinner.setValue(self.denormalize(value))
[docs] def normalize(self, value): delta = self.maximum - self.minimum assert delta > 0 normalized = ((value - self.minimum) * (10000)) / delta return normalized
[docs] def denormalize(self, value): delta = self.maximum - self.minimum assert delta > 0 denormalized = ((value * delta) / (10000)) + self.minimum return denormalized
""" Getters & Setters """
[docs] def get_value(self): return self.value
[docs] def set_value(self, value): if self.precision == 0: self.value = int(value) else: self.value = value self.spinner.setValue(value)
[docs]class FileChooser(QWidget): """ Combined LineEdit and Pushbutton for standard file dialog to select a file. """ def __init__(self, parent=None, suffix_string="CSV files (*.csv *.CSV)"): super(QWidget, self).__init__(parent) self.suffix_string = suffix_string self.filename = None self.lineedit = QLineEdit(self) self.button = QPushButton(QIcon.fromTheme('document-open'), "Select file...", self) self.button.pressed.connect(self.show_dialog) layout = QHBoxLayout(self) layout.setMargin(0) layout.addWidget(self.lineedit) layout.addWidget(self.button) self.setLayout(layout)
[docs] def highlight(self, boolean=True): """ Indicate errors or pending actions by changing background color. """ css = "QLineEdit {background-color: #ffe08c;}" if boolean: self.lineedit.setStyleSheet(css) else: self.lineedit.setStyleSheet(None)
[docs] def show_dialog(self): dialog = QFileDialog() dialog.setDefaultSuffix(self.suffix_string) fname = dialog.getOpenFileName(self, 'Open file', expanduser("~"), self.suffix_string + ";;All files (*)" ) self.lineedit.setText(fname) self.set_filename(fname)
""" Getters & Setters """
[docs] def get_suffix_string(self): return self.suffix_string
[docs] def set_suffix_string(self, suffix_string): self.suffix_string = suffix_string
[docs] def get_filename(self): return self.filename
[docs] def set_filename(self, filename): """ Set filename while maintaining cursor position and validating input on the fly. """ self.filename = filename # validate file if not (isfile(filename) and os.access(filename, os.R_OK)): self.highlight(True) self.lineedit.setToolTip( "file either not existing or not readable" ) else: self.highlight(False) self.lineedit.setToolTip(None) cursor = self.lineedit.cursorPosition() self.lineedit.setText(filename) self.lineedit.setCursorPosition(cursor)
[docs]class OptionSwitcher(QWidget): """ Group of coupled radio buttons to choose between exclusive options. """ def __init__(self, parent=None, options=[True, False]): super(QWidget, self).__init__(parent) self.options = options self.current_index = 0 self.group = QButtonGroup(self) layout = QHBoxLayout(self) layout.setMargin(0) for idx, option in enumerate(self.options): lbl = QLabel(str(option), self) btn = QRadioButton(self) btn.setChecked(idx == self.current_index) self.group.addButton(btn, idx) layout.addWidget(btn) layout.addWidget(lbl) self.setLayout(layout) """ Getters & Setters """
[docs] def get_options(self): return self.options
[docs] def set_options(self, options): self.options = options
[docs] def get_current_index(self): return self.current_index
[docs] def set_current_index(self, index): if 0 <= index and index < len(self.options): self.current_index = index self.group.button(index).setChecked(True)