class DictationOverlay(QWidget): """Frameless window showing the partial dictation results """ app = property(appref.app) DEFAULT_FLAGS = ( Qt.WindowStaysOnTopHint | Qt.FramelessWindowHint | Qt.WindowTransparentForInput | Qt.Tool | Qt.WindowDoesNotAcceptFocus ) REPOSITION_FLAGS = Qt.WindowStaysOnTopHint | Qt.Tool def __init__(self, *args, **named): super(DictationOverlay, self).__init__(*args, **named) self.setWindowTitle('%s Text Preview' % (defaults.APP_NAME_SHORT)) self.setWindowFlags(self.DEFAULT_FLAGS) # self.setAttribute(Qt.WA_TranslucentBackground, True) # self.setAttribute(Qt.WA_NoSystemBackground, True) self.setAttribute(Qt.WA_ShowWithoutActivating, True) # self.setMaximumHeight(40) # self.setMinimumWidth(400) self.setWindowOpacity(0.8) self.label = QPushButton(defaults.APP_NAME_HUMAN, self) self.label.setFlat(True) self.label.connect(self.label, SIGNAL('clicked()'), self.save_new_position) # self.setCentralWidget(self.label) self.timer = QTimer(self) self.timer.connect(self.timer, SIGNAL('timeout()'), self.on_timer_finished) def show_for_reposition(self): """Allow the user to reposition""" self.setWindowFlags(Qt.WindowStaysOnTopHint) self.set_text('Drag, then click here', 0) GEOMETRY_SAVE_KEY = 'overlay.geometry' def save_new_position(self, *args): """On close during reposition, save geometry and hide""" log.info("Saving new position: %s", self.geometry()) self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint) self.app.settings.setValue(self.GEOMETRY_SAVE_KEY, self.saveGeometry()) self.hide() self.disconnect(SIGNAL('click()'), self.save_new_position) def set_text(self, text, timeout=500): log.info("Setting text: %s", text) self.label.setText(text) self.label.adjustSize() self.adjustSize() self.show() if timeout: self.timer.start(500) def on_timer_finished(self, evt=None): """When the timer finishes without any interruption/reset, hide the window""" self.hide() self.timer.stop()
def __init__(self, targetImage=None, axeSize=500, layer=None, parent=None, mainForm=None, curveType='quadric'): super().__init__(targetImage=targetImage, axeSize=axeSize, layer=layer, parent=parent, mainForm=mainForm) graphicsScene = self.scene() # init the curve if curveType == 'quadric': curve = activeQuadricSpline(graphicsScene.axeSize) else: curve = activeCubicSpline(graphicsScene.axeSize) graphicsScene.addItem(curve) graphicsScene.quadricB = curve curve.channel = channelValues.Br curve.histImg = graphicsScene.layer.inputImg().histogram( size=graphicsScene.axeSize, bgColor=graphicsScene.bgColor, range=(0, 255), chans=channelValues.Br) #, mode='Luminosity') curve.initFixedPoints() # set current curve graphicsScene.cubicItem = graphicsScene.quadricB graphicsScene.cubicItem.setVisible(True) self.setWhatsThis("""<b>Contrast Curve</b><br> Drag <b>control points</b> and <b>tangents</b> with the mouse.<br> <b>Add</b> a control point by clicking on the curve.<br> <b>Remove</b> a control point by clicking on it.<br> <b>Zoom</b> with the mouse wheel.<br> """) def onResetCurve(): """ Reset the selected curve """ self.scene().cubicItem.reset() #self.scene().onUpdateLUT() l = self.scene().layer l.applyToStack() l.parentImage.onImageChanged() # buttons pushButton1 = QPushButton("Reset to Auto Curve") pushButton1.setGeometry(10, 20, 100, 30) # x,y,w,h pushButton1.adjustSize() pushButton1.clicked.connect(onResetCurve) graphicsScene.addWidget(pushButton1) self.pushButton = pushButton1
def __init__(self, targetImage=None, axeSize=500, layer=None, parent=None): super().__init__(layer=layer, targetImage=targetImage, parent=parent) # options optionList1, optionNames1 = [ 'Free', 'Rotation', 'Translation', 'Align' ], ['Free Transformation', 'Rotation', 'Translation', 'Align'] self.listWidget1 = optionsWidget(options=optionList1, optionNames=optionNames1, exclusive=True, changed=self.dataChanged) optionList2, optionNames2 = ['Transparent' ], ['Set Transparent Pixels To Black'] self.listWidget2 = optionsWidget(options=optionList2, optionNames=optionNames2, exclusive=False, changed=self.dataChanged) self.options = UDict( (self.listWidget1.options, self.listWidget2.options)) # set initial selection to Perspective self.listWidget1.checkOption(optionList1[0]) pushButton1 = QPushButton(' Reset Transformation ') pushButton1.adjustSize() pushButton1.clicked.connect(self.reset) # layout l = QVBoxLayout() l.setAlignment(Qt.AlignTop) l.addWidget(self.listWidget1) l.addWidget(self.listWidget2) hl = QHBoxLayout() hl.setAlignment(Qt.AlignHCenter) hl.addWidget(pushButton1) l.addLayout(hl) self.setLayout(l) self.adjustSize() self.setDefaults() self.setWhatsThis(""" <b>Geometric transformation :</b><br> Choose a transformation type and drag either corner of the image using the small square red buttons.<br> Ctrl+Alt+Drag to change the <b>initial positions</b> of buttons.<br> Check <i>Align</i> to align the image with the underlying layers (for example to blend bracketed images). Note that this option may modify or cancel the current transformation. """) # end of setWhatsThis
def __init__(self, targetImage=None, axeSize=500, layer=None, parent=None, mainForm=None): super().__init__(targetImage=targetImage, axeSize=axeSize, layer=layer, parent=parent, mainForm=mainForm) graphicsScene = self.scene() ######### # L curve ######### cubic = activeCubicSpline(axeSize) graphicsScene.addItem(cubic) graphicsScene.cubicR = cubic cubic.channel = channelValues.L # get histogram as a Qimage cubic.histImg = graphicsScene.layer.inputImg().histogram(size=graphicsScene.axeSize, bgColor=graphicsScene.bgColor, range=(0, 1), chans=channelValues.L, mode='Lab') # L curve use the default axes cubic.axes = graphicsScene.defaultAxes cubic.initFixedPoints() cubic.axes.setVisible(False) cubic.setVisible(False) ########## # a curve (Green--> Magenta axis) ######### cubic = activeCubicSpline(axeSize) graphicsScene.addItem(cubic) graphicsScene.cubicG = cubic cubic.channel = channelValues.a cubic.histImg = graphicsScene.layer.inputImg().histogram(size=graphicsScene.axeSize, bgColor=graphicsScene.bgColor, range=(-100, 100), chans=channelValues.a, mode='Lab') # add specific axes gradient = QRadialGradient() gradient.setCenter(QPoint(0, 1)) gradient.setRadius(axeSize*1.4) gradient.setColorAt(0.0, Qt.green) gradient.setColorAt(1.0, Qt.magenta) cubic.axes = self.drawPlotGrid(axeSize, gradient) graphicsScene.addItem(cubic.axes) cubic.initFixedPoints() cubic.axes.setVisible(False) cubic.setVisible(False) # b curve (Blue-->Yellow axis) cubic = activeCubicSpline(axeSize) graphicsScene.addItem(cubic) graphicsScene.cubicB = cubic cubic.channel = channelValues.b cubic.histImg = graphicsScene.layer.inputImg().histogram(size=graphicsScene.axeSize, bgColor=graphicsScene.bgColor, range=(-100, 100), chans=channelValues.b, mode='Lab') # add specific axes gradient.setColorAt(0.0, Qt.blue) gradient.setColorAt(1.0, Qt.yellow) cubic.axes = self.drawPlotGrid(axeSize, gradient) graphicsScene.addItem(cubic.axes) cubic.initFixedPoints() cubic.axes.setVisible(False) cubic.setVisible(False) # set current to L curve and axes graphicsScene.cubicItem = graphicsScene.cubicR graphicsScene.cubicItem.setVisible(True) graphicsScene.cubicItem.axes.setVisible(True) # buttons pushButton1 = QPushButton("Reset Current") pushButton1.move(100, 20) pushButton1.adjustSize() pushButton1.clicked.connect(self.resetCurve) graphicsScene.addWidget(pushButton1) pushButton2 = QPushButton("Reset All") pushButton2.move(100, 50) pushButton2.adjustSize() pushButton2.clicked.connect(self.resetAllCurves) graphicsScene.addWidget(pushButton2) # options options = ['L', 'a', 'b'] self.listWidget1 = optionsWidget(options=options, exclusive=True) self.listWidget1.setGeometry(0, 10, self.listWidget1.sizeHintForColumn(0) + 5, self.listWidget1.sizeHintForRow(0) * len(options) + 5) graphicsScene.addWidget(self.listWidget1) # selection changed handler curves = [graphicsScene.cubicR, graphicsScene.cubicG, graphicsScene.cubicB] curveDict = dict(zip(options, curves)) def onSelect1(item): cubicItem = self.scene().cubicItem cubicItem.setVisible(False) cubicItem.axes.setVisible(False) self.scene().cubicItem = curveDict[item.text()] self.scene().cubicItem.setVisible(True) self.scene().cubicItem.axes.setVisible(True) # Force to redraw histogram self.scene().invalidate(QRectF(0.0, -self.scene().axeSize, self.scene().axeSize, self.scene().axeSize), QGraphicsScene.BackgroundLayer) self.listWidget1.onSelect = onSelect1 # set initial selection to L item = self.listWidget1.items[options[0]] item.setCheckState(Qt.Checked) self.listWidget1.select(item) self.setWhatsThis("""<b>Lab curves</b><br>""" + self.whatsThis()) def f(): l = graphicsScene.layer l.applyToStack() l.parentImage.onImageChanged() self.scene().cubicR.curveChanged.sig.connect(f) self.scene().cubicG.curveChanged.sig.connect(f) self.scene().cubicB.curveChanged.sig.connect(f)
class MapWidget(QQuickWidget): def __init__(self, data, model): super(MapWidget, self).__init__(resizeMode=QQuickWidget.SizeRootObjectToView) self.data = data self.model = model self.attribute_button = QPushButton(self) self.attribute_button.setStyleSheet("color: black") self.menu = QMenu("Pick an attribute", self) # Create Menu Options self.humidity_attribute = QAction("humidity") self.pressure_attribute = QAction("pressure") self.temperature_attribute = QAction("temperature") self.wind_speed_attribute = QAction("wind_speed") # due to frequent access of dates based on index, we store this data separately self.uniqueDates = self.data["datetime"].apply( lambda x: x.split(' ')[0]).unique().tolist() self.aggregation = 1 self.rootContext().setContextProperty("markermodel", model) self.rootContext().setContextProperty("MapWidget", self) qml_path = os.path.join(os.path.dirname(__file__), "map.qml") self.setSource(QUrl.fromLocalFile(qml_path)) positions = self.get_positions(self.data) names = self.get_names(self.data) # get first date of dataset in yy-mm-dd self.currentDate = self.uniqueDates[0] # Set Labels self.date_label = QLabel( "selected date: " + str(self.currentDate).replace("-", "."), self) self.date_label.setStyleSheet("color: black") # Set Previous and Next Buttons self.previous_button = QPushButton("Previous", self) self.next_button = QPushButton("Next", self) self.previous_button.clicked.connect( partial(self.on_button_clicked, "previous")) self.next_button.clicked.connect( partial(self.on_button_clicked, "next")) values = self.get_values(self.data, "humidity") colors = self.get_colors(self.data, "humidity") for i in range(0, len(names)): geo_coordinates = QGeoCoordinate(positions[i][0], positions[i][1]) name = names[i] value = values[i] color = colors[i] model.append_marker({ "position": geo_coordinates, "color": color, "name": name, "value": value, "date": self.currentDate }) self.create_interface() return def add_attribute_to_menu(self, attribute_action, attribute): attribute_action.triggered.connect(lambda: self.clicked(attribute)) self.menu.addAction(attribute_action) def create_date_picker(self, index): tmp_time = self.uniqueDates[index] time_QFormat = tmp_time.split("-") # date is parsed and converted to int to comply with required format of QDate date_picker = QDateTimeEdit( QDate(int(time_QFormat[0]), int(time_QFormat[1]), int(time_QFormat[2])), self) date_picker.setDisplayFormat("yyyy.MM.dd") date_picker.setCalendarPopup(True) date_picker.setCalendarWidget(QCalendarWidget()) date_picker.resize(date_picker.width() + 20, date_picker.height()) return date_picker def set_date_pickers(self, slider): # Set Date Picker for Start of self.slider date_picker_start = self.create_date_picker(0) date_picker_start.setToolTip( "Select the BEGINNING of the time period from which the data is displayed" ) date_picker_start.move( slider.property("x") - date_picker_start.width() - 30, slider.property("y")) # Set Date Picker for End of self.slider date_picker_end = self.create_date_picker(-1) date_picker_end.setToolTip( "Select the END of the time period from which the data is displayed" ) date_picker_end.move( slider.property("x") + slider.property("width") + 30, slider.property("y")) # Set Date Pickers Boundaries Based on First and Last Date in Given Data date_picker_start.setMinimumDate(date_picker_start.date()) date_picker_end.setMinimumDate(date_picker_start.date()) date_picker_start.setMaximumDate(date_picker_end.date()) date_picker_end.setMaximumDate(date_picker_end.date()) return date_picker_start, date_picker_end def create_interface(self): self.attribute_button.move(50, 0) # Create a Menu Option for Each Attribute self.add_attribute_to_menu(self.humidity_attribute, "humidity") self.add_attribute_to_menu(self.pressure_attribute, "pressure") self.add_attribute_to_menu(self.temperature_attribute, "temperature") self.add_attribute_to_menu(self.wind_speed_attribute, "wind_speed") self.attribute_button.setMenu(self.menu) self.attribute_button.resize(self.menu.width() + 50, self.attribute_button.height()) # Get self.slider from QML File self.slider = self.rootObject().findChild(QObject, "slider") # Set Date Pickers self.date_picker_start, self.date_picker_end = self.set_date_pickers( self.slider) self.date_picker_start.dateChanged.connect(lambda: self.change_date( self.slider, self.self.date_picker_start, self.date_picker_end)) self.date_picker_end.dateChanged.connect(lambda: self.change_date( self.slider, self.self.date_picker_start, self.date_picker_end)) # Label Holding the Current Date Selected by User self.date_label.move( self.slider.property("x") + (self.slider.width() / 2) - 100, self.slider.property("y") + 30) self.date_label.adjustSize() # Set Buttons Position self.previous_button.setStyleSheet("color: black") self.previous_button.move(self.slider.property("x"), self.slider.property("y") + 50) self.previous_button.adjustSize() self.next_button.setStyleSheet("color: black") self.next_button.move( self.slider.property("x") + self.slider.width() - 70, self.slider.property("y") + 50) self.next_button.adjustSize() jump_label = QLabel("self.slider jump (in days): ", self) jump_label.setStyleSheet("color: black") jump_label.move(self.date_label.x(), self.date_label.y() + 40) jump_label.adjustSize() self.jump_value = QLineEdit(self) self.jump_value.move(jump_label.x() + jump_label.width(), jump_label.y() - 5) self.jump_value.resize(35, self.jump_value.height()) self.jump_value.editingFinished.connect( lambda: self.slider.setProperty("stepSize", self.jump_value.text() )) agg_label = QLabel(self) agg_label.setStyleSheet("color: black") agg_label.move(self.date_label.x(), self.jump_value.y() + 40) agg_label.setText("mean (in days): ") agg_label.adjustSize() agg_value = QLineEdit(self) agg_value.move(self.jump_value.x(), agg_label.y() - 5) agg_value.resize(35, agg_value.height()) agg_value.editingFinished.connect( lambda: self.set_agg(agg_value.text())) # Initialize Visualization self.humidity_attribute.trigger() self.change_date(self.slider, self.date_picker_start, self.date_picker_end) def on_button_clicked(self, action): jump_value = int(self.jump_value.text()) slider_value = int(self.slider.property("value")) current_date = pandas.to_datetime(self.currentDate) start_date = self.date_picker_start.date().toPython() end_date = self.date_picker_end.date().toPython() if action == "next": if current_date + datetime.timedelta(days=jump_value) <= end_date: self.slider.setProperty("value", slider_value + jump_value) self.update_date(int(self.slider.property("value"))) elif action == "previous": if current_date - datetime.timedelta( days=jump_value) >= start_date: self.slider.setProperty("value", slider_value - jump_value) self.update_date(int(self.slider.property("value"))) @Slot(int) def update_date(self, value): self.currentDate = self.uniqueDates[value - 1] self.date_label.setText("selected date: " + str(self.currentDate).replace("-", ".")) self.clicked(self.attribute_button.text()) # TODO: visualise time series data, not just int created by aggregation # TODO: create setting of visualised time period for user # calculates the difference (in days) between start date and end date and rescales the self.slider def set_agg(self, value): self.aggregation = int(value) self.clicked(self.attribute_button.text()) def change_date(self, slider, date_picker_start, date_picker_end): dif = self.uniqueDates\ .index(date_picker_end.date().toString("yyyy-MM-dd")) - self.uniqueDates.index(date_picker_start.date().toString("yyyy-MM-dd")) slider.setProperty("to", dif + 1) # when button is clicked, changes values in all model items to a different attribute def clicked(self, attribute): self.attribute_button.setText(attribute) values = self.get_values(self.data, attribute) colors = self.get_colors(self.data, attribute) for i in range(0, len(values)): self.model.setData(i, values[i], colors[i], MarkerModel.ValueRole) @staticmethod def get_positions(data): tmp = data.drop_duplicates('city').sort_values(by=['city']) positions = [[x, y] for x, y in zip(tmp['latitude'], tmp['longitude'])] return positions @staticmethod def get_names(data): tmp = data.drop_duplicates('city').sort_values(by=['city']) names = tmp['city'].values.tolist() return names # creates an ordered list of aggregated values of a specified attribute def get_values(self, data, attribute): data['datetime'] = pandas.to_datetime(data['datetime']) start_date = pandas.to_datetime(self.currentDate) end_date = start_date + datetime.timedelta(days=self.aggregation) tmp = data[data['datetime'] >= start_date] tmp = tmp[tmp['datetime'] <= end_date] values = tmp.groupby('city').apply( lambda x: x[attribute].mean()).values.round(2).tolist() return values @staticmethod def get_colors(data, attribute): tmp = data.groupby('city').agg({attribute: 'mean'}) max_value = round(tmp[attribute].max()) min_value = round(tmp[attribute].min()) diff = max_value - min_value step = round(1 / 6 * diff) if attribute == 'pressure': attribute_values = { 0: [255, 255, 255], 1: [204, 229, 255], 2: [102, 178, 255], 3: [0, 128, 255], 4: [0, 0, 255], 5: [0, 0, 102], 6: [0, 0, 51] } elif attribute == 'temperature': attribute_values = { 0: [0, 102, 204], 1: [102, 178, 255], 2: [204, 229, 255], 3: [255, 204, 204], 4: [255, 102, 102], 5: [204, 0, 0], 6: [102, 0, 0] } # TODO: create more suited colors for humidity and wind speed elif attribute == 'humidity': attribute_values = { 0: [0, 102, 204], 1: [102, 178, 255], 2: [204, 229, 255], 3: [255, 204, 204], 4: [255, 102, 102], 5: [204, 0, 0], 6: [102, 0, 0] } elif attribute == 'wind_speed': attribute_values = { 0: [0, 102, 204], 1: [102, 178, 255], 2: [204, 229, 255], 3: [255, 204, 204], 4: [255, 102, 102], 5: [204, 0, 0], 6: [102, 0, 0] } values = numpy.array([ min_value, min_value + 1 * step, min_value + 2 * step, min_value + 3 * step, min_value + 4 * step, min_value + 5 * step, max_value ]) tmp['distances'] = tmp[attribute].apply(lambda x: abs(x - values)) tmp['index'] = tmp['distances'].apply(lambda x: numpy.argmin(x)) tmp['color'] = tmp['index'].apply(lambda x: attribute_values.get(x)) colors = tmp['color'].tolist() colors_list = [] for color_tmp in colors: color = QColor(color_tmp[0], color_tmp[1], color_tmp[2], 255) colors_list.append(color) # returns QJSValue return colors_list def createAction(self, attribute): action = QAction(attribute) action.triggered.connect(self.clicked(attribute)) self.menu.addAction(action) return action
class Page(QWidget): call_exit = Signal( str ) # arg is function name (self.func.__name__) for each page in pages def __init__( self, func=None, func_args=[], func_kwargs={}, margin=30, vert_spacing=10, current_layout="TopBottomLayout", description="", single_pass: bool = False, *args, **kwargs ): super().__init__() # static definitions self.func = func self.args = func_args self.kwargs = func_kwargs self.widget_list = [] self.margin = margin self.vert_spacing = vert_spacing self.single_pass = single_pass self.stdout = sys.stdout self.stderr = sys.stderr self.Current_Layout = layouts.Layout_Dict["TopBottomLayout"] if current_layout in layouts.Layout_Dict: self.Current_Layout = layouts.Layout_Dict[current_layout](self) # Initiallize self.canvas = QWidget() self.canvas.setObjectName("canvas") # create a scroll bar self.widget_scroll = QScrollArea(self) self.widget_scroll.setObjectName("widget_scroll") # use a QFormLayout to place widgets self.canvas_layout = QFormLayout() self.canvas_layout.setObjectName("canvas_layout") # set canvas_layout self.canvas_layout.setMargin(self.margin) self.canvas_layout.setSpacing(self.vert_spacing) self.canvas_layout.setRowWrapPolicy(self.canvas_layout.WrapAllRows) # default description is func.__doc__ self.description = QLabel( self.getDescription(description) ) # doesn't need to scroll self.description.setParent(self) self.description.setWordWrap(True) self.description.setTextFormat(Qt.MarkdownText) self.description.setOpenExternalLinks(True) # create a Run button to excute the function self.run_button = QPushButton("&Run", self) self.run_button.clicked.connect(self.Run) self.run_button.adjustSize() # allow the user to run the func multiple times to test output # but only the last return is delivered (as a confirmed run) self.run_thread = RunThread(self.func, self.args, self.kwargs) self.run_thread.finished.connect(self.Done) def getDescription(self, pre_defined_desc: str = ""): """ returns the description of current page. """ if pre_defined_desc.strip(" \r\n") != "": return pre_defined_desc if self.func == None: log.error("No backend function found") return "" docstring = self.func.__doc__.strip(" \r\n\t") if docstring == "": log.warning("Bad docstring for function {0}".format(self.func.__name__)) return "function {0}".format(self.func.__name__) # suppose "------" is the splitor between function description and arguments description # in numpy-style docstring, "------" has "Parameter" before it. # match it with "[a-zA-Z_]*?[\n\r]*?". desc_part = re.match( r"([\S\s\n\r]+?)[a-z_]*?[\n\r\s]*?------", docstring, re.M | re.I ) if desc_part == None: log.info("whole description:\n{0}".format(docstring)) return docstring log.info("recognized description:\n{0}".format(desc_part.group(1))) return desc_part.group(1) ### slot functions def Run(self): """ Run the function(self.func) in another thread(self.run_thread). """ # load args for i in self.widget_list: self.kwargs.update({i.objectName(): i.getValue()}) # redirect standard output self.output_dialog = output_dialog.OutputDialog(self.func.__name__, parent=self) sys.stdout = self.output_dialog sys.stderr = self.output_dialog # avoid multiple clicks self.run_button.setText("Running...") self.run_button.setEnabled(False) self.run_thread.start() log.info('func "{0}" started'.format(self.func.__name__)) self.output_dialog.exec_() def Done(self): """ Done is called when the function is finished(i.e. self.run_thread.finished is omitted) Restore the run button. """ log.info('func "{0}" ended'.format(self.func.__name__)) self.output_dialog.setWindowTitle( "Output of {0} - returns {1}".format( self.func.__name__, self.run_thread.ret ) ) self.output_dialog.revive() self.run_button.setText("Run") self.run_button.setEnabled(True) if self.single_pass: self.call_exit.emit(self.func.__name__)
def __init__(self, targetImage=None, axeSize=500, layer=None, parent=None, colorModel='HSV', mainForm=None): super().__init__(targetImage=targetImage, axeSize=axeSize, layer=layer, parent=parent, mainForm=mainForm) graphicsScene = self.scene() graphicsScene.colorModel = colorModel # hue curve init. cubic = activeCubicSpline(axeSize) graphicsScene.addItem(cubic) graphicsScene.cubicR = cubic cubic.channel = channelValues.Hue """ cubic.histImg = graphicsScene.layer.histogram(size=axeSize, bgColor=graphicsScene.bgColor, range=(0, 360), chans=channelValues.Hue, mode='HSpB') """ cubic.initFixedPoints() # sat curve init. cubic = activeCubicSpline(axeSize) graphicsScene.addItem(cubic) graphicsScene.cubicG = cubic cubic.channel = channelValues.Sat """ cubic.histImg = graphicsScene.layer.histogram(size=axeSize, bgColor=graphicsScene.bgColor, range=(0,1), chans=channelValues.Sat, mode='HSpB') """ cubic.initFixedPoints() # brightness curve init. cubic = activeCubicSpline(axeSize) graphicsScene.addItem(cubic) graphicsScene.cubicB = cubic cubic.channel = channelValues.Br """ cubic.histImg = graphicsScene.layer.histogram(size=axeSize, bgColor=graphicsScene.bgColor, range=(0,1), chans=channelValues.Br, mode='HSpB') """ cubic.initFixedPoints() # init histograms self.updateHists() # set current curve to sat graphicsScene.cubicItem = graphicsScene.cubicG graphicsScene.cubicItem.setVisible(True) # buttons pushButton1 = QPushButton("Reset Current") pushButton1.move(100, 20) pushButton1.adjustSize() pushButton1.clicked.connect(self.resetCurve) graphicsScene.addWidget(pushButton1) pushButton2 = QPushButton("Reset All") pushButton2.move(100, 50) pushButton2.adjustSize() pushButton2.clicked.connect(self.resetAllCurves) graphicsScene.addWidget(pushButton2) # options options = ['H', 'S', 'B'] self.listWidget1 = optionsWidget(options=options, exclusive=True) self.listWidget1.setGeometry( 0, 10, self.listWidget1.sizeHintForColumn(0) + 5, self.listWidget1.sizeHintForRow(0) * len(options) + 5) graphicsScene.addWidget(self.listWidget1) # selection changed handler curves = [ graphicsScene.cubicR, graphicsScene.cubicG, graphicsScene.cubicB ] curveDict = dict(zip(options, curves)) def onSelect1(item): self.scene().cubicItem.setVisible(False) self.scene().cubicItem = curveDict[item.text()] self.scene().cubicItem.setVisible(True) # draw histogram self.scene().invalidate( QRectF(0.0, -self.scene().axeSize, self.scene().axeSize, self.scene().axeSize), QGraphicsScene.BackgroundLayer) self.listWidget1.onSelect = onSelect1 # set initial selection to Saturation item = self.listWidget1.items[options[1]] item.setCheckState(Qt.Checked) self.listWidget1.select(item) self.setWhatsThis("""<b>HSV curves</b><br>""" + self.whatsThis()) def f(): layer = graphicsScene.layer layer.applyToStack() layer.parentImage.onImageChanged() self.scene().cubicR.curveChanged.sig.connect(f) self.scene().cubicG.curveChanged.sig.connect(f) self.scene().cubicB.curveChanged.sig.connect(f)
def __init__(self, targetImage=None, axeSize=500, layer=None, parent=None): super().__init__(layer=layer, targetImage=targetImage, parent=parent) self.options = None pushButton1 = QPushButton(' Undo ') pushButton1.adjustSize() pushButton2 = QPushButton(' Redo ') pushButton2.adjustSize() pushButton1.clicked.connect(self.undo) pushButton2.clicked.connect(self.redo) spacingSlider = QSlider(Qt.Horizontal) spacingSlider.setObjectName('spacingSlider') spacingSlider.setRange(1,60) spacingSlider.setTickPosition(QSlider.TicksBelow) spacingSlider.setSliderPosition(10) spacingSlider.sliderReleased.connect(self.parent().label.brushUpdate) self.spacingSlider = spacingSlider jitterSlider = QSlider(Qt.Horizontal) jitterSlider.setObjectName('jitterSlider') jitterSlider.setRange(0, 100) jitterSlider.setTickPosition(QSlider.TicksBelow) jitterSlider.setSliderPosition(0) jitterSlider.sliderReleased.connect(self.parent().label.brushUpdate) self.jitterSlider = jitterSlider orientationSlider = QSlider(Qt.Horizontal) orientationSlider.setObjectName('orientationSlider') orientationSlider.setRange(0, 360) orientationSlider.setTickPosition(QSlider.TicksBelow) orientationSlider.setSliderPosition(180) orientationSlider.sliderReleased.connect(self.parent().label.brushUpdate) self.orientationSlider = orientationSlider # sample self.sample = QLabel() #self.sample.setMinimumSize(200, 100) pxmp = QPixmap(250,100) pxmp.fill(QColor(255, 255, 255, 255)) self.sample.setPixmap(pxmp) qpp = QPainterPath() qpp.moveTo(QPointF(20, 50)) qpp.cubicTo(QPointF(80, 25), QPointF(145, 70), QPointF(230, 60)) # c1, c2, endPoint self.samplePoly = qpp.toFillPolygon(QTransform()) # we want an unclosed polygon self.samplePoly.removeLast() # layout l = QVBoxLayout() l.setAlignment(Qt.AlignTop) hl = QHBoxLayout() hl.setAlignment(Qt.AlignHCenter) hl.addWidget(pushButton1) hl.addWidget(pushButton2) l.addLayout(hl) l.addWidget(QLabel('Brush Dynamics')) hl1 = QHBoxLayout() hl1.addWidget(QLabel('Spacing')) hl1.addWidget(spacingSlider) l.addLayout(hl1) hl2 = QHBoxLayout() hl2.addWidget(QLabel('Jitter')) hl2.addWidget(jitterSlider) l.addLayout(hl2) hl3 = QHBoxLayout() hl3.addWidget(QLabel('Orientation')) hl3.addWidget(self.orientationSlider) l.addLayout(hl3) l.addWidget(self.sample) self.setLayout(l) self.adjustSize() self.setDefaults() self.setWhatsThis( """ <b>Drawing :</b><br> Choose a brush family, flow, hardness and opacity. """ ) # end of setWhatsThis
def __init__(self, targetImage=None, axeSize=500, layer=None, parent=None, mainForm=None): super(transForm, self).__init__(parent=parent) self.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) self.setMinimumSize(axeSize, axeSize) self.setAttribute(Qt.WA_DeleteOnClose) # back links to image self.targetImage = weakProxy(targetImage) self.img = weakProxy(targetImage) self.layer = weakProxy(layer) self.mainForm = mainForm # options optionList1, optionNames1 = ['Free', 'Rotation', 'Translation'], [ 'Free Transformation', 'Rotation', 'Translation' ] self.listWidget1 = optionsWidget(options=optionList1, optionNames=optionNames1, exclusive=True) optionList2, optionNames2 = ['Transparent' ], ['Set Transparent Pixels To Black'] self.listWidget2 = optionsWidget(options=optionList2, optionNames=optionNames2, exclusive=False) self.options = UDict( (self.listWidget1.options, self.listWidget2.options)) # set initial selection to Perspective self.listWidget1.checkOption(optionList1[0]) # option changed handler def g(item): l = self.layer l.tool.setBaseTransform() #self.layer.tool.setVisible(True) l.applyToStack() l.parentImage.onImageChanged() self.listWidget1.onSelect = g self.listWidget2.onSelect = g pushButton1 = QPushButton(' Reset Transformation ') pushButton1.adjustSize() def f(): self.layer.tool.resetTrans() pushButton1.clicked.connect(f) # layout l = QVBoxLayout() l.setAlignment(Qt.AlignTop) l.addWidget(self.listWidget1) l.addWidget(self.listWidget2) hl = QHBoxLayout() hl.setAlignment(Qt.AlignHCenter) hl.addWidget(pushButton1) l.addLayout(hl) self.setLayout(l) self.adjustSize() self.setWhatsThis(""" <b>Geometric transformation :</b><br> Choose a transformation type and drag either corner of the image using the small square red buttons.<br> Ctrl+Alt+Drag to change the <b>initial positions</b> of buttons. """)