class JObject: def __init__(self, visible=True): self._visible = visible self._color = QColor(255, 255, 255) self._background_color = QColor(0, 0, 0) def setVisibility(self, v): self._visible = v def getVisibility(self): return self._visible def setColor(self, color): self._color = color def getColor(self, color): return self._color def setOpenGlColor(self): glColor3f(self._color.red() / 255.0, self._color.green() / 255.0, self._color.blue() / 255.0) def setGlBackGroundColor(self): glColor3f(self._background_color.red() / 255.0, self._background_color.green() / 255.0, self._background_color.blue() / 255.0) def setGlColor(self): glColor3f(self._color.red() / 255.0, self._color.green() / 255.0, self._color.blue() / 255.0)
def mergedColors(colorA: QColor, colorB: QColor, factor=50): """ Creates a merged new QColor of colorA and colorB and returns it """ maxFactor = 100 tmp = QColor(colorA) tmp.setRed((tmp.red() * factor) / maxFactor + (colorB.red() * (maxFactor - factor)) / maxFactor) tmp.setGreen((tmp.green() * factor) / maxFactor + (colorB.green() * (maxFactor - factor)) / maxFactor) tmp.setBlue((tmp.blue() * factor) / maxFactor + (colorB.blue() * (maxFactor - factor)) / maxFactor) return tmp
def refresh(self): tmp = self.strip.state() for i in xrange(len(self.buttons)): c = QColor(int(tmp[i*3+0]),int(tmp[i*3+1]),int(tmp[i*3+2])) pal = self.buttons[i][0].palette() pal.setBrush( QPalette.Button, QColor(c.red(),c.green(),c.blue())) self.buttons[i][0].setPalette(pal) self.buttons[i][1] = c
def _update_colors(self): op = self.topLevelOperatorView.opCarving ctable = self._doneSegmentationLayer.colorTable for name, label in self._shownObjects3D.iteritems(): color = QColor(ctable[op.MST.value.object_names[name]]) color = (color.red() / 255.0, color.green() / 255.0, color.blue() / 255.0) self._renderMgr.setColor(label, color)
def testSetColorForClass(self): """ Test that clicking the CANVAS sets the current class color if the layer is a vector layer. """ self.prepareTestCanvas() #self.bucketFill.setColorForClass( # QPoint(50, 15), QtCore.Qt.LeftButton) myColor = QColor(CANVAS.canvasPixmap().toImage().pixel(50, 15)) # Just for if you want to see what it has rendered CANVAS.saveAsImage('test.png') # expected R: 182 G: 109 B: 194 myExpectedColor = QColor(182, 109, 194) myMessage = (('Unexpected color\n Received R: %i G: %i B: %i ' '\n Expected: R: %i G: %i B: %i') % (myColor.red(), myColor.green(), myColor.blue(), myExpectedColor.red(), myExpectedColor.green(), myExpectedColor.blue())) assert myColor == myExpectedColor, myMessage
def __init__(self, points, rgb, alpha): self.points = points colour = QColor(rgb) self.red = colour.red() self.green = colour.green() self.blue = colour.blue() colour.setAlphaF(alpha) self.alpha = alpha self.rgba = colour.rgb() self.projected = []
def _update_colors(self): op = self.topLevelOperatorView ctable = self._doneSegmentationLayer.colorTable for name, label in self._shownObjects3D.iteritems(): color = QColor(ctable[op.MST.value.object_names[name]]) color = (color.red() / 255.0, color.green() / 255.0, color.blue() / 255.0) self._renderMgr.setColor(label, color) if self._showSegmentationIn3D and self._segmentation_3d_label is not None: self._renderMgr.setColor(self._segmentation_3d_label, (0.0, 1.0, 0.0)) # Green
def render_color_scribble(self): r = [] g = [] b = [] for i in range(8): for j in range(8): color = QColor(self.scribble_area.image.pixel(j, i)) r.append(color.red()) g.append(color.green()) b.append(color.blue()) self.set_rgb(r, g, b)
def calculate_px_rgb(sub_image, xy_length): """ I hate that this function uses a double for loop Any way to just map a full QImage to numpy array??? """ px_tot = np.zeros(3) for x in xrange(xy_length): for y in xrange(xy_length): color = QColor(sub_image.pixel(x, y)) px_tot += (color.red(), color.green(), color.blue()) avg_rgb = (px_tot / float(sub_image.width() * sub_image.height())).astype(np.int16) return avg_rgb[0], avg_rgb[1], avg_rgb[2]
def _set_background_color(self): myColor = QColor("#F2EFE9") # Write it to the project (will still need to be saved!) QgsProject.instance().writeEntry("Gui", "/CanvasColorRedPart", myColor.red()) QgsProject.instance().writeEntry("Gui", "/CanvasColorGreenPart", myColor.green()) QgsProject.instance().writeEntry("Gui", "/CanvasColorBluePart", myColor.blue()) # And apply for the current session self.iface.mapCanvas().setCanvasColor(myColor) self.iface.mapCanvas().refresh()
def get_pixel_value(pixels, x, y): if ascii_mode_enabled: color = "MNHQ$OC?7>!:-;. " else: color = "" * 16 rgba = QColor(pixels.pixel(x, y)) rgb = rgba.red(), rgba.green(), rgba.blue() index = int(sum(rgb) / 3.0 / 256.0 * 16) pair = curses.color_pair(index + 10) if ascii_mode_enabled: pair = 1 try: return color[index], pair except IndexError: return " ", pair
def setTheme(self, color): c = QColor() c.setNamedColor(color) c.setRed(self.qMin(c.red() + 40, 255)) c.setGreen(self.qMin(c.green() + 40, 255)) c.setBlue(self.qMin(c.blue() + 40, 255)) self.myTheme[0] = color self.myTheme[1] = c.name() try: f = open(COLOR_PATH, "w") for item in self.myTheme: f.write("%s\n" % item) f.close() except IOError: self.createConfig()
def hsl_changed(self, *args): if self.changing: return h, s, l = self.spin_h.value(), self.spin_s.value(), self.spin_l.value() hsl = QColor() hsl.setHsl(h, s, l) r, g, b = hsl.red(), hsl.green(), hsl.blue() self.changing = True self.spin_r.setValue(r) self.spin_g.setValue(g) self.spin_b.setValue(b) self.changing = False self.rgb_led.set_rgb_value(r, g, b) self.label_color.setStyleSheet('QLabel {{ background: #{:02x}{:02x}{:02x} }}'.format(r, g, b))
def hsl_changed(self, *args): if self.changing: return h, s, l = self.spin_h.value(), self.spin_s.value(), self.spin_l.value() hsl = QColor() hsl.setHsl(h, s, l) r, g, b = hsl.red(), hsl.green(), hsl.blue() self.changing = True self.spin_r.setValue(r) self.spin_g.setValue(g) self.spin_b.setValue(b) self.changing = False self.rgb_led_button.set_color(r, g, b) self.label_color.setStyleSheet( 'QLabel {{ background: #{:02x}{:02x}{:02x} }}'.format(r, g, b))
def font_bmp_to_alpha(filename): image = QImage(filename) image = image.convertToFormat(QImage.Format_ARGB32_Premultiplied) # Because the game uses 8bit grayscale bitmaps for its fonts with white as # fully visible and black as fully transparent, I'm using a naive technique # that averages the RGB value of a pixel and sets that as its alpha value. # I'm sure this will do fun stuff to other images, but it does the job # for the game's fonts, and that's all that really matters. ヽ(´ー`)ノ for i in range(image.width()): for j in range(image.height()): color = QColor(image.pixel(i, j)) alpha = (color.red() + color.green() + color.blue()) / 3 color.setAlpha(alpha) image.setPixel(i, j, color.rgba()) return image
def convertImagetoText(self): if str(self.image_file_name).endswith("txt") or str(self.image_file_name).endswith("TXT"): return self.image_file_name else: out_file_name = os.getcwd() + "/Output/temp_image.txt" out_file = open(out_file_name, "w") separator = ' ' image = QtGui.QImage(self.image_file_name) x_pixels = image.width() z_pixels = image.height() for z_index in range (0, z_pixels): row = "" for x_index in range (0, x_pixels): color = QColor(image.pixel(x_index, z_index)) red = color.red() blue = color.blue() green = color.green() grey = (red*11+green*16+blue*5)/32 if x_index == x_pixels - 1: row += str(int(grey)) else: row += str(int(grey)) + separator out_file.write(row + "\r") out_file.flush() out_file.close() return out_file_name
def applyLegend(self, levels, colHEX_RGB): nLevels = len(levels)-1 self.ui.tableWidget.setRowCount(nLevels) for row in range(nLevels): item1 = QtGui.QTableWidgetItem() item1.setText(str(levels[row])) self.ui.tableWidget.setItem(row, 0, item1) item2 = QtGui.QTableWidgetItem() item2.setText(str(levels[row+1])) self.ui.tableWidget.setItem(row, 1, item2) col = colors.hex2color(colHEX_RGB[row]) colPy = QColor(int(col[0]*255),int(col[1]*255),int(col[2]*255)) item3 = QtGui.QTableWidgetItem() item3.setBackground(colPy) item3.setFlags(QtCore.Qt.ItemIsEnabled) item3.setText(str(colPy.red()) + ", " + str(colPy.green()) + ", " + str(colPy.blue())) self.ui.tableWidget.setItem(row, 2, item3)
def color(cls, mscolor, opacity=100): n = len(mscolor) a = int(round(opacity * 2.55)) color_ = QColor("red") #color de error if isinstance(mscolor, list): if n == 3: color_ = QColor(mscolor[0], mscolor[1], mscolor[2], a) elif isinstance(mscolor, (str, unicode)): match = cls.REGEX_ATTR.search(mscolor) if mscolor[:1] == "#": print("#", n) r = int(mscolor[1:3], 16) g = int(mscolor[3:5], 16) b = int(mscolor[5:7], 16) if n == 7: color_ = QColor(r, g, b, a) elif n == 9: a2 = int(mscolor[7:9], 16) #unificar "a" con opacity y alpha del string #es el promedio, o % de la que ya tiene a = int(round((a + a2) / 2)) #a = int(a2 * opacity * 1.0 / 100) color_ = QColor(r, g, b, a) elif match: #Color es definido por atributo return (match.group(1), True) else: if mscolor in QColor.colorNames(): color_ = QColor(mscolor) color_.setAlpha(a) r = color_.red() g = color_.green() b = color_.blue() a = color_.alpha() qcolor_ = "{},{},{},{}".format(r, g, b, a) return (qcolor_, False, r, g, b, a)
class arcPoint(): global currentColor def __init__(self, x, y=0, z=0, color=None): if x.__class__.__name__ == 'arcPoint': self.x = x.x self.y = x.y self.z = x.z self.color = QColor(x.color.red(), x.color.green(), x.color.blue()) else: self.x = x self.y = y self.z = z if color: self.color = QColor(color.red(), color.green(), color.blue()) else: self.color = QColor(currentColor.red(), currentColor.green(), currentColor.blue()) def __sub__(self, p): return arcPoint(self.x - p.x, self.y - p.y, self.z - p.z, QColor(self.color.red(), self.color.green(), self.color.blue())) def __add__(self, p): return arcPoint(self.x + p.x, self.y + p.y, self.z + p.z, QColor(self.color.red(), self.color.green(), self.color.blue())) def __eq__(self, p): return self.x == p.x and self.y == p.y and self.z == p.z def __ne__(self, p): return not self.__eq__(p) def __str__(self): return '<' + str(self.x) + ',' + str(self.y) + ',' + str(self.z) + '>' def __repr__(self): return '<' + str(self.x) + ',' + str(self.y) + ',' + str(self.z) + '>' def __mul__(self, k): return arcPoint(self.x*k, self.y*k, self.z*k, QColor(self.color.red(), self.color.green(), self.color.blue())) def __rmul__(self, k): return arcPoint(self.x*k, self.y*k, self.z*k, QColor(self.color.red(), self.color.green(), self.color.blue())) def dotProduct(self, p): return p.x*self.x + p.y*self.y + p.z*self.z def vectorProduct(self, p): newPoint = arcPoint(self.x, self.y, self.z) newPoint.x = self.y*p.z - p.y*self.z if newPoint.x == -0.0: newPoint.x = 0.0 newPoint.y = self.z*p.x - p.z*self.x if newPoint.y == -0.0: newPoint.y = 0.0 newPoint.z = self.x*p.y - p.x*self.y if newPoint.z == -0.0: newPoint.z = 0.0 return newPoint def multMatrix(self, matrix): newPoint = arcMultiplyMatrices(matrix, [[self.x], [self.y], [self.z], [1]]) self.x = newPoint[0][0] self.y = newPoint[1][0] self.z = newPoint[2][0] def normalize(self): norm = sqrt(self.x*self.x + self.y*self.y + self.z*self.z) if norm > 0: self.x = self.x/norm self.y = self.y/norm self.z = self.z/norm return self def getNormal(self): norm = sqrt(self.x*self.x + self.y*self.y + self.z*self.z) p = arcPoint(self.x, self.y, self.z, self.color) if norm > 0: p.x = p.x/norm p.y = p.y/norm p.z = p.z/norm return p
class SearchInFiles(foundations.ui.common.QWidgetFactory(uiFile=UI_FILE)): """ Defines search and replace in files dialog used by the **ScriptEditor** Component. """ def __init__(self, parent, *args, **kwargs): """ Initializes the class. :param parent: Object parent. :type parent: QObject :param \*args: Arguments. :type \*args: \* :param \*\*kwargs: Keywords arguments. :type \*\*kwargs: \*\* """ LOGGER.debug("> Initializing '{0}()' class.".format(self.__class__.__name__)) super(SearchInFiles, self).__init__(parent, *args, **kwargs) # --- Setting class attributes. --- self.__container = self.__scriptEditor = parent self.__filesCache = foundations.cache.Cache() self.__searchPatternsModel = None self.__replaceWithPatternsModel = None self.__model = None self.__view = None self.__delegate = None self.__locations = OrderedDict([("Add Directory ...", "directory"), ("Add File ...", "file"), ("Add Opened Files", "editors"), ("Add Include Filter", "includeFilter"), ("Add Exclude Filter", "excludeFilter")]) self.__locationsMenu = None self.__defaultFilterIn = "*.txt" self.__filtersInFormat = "{0}" self.__defaultFilterOut = "*.txt" self.__filtersOutFormat = "!{0}" self.__defaultTarget = "Opened Files" self.__targetsFormat = "<{0}>" self.__defaultLineNumberWidth = 6 self.__defaultLineColor = QColor(144, 144, 144) self.__ignoreHiddenFiles = True self.__searchWorkerThread = None SearchInFiles.__initializeUi(self) #****************************************************************************************************************** #*** Attributes properties. #****************************************************************************************************************** @property def container(self): """ Property for **self.__container** attribute. :return: self.__container. :rtype: QObject """ return self.__container @container.setter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def container(self, value): """ Setter for **self.__container** attribute. :param value: Attribute value. :type value: QObject """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is read only!".format(self.__class__.__name__, "container")) @container.deleter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def container(self): """ Deleter for **self.__container** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "container")) @property def scriptEditor(self): """ Property for **self.__scriptEditor** attribute. :return: self.__scriptEditor. :rtype: QWidget """ return self.__scriptEditor @scriptEditor.setter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def scriptEditor(self, value): """ Setter for **self.__scriptEditor** attribute. :param value: Attribute value. :type value: QWidget """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is read only!".format(self.__class__.__name__, "scriptEditor")) @scriptEditor.deleter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def scriptEditor(self): """ Deleter for **self.__scriptEditor** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "scriptEditor")) @property def filesCache(self): """ Property for **self.__filesCache** attribute. :return: self.__filesCache. :rtype: Cache """ return self.__filesCache @filesCache.setter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def filesCache(self, value): """ Setter for **self.__filesCache** attribute. :param value: Attribute value. :type value: Cache """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is read only!".format(self.__class__.__name__, "filesCache")) @filesCache.deleter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def filesCache(self): """ Deleter for **self.__filesCache** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "filesCache")) @property def searchPatternsModel(self): """ Property for **self.__searchPatternsModel** attribute. :return: self.__searchPatternsModel. :rtype: PatternsModel """ return self.__searchPatternsModel @searchPatternsModel.setter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def searchPatternsModel(self, value): """ Setter for **self.__searchPatternsModel** attribute. :param value: Attribute value. :type value: PatternsModel """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is read only!".format(self.__class__.__name__, "searchPatternsModel")) @searchPatternsModel.deleter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def searchPatternsModel(self): """ Deleter for **self.__searchPatternsModel** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "searchPatternsModel")) @property def replaceWithPatternsModel(self): """ Property for **self.__replaceWithPatternsModel** attribute. :return: self.__replaceWithPatternsModel. :rtype: PatternsModel """ return self.__replaceWithPatternsModel @replaceWithPatternsModel.setter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def replaceWithPatternsModel(self, value): """ Setter for **self.__replaceWithPatternsModel** attribute. :param value: Attribute value. :type value: PatternsModel """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is read only!".format(self.__class__.__name__, "replaceWithPatternsModel")) @replaceWithPatternsModel.deleter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def replaceWithPatternsModel(self): """ Deleter for **self.__replaceWithPatternsModel** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "replaceWithPatternsModel")) @property def model(self): """ Property for **self.__model** attribute. :return: self.__model. :rtype: SearchResultsModel """ return self.__model @model.setter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def model(self, value): """ Setter for **self.__model** attribute. :param value: Attribute value. :type value: SearchResultsModel """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is read only!".format(self.__class__.__name__, "model")) @model.deleter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def model(self): """ Deleter for **self.__model** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "model")) @property def view(self): """ Property for **self.__view** attribute. :return: self.__view. :rtype: QWidget """ return self.__view @view.setter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def view(self, value): """ Setter for **self.__view** attribute. :param value: Attribute value. :type value: QWidget """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is read only!".format(self.__class__.__name__, "view")) @view.deleter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def view(self): """ Deleter for **self.__view** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "view")) @property def delegate(self): """ Property for **self.__delegate** attribute. :return: self.__delegate. :rtype: QItemDelegate """ return self.__delegate @delegate.setter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def delegate(self, value): """ Setter for **self.__delegate** attribute. :param value: Attribute value. :type value: QItemDelegate """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is read only!".format(self.__class__.__name__, "delegate")) @delegate.deleter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def delegate(self): """ Deleter for **self.__delegate** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "delegate")) @property def locations(self): """ Property for **self.__locations** attribute. :return: self.__locations. :rtype: OrderedDict """ return self.__locations @locations.setter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def locations(self, value): """ Setter for **self.__locations** attribute. :param value: Attribute value. :type value: OrderedDict """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is read only!".format(self.__class__.__name__, "locations")) @locations.deleter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def locations(self): """ Deleter for **self.__locations** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "locations")) @property def locationsMenu(self): """ Property for **self.__locationsMenu** attribute. :return: self.__locationsMenu. :rtype: QMenu """ return self.__locationsMenu @locationsMenu.setter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def locationsMenu(self, value): """ Setter for **self.__locationsMenu** attribute. :param value: Attribute value. :type value: QMenu """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is read only!".format(self.__class__.__name__, "locationsMenu")) @locationsMenu.deleter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def locationsMenu(self): """ Deleter for **self.__locationsMenu** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "locationsMenu")) @property def defaultFilterIn(self): """ Property for **self.__defaultFilterIn** attribute. :return: self.__defaultFilterIn. :rtype: unicode """ return self.__defaultFilterIn @defaultFilterIn.setter @foundations.exceptions.handleExceptions(AssertionError) def defaultFilterIn(self, value): """ Setter for **self.__defaultFilterIn** attribute. :param value: Attribute value. :type value: unicode """ if value is not None: assert type(value) is unicode, "'{0}' attribute: '{1}' type is not 'unicode'!".format( "defaultFilterIn", value) assert os.path.exists(value), "'{0}' attribute: '{1}' file doesn't exists!".format("defaultFilterIn", value) self.__defaultFilterIn = value @defaultFilterIn.deleter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def defaultFilterIn(self): """ Deleter for **self.__defaultFilterIn** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "defaultFilterIn")) @property def filtersInFormat(self): """ Property for **self.__filtersInFormat** attribute. :return: self.__filtersInFormat. :rtype: unicode """ return self.__filtersInFormat @filtersInFormat.setter @foundations.exceptions.handleExceptions(AssertionError) def filtersInFormat(self, value): """ Setter for **self.__filtersInFormat** attribute. :param value: Attribute value. :type value: unicode """ if value is not None: assert type(value) is unicode, "'{0}' attribute: '{1}' type is not 'unicode'!".format( "filtersInFormat", value) assert os.path.exists(value), "'{0}' attribute: '{1}' file doesn't exists!".format("filtersInFormat", value) self.__filtersInFormat = value @filtersInFormat.deleter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def filtersInFormat(self): """ Deleter for **self.__filtersInFormat** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "filtersInFormat")) @property def defaultFilterOut(self): """ Property for **self.__defaultFilterOut** attribute. :return: self.__defaultFilterOut. :rtype: unicode """ return self.__defaultFilterOut @defaultFilterOut.setter @foundations.exceptions.handleExceptions(AssertionError) def defaultFilterOut(self, value): """ Setter for **self.__defaultFilterOut** attribute. :param value: Attribute value. :type value: unicode """ if value is not None: assert type(value) is unicode, "'{0}' attribute: '{1}' type is not 'unicode'!".format( "defaultFilterOut", value) assert os.path.exists(value), "'{0}' attribute: '{1}' file doesn't exists!".format("defaultFilterOut", value) self.__defaultFilterOut = value @defaultFilterOut.deleter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def defaultFilterOut(self): """ Deleter for **self.__defaultFilterOut** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "defaultFilterOut")) @property def filtersOutFormat(self): """ Property for **self.__filtersOutFormat** attribute. :return: self.__filtersOutFormat. :rtype: unicode """ return self.__filtersOutFormat @filtersOutFormat.setter @foundations.exceptions.handleExceptions(AssertionError) def filtersOutFormat(self, value): """ Setter for **self.__filtersOutFormat** attribute. :param value: Attribute value. :type value: unicode """ if value is not None: assert type(value) is unicode, "'{0}' attribute: '{1}' type is not 'unicode'!".format( "filtersOutFormat", value) assert os.path.exists(value), "'{0}' attribute: '{1}' file doesn't exists!".format("filtersOutFormat", value) self.__filtersOutFormat = value @filtersOutFormat.deleter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def filtersOutFormat(self): """ Deleter for **self.__filtersOutFormat** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "filtersOutFormat")) @property def defaultTarget(self): """ Property for **self.__defaultTarget** attribute. :return: self.__defaultTarget. :rtype: unicode """ return self.__defaultTarget @defaultTarget.setter @foundations.exceptions.handleExceptions(AssertionError) def defaultTarget(self, value): """ Setter for **self.__defaultTarget** attribute. :param value: Attribute value. :type value: unicode """ if value is not None: assert type(value) is unicode, "'{0}' attribute: '{1}' type is not 'unicode'!".format( "defaultTarget", value) assert os.path.exists(value), "'{0}' attribute: '{1}' file doesn't exists!".format("defaultTarget", value) self.__defaultTarget = value @defaultTarget.deleter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def defaultTarget(self): """ Deleter for **self.__defaultTarget** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "defaultTarget")) @property def targetsFormat(self): """ Property for **self.__targetsFormat** attribute. :return: self.__targetsFormat. :rtype: unicode """ return self.__targetsFormat @targetsFormat.setter @foundations.exceptions.handleExceptions(AssertionError) def targetsFormat(self, value): """ Setter for **self.__targetsFormat** attribute. :param value: Attribute value. :type value: unicode """ if value is not None: assert type(value) is unicode, "'{0}' attribute: '{1}' type is not 'unicode'!".format( "targetsFormat", value) assert os.path.exists(value), "'{0}' attribute: '{1}' file doesn't exists!".format("targetsFormat", value) self.__targetsFormat = value @targetsFormat.deleter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def targetsFormat(self): """ Deleter for **self.__targetsFormat** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "targetsFormat")) @property def defaultLineNumberWidth(self): """ Property for **self.__defaultLineNumberWidth** attribute. :return: self.__defaultLineNumberWidth. :rtype: int """ return self.__defaultLineNumberWidth @defaultLineNumberWidth.setter @foundations.exceptions.handleExceptions(AssertionError) def defaultLineNumberWidth(self, value): """ Setter for **self.__defaultLineNumberWidth** attribute. :param value: Attribute value. :type value: int """ if value is not None: assert type(value) is int, "'{0}' attribute: '{1}' type is not 'int'!".format( "defaultLineNumberWidth", value) assert value > 0, "'{0}' attribute: '{1}' need to be exactly positive!".format("defaultLineNumberWidth", value) self.__defaultLineNumberWidth = value @defaultLineNumberWidth.deleter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def defaultLineNumberWidth(self): """ Deleter for **self.__defaultLineNumberWidth** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "defaultLineNumberWidth")) @property def defaultLineColor(self): """ Property for **self.__defaultLineColor** attribute. :return: self.__defaultLineColor. :rtype: QColor """ return self.__defaultLineColor @defaultLineColor.setter @foundations.exceptions.handleExceptions(AssertionError) def defaultLineColor(self, value): """ Setter for **self.__defaultLineColor** attribute. :param value: Attribute value. :type value: QColor """ if value is not None: assert type(value) is QColor, "'{0}' attribute: '{1}' type is not 'QColor'!".format("defaultLineColor", value) self.__defaultLineColor = value @defaultLineColor.deleter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def defaultLineColor(self): """ Deleter for **self.__defaultLineColor** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "defaultLineColor")) @property def ignoreHiddenFiles(self): """ Property for **self.__ignoreHiddenFiles** attribute. :return: self.__ignoreHiddenFiles. :rtype: bool """ return self.__ignoreHiddenFiles @ignoreHiddenFiles.setter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def ignoreHiddenFiles(self, value): """ Setter for **self.__ignoreHiddenFiles** attribute. :param value: Attribute value. :type value: bool """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is read only!".format(self.__class__.__name__, "ignoreHiddenFiles")) @ignoreHiddenFiles.deleter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def ignoreHiddenFiles(self): """ Deleter for **self.__ignoreHiddenFiles** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "ignoreHiddenFiles")) @property def searchWorkerThread(self): """ Property for **self.__searchWorkerThread** attribute. :return: self.__searchWorkerThread. :rtype: QThread """ return self.__searchWorkerThread @searchWorkerThread.setter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def searchWorkerThread(self, value): """ Setter for **self.__searchWorkerThread** attribute. :param value: Attribute value. :type value: QThread """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is read only!".format(self.__class__.__name__, "searchWorkerThread")) @searchWorkerThread.deleter @foundations.exceptions.handleExceptions(foundations.exceptions.ProgrammingError) def searchWorkerThread(self): """ Deleter for **self.__searchWorkerThread** attribute. """ raise foundations.exceptions.ProgrammingError( "{0} | '{1}' attribute is not deletable!".format(self.__class__.__name__, "searchWorkerThread")) #****************************************************************************************************************** #*** Class methods #****************************************************************************************************************** def show(self): """ Reimplements the :meth:`QWidget.show` method. """ selectedText = self.__container.getCurrentEditor().getSelectedText() selectedText and SearchAndReplace.insertPattern(selectedText, self.__searchPatternsModel) self.Search_comboBox.lineEdit().selectAll() self.Search_comboBox.setFocus() super(SearchInFiles, self).show() self.raise_() def closeEvent(self, event): """ Reimplements the :meth:`QWidget.closeEvent` method. :param event: QEvent. :type event: QEvent """ self.__interruptSearch() super(SearchInFiles, self).closeEvent(event) def __initializeUi(self): """ Initializes the Widget ui. """ umbra.ui.common.setWindowDefaultIcon(self) self.__model = SearchResultsModel(self) self.__delegate = RichText_QStyledItemDelegate(self) self.Search_Results_treeView.setParent(None) self.Search_Results_treeView = SearchResults_QTreeView(self, self.__model, message="No Search Result to view!") self.Search_Results_treeView.setItemDelegate(self.__delegate) self.Search_Results_treeView.setObjectName("Search_Results_treeView") self.Search_Results_frame_gridLayout.addWidget(self.Search_Results_treeView, 0, 0) self.__view = self.Search_Results_treeView self.__view.setContextMenuPolicy(Qt.ActionsContextMenu) self.__view_addActions() self.__searchPatternsModel = self.__container.searchAndReplace.searchPatternsModel self.Search_comboBox.setModel(self.__container.searchAndReplace.searchPatternsModel) self.Search_comboBox.setInsertPolicy(QComboBox.InsertAtTop) self.Search_comboBox.completer().setCaseSensitivity(Qt.CaseSensitive) self.__replaceWithPatternsModel = self.__container.searchAndReplace.replaceWithPatternsModel self.Replace_With_comboBox.setModel(self.__container.searchAndReplace.replaceWithPatternsModel) self.Replace_With_comboBox.setInsertPolicy(QComboBox.InsertAtTop) self.Replace_With_comboBox.completer().setCaseSensitivity(Qt.CaseSensitive) self.Where_lineEdit.setParent(None) self.Where_lineEdit = Search_QLineEdit(self) self.Where_lineEdit.setObjectName("Where_lineEdit") self.Where_frame_gridLayout.addWidget(self.Where_lineEdit, 0, 0) self.__locationsMenu = QMenu() for title, location in self.__locations.iteritems(): self.__locationsMenu.addAction(self.__container.engine.actionsManager.registerAction( "Actions|Umbra|Components|factory.scriptEditor|Search In Files|{0}".format(title), text="{0}".format(title), slot=functools.partial(self.__addLocation, location))) self.Where_lineEdit.searchActiveLabel.setMenu(self.__locationsMenu) self.Where_lineEdit.setPlaceholderText("Use the magnifier to add locations!") self.installEventFilter(ValidationFilter(self)) # Signals / Slots. self.__view.selectionModel().selectionChanged.connect(self.__view_selectionModel__selectionChanged) self.__view.doubleClicked.connect(self.__view__doubleClicked) self.__searchPatternsModel.patternInserted.connect(functools.partial( self.__patternsModel__patternInserted, self.Search_comboBox)) self.__replaceWithPatternsModel.patternInserted.connect(functools.partial( self.__patternsModel__patternInserted, self.Replace_With_comboBox)) self.Search_pushButton.clicked.connect(self.__Search_pushButton__clicked) self.Close_pushButton.clicked.connect(self.__Close_pushButton__clicked) def __view_addActions(self): """ Sets the View actions. """ self.__view.addAction(self.__container.engine.actionsManager.registerAction( "Actions|Umbra|Components|factory.scriptEditor|Search In Files|Replace All", slot=self.__view_replaceAllAction__triggered)) self.__view.addAction(self.__container.engine.actionsManager.registerAction( "Actions|Umbra|Components|factory.scriptEditor|Search In Files|Replace Selected", slot=self.__view_replaceSelectedAction__triggered)) separatorAction = QAction(self.__view) separatorAction.setSeparator(True) self.__view.addAction(separatorAction) self.__view.addAction(self.__container.engine.actionsManager.registerAction( "Actions|Umbra|Components|factory.scriptEditor|Search In Files|Save All", slot=self.__view_saveAllAction__triggered)) self.__view.addAction(self.__container.engine.actionsManager.registerAction( "Actions|Umbra|Components|factory.scriptEditor|Search In Files|Save Selected", slot=self.__view_saveSelectedAction__triggered)) def __view_replaceAllAction__triggered(self, checked): """ Defines the slot triggered by **'Actions|Umbra|Components|factory.scriptEditor|Search In Files|Replace All'** action. :param checked: Action checked state. :type checked: bool :return: Method success. :rtype: bool """ allNodes = filter(lambda x: x.family in ("SearchFile", "SearchOccurence"), self.__model.rootNode.children) if allNodes: return self.replace(allNodes) def __view_replaceSelectedAction__triggered(self, checked): """ Defines the slot triggered by **'Actions|Umbra|Components|factory.scriptEditor|Search In Files|Replace Selected'** action. :param checked: Action checked state. :type checked: bool :return: Method success. :rtype: bool """ selectedNodes = filter(lambda x: x.family in ("SearchFile", "SearchOccurence"), self.__view.getSelectedNodes()) if selectedNodes: return self.replace(filter(lambda x: x.parent not in selectedNodes, selectedNodes)) def __view_saveAllAction__triggered(self, checked): """ Defines the slot triggered by **'Actions|Umbra|Components|factory.scriptEditor|Search In Files|Save All'** action. :param checked: Action checked state. :type checked: bool :return: Method success. :rtype: bool """ allNodes = filter(lambda x: x.family is "ReplaceResult", self.__model.rootNode.children) if allNodes: return self.saveFiles(allNodes) def __view_saveSelectedAction__triggered(self, checked): """ Defines the slot triggered by **'Actions|Umbra|Components|factory.scriptEditor|Search In Files|Save Selected'** action. :param checked: Action checked state. :type checked: bool :return: Method success. :rtype: bool """ selectedNodes = filter(lambda x: x.family is "ReplaceResult", self.__view.getSelectedNodes()) if selectedNodes: return self.saveFiles(selectedNodes) def __patternsModel__patternInserted(self, comboBox, index): """ Defines the slot triggered by a pattern when inserted into a patterns Model. :param comboBox: Pattern Model attached comboBox. :type comboBox: QComboBox :param index: Inserted pattern index. :type index: QModelIndex """ comboBox.setCurrentIndex(index.row()) def __Search_pushButton__clicked(self, checked): """ Defines the slot triggered by **Search_pushButton** Widget when clicked. :param checked: Checked state. :type checked: bool """ self.search() def __Close_pushButton__clicked(self, checked): """ Defines the slot triggered by **Close_pushButton** Widget when clicked. :param checked: Checked state. :type checked: bool """ self.close() def __view__doubleClicked(self, index): """ Defines the slot triggered by a View when double clicked. :param index: Clicked item index. :type index: QModelIndex """ node = self.__model.getNode(index) if node.family == "SearchOccurence": file = node.parent.file occurence = node elif node.family in ("SearchFile", "ReplaceResult"): file = node.file occurence = None self.__highlightOccurence(file, occurence) def __view_selectionModel__selectionChanged(self, selectedItems, deselectedItems): """ Defines the slot triggered by the View **selectionModel** when selection changed. :param selectedItems: Selected items. :type selectedItems: QItemSelection :param deselectedItems: Deselected items. :type deselectedItems: QItemSelection """ indexes = selectedItems.indexes() if not indexes: return node = self.__model.getNode(indexes.pop()) if node.family == "SearchOccurence": file = node.parent.file occurence = node elif node.family in ("SearchFile", "ReplaceResult"): file = node.file occurence = None if self.__container.getEditor(file): self.__highlightOccurence(file, occurence) def __searchWorkerThread__searchFinished(self, searchResults): """ Defines the slot triggered by :attr:`SearchInFiles.grepWorkerThread` attribute worker thread when the search is finished. :param searchResults: Search results. :type searchResults: list """ self.setSearchResults(searchResults) self.__container.engine.stopProcessing() metrics = self.__model.getMetrics() self.__container.engine.notificationsManager.notify( "{0} | '{1}' pattern occurence(s) found in '{2}' files!".format(self.__class__.__name__, metrics["SearchOccurence"], metrics["SearchFile"])) def __addLocation(self, type, *args): """ Defines the slot triggered by **Where_lineEdit** Widget when a context menu entry is clicked. :param type: Location type. :type type: unicode :param \*args: Arguments. :type \*args: \* """ if type == "directory": location = umbra.ui.common.storeLastBrowsedPath((QFileDialog.getExistingDirectory(self, "Add Directory:", RuntimeGlobals.lastBrowsedPath))) elif type == "file": location = umbra.ui.common.storeLastBrowsedPath((QFileDialog.getOpenFileName(self, "Add File:", RuntimeGlobals.lastBrowsedPath, "All Files (*)"))) elif type == "editors": location = self.__targetsFormat.format(self.__defaultTarget) elif type == "includeFilter": location = self.__filtersInFormat.format(self.__defaultFilterIn) elif type == "excludeFilter": location = self.__filtersOutFormat.format(self.__defaultFilterOut) location and self.Where_lineEdit.setText(", ".join(filter(bool, (foundations.strings.toString( self.Where_lineEdit.text()), location)))) def __formatOccurence(self, occurence): """ Formats the given occurence and returns the matching rich html text. :param occurence: Occurence to format. :type occurence: Occurence :return: Rich text. :rtype: unicode """ color = "rgb({0}, {1}, {2})" spanFormat = "<span style=\"color: {0};\">{{0}}</span>".format(color.format(self.__defaultLineColor.red(), self.__defaultLineColor.green(), self.__defaultLineColor.blue())) line = foundations.strings.toString(occurence.text) start = spanFormat.format(line[:occurence.column]) pattern = "<b>{0}</b>".format(line[occurence.column:occurence.column + occurence.length]) end = spanFormat.format(line[occurence.column + occurence.length:]) return "".join((start, pattern, end)) def __formatReplaceMetrics(self, file, metrics): """ Formats the given replace metrics and returns the matching rich html text. :param file: File. :type file: unicode :param metrics: Replace metrics to format. :type metrics: unicode :return: Rich text. :rtype: unicode """ color = "rgb({0}, {1}, {2})" spanFormat = "<span style=\"color: {0};\">{{0}}</span>".format(color.format(self.__defaultLineColor.red(), self.__defaultLineColor.green(), self.__defaultLineColor.blue())) dirName, baseName = (os.path.dirname(file), os.path.basename(file)) return "".join((spanFormat.format("'"), spanFormat.format(dirName), spanFormat.format(os.path.sep), baseName, spanFormat.format("' file: '"), foundations.strings.toString(metrics), spanFormat.format("' occurence(s) replaced!"))) def __highlightOccurence(self, file, occurence): """ Highlights given file occurence. :param file: File containing the occurence. :type file: unicode :param occurence: Occurence to highlight. :type occurence: Occurence or SearchOccurenceNode """ if not self.__container.getEditor(file): cacheData = self.__filesCache.getContent(file) if cacheData: document = cacheData.document or self.__getDocument(cacheData.content) self.__container.loadDocument(document, file) self.__uncache(file) else: self.__container.loadFile(file) else: self.__container.setCurrentEditor(file) if not occurence: return cursor = self.__container.getCurrentEditor().textCursor() cursor.setPosition(occurence.position, QTextCursor.MoveAnchor) cursor.setPosition(occurence.position + occurence.length, QTextCursor.KeepAnchor) self.__container.getCurrentEditor().setTextCursor(cursor) def __getDocument(self, content): """ Returns a `QTextDocument <http://doc.qt.nokia.com/qtextdocument.html>`_ class instance with given content. :return: Document. :rtype: QTextDocument """ document = QTextDocument(QString(content)) document.clearUndoRedoStacks() document.setModified(False) return document def __replaceWithinDocument(self, document, occurrences, replacementPattern): """ Replaces given pattern occurrences in given document using given settings. :param document: Document. :type document: QTextDocument :param replacementPattern: Replacement pattern. :type replacementPattern: unicode :return: Replaced occurrences count. :rtype: int """ cursor = QTextCursor(document) cursor.beginEditBlock() offset = count = 0 for occurence in sorted(occurrences, key=lambda x: x.position): cursor.setPosition(offset + occurence.position, QTextCursor.MoveAnchor) cursor.setPosition(offset + occurence.position + occurence.length, QTextCursor.KeepAnchor) cursor.insertText(replacementPattern) offset += len(replacementPattern) - occurence.length count += 1 cursor.endEditBlock() return count def __getSettings(self): """ Returns the current search and replace settings. :return: Settings. :rtype: dict """ return {"caseSensitive" : self.Case_Sensitive_checkBox.isChecked(), "wholeWord" : self.Whole_Word_checkBox.isChecked(), "regularExpressions" : self.Regular_Expressions_checkBox.isChecked()} def __interruptSearch(self): """ Interrupt the current search. """ if self.__searchWorkerThread: self.__searchWorkerThread.quit() self.__searchWorkerThread.wait() self.__container.engine.stopProcessing(warning=False) def __cache(self, file, content, document): """ Caches given file. :param file: File to cache. :type file: unicode :param content: File content. :type content: list :param document: File document. :type document: QTextDocument """ self.__filesCache.addContent(**{file : CacheData(content=content, document=document)}) def __uncache(self, file): """ Uncaches given file. :param file: File to uncache. :type file: unicode """ if file in self.__filesCache: self.__filesCache.removeContent(file) def setSearchResults(self, searchResults): """ Sets the Model Nodes using given search results. :param searchResults: Search results. :type searchResults: list :return: Method success. :rtype: bool """ rootNode = umbra.ui.nodes.DefaultNode(name="InvisibleRootNode") for searchResult in searchResults: searchFileNode = SearchFileNode(name=searchResult.file, parent=rootNode) searchFileNode.update(searchResult) width = \ max(self.__defaultLineNumberWidth, max([len(foundations.strings.toString(occurence.line)) for occurence in searchResult.occurrences])) for occurence in searchResult.occurrences: formatter = "{{0:>{0}}}".format(width) name = "{0}:{1}".format(formatter.format(occurence.line + 1).replace(" ", " "), self.__formatOccurence(occurence)) searchOccurenceNode = SearchOccurenceNode(name=name, parent=searchFileNode) searchOccurenceNode.update(occurence) self.__model.initializeModel(rootNode) return True def setReplaceResults(self, replaceResults): """ Sets the Model Nodes using given replace results. :param replaceResults: Replace results. :type replaceResults: list :return: Method success. :rtype: bool """ rootNode = umbra.ui.nodes.DefaultNode(name="InvisibleRootNode") for file, metrics in sorted(replaceResults.iteritems()): replaceResultNode = ReplaceResultNode(name=self.__formatReplaceMetrics(file, metrics), parent=rootNode, file=file) self.__model.initializeModel(rootNode) return True def search(self): """ Searchs user defined locations for search pattern. :return: Method success. :rtype: bool """ self.__interruptSearch() searchPattern = self.Search_comboBox.currentText() replacementPattern = self.Replace_With_comboBox.currentText() if not searchPattern: return False SearchAndReplace.insertPattern(searchPattern, self.__searchPatternsModel) SearchAndReplace.insertPattern(replacementPattern, self.__replaceWithPatternsModel) location = umbra.ui.common.parseLocation( foundations.strings.toString(self.Where_lineEdit.text()) or \ self.__targetsFormat.format(self.__defaultTarget)) self.__ignoreHiddenFiles and location.filtersOut.append("\\\.|/\.") settings = self.__getSettings() self.__searchWorkerThread = Search_worker(self, searchPattern, location, settings) # Signals / Slots. self.__searchWorkerThread.searchFinished.connect(self.__searchWorkerThread__searchFinished) self.__container.engine.workerThreads.append(self.__searchWorkerThread) self.__container.engine.startProcessing("Searching In Files ...") self.__searchWorkerThread.start() return True def replace(self, nodes): """ Replaces user defined files search pattern occurrences with replacement pattern using given nodes. :param nodes: Nodes. :type nodes: list :return: Method success. :rtype: bool """ files = {} for node in nodes: if node.family == "SearchFile": files[node.file] = node.children elif node.family == "SearchOccurence": file = node.parent.file if not file in files: files[file] = [] files[file].append(node) replacementPattern = self.Replace_With_comboBox.currentText() SearchAndReplace.insertPattern(replacementPattern, self.__replaceWithPatternsModel) replaceResults = {} for file, occurrences in files.iteritems(): editor = self.__container.getEditor(file) if editor: document = editor.document() else: cacheData = self.__filesCache.getContent(file) if cacheData is None: LOGGER.warning( "!> {0} | '{1}' file doesn't exists in files cache!".format(self.__class__.__name__, file)) continue content = self.__filesCache.getContent(file).content document = self.__getDocument(content) self.__cache(file, content, document) replaceResults[file] = self.__replaceWithinDocument(document, occurrences, replacementPattern) self.setReplaceResults(replaceResults) self.__container.engine.notificationsManager.notify( "{0} | '{1}' pattern occurence(s) replaced in '{2}' files!".format(self.__class__.__name__, sum(replaceResults.values()), len(replaceResults.keys()))) def saveFiles(self, nodes): """ Saves user defined files using give nodes. :param nodes: Nodes. :type nodes: list :return: Method success. :rtype: bool """ metrics = {"Opened" : 0, "Cached" : 0} for node in nodes: file = node.file if self.__container.getEditor(file): if self.__container.saveFile(file): metrics["Opened"] += 1 self.__uncache(file) else: cacheData = self.__filesCache.getContent(file) if cacheData is None: LOGGER.warning( "!> {0} | '{1}' file doesn't exists in files cache!".format(self.__class__.__name__, file)) continue if cacheData.document: fileHandle = File(file) fileHandle.content = [cacheData.document.toPlainText().toUtf8()] if fileHandle.write(): metrics["Cached"] += 1 self.__uncache(file) else: LOGGER.warning( "!> {0} | '{1}' file document doesn't exists in files cache!".format(self.__class__.__name__, file)) self.__container.engine.notificationsManager.notify( "{0} | '{1}' opened file(s) and '{2}' cached file(s) saved!".format(self.__class__.__name__, metrics["Opened"], metrics["Cached"]))
def __init__(self, iface, geometry, mntButton=False, zerosButton=False): """ Constructor :param iface: interface :param width: dock widget geometry """ QDockWidget.__init__(self) self.setWindowTitle(QCoreApplication.translate("VDLTools", "Profile Tool")) self.__iface = iface self.__geom = geometry self.__canvas = self.__iface.mapCanvas() self.__types = ['PDF', 'PNG'] # ], 'SVG', 'PS'] self.__libs = [] if Qwt5_loaded: self.__lib = 'Qwt5' self.__libs.append('Qwt5') if matplotlib_loaded: self.__libs.append('Matplotlib') elif matplotlib_loaded: self.__lib = 'Matplotlib' self.__libs.append('Matplotlib') else: self.__lib = None self.__iface.messageBar().pushMessage( QCoreApplication.translate("VDLTools", "No graph lib available (qwt5 or matplotlib)"), level=QgsMessageBar.CRITICAL, duration=0) self.__doTracking = False self.__vline = None self.__profiles = None self.__numLines = None self.__mntPoints = None self.__marker = None self.__tabmouseevent = None if self.__geom is not None: self.setGeometry(self.__geom) self.__contentWidget = QWidget() self.setWidget(self.__contentWidget) self.__boxLayout = QHBoxLayout() self.__contentWidget.setLayout(self.__boxLayout) self.__plotFrame = QFrame() self.__frameLayout = QHBoxLayout() self.__plotFrame.setLayout(self.__frameLayout) self.__printLayout = QHBoxLayout() self.__printLayout.addWidget(self.__plotFrame) self.__legendLayout = QVBoxLayout() self.__printLayout.addLayout(self.__legendLayout) self.__printWdg = QWidget() self.__printWdg.setLayout(self.__printLayout) self.__plotWdg = None self.__changePlotWidget() size = QSize(150, 20) self.__boxLayout.addWidget(self.__printWdg) self.__vertLayout = QVBoxLayout() self.__libCombo = QComboBox() self.__libCombo.setFixedSize(size) self.__libCombo.addItems(self.__libs) self.__vertLayout.addWidget(self.__libCombo) self.__libCombo.currentIndexChanged.connect(self.__setLib) if mntButton: self.__displayMnt = False self.__mntButton = QPushButton(QCoreApplication.translate("VDLTools", "Display MNT")) self.__mntButton.setFixedSize(size) self.__mntButton.clicked.connect(self.__mnt) self.__vertLayout.addWidget(self.__mntButton) if zerosButton: self.__displayZeros = False self.__zerosButton = QPushButton(QCoreApplication.translate("VDLTools", "Display Zeros")) self.__zerosButton.setFixedSize(size) self.__zerosButton.clicked.connect(self.__zeros) self.__vertLayout.addWidget(self.__zerosButton) else: self.__displayZeros = True self.__maxLabel = QLabel("y max") self.__maxLabel.setFixedSize(size) self.__vertLayout.addWidget(self.__maxLabel) self.__maxSpin = QSpinBox() self.__maxSpin.setFixedSize(size) self.__maxSpin.setRange(-10000, 10000) self.__maxSpin.valueChanged.connect(self.__reScalePlot) self.__vertLayout.addWidget(self.__maxSpin) self.__vertLayout.insertSpacing(10, 20) self.__minLabel = QLabel("y min") self.__minLabel.setFixedSize(size) self.__vertLayout.addWidget(self.__minLabel) self.__minSpin = QSpinBox() self.__minSpin.setFixedSize(size) self.__minSpin.setRange(-10000, 10000) self.__minSpin.valueChanged.connect(self.__reScalePlot) self.__vertLayout.addWidget(self.__minSpin) self.__vertLayout.insertSpacing(10, 40) self.__typeCombo = QComboBox() self.__typeCombo.setFixedSize(size) self.__typeCombo.addItems(self.__types) self.__vertLayout.addWidget(self.__typeCombo) self.__saveButton = QPushButton(QCoreApplication.translate("VDLTools", "Save")) self.__saveButton.setFixedSize(size) self.__saveButton.clicked.connect(self.__save) self.__vertLayout.addWidget(self.__saveButton) self.__boxLayout.addLayout(self.__vertLayout) self.__maxSpin.setEnabled(False) self.__minSpin.setEnabled(False) self.__colors = [] for cn in QColor.colorNames(): qc = QColor(cn) val = qc.red() + qc.green() + qc.blue() if 0 < val < 450: self.__colors.append(cn)
class Bezier(JObject): def __init__(self): JObject.__init__(self) self._control_points = [] self._qGray = QColor(100,100,100) self._qRed = QColor(245, 66, 78) p1 = JCircle(40) p1.setVisibility(False) p1.setColor(self._qGray) p2 = JCircle(40) p2.setVisibility(False) p2.setColor(self._qGray) p3 = JCircle(40) p3.setVisibility(False) p3.setColor(self._qGray) p4 = JCircle(40) p4.setVisibility(False) p4.setColor(self._qGray) self._control_points.append(p1) self._control_points.append(p2) self._control_points.append(p3) self._control_points.append(p4) # Trasla solo i due punti di controllo centrali def translate_2central_points(self, tx, ty): self._control_points[1].translate(tx, ty) self._control_points[2].translate(tx, ty) def get_selected(self, x, y): result = None if self._visible: for control_point in self._control_points: if control_point.isSelected(x, y): result = control_point break return result def paint(self, paintHidden=False): self.setOpenGlColor() if self.getVisibility() or paintHidden: points = [] for control_point in self._control_points: points.append(control_point.getCenter()) control_point.paint(paintHidden) if paintHidden: glColor3f(self._qGray.red()/255.0, self._qGray.green()/255.0, self._qGray.blue()/255.0 ) # Visualizza le linee di controllo glBegin(GL_LINE_STRIP) for p in points: glVertex2f(p.getX(), p.getY()) glEnd() glColor3f(self._qRed.red()/255.0, self._qRed.green()/255.0, self._qRed.blue()/255.0 ) glBegin(GL_LINE_STRIP) for i in range(0, 100): t = i / 100.0 # Formula parametrica della Curva di Bezier cubica p = points[0]*(1-t)**3 + points[1]*3*t*(1-t)**2 + points[2]*3*t**2*(1-t) + points[3]*t**3 glVertex2f(p.getX(), p.getY()) glEnd()
def typeChanged(self, index): """ Type is changed, index is the new selected index """ self.ui.view.clear() # If nothing is selected if index < 0: self.ui.title_label.setEnabled(False) self.ui.title.setEnabled(False) self.ui.title.setText('') self.ui.view_label.hide() self.ui.view.hide() self.ui.color_label.setEnabled(False) self.ui.color_button.setEnabled(False) self.ui.firewall.setEnabled(False) self.ui.firewall_label.setEnabled(False) self.ui.buttonBox.button(QDialogButtonBox.Ok).setEnabled(False) self._set_args(False) return fragtypename = unicode(self.ui.type.itemData(index).toString()) fragtype = frag_types[fragtypename] if not self.fragment or self.fragment.type != fragtypename: # self.window.user_settings.removeFragment(self.fragment) self.fragment = self.window.user_settings.createFragment(fragtypename, False) self.ui.title_label.setEnabled(True) self.ui.title.setEnabled(True) self.ui.title.setText(fragtype.title) self.ui.view_label.setEnabled(True) self.ui.view.setEnabled(True) self.ui.color_label.setEnabled(True) self.ui.color_button.setEnabled(True) self.ui.firewall.setEnabled(True) self.ui.firewall_label.setEnabled(True) # Add views related to this fragment type. for view in fragtype.views: # if not views_list.has_key(view): # continue if not isinstance(view, GraphicsView): continue # self.ui.view.addItem(views_list[view].name(), QVariant(view)) self.ui.view.addItem(view.name(), QVariant(view)) if len(fragtype.views) > 1: self.ui.view_label.show() self.ui.view.show() else: self.ui.view_label.hide() self.ui.view.hide() # Set the fragment background color color = QColor(self.fragment.background_color) self.ui.color.setStyleSheet('background-color: rgb(%d, %d, %d)' % (color.red(), color.green(), color.blue())) # Firewall i = self.ui.firewall.findData(QVariant(self.fragment.firewall)) self.ui.firewall.setCurrentIndex(i) self._set_args() self.ui.buttonBox.button(QDialogButtonBox.Ok).setEnabled(True)
def __drawAxes(self, painter): """ Pozor, tato metoda vracia nove velkosti X a Y pretoze pri kresleni osi sa rata aj s velkostou textu ktora je variabilna """ palette = QPalette() penColor = QColor(palette.color(QPalette.WindowText)) ciara = QPen(penColor) pozadieBaseColor = QColor(palette.color(QPalette.Base)) pozadieMixColor = QColor(90, 150, 250); red = (pozadieBaseColor.red() * 4 + pozadieMixColor.red()) / 5 green = (pozadieBaseColor.green() * 4 + pozadieMixColor.green()) / 5 blue = (pozadieBaseColor.blue() * 4 + pozadieMixColor.blue()) / 5 pozadieColor = QColor(red, green, blue); pozadie = QBrush(pozadieColor) painter.setPen(ciara) painter.setBrush(pozadie) xVelkost = self.width() - (2 * self.__padding) yVelkost = self.height() - (2 * self.__padding) xOs = self.__calcAxesData(xVelkost, self.__xMedzery, self.__minDay, self.__maxDay) yOs = self.__calcAxesData(yVelkost, self.__yMedzery, self.__minPoints, self.__maxPoints) xText = self.__convertXData(xOs) yText = self.__convertYData(yOs) (xxText, xyText) = self.__calcMaxTextSize(self.font(), xText) (yxText, yyText) = self.__calcMaxTextSize(self.font(), yText) xVelkost = xVelkost - yxText yVelkost = yVelkost - xyText painter.translate(yxText + 5, 5) rect = QRect(0, 0, xVelkost, yVelkost) painter.drawRect(rect) penColor.setAlpha(60) painter.setPen(QPen(penColor)) for hodnota in yOs: y = self.__getYCoord(yVelkost, hodnota) painter.drawLine(0, y, xVelkost, y) for hodnota in xOs: x = self.__getXCoord(xVelkost, hodnota) painter.drawLine(x, 0, x, yVelkost) painter.setPen(palette.color(QPalette.WindowText)) for i in range(len(yText)): hodnota = yOs[i] text = yText[i] y = self.__getYCoord(yVelkost, hodnota) textRect = QRect(-yxText-3, y - yyText / 2, yxText, yyText) painter.drawText(textRect, Qt.AlignRight, text) for i in range(len(xText)): hodnota = xOs[i] text = xText[i] x = self.__getXCoord(xVelkost, hodnota) textRect = QRect(x - xxText / 2, yVelkost + xyText / 2, xxText, xyText) painter.drawText(textRect, Qt.AlignHCenter, text) return (xVelkost, yVelkost)
def __init__(self, iface): """ Constructor :param iface: interface """ QDockWidget.__init__(self) self.setWindowTitle(QCoreApplication.translate("VDLTools", "Profile Tool")) self.resize(1024, 400) self.__iface = iface self.__canvas = self.__iface.mapCanvas() self.__types = ['PDF', 'PNG'] # ], 'SVG', 'PS'] self.__libs = [] if Qwt5_loaded: self.__lib = 'Qwt5' self.__libs.append('Qwt5') if matplotlib_loaded: self.__libs.append('Matplotlib') elif matplotlib_loaded: self.__lib = 'Matplotlib' self.__libs.append('Matplotlib') else: self.__lib = None self.__iface.messageBar().pushMessage( QCoreApplication.translate("VDLTools", "No graph lib available (qwt5 or matplotlib)"), level=QgsMessageBar.CRITICAL, duration=0) self.__doTracking = False self.__vline = None self.__profiles = None self.__numLines = None self.__mntPoints = None self.__marker = None self.__tabmouseevent = None self.__contentWidget = QWidget() self.setWidget(self.__contentWidget) self.__boxLayout = QHBoxLayout() self.__contentWidget.setLayout(self.__boxLayout) self.__plotFrame = QFrame() self.__frameLayout = QHBoxLayout() self.__plotFrame.setLayout(self.__frameLayout) self.__printLayout = QHBoxLayout() self.__printLayout.addWidget(self.__plotFrame) self.__legendLayout = QVBoxLayout() self.__printLayout.addLayout(self.__legendLayout) self.__printWdg = QWidget() self.__printWdg.setLayout(self.__printLayout) self.__plotWdg = None self.__changePlotWidget() size = QSize(150, 20) self.__boxLayout.addWidget(self.__printWdg) self.__vertLayout = QVBoxLayout() self.__libCombo = QComboBox() self.__libCombo.setFixedSize(size) self.__libCombo.addItems(self.__libs) self.__vertLayout.addWidget(self.__libCombo) self.__libCombo.currentIndexChanged.connect(self.__setLib) self.__maxLabel = QLabel("y max") self.__maxLabel.setFixedSize(size) self.__vertLayout.addWidget(self.__maxLabel) self.__maxSpin = QSpinBox() self.__maxSpin.setFixedSize(size) self.__maxSpin.setRange(-10000, 10000) self.__maxSpin.valueChanged.connect(self.__reScalePlot) self.__vertLayout.addWidget(self.__maxSpin) self.__vertLayout.insertSpacing(10, 20) self.__minLabel = QLabel("y min") self.__minLabel.setFixedSize(size) self.__vertLayout.addWidget(self.__minLabel) self.__minSpin = QSpinBox() self.__minSpin.setFixedSize(size) self.__minSpin.setRange(-10000, 10000) self.__minSpin.valueChanged.connect(self.__reScalePlot) self.__vertLayout.addWidget(self.__minSpin) self.__vertLayout.insertSpacing(10, 40) self.__typeCombo = QComboBox() self.__typeCombo.setFixedSize(size) self.__typeCombo.addItems(self.__types) self.__vertLayout.addWidget(self.__typeCombo) self.__saveButton = QPushButton(QCoreApplication.translate("VDLTools", "Save")) self.__saveButton.setFixedSize(size) self.__saveButton.clicked.connect(self.__save) self.__vertLayout.addWidget(self.__saveButton) self.__boxLayout.addLayout(self.__vertLayout) self.__maxSpin.setEnabled(False) self.__minSpin.setEnabled(False) self.__colors = [] for cn in QColor.colorNames(): qc = QColor(cn) val = qc.red() + qc.green() + qc.blue() if 0 < val < 450: self.__colors.append(cn)
def attachCurves(self, names, settings, usedMnts): """ To attach the curves for the layers to the profile :param names: layers names """ if (self.__profiles is None) or (self.__profiles == 0): return self.__getLinearPoints() if usedMnts is not None and (usedMnts[0] or usedMnts[1] or usedMnts[2]): self.__getMnt(settings) c = 0 if self.__mntPoints is not None: for p in range(len(self.__mntPoints[0])): if usedMnts[p]: legend = QLabel("<font color='" + self.__colors[c] + "'>" + self.__mntPoints[0][p] + "</font>") self.__legendLayout.addWidget(legend) if self.__lib == 'Qwt5': xx = [list(g) for k, g in itertools.groupby(self.__mntPoints[1], lambda x: x is None) if not k] yy = [list(g) for k, g in itertools.groupby(self.__mntPoints[2][p], lambda x: x is None) if not k] for j in range(len(xx)): curve = QwtPlotCurve(self.__mntPoints[0][p]) curve.setData(xx[j], yy[j]) curve.setPen(QPen(QColor(self.__colors[c]), 3)) curve.attach(self.__plotWdg) elif self.__lib == 'Matplotlib': qcol = QColor(self.__colors[c]) self.__plotWdg.figure.get_axes()[0].plot(self.__mntPoints[1], self.__mntPoints[2][p], gid=self.__mntPoints[0][p], linewidth=3) tmp = self.__plotWdg.figure.get_axes()[0].get_lines() for t in range(len(tmp)): if self.__mntPoints[0][p] == tmp[t].get_gid(): tmp[c].set_color((old_div(qcol.red(), 255.0), old_div(qcol.green(), 255.0), old_div(qcol.blue(), 255.0), old_div(qcol.alpha(), 255.0))) self.__plotWdg.draw() break c += 1 if 'z' in self.__profiles[0]: for i in range(len(self.__profiles[0]['z'])): if i < self.__numLines: v = 0 else: v = i - self.__numLines + 1 name = names[v] xx = [] yy = [] for prof in self.__profiles: xx.append(prof['l']) yy.append(prof['z'][i]) for j in range(len(yy)): if yy[j] is None: xx[j] = None if i == 0 or i > (self.__numLines-1): legend = QLabel("<font color='" + self.__colors[c] + "'>" + name + "</font>") self.__legendLayout.addWidget(legend) if self.__lib == 'Qwt5': # Split xx and yy into single lines at None values xx = [list(g) for k, g in itertools.groupby(xx, lambda x: x is None) if not k] yy = [list(g) for k, g in itertools.groupby(yy, lambda x: x is None) if not k] # Create & attach one QwtPlotCurve per one single line for j in range(len(xx)): curve = QwtPlotCurve(name) curve.setData(xx[j], yy[j]) curve.setPen(QPen(QColor(self.__colors[c]), 3)) if i > (self.__numLines-1): curve.setStyle(QwtPlotCurve.Dots) pen = QPen(QColor(self.__colors[c]), 8) pen.setCapStyle(Qt.RoundCap) curve.setPen(pen) curve.attach(self.__plotWdg) elif self.__lib == 'Matplotlib': qcol = QColor(self.__colors[c]) if i < self.__numLines: self.__plotWdg.figure.get_axes()[0].plot(xx, yy, gid=name, linewidth=3) else: self.__plotWdg.figure.get_axes()[0].plot(xx, yy, gid=name, linewidth=5, marker='o', linestyle='None') tmp = self.__plotWdg.figure.get_axes()[0].get_lines() for t in range(len(tmp)): if name == tmp[t].get_gid(): tmp[c].set_color((old_div(qcol.red(), 255.0), old_div(qcol.green(), 255.0), old_div(qcol.blue(), 255.0), old_div(qcol.alpha(), 255.0))) self.__plotWdg.draw() break c += 1 # scaling this try: self.__reScalePlot(None, True) except: self.__iface.messageBar().pushMessage( QCoreApplication.translate("VDLTools", "Rescale problem... (trace printed)"), level=QgsMessageBar.CRITICAL, duration=0) print( QCoreApplication.translate("VDLTools", "rescale problem : "), sys.exc_info()[0], traceback.format_exc()) if self.__lib == 'Qwt5': self.__plotWdg.replot() elif self.__lib == 'Matplotlib': self.__plotWdg.figure.get_axes()[0].redraw_in_frame() self.__plotWdg.draw() self.__activateMouseTracking(True) self.__marker.show()
def attachCurves(self, names, settings, usedMnts): """ To attach the curves for the layers to the profile :param names: layers names """ if (self.__profiles is None) or (self.__profiles == 0): return self.__getLinearPoints() if usedMnts is not None and (usedMnts[0] or usedMnts[1] or usedMnts[2]): self.__getMnt(settings) c = 0 if self.__mntPoints is not None: for p in range(len(self.__mntPoints[0])): if usedMnts[p]: legend = QLabel("<font color='" + self.__colors[c] + "'>" + self.__mntPoints[0][p] + "</font>") self.__legendLayout.addWidget(legend) if self.__lib == 'Qwt5': xx = [list(g) for k, g in itertools.groupby(self.__mntPoints[1], lambda x: x is None) if not k] yy = [list(g) for k, g in itertools.groupby(self.__mntPoints[2][p], lambda x: x is None) if not k] for j in range(len(xx)): curve = QwtPlotCurve(self.__mntPoints[0][p]) curve.setData(xx[j], yy[j]) curve.setPen(QPen(QColor(self.__colors[c]), 3)) curve.attach(self.__plotWdg) elif self.__lib == 'Matplotlib': qcol = QColor(self.__colors[c]) self.__plotWdg.figure.get_axes()[0].plot(self.__mntPoints[1], self.__mntPoints[2][p], gid=self.__mntPoints[0][p], linewidth=3) tmp = self.__plotWdg.figure.get_axes()[0].get_lines() for t in range(len(tmp)): if self.__mntPoints[0][p] == tmp[t].get_gid(): tmp[c].set_color((old_div(qcol.red(), 255.0), old_div(qcol.green(), 255.0), old_div(qcol.blue(), 255.0), old_div(qcol.alpha(), 255.0))) self.__plotWdg.draw() break c += 1 if 'z' in self.__profiles[0]: for i in range(len(self.__profiles[0]['z'])): if i < self.__numLines: v = 0 else: v = i - self.__numLines + 1 name = names[v] xx = [] yy = [] for prof in self.__profiles: xx.append(prof['l']) yy.append(prof['z'][i]) for j in range(len(yy)): if yy[j] is None: xx[j] = None if i == 0 or i > (self.__numLines-1): legend = QLabel("<font color='" + self.__colors[c] + "'>" + name + "</font>") self.__legendLayout.addWidget(legend) if self.__lib == 'Qwt5': # Split xx and yy into single lines at None values xx = [list(g) for k, g in itertools.groupby(xx, lambda x: x is None) if not k] yy = [list(g) for k, g in itertools.groupby(yy, lambda x: x is None) if not k] # Create & attach one QwtPlotCurve per one single line for j in range(len(xx)): curve = QwtPlotCurve(name) curve.setData(xx[j], yy[j]) curve.setPen(QPen(QColor(self.__colors[c]), 3)) if i > (self.__numLines-1): curve.setStyle(QwtPlotCurve.Dots) pen = QPen(QColor(self.__colors[c]), 8) pen.setCapStyle(Qt.RoundCap) curve.setPen(pen) curve.attach(self.__plotWdg) elif self.__lib == 'Matplotlib': qcol = QColor(self.__colors[c]) if i < self.__numLines: self.__plotWdg.figure.get_axes()[0].plot(xx, yy, gid=name, linewidth=3) else: self.__plotWdg.figure.get_axes()[0].plot(xx, yy, gid=name, linewidth=5, marker='o', linestyle='None') tmp = self.__plotWdg.figure.get_axes()[0].get_lines() for t in range(len(tmp)): if name == tmp[t].get_gid(): tmp[c].set_color((old_div(qcol.red(), 255.0), old_div(qcol.green(), 255.0), old_div(qcol.blue(), 255.0), old_div(qcol.alpha(), 255.0))) self.__plotWdg.draw() break c += 1 # scaling this try: self.__reScalePlot(None, True) except: self.__iface.messageBar().pushMessage( QCoreApplication.translate("VDLTools", "Rescale problem... (trace printed)"), level=QgsMessageBar.CRITICAL, duration=0) print(sys.exc_info()[0], traceback.format_exc()) if self.__lib == 'Qwt5': self.__plotWdg.replot() elif self.__lib == 'Matplotlib': self.__plotWdg.figure.get_axes()[0].redraw_in_frame() self.__plotWdg.draw() self.__activateMouseTracking(True) self.__marker.show()
class OIBlock(QWidget): border_color = QColor(137, 117, 89) padding = 0.05 radius = 0.08 def __init__(self, block, parent): QWidget.__init__(self, parent) self.__nodes = [] self.__block = block self._resizable = True self.__block.repaint.connect(self.repaint) self._bg_color = QColor(159, 160, 144, 255) self._fg_color = QColor(255, 255, 255) self.setGeometry(block.get_geometry(Info.dpi)) self.__action = Action.NONE self.__status = Mode.EDIT_LOGIC self.__corner_path = None self.__origin = None self.__translation = QPoint() if self._resizable: self.__init_corner() self.__init_nodes() self.__init_listeners() self.setMouseTracking(True) def __init_nodes(self): y = .45 x = .01 for k in self.__block.inputs: i = self.__block.inputs[k] n = OINode(QPointF(x, y), Alignment.Left, i) self.__nodes.append(n) y += 0.05 + n.size x = self.width() / Info.dpi - .12 y = 0.45 for k in self.__block.outputs: o = self.__block.outputs[k] n = OINode(QPointF(x, y), Alignment.Right, o) self.__nodes.append(n) y += .05 + n.size def __init_listeners(self): self.__block.selected.connect(self.select) self.__block.settings['Width'].value_update.connect( self.geometry_update) self.__block.settings['Height'].value_update.connect( self.geometry_update) self.__block.settings['X'].value_update.connect(self.geometry_update) self.__block.settings['Y'].value_update.connect(self.geometry_update) def select(self, val: bool): if val: effect = QGraphicsDropShadowEffect() effect.setBlurRadius(20) effect.setXOffset(0) effect.setYOffset(0) effect.setColor(QColor(0, 0, 0, 180)) self.setGraphicsEffect(effect) self.raise_() else: eff = self.graphicsEffect() del eff self.setGraphicsEffect(None) def geometry_update(self): r = self.__block.get_geometry(Info.dpi) r.translate(self.__translation) self.setGeometry(r) self.__update_nodes() def __update_nodes(self): x = self.width() / Info.dpi - .12 for n in self.__nodes: if n.alignment == Alignment.Right: y = n.pos.y() n.pos = QPointF(x, y) self.repaint() def selected(self): return self.__block.is_selected() def bg(self): return self._bg_color def title_bg(self): return self._bg_color.light(80) def block(self): return self.__block def _paint(self, p: QPainter): self._paint_bg(p) self._paint_title(p) p.setPen(QPen(self.pen().brush(), 0.01 * Info.dpi)) self._paint_nodes(p) # self._paint_outs(p) # self._paint_content(p) def pen(self): p = QPen( OIBlock.border_color.lighter().lighter() if self.selected() else OIBlock.border_color, .02 * Info.dpi) return p def _paint_bg(self, p: QPainter): dpi = Info.dpi pen = self.pen() p.setRenderHint(QPainter.Antialiasing, True) p.setPen(pen) p.setBrush(self.bg()) p.drawRoundedRect(OIBlock.padding * dpi, OIBlock.padding * dpi, self.width() - 2 * OIBlock.padding * dpi, self.height() - 2 * OIBlock.padding * dpi, OIBlock.radius * dpi, OIBlock.radius * dpi) p.setBrush(self.title_bg()) p.drawRoundedRect(OIBlock.padding * dpi, OIBlock.padding * dpi, self.width() - 2 * OIBlock.padding * dpi, .35 * dpi + OIBlock.padding * dpi, OIBlock.radius * dpi, OIBlock.radius * dpi) p.setBrush(self.bg()) p.setPen(QColor(0, 0, 0, 0)) p.drawRect(0.01 * dpi + OIBlock.padding * dpi, 0.35 * dpi + OIBlock.padding * dpi, self.width() - 0.02 * dpi - 2 * OIBlock.padding * dpi, 0.10 * dpi) p.setPen(pen) if self._resizable: if self.__corner_path is None: self.__init_corner() p.setBrush(pen.brush()) p.drawPath( self.__corner_path.translated(self.width(), self.height())) def _paint_title(self, p: QPainter): dpi = Info.dpi p.drawLine(OIBlock.padding * dpi, 0.35 * dpi + OIBlock.padding * dpi, self.width() - (0.01 + OIBlock.padding) * dpi, 0.35 * dpi + OIBlock.padding * dpi) p.setPen(self._fg_color) f = p.font() f.setPointSize(10) f.setBold(True) p.setFont(f) p.drawText( QRectF((0.04 + OIBlock.padding) * dpi, (OIBlock.padding + .01) * dpi, self.width() - .12 * dpi, .25 * dpi), str(self.__block.name())) f.setBold(False) f.setPointSize(8) p.setPen( QColor(self._fg_color.red(), self._fg_color.green(), self._fg_color.blue(), 100)) p.setFont(f) p.drawText( QRectF((.04 + OIBlock.padding) * dpi, (.17 + OIBlock.padding) * dpi, self.width() - .12 * dpi, .15 * dpi), str(self.__block.type_name())) def __init_corner(self): path = QPainterPath() dpi = Info.dpi path.moveTo(-OIBlock.padding * 1.2 * dpi, (-.15 - OIBlock.padding * 1.2) * dpi) path.lineTo((-.15 - OIBlock.padding * 1.2) * dpi, -OIBlock.padding * 1.2 * dpi) path.lineTo(-OIBlock.padding * 1.2 * dpi, -OIBlock.padding * 1.2 * dpi) path.closeSubpath() self.__corner_path = path def _paint_nodes(self, p: QPainter): for n in self.__nodes: n.paint(p) return def _paint_content(self, p: QPainter): # nothing to do return def paintEvent(self, e: QPaintEvent): if e.isAccepted(): p = QPainter(self) self._paint(p) def _check_corner(self, pos): path = self.__corner_path.translated(self.width(), self.height()) return path.contains(pos) def _check_action(self, action): if self.__action != Action.NONE and action != Action.NONE: return False return True def _check_nodes(self, p: QPoint): for n in self.__nodes: if n.contains(p): return n return None def mousePressEvent(self, e: QMouseEvent): self.__block.select() n = self._check_nodes(e.pos()) if n is not None: print('Node found') return if e.button() == Qt.LeftButton: if self._resizable: if self._check_corner(e.pos()) and self._check_action( Action.RESIZE): self.__origin = e.pos() self.__action = Action.RESIZE self.setCursor(Qt.SizeFDiagCursor) return if self._check_action(Action.DRAG): self.__origin = e.pos() self.__action = Action.DRAG self.setCursor(Qt.DragMoveCursor) def mouseMoveEvent(self, e: QMouseEvent): if self.__action == Action.DRAG: dx = e.x() - self.__origin.x() dy = e.y() - self.__origin.y() self.set_pos(self.x() + dx, self.y() + dy) elif self.__action == Action.RESIZE: self.set_size(e.x(), e.y()) else: if self._resizable and self.__corner_path.translated( self.width(), self.height()).contains(e.pos()): self.setCursor(Qt.SizeFDiagCursor) else: self.setCursor(Qt.ArrowCursor) def mouseReleaseEvent(self, e: QMouseEvent): self.__action = Action.NONE self.setCursor(Qt.ArrowCursor) def set_size(self, w, h): w1 = w / Info.dpi h1 = h / Info.dpi W = self.__block.settings['Width'].value() H = self.__block.settings['Height'].value() if w1 < W.min: w1 = W.min elif w1 > W.max: w1 = W.max if h1 < H.min: h1 = H.min elif h1 > H.max: h1 = H.max self.__block.set_setting('Width', w1) self.__block.set_setting('Height', h1) def set_pos(self, x, y): x = x - self.__translation.x() y = y - self.__translation.y() self.__block.set_setting('X', x / Info.dpi) self.__block.set_setting('Y', y / Info.dpi) def translate(self, p): self.__translation = p self.geometry_update()
def traffic_overlay(waypoints, time, wait=5, debug=False): # sanity check if len(waypoints) < 2: raise ValueError # parse waypoints into origin, destination, and mid-waypoints origin = waypoints[0] destin = waypoints[-1] waypts = waypoints[1:-1] # build url url = "http://maps.googleapis.com/maps/api/directions/json?" f = {"origin" : origin, "destination" : destin, "waypoints" : "|".join(waypts), "sensor" : "false"} url += urllib.parse.urlencode(f) g = urllib.request.urlopen(url).read().decode() j = json.loads(g) #pprint.pprint(j) # error if not one route nroute = len(j['routes']) if nroute != 1: raise ValueError nleg = len(j['routes'][0]['legs']) # sanity check if nleg != len(waypoints)-1: raise ValueError coord = [] for leg in j['routes'][0]['legs']: for s in leg['steps']: c = decode_polyline(s['polyline']['points']) # make sure we don't add the same point twice! if len(coord) > 0: if all([(coord[-1][i] - c[0][i]) < 1e-10 for i in range(2)]): coord.extend(c[1:]) else: coord.extend(c) else: coord.extend(c) # temporary html file html_file = "_map.html" # find min/max lat/lng lats = [x[0] for x in coord] lngs = [x[1] for x in coord] img_size = (2048, 2048) _write_traffic_html((min(lats), max(lats)), (min(lngs), max(lngs)), html_file, width=2048, height=2048) # take screenshot S = WebScreenShot() image = S.capture(html_file, wait=wait) # bounds are returned in a cookie (ohh la la) cookie = S.get_cookies() bounds = json.loads(cookie[0])['k'] # loop through polyline points and compute overlay value at each point image_size = [image.height(), image.width()] pplat = image_size[0]/(bounds['upper_right_lat']-bounds['lower_left_lat']) pplng = image_size[1]/(bounds['upper_right_lng']-bounds['lower_left_lng']) val = [0] * len(coord) for i, c in enumerate(coord): x = int((c[0] - bounds['lower_left_lng'])*pplng) y = int((bounds['upper_right_lat'] - c[1])*pplat) v = QColor(image.pixel(QPoint(x, y))) v_rgb = (v.red(), v.green(), v.blue()) val[i] = color_to_value(v_rgb) # if debugging, change pixel color to black for each point sampled # and then save the image as _img.jpg if debug: image.setPixel(QPoint(x, y), 0) if debug: image.save("_img.jpg") print(coord)
class OIBlock(QWidget): border_color = QColor(137, 117, 89) padding = 0.05 radius = 0.08 def __init__(self, block, parent): QWidget.__init__(self, parent) self.__nodes = [] self.__block = block self._resizable = True self.__block.repaint.connect(self.repaint) self._bg_color = QColor(159, 160, 144, 255) self._fg_color = QColor(255, 255, 255) self.setGeometry(block.get_geometry(Info.dpi)) self.__action = Action.NONE self.__status = Mode.EDIT_LOGIC self.__corner_path = None self.__origin = None self.__translation = QPoint() if self._resizable: self.__init_corner() self.__init_nodes() self.__init_listeners() self.setMouseTracking(True) def __init_nodes(self): y = .45 x = .01 for k in self.__block.inputs: i = self.__block.inputs[k] n = OINode(QPointF(x, y), Alignment.Left, i) self.__nodes.append(n) y += 0.05 + n.size x = self.width() / Info.dpi - .12 y = 0.45 for k in self.__block.outputs: o = self.__block.outputs[k] n = OINode(QPointF(x, y), Alignment.Right, o) self.__nodes.append(n) y += .05 + n.size def __init_listeners(self): self.__block.selected.connect(self.select) self.__block.settings['Width'].value_update.connect(self.geometry_update) self.__block.settings['Height'].value_update.connect(self.geometry_update) self.__block.settings['X'].value_update.connect(self.geometry_update) self.__block.settings['Y'].value_update.connect(self.geometry_update) def select(self, val: bool): if val: effect = QGraphicsDropShadowEffect() effect.setBlurRadius(20) effect.setXOffset(0) effect.setYOffset(0) effect.setColor(QColor(0, 0, 0, 180)) self.setGraphicsEffect(effect) self.raise_() else: eff = self.graphicsEffect() del eff self.setGraphicsEffect(None) def geometry_update(self): r = self.__block.get_geometry(Info.dpi) r.translate(self.__translation) self.setGeometry(r) self.__update_nodes() def __update_nodes(self): x = self.width() / Info.dpi - .12 for n in self.__nodes: if n.alignment == Alignment.Right: y = n.pos.y() n.pos = QPointF(x, y) self.repaint() def selected(self): return self.__block.is_selected() def bg(self): return self._bg_color def title_bg(self): return self._bg_color.light(80) def block(self): return self.__block def _paint(self, p: QPainter): self._paint_bg(p) self._paint_title(p) p.setPen(QPen(self.pen().brush(), 0.01 * Info.dpi)) self._paint_nodes(p) # self._paint_outs(p) # self._paint_content(p) def pen(self): p = QPen(OIBlock.border_color.lighter().lighter() if self.selected() else OIBlock.border_color, .02 * Info.dpi) return p def _paint_bg(self, p: QPainter): dpi = Info.dpi pen = self.pen() p.setRenderHint(QPainter.Antialiasing, True) p.setPen(pen) p.setBrush(self.bg()) p.drawRoundedRect(OIBlock.padding * dpi, OIBlock.padding * dpi, self.width() - 2 * OIBlock.padding * dpi, self.height() - 2 * OIBlock.padding * dpi, OIBlock.radius * dpi, OIBlock.radius * dpi) p.setBrush(self.title_bg()) p.drawRoundedRect(OIBlock.padding * dpi, OIBlock.padding * dpi, self.width() - 2 * OIBlock.padding * dpi, .35 * dpi + OIBlock.padding * dpi, OIBlock.radius * dpi, OIBlock.radius * dpi) p.setBrush(self.bg()) p.setPen(QColor(0, 0, 0, 0)) p.drawRect(0.01 * dpi + OIBlock.padding * dpi, 0.35 * dpi + OIBlock.padding * dpi, self.width() - 0.02 * dpi - 2 * OIBlock.padding * dpi, 0.10 * dpi) p.setPen(pen) if self._resizable: if self.__corner_path is None: self.__init_corner() p.setBrush(pen.brush()) p.drawPath(self.__corner_path.translated(self.width(), self.height())) def _paint_title(self, p: QPainter): dpi = Info.dpi p.drawLine(OIBlock.padding * dpi, 0.35 * dpi + OIBlock.padding * dpi, self.width() - (0.01 + OIBlock.padding) * dpi, 0.35 * dpi + OIBlock.padding * dpi) p.setPen(self._fg_color) f = p.font() f.setPointSize(10) f.setBold(True) p.setFont(f) p.drawText( QRectF((0.04 + OIBlock.padding) * dpi, (OIBlock.padding + .01) * dpi, self.width() - .12 * dpi, .25 * dpi), str(self.__block.name())) f.setBold(False) f.setPointSize(8) p.setPen(QColor(self._fg_color.red(), self._fg_color.green(), self._fg_color.blue(), 100)) p.setFont(f) p.drawText( QRectF((.04 + OIBlock.padding) * dpi, (.17 + OIBlock.padding) * dpi, self.width() - .12 * dpi, .15 * dpi), str(self.__block.type_name())) def __init_corner(self): path = QPainterPath() dpi = Info.dpi path.moveTo(-OIBlock.padding * 1.2 * dpi, (-.15 - OIBlock.padding * 1.2) * dpi) path.lineTo((-.15 - OIBlock.padding * 1.2) * dpi, -OIBlock.padding * 1.2 * dpi) path.lineTo(-OIBlock.padding * 1.2 * dpi, -OIBlock.padding * 1.2 * dpi) path.closeSubpath() self.__corner_path = path def _paint_nodes(self, p: QPainter): for n in self.__nodes: n.paint(p) return def _paint_content(self, p: QPainter): # nothing to do return def paintEvent(self, e: QPaintEvent): if e.isAccepted(): p = QPainter(self) self._paint(p) def _check_corner(self, pos): path = self.__corner_path.translated(self.width(), self.height()) return path.contains(pos) def _check_action(self, action): if self.__action != Action.NONE and action != Action.NONE: return False return True def _check_nodes(self, p:QPoint): for n in self.__nodes: if n.contains(p): return n return None def mousePressEvent(self, e: QMouseEvent): self.__block.select() n = self._check_nodes(e.pos()) if n is not None: print('Node found') return if e.button() == Qt.LeftButton: if self._resizable: if self._check_corner(e.pos()) and self._check_action(Action.RESIZE): self.__origin = e.pos() self.__action = Action.RESIZE self.setCursor(Qt.SizeFDiagCursor) return if self._check_action(Action.DRAG): self.__origin = e.pos() self.__action = Action.DRAG self.setCursor(Qt.DragMoveCursor) def mouseMoveEvent(self, e: QMouseEvent): if self.__action == Action.DRAG: dx = e.x() - self.__origin.x() dy = e.y() - self.__origin.y() self.set_pos(self.x() + dx, self.y() + dy) elif self.__action == Action.RESIZE: self.set_size(e.x(), e.y()) else: if self._resizable and self.__corner_path.translated(self.width(), self.height()).contains(e.pos()): self.setCursor(Qt.SizeFDiagCursor) else: self.setCursor(Qt.ArrowCursor) def mouseReleaseEvent(self, e: QMouseEvent): self.__action = Action.NONE self.setCursor(Qt.ArrowCursor) def set_size(self, w, h): w1 = w / Info.dpi h1 = h / Info.dpi W = self.__block.settings['Width'].value() H = self.__block.settings['Height'].value() if w1 < W.min: w1 = W.min elif w1 > W.max: w1 = W.max if h1 < H.min: h1 = H.min elif h1 > H.max: h1 = H.max self.__block.set_setting('Width', w1) self.__block.set_setting('Height', h1) def set_pos(self, x, y): x = x - self.__translation.x() y = y - self.__translation.y() self.__block.set_setting('X', x / Info.dpi) self.__block.set_setting('Y', y / Info.dpi) def translate(self, p): self.__translation = p self.geometry_update()