def write_xml(configDictionary={}, pageData=[], pagesLocationList=[], locationBasic=str(), locationStandAlone=str(), projectUrl=str()): acbfGenreList = [ "science_fiction", "fantasy", "adventure", "horror", "mystery", "crime", "military", "real_life", "superhero", "humor", "western", "manga", "politics", "caricature", "sports", "history", "biography", "education", "computer", "religion", "romance", "children", "non-fiction", "adult", "alternative", "other", "artbook" ] acbfAuthorRolesList = [ "Writer", "Adapter", "Artist", "Penciller", "Inker", "Colorist", "Letterer", "Cover Artist", "Photographer", "Editor", "Assistant Editor", "Translator", "Other", "Designer" ] document = QDomDocument() root = document.createElement("ACBF") root.setAttribute("xmlns", "http://www.acbf.info/xml/acbf/1.1") document.appendChild(root) emphasisStyle = {} strongStyle = {} if "acbfStyles" in configDictionary.keys(): stylesDictionary = configDictionary.get("acbfStyles", {}) emphasisStyle = stylesDictionary.get("emphasis", {}) strongStyle = stylesDictionary.get("strong", {}) styleString = "\n" tabs = " " for key in sorted(stylesDictionary.keys()): style = stylesDictionary.get(key, {}) if key == "emphasis" or key == "strong": styleClass = key + " {\n" elif key == "speech": styleClass = "text-area {\n" elif key == "general": styleClass = "* {\n" elif key == "inverted": styleClass = "text-area[inverted=\"true\"] {\n" else: styleClass = "text-area[type=\"" + key + "\"] {\n" styleString += tabs + styleClass if "color" in style.keys(): styleString += tabs + tabs + "color:" + style["color"] + ";\n" if "font" in style.keys(): fonts = style["font"] genericfont = style.get("genericfont", "sans-serif") if isinstance(fonts, list): styleString += tabs + tabs + "font-family:\"" + str( "\", \"").join(fonts) + "\", " + genericfont + ";\n" else: styleString += tabs + tabs + "font-family:\"" + fonts + "\", " + genericfont + ";\n" if "bold" in style.keys(): if style["bold"]: styleString += tabs + tabs + "font-weight: bold;\n" if "ital" in style.keys(): if style["ital"]: styleString += tabs + tabs + "font-style: italic;\n" else: styleString += tabs + tabs + "font-style: normal;\n" styleString += tabs + "}\n" style = document.createElement("style") style.setAttribute("type", "text/css") style.appendChild(document.createTextNode(styleString)) root.appendChild(style) meta = document.createElement("meta-data") translationFolder = configDictionary.get("translationLocation", "translations") fullTranslationPath = os.path.join(projectUrl, translationFolder) poParser = po_parser.po_file_parser(fullTranslationPath, True) bookInfo = document.createElement("book-info") if "authorList" in configDictionary.keys(): for authorE in range(len(configDictionary["authorList"])): author = document.createElement("author") authorDict = configDictionary["authorList"][authorE] if "first-name" in authorDict.keys(): authorN = document.createElement("first-name") authorN.appendChild( document.createTextNode(str(authorDict["first-name"]))) author.appendChild(authorN) if "last-name" in authorDict.keys(): authorN = document.createElement("last-name") authorN.appendChild( document.createTextNode(str(authorDict["last-name"]))) author.appendChild(authorN) if "initials" in authorDict.keys(): authorN = document.createElement("middle-name") authorN.appendChild( document.createTextNode(str(authorDict["initials"]))) author.appendChild(authorN) if "nickname" in authorDict.keys(): authorN = document.createElement("nickname") authorN.appendChild( document.createTextNode(str(authorDict["nickname"]))) author.appendChild(authorN) if "homepage" in authorDict.keys(): authorN = document.createElement("home-page") authorN.appendChild( document.createTextNode(str(authorDict["homepage"]))) author.appendChild(authorN) if "email" in authorDict.keys(): authorN = document.createElement("email") authorN.appendChild( document.createTextNode(str(authorDict["email"]))) author.appendChild(authorN) if "role" in authorDict.keys(): if str(authorDict["role"]).title() in acbfAuthorRolesList: author.setAttribute("activity", str(authorDict["role"])) if "language" in authorDict.keys(): author.setAttribute( "lang", str(authorDict["language"]).replace("_", "-")) bookInfo.appendChild(author) bookTitle = document.createElement("book-title") if "title" in configDictionary.keys(): bookTitle.appendChild( document.createTextNode(str(configDictionary["title"]))) else: bookTitle.appendChild( document.createTextNode(str("Comic with no Name"))) bookInfo.appendChild(bookTitle) extraGenres = [] if "genre" in configDictionary.keys(): genreListConf = configDictionary["genre"] if isinstance(configDictionary["genre"], dict): genreListConf = configDictionary["genre"].keys() for genre in genreListConf: genreModified = str(genre).lower() genreModified.replace(" ", "_") if genreModified in acbfGenreList: bookGenre = document.createElement("genre") bookGenre.appendChild( document.createTextNode(str(genreModified))) if isinstance(configDictionary["genre"], dict): genreMatch = configDictionary["genre"][genreModified] if genreMatch > 0: bookGenre.setAttribute("match", str(genreMatch)) bookInfo.appendChild(bookGenre) else: extraGenres.append(genre) if "characters" in configDictionary.keys(): character = document.createElement("characters") for name in configDictionary["characters"]: char = document.createElement("name") char.appendChild(document.createTextNode(str(name))) character.appendChild(char) bookInfo.appendChild(character) annotation = document.createElement("annotation") if "summary" in configDictionary.keys(): paragraphList = str(configDictionary["summary"]).split("\n") for para in paragraphList: p = document.createElement("p") p.appendChild(document.createTextNode(str(para))) annotation.appendChild(p) else: p = document.createElement("p") p.appendChild( document.createTextNode( str("There was no summary upon generation of this file."))) annotation.appendChild(p) bookInfo.appendChild(annotation) keywords = document.createElement("keywords") stringKeywordsList = [] for key in extraGenres: stringKeywordsList.append(str(key)) if "otherKeywords" in configDictionary.keys(): for key in configDictionary["otherKeywords"]: stringKeywordsList.append(str(key)) if "format" in configDictionary.keys(): for key in configDictionary["format"]: stringKeywordsList.append(str(key)) keywords.appendChild(document.createTextNode( ", ".join(stringKeywordsList))) bookInfo.appendChild(keywords) coverpageurl = "" coverpage = document.createElement("coverpage") if "pages" in configDictionary.keys(): if "cover" in configDictionary.keys(): pageList = [] pageList = configDictionary["pages"] coverNumber = max([pageList.index(configDictionary["cover"]), 0]) image = document.createElement("image") if len(pagesLocationList) >= coverNumber: coverpageurl = pagesLocationList[coverNumber] image.setAttribute("href", os.path.basename(coverpageurl)) coverpage.appendChild(image) bookInfo.appendChild(coverpage) if "language" in configDictionary.keys(): language = document.createElement("languages") textlayer = document.createElement("text-layer") textlayer.setAttribute( "lang", str(configDictionary["language"]).replace("_", "-")) textlayer.setAttribute("show", "false") textlayerNative = document.createElement("text-layer") textlayerNative.setAttribute( "lang", str(configDictionary["language"]).replace("_", "-")) textlayerNative.setAttribute("show", "true") language.appendChild(textlayer) language.appendChild(textlayerNative) translationComments = {} for lang in poParser.get_translation_list(): textlayer = document.createElement("text-layer") textlayer.setAttribute("lang", lang) textlayer.setAttribute("show", "true") language.appendChild(textlayer) translationComments[lang] = [] translation = poParser.get_entry_for_key( "@meta-title " + configDictionary["title"], lang).get("trans", None) if translation is not None: bookTitleTr = document.createElement("book-title") bookTitleTr.setAttribute("lang", lang) bookTitleTr.appendChild(document.createTextNode(translation)) bookInfo.insertAfter(bookTitleTr, bookTitle) translation = poParser.get_entry_for_key( "@meta-summary " + configDictionary["summary"], lang).get("trans", None) if translation is not None: annotationTr = document.createElement("annotation") annotationTr.setAttribute("lang", lang) paragraph = document.createElement("p") paragraph.appendChild(document.createTextNode(translation)) annotationTr.appendChild(paragraph) bookInfo.insertAfter(annotationTr, annotation) translation = poParser.get_entry_for_key( "@meta-keywords " + ", ".join(configDictionary["otherKeywords"]), lang).get("trans", None) if translation is not None: keywordsTr = document.createElement("keywords") keywordsTr.setAttribute("lang", lang) keywordsTr.appendChild(document.createTextNode(translation)) bookInfo.insertAfter(keywordsTr, keywords) bookInfo.appendChild(language) bookTitle.setAttribute( "lang", str(configDictionary["language"]).replace("_", "-")) annotation.setAttribute( "lang", str(configDictionary["language"]).replace("_", "-")) keywords.setAttribute( "lang", str(configDictionary["language"]).replace("_", "-")) if "databaseReference" in configDictionary.keys(): database = document.createElement("databaseref") dbRef = configDictionary["databaseReference"] database.setAttribute("dbname", dbRef.get("name", "")) if "type" in dbRef.keys(): database.setAttribute("type", dbRef["type"]) database.appendChild(document.createTextNode(dbRef.get("entry", ""))) bookInfo.appendChild(database) if "seriesName" in configDictionary.keys(): sequence = document.createElement("sequence") sequence.setAttribute("title", configDictionary["seriesName"]) if "seriesVolume" in configDictionary.keys(): sequence.setAttribute("volume", str(configDictionary["seriesVolume"])) if "seriesNumber" in configDictionary.keys(): sequence.appendChild( document.createTextNode(str(configDictionary["seriesNumber"]))) else: sequence.appendChild(document.createTextNode(str(0))) bookInfo.appendChild(sequence) contentrating = document.createElement("content-rating") if "rating" in configDictionary.keys(): contentrating.appendChild( document.createTextNode(str(configDictionary["rating"]))) else: contentrating.appendChild(document.createTextNode(str("Unrated."))) if "ratingSystem" in configDictionary.keys(): contentrating.setAttribute("type", configDictionary["ratingSystem"]) bookInfo.appendChild(contentrating) if "readingDirection" in configDictionary.keys(): readingDirection = document.createElement("reading-direction") if configDictionary["readingDirection"] == "rightToLeft": readingDirection.appendChild(document.createTextNode(str("RTL"))) else: readingDirection.appendChild(document.createTextNode(str("LTR"))) bookInfo.appendChild(readingDirection) meta.appendChild(bookInfo) publisherInfo = document.createElement("publish-info") if "publisherName" in configDictionary.keys(): publisherName = document.createElement("publisher") publisherName.appendChild( document.createTextNode(str(configDictionary["publisherName"]))) publisherInfo.appendChild(publisherName) if "publishingDate" in configDictionary.keys(): publishingDate = document.createElement("publish-date") publishingDate.setAttribute("value", configDictionary["publishingDate"]) publishingDate.appendChild( document.createTextNode( QDate.fromString(configDictionary["publishingDate"], Qt.ISODate).toString( Qt.SystemLocaleLongDate))) publisherInfo.appendChild(publishingDate) if "publisherCity" in configDictionary.keys(): publishCity = document.createElement("city") publishCity.appendChild( document.createTextNode(str(configDictionary["publisherCity"]))) publisherInfo.appendChild(publishCity) if "isbn-number" in configDictionary.keys(): publishISBN = document.createElement("isbn") publishISBN.appendChild( document.createTextNode(str(configDictionary["isbn-number"]))) publisherInfo.appendChild(publishISBN) license = str(configDictionary.get("license", "")) if license.isspace() is False and len(license) > 0: publishLicense = document.createElement("license") publishLicense.appendChild(document.createTextNode(license)) publisherInfo.appendChild(publishLicense) meta.appendChild(publisherInfo) documentInfo = document.createElement("document-info") # TODO: ACBF apparently uses first/middle/last/nick/email/homepage for the document author too... # The following code compensates for me not understanding this initially. if "acbfAuthor" in configDictionary.keys(): if isinstance(configDictionary["acbfAuthor"], list): for e in configDictionary["acbfAuthor"]: acbfAuthor = document.createElement("author") authorDict = e if "first-name" in authorDict.keys(): authorN = document.createElement("first-name") authorN.appendChild( document.createTextNode(str(authorDict["first-name"]))) acbfAuthor.appendChild(authorN) if "last-name" in authorDict.keys(): authorN = document.createElement("last-name") authorN.appendChild( document.createTextNode(str(authorDict["last-name"]))) acbfAuthor.appendChild(authorN) if "initials" in authorDict.keys(): authorN = document.createElement("middle-name") authorN.appendChild( document.createTextNode(str(authorDict["initials"]))) acbfAuthor.appendChild(authorN) if "nickname" in authorDict.keys(): authorN = document.createElement("nickname") authorN.appendChild( document.createTextNode(str(authorDict["nickname"]))) acbfAuthor.appendChild(authorN) if "homepage" in authorDict.keys(): authorN = document.createElement("home-page") authorN.appendChild( document.createTextNode(str(authorDict["homepage"]))) acbfAuthor.appendChild(authorN) if "email" in authorDict.keys(): authorN = document.createElement("email") authorN.appendChild( document.createTextNode(str(authorDict["email"]))) acbfAuthor.appendChild(authorN) if "language" in authorDict.keys(): acbfAuthor.setAttribute( "lang", str(authorDict["language"]).replace("_", "-")) documentInfo.appendChild(acbfAuthor) else: acbfAuthor = document.createElement("author") acbfAuthorNick = document.createElement("nickname") acbfAuthorNick.appendChild( document.createTextNode(str(configDictionary["acbfAuthor"]))) acbfAuthor.appendChild(acbfAuthorNick) documentInfo.appendChild(acbfAuthor) else: acbfAuthor = document.createElement("author") acbfAuthorNick = document.createElement("nickname") acbfAuthorNick.appendChild(document.createTextNode(str("Anon"))) acbfAuthor.appendChild(acbfAuthorNick) documentInfo.appendChild(acbfAuthor) acbfDate = document.createElement("creation-date") now = QDate.currentDate() acbfDate.setAttribute("value", now.toString(Qt.ISODate)) acbfDate.appendChild( document.createTextNode(str(now.toString(Qt.SystemLocaleLongDate)))) documentInfo.appendChild(acbfDate) if "acbfSource" in configDictionary.keys(): acbfSource = document.createElement("source") acbfSourceP = document.createElement("p") acbfSourceP.appendChild( document.createTextNode(str(configDictionary["acbfSource"]))) acbfSource.appendChild(acbfSourceP) documentInfo.appendChild(acbfSource) if "acbfID" in configDictionary.keys(): acbfID = document.createElement("id") acbfID.appendChild( document.createTextNode(str(configDictionary["acbfID"]))) documentInfo.appendChild(acbfID) if "acbfVersion" in configDictionary.keys(): acbfVersion = document.createElement("version") acbfVersion.appendChild( document.createTextNode(str(configDictionary["acbfVersion"]))) documentInfo.appendChild(acbfVersion) if "acbfHistory" in configDictionary.keys(): if len(configDictionary["acbfHistory"]) > 0: acbfHistory = document.createElement("history") for h in configDictionary["acbfHistory"]: p = document.createElement("p") p.appendChild(document.createTextNode(str(h))) acbfHistory.appendChild(p) documentInfo.appendChild(acbfHistory) meta.appendChild(documentInfo) root.appendChild(meta) body = document.createElement("body") references = document.createElement("references") def figure_out_type(svg=QDomElement()): type = None skipList = ["speech", "emphasis", "strong", "inverted", "general"] if svg.attribute("text-anchor") == "middle" or svg.attribute( "text-align") == "center": if "acbfStyles" in configDictionary.keys(): stylesDictionary = configDictionary.get("acbfStyles", {}) for key in stylesDictionary.keys(): if key not in skipList: style = stylesDictionary.get(key, {}) font = style.get("font", "") if isinstance(fonts, list): if svg.attribute("family") in font: type = key elif svg.attribute("family") == font: type = key else: type = None elif svg.attribute("text-align") == "justified": type = "formal" else: type = "commentary" inverted = None #Figure out whether this is inverted colored text. if svg.hasAttribute("fill"): stylesDictionary = configDictionary.get("acbfStyles", {}) key = stylesDictionary.get("general", {}) regular = QColor(key.get("color", "#000000")) key = stylesDictionary.get("inverted", {}) invertedColor = QColor(key.get("color", "#FFFFFF")) textColor = QColor(svg.attribute("fill")) # Proceed to get luma for the three colors. lightnessR = (0.21 * regular.redF()) + ( 0.72 * regular.greenF()) + (0.07 * regular.blueF()) lightnessI = (0.21 * invertedColor.redF()) + ( 0.72 * invertedColor.greenF()) + (0.07 * invertedColor.blueF()) lightnessT = (0.21 * textColor.redF()) + ( 0.72 * textColor.greenF()) + (0.07 * textColor.blueF()) if lightnessI > lightnessR: if lightnessT > (lightnessI + lightnessR) * 0.5: inverted = "true" else: if lightnessT < (lightnessI + lightnessR) * 0.5: inverted = "true" return [type, inverted] listOfPageColors = [] for p in range(0, len(pagesLocationList)): page = pagesLocationList[p] imageFile = QImage() imageFile.load(page) imageRect = imageFile.rect().adjusted(0, 0, -1, -1) pageColor = findDominantColor([ imageFile.pixelColor(imageRect.topLeft()), imageFile.pixelColor(imageRect.topRight()), imageFile.pixelColor(imageRect.bottomRight()), imageFile.pixelColor(imageRect.bottomLeft()) ]) listOfPageColors.append(pageColor) language = "en" if "language" in configDictionary.keys(): language = str(configDictionary["language"]).replace("_", "-") textLayer = document.createElement("text-layer") textLayer.setAttribute("lang", language) data = pageData[p] transform = data["transform"] frameList = [] listOfTextColors = [] for v in data["vector"]: boundingBoxText = [] listOfBoundaryColors = [] for point in v["boundingBox"]: offset = QPointF(transform["offsetX"], transform["offsetY"]) pixelPoint = QPointF(point.x() * transform["resDiff"], point.y() * transform["resDiff"]) newPoint = pixelPoint - offset x = max( 0, min(imageRect.width(), int(newPoint.x() * transform["scaleWidth"]))) y = max( 0, min(imageRect.height(), int(newPoint.y() * transform["scaleHeight"]))) listOfBoundaryColors.append(imageFile.pixelColor(x, y)) pointText = str(x) + "," + str(y) boundingBoxText.append(pointText) mainColor = findDominantColor(listOfBoundaryColors) if "text" in v.keys(): textArea = document.createElement("text-area") textArea.setAttribute("points", " ".join(boundingBoxText)) # TODO: Rotate will require proper global transform api as transform info is not written intotext. #textArea.setAttribute("text-rotation", str(v["rotate"])) svg = QDomDocument() svg.setContent(v["text"]) figureOut = figure_out_type(svg.documentElement()) type = figureOut[0] inverted = figureOut[1] paragraph = QDomDocument() paragraph.appendChild(paragraph.createElement("p")) parseTextChildren(paragraph, svg.documentElement(), paragraph.documentElement(), emphasisStyle, strongStyle) textArea.appendChild(paragraph.documentElement()) textArea.setAttribute("bgcolor", mainColor.name()) if type is not None: textArea.setAttribute("type", type) if inverted is not None: textArea.setAttribute("inverted", inverted) textLayer.appendChild(textArea) else: f = {} f["points"] = " ".join(boundingBoxText) frameList.append(f) listOfTextColors.append(mainColor) textLayer.setAttribute("bgcolor", findDominantColor(listOfTextColors).name()) textLayerList = document.createElement("trlist") for lang in poParser.get_translation_list(): textLayerTr = document.createElement("text-layer") textLayerTr.setAttribute("lang", lang) for i in range(len(data["vector"])): d = data["vector"] v = d[i] boundingBoxText = [] for point in v["boundingBox"]: offset = QPointF(transform["offsetX"], transform["offsetY"]) pixelPoint = QPointF(point.x() * transform["resDiff"], point.y() * transform["resDiff"]) newPoint = pixelPoint - offset x = int(newPoint.x() * transform["scaleWidth"]) y = int(newPoint.y() * transform["scaleHeight"]) pointText = str(x) + "," + str(y) boundingBoxText.append(pointText) if "text" in v.keys(): textArea = document.createElement("text-area") textArea.setAttribute("points", " ".join(boundingBoxText)) # TODO: Rotate will require proper global transform api as transform info is not written intotext. #textArea.setAttribute("text-rotation", str(v["rotate"])) svg = QDomDocument() svg.setContent(v["text"]) figureOut = figure_out_type(svg.documentElement()) type = figureOut[0] inverted = figureOut[1] string = re.sub("\<\/*?text.*?\>", '', str(v["text"])) string = re.sub("\s+?", " ", string) translationEntry = poParser.get_entry_for_key(string, lang) string = translationEntry.get("trans", string) svg.setContent("<text>" + string + "</text>") paragraph = QDomDocument() paragraph.appendChild(paragraph.createElement("p")) parseTextChildren(paragraph, svg.documentElement(), paragraph.documentElement(), emphasisStyle, strongStyle) if "translComment" in translationEntry.keys(): key = translationEntry["translComment"] listOfComments = [] listOfComments = translationComments[lang] index = 0 if key in listOfComments: index = listOfComments.index(key) + 1 else: listOfComments.append(key) index = len(listOfComments) translationComments[lang] = listOfComments refID = "-".join(["tn", lang, str(index)]) anchor = document.createElement("a") anchor.setAttribute("href", "#" + refID) anchor.appendChild(document.createTextNode("*")) paragraph.documentElement().appendChild(anchor) textArea.appendChild(paragraph.documentElement()) textLayerTr.appendChild(textArea) if type is not None: textArea.setAttribute("type", type) if inverted is not None: textArea.setAttribute("inverted", inverted) textArea.setAttribute("bgcolor", listOfTextColors[i].name()) if textLayerTr.hasChildNodes(): textLayerTr.setAttribute( "bgcolor", findDominantColor(listOfTextColors).name()) textLayerList.appendChild(textLayerTr) if page is not coverpageurl: pg = document.createElement("page") image = document.createElement("image") image.setAttribute("href", os.path.basename(page)) pg.appendChild(image) if "acbf_title" in data["keys"]: title = document.createElement("title") title.setAttribute("lang", language) title.appendChild(document.createTextNode(str(data["title"]))) pg.appendChild(title) for lang in poParser.get_translation_list(): titleTrans = " " titlekey = "@page-title " + str(data["title"]) translationEntry = poParser.get_entry_for_key( titlekey, lang) titleTrans = translationEntry.get("trans", titleTrans) if titleTrans.isspace() is False: titleT = document.createElement("title") titleT.setAttribute("lang", lang) titleT.appendChild(document.createTextNode(titleTrans)) pg.appendChild(titleT) if "acbf_none" in data["keys"]: pg.setAttribute("transition", "none") if "acbf_blend" in data["keys"]: pg.setAttribute("transition", "blend") if "acbf_fade" in data["keys"]: pg.setAttribute("transition", "fade") if "acbf_horizontal" in data["keys"]: pg.setAttribute("transition", "scroll_right") if "acbf_vertical" in data["keys"]: pg.setAttribute("transition", "scroll_down") if textLayer.hasChildNodes(): pg.appendChild(textLayer) pg.setAttribute("bgcolor", pageColor.name()) for n in range(0, textLayerList.childNodes().size()): node = textLayerList.childNodes().at(n) pg.appendChild(node) for f in frameList: frame = document.createElement("frame") frame.setAttribute("points", f["points"]) pg.appendChild(frame) body.appendChild(pg) else: for f in frameList: frame = document.createElement("frame") frame.setAttribute("points", f["points"]) coverpage.appendChild(frame) coverpage.appendChild(textLayer) for n in range(0, textLayerList.childNodes().size()): node = textLayerList.childNodes().at(n) coverpage.appendChild(node) bodyColor = findDominantColor(listOfPageColors) body.setAttribute("bgcolor", bodyColor.name()) if configDictionary.get("includeTranslComment", False): for lang in translationComments.keys(): for key in translationComments[lang]: index = translationComments[lang].index(key) + 1 refID = "-".join(["tn", lang, str(index)]) ref = document.createElement("reference") ref.setAttribute("lang", lang) ref.setAttribute("id", refID) transHeaderStr = configDictionary.get("translatorHeader", "Translator's Notes") transHeaderStr = poParser.get_entry_for_key( "@meta-translator " + transHeaderStr, lang).get("trans", transHeaderStr) translatorHeader = document.createElement("p") translatorHeader.appendChild( document.createTextNode(transHeaderStr + ":")) ref.appendChild(translatorHeader) refPara = document.createElement("p") refPara.appendChild(document.createTextNode(key)) ref.appendChild(refPara) references.appendChild(ref) root.appendChild(body) if references.childNodes().size(): root.appendChild(references) f = open(locationBasic, 'w', newline="", encoding="utf-8") f.write(document.toString(indent=2)) f.close() success = True success = createStandAloneACBF(configDictionary, document, locationStandAlone, pagesLocationList) return success
(7, 7560, 7830, 7540, 7800, 7584), ) app = QApplication(sys.argv) # series = QCandlestickSeries() series.setDecreasingColor(Qt.red) series.setIncreasingColor(Qt.green) ma5 = qc.QLineSeries() # 5-days average data line tm = [] # stores str type data # in a loop, series and ma5 append corresponding data for num, o, h, l, c, m in data: series.append(QCandlestickSet(o, h, l, c)) ma5.append(QPointF(num, m)) tm.append(str(num)) chart = QChart() chart.addSeries(series) # candle chart.addSeries(ma5) # ma5 line chart.setAnimationOptions(QChart.SeriesAnimations) chart.createDefaultAxes() chart.legend().hide() chart.axisX(series).setCategories(tm) chart.axisX(ma5).setVisible(False) chartview = QChartView(chart)
class ScaleTextItem(QGraphicsItem): HEIGHT = 40 WIDTH = 13 * HEIGHT FONT_SIZE = 20 FONT_FAMILY = 'Helvetica' FONT = QFont(FONT_FAMILY, FONT_SIZE) BOUNDING_RECT = QRectF(QPointF(-WIDTH / 2, -HEIGHT / 2), QPointF(WIDTH / 2, HEIGHT / 2)) ################################################################################ def __init__(self, parent=None): super().__init__(parent) self._rects = [ QRectF( QPointF(-self.WIDTH / 2 + (i * self.HEIGHT), -self.HEIGHT / 2), QPointF(-self.WIDTH / 2 + (i + 1) * self.HEIGHT, self.HEIGHT / 2)) for i in range(13) ] self._scale = None self._notes = None ################################################################################ def setScale(self, scale): """ """ self._scale = scale.split() if any(['#' in note for note in scale]) and all( ['b' not in note for note in self._scale]): notes = NOTES_SHARP.split() elif any(['b' in note for note in scale]) and all( ['#' not in note for note in self._scale]): notes = NOTES_FLAT.split() else: notes = NOTES_SHARP.split() self._notes = notes[notes.index( self._scale[0]):] + notes[:notes.index(self._scale[0]) + 1] self.update() ################################################################################ def paint(self, painter, option, widget): """ """ painter.setFont(self.FONT) for i in range(len(self._notes)): note = self._notes[i] if note in self._scale: painter.setPen(Qt.green) else: painter.setPen(Qt.darkRed) painter.drawText(self._rects[i], Qt.AlignCenter, note) ################################################################################ def boundingRect(self): """ """ return self.BOUNDING_RECT ################################################################################
from PyQt5.QtCore import QPropertyAnimation, pyqtProperty from PyQt5.QtGui import QBrush, QPen, QPainterPath, QColor, QPolygonF from PyQt5.QtGui import QRadialGradient, QTransform # from PyQt5.QtWidgets import QGraphicsItem from PyQt5.QtWidgets import QGraphicsRectItem from PyQt5.QtWidgets import QGraphicsLineItem, QGraphicsPathItem from PyQt5.QtWidgets import QGraphicsEllipseItem from cadnano.gui.palette import getColorObj, getBrushObj from cadnano.gui.palette import getPenObj, getNoPen # from cadnano import util from . import slicestyles as styles PXI_PP_ITEM_WIDTH = IW = 2.0 # 1.5 TRIANGLE = QPolygonF() TRIANGLE.append(QPointF(0, 0)) TRIANGLE.append(QPointF(0.75*IW, 0.5*IW)) TRIANGLE.append(QPointF(0, IW)) TRIANGLE.append(QPointF(0, 0)) # TRIANGLE.translate(-0.75*IW, -0.5*IW) TRIANGLE.translate(-0.25*IW, -0.5*IW) PXI_RECT = QRectF(0, 0, IW, IW) T90, T270 = QTransform(), QTransform() T90.rotate(90) T270.rotate(270) FWDPXI_PP, REVPXI_PP = QPainterPath(), QPainterPath() FWDPXI_PP.addPolygon(T90.map(TRIANGLE)) REVPXI_PP.addPolygon(T270.map(TRIANGLE)) # FWDPXI_PP.moveTo(-0.5*IW, 0.7*IW)
_rect = QRectF(0, 0, _BASE_WIDTH, _BASE_WIDTH) _blankRect = QRectF(0, 0, 2 * _BASE_WIDTH, _BASE_WIDTH) PPL5 = QPainterPath() # Left 5' PainterPath PPR5 = QPainterPath() # Right 5' PainterPath PPL3 = QPainterPath() # Left 3' PainterPath PPR3 = QPainterPath() # Right 3' PainterPath # set up PPL5 (left 5' blue square) PPL5.addRect(0.25 * _BASE_WIDTH, 0.125 * _BASE_WIDTH, 0.75 * _BASE_WIDTH, 0.75 * _BASE_WIDTH) # set up PPR5 (right 5' blue square) PPR5.addRect(0, 0.125 * _BASE_WIDTH, 0.75 * _BASE_WIDTH, 0.75 * _BASE_WIDTH) # set up PPL3 (left 3' blue triangle) L3_POLY = QPolygonF() L3_POLY.append(QPointF(_BASE_WIDTH, 0)) L3_POLY.append(QPointF(0.25 * _BASE_WIDTH, 0.5 * _BASE_WIDTH)) L3_POLY.append(QPointF(_BASE_WIDTH, _BASE_WIDTH)) PPL3.addPolygon(L3_POLY) # set up PPR3 (right 3' blue triangle) R3_POLY = QPolygonF() R3_POLY.append(QPointF(0, 0)) R3_POLY.append(QPointF(0.75 * _BASE_WIDTH, 0.5 * _BASE_WIDTH)) R3_POLY.append(QPointF(0, _BASE_WIDTH)) PPR3.addPolygon(R3_POLY) class ForcedXoverNode3(QGraphicsRectItem): """ This is a QGraphicsRectItem to allow actions and also a QGraphicsSimpleTextItem to allow a label to be drawn
def boundRectToModel(self): """update the boundaries to what's in the model with a minimum size """ xTL, yTL, xBR, yBR = self.getModelMinBounds() self._rect = QRectF(QPointF(xTL, yTL), QPointF(xBR, yBR))
def turnRect(self, rect, angle): p1 = self.turnPoint(rect.topLeft(), angle) p2 = self.turnPoint(rect.bottomRight(), angle) topLeft = QPointF(min(p1.x(), p2.x()), min(p1.y(), p2.y())) bottomRight = QPointF(max(p1.x(), p2.x()), max(p1.y(), p2.y())) return QRectF(topLeft, bottomRight)
def __init__(self, entity, pos, scene): self.entity_width = 180 self.entity_height = 80 self.entity_pen = QPen(Qt.black, 5, Qt.SolidLine) self.entity_brush = QBrush(Qt.green, Qt.SolidPattern) self.attribute_width = 90 self.attribute_height = 50 self.attribute_pen = QPen(Qt.black, 3, Qt.SolidLine) self.attribute_brush = QBrush(Qt.blue, Qt.Dense6Pattern) self.at_connection_pen = QPen(Qt.black, 3, Qt.SolidLine) self.entity = entity self.no_atr = len(self.entity.attr_list) self.inter_atr_margin = 15 self.min_height = -50 self.container_width = self.entity_width + self.attribute_width self.container_height = -1 * self.min_height * self.no_atr + self.attribute_height self.en_shape = scene.addRect( QRectF(0, 0, self.entity_width, self.entity_height), self.entity_pen, self.entity_brush) self.txt_style = ''' QWidget{border:3px dashed black;padding-bottom:5px;} ''' self.txt_en_geometry = QRectF(0.0, 0.0, self.entity_width / 2, self.entity_height / 2) self.txt_atr_geometry = QRectF(0.0, 0.0, self.attribute_width / 2, self.attribute_height / 2) self.txt_atr_child_geometry = QRectF(0.0, 0.0, self.attribute_width / 2, self.attribute_height / 2) self.txt_atr_pos = QPointF(self.attribute_width / 4, self.attribute_height / 4) self.txt_en_pos = QPointF(self.entity_width / 4, self.entity_height / 4) self.en_txt = scene.addWidget(QLineEdit()) self.en_txt.setParentItem(self.en_shape) self.en_txt.setGeometry(self.txt_en_geometry) self.en_txt.widget().setStyleSheet(self.txt_style) self.en_txt.widget().setText(self.entity.name) self.en_txt.setPos(self.txt_en_pos) self.en_txt.widget().editingFinished.connect( lambda: ContainerItem.trial(self, -1, self.en_txt.widget(), 0)) self.scene = scene self.en_shape.setPos(pos) self.con_list = [] self.atr_shape_list = [] self.atr_txt_list = [] self.rel_orgn = QPointF(0, self.entity_height) self.orgn_step = 15 self.id = 0 if (self.no_atr > 1): self.atr_step = self.entity_width / (self.no_atr - 1) if (2 * self.atr_step < self.attribute_width): self.attribute_width = 2 * self.atr_step - self.inter_atr_margin self.txt_atr_geometry = QRectF(0.0, 0.0, self.attribute_width / 2, self.attribute_height / 2) for i in range(0, self.no_atr): self.attach_attribute( QLineF(self.atr_step * i, 0, self.atr_step * i, self.min_height - i * self.attribute_height), self.entity.attr_list[i].name, i, self.entity.attr_list[i].type, self.en_shape, self.attribute_width, self.attribute_height, self.txt_atr_geometry, -1) if (self.entity.attr_list[i].isComposite): no_child = len(self.entity.attr_list[i].attrib_childs) if (no_child > 1): ch_step = self.attribute_width / ( len(self.entity.attr_list[0].attrib_childs) - 1) else: ch_step = self.attribute_width par_x = self.atr_step * i - self.attribute_width / 2 par_y = self.min_height - i * self.attribute_height - self.attribute_height for j in range(0, no_child): self.attach_attribute( QLineF( par_x + (ch_step) * j, self.get_y_elipse( par_x + (ch_step) * j, par_x + self.attribute_width / 2, par_y + self.attribute_height / 2), par_x + ch_step * j, par_y + self.min_height / 2 - j * self.attribute_height * 0.75), self.entity.attr_list[i].attrib_childs[j].name, i, self.entity.attr_list[i].attrib_childs[j].type, self.en_shape, self.attribute_width * 0.75, self.attribute_height * 0.75, self.txt_atr_child_geometry, j) child_height = -1 * par_y - 1 * self.min_height + no_child * 0.75 * self.attribute_height if (child_height > self.container_height): self.container_height = child_height elif (self.no_atr == 1): self.attach_attribute(QLineF(0, 0, 0, self.min_height), self.entity.attr_list[0].name, 0, 'prime', self.en_shape, self.attribute_width, self.attribute_height, self.txt_atr_geometry, -1) if (self.entity.attr_list[0].isComposite): no_child = len(self.entity.attr_list[0].attrib_childs) if (no_child > 1): ch_step = self.attribute_width / ( len(self.entity.attr_list[0].attrib_childs) - 1) else: ch_step = self.attribute_width par_x = 0 - self.attribute_width / 2 par_y = 0 + self.min_height - self.attribute_height for j in range(0, no_child): self.attach_attribute( QLineF( par_x + (ch_step) * j, self.get_y_elipse( par_x + (ch_step) * j, 0, self.min_height - self.attribute_height / 2), par_x + ch_step * j, par_y + self.min_height / 2 - j * self.attribute_height * 0.75), self.entity.attr_list[0].attrib_childs[j].name, 0, self.entity.attr_list[0].attrib_childs[j].type, self.en_shape, self.attribute_width * 0.75, self.attribute_height * 0.75, self.txt_atr_child_geometry, j) self.id += 1 self.container_height += self.attribute_height / 2 + -1 * self.min_height / 2 - j * self.attribute_height / 2 + 10 child_height = -1 * par_y - 1 * self.min_height + no_child * 0.75 * self.attribute_height if (child_height > self.container_height): self.container_height = child_height
def add_relation(self, x, r): if (len(r.attrib_list) != 0): self.level += self.rel_height / 2 + self.r_atr_h * ( len(r.attrib_list) - 1) + self.r_atr_line Qpoints = [ QPointF(x, self.level), QPointF(x + self.rel_width / 2, self.level + self.rel_height / 2), QPointF(x + self.rel_width, self.level), QPointF(x + self.rel_width / 2, self.level - self.rel_height / 2) ] rel_shape = self.scene.addPolygon(QPolygonF(Qpoints), self.rel_pen, self.rel_Brush) rel_name = self.scene.addWidget(QLineEdit()) left_p = self.scene.addWidget(QLineEdit()) right_p = self.scene.addWidget(QLineEdit()) #rel_name.setParentItem(rel_shape) rel_name.setGeometry(QRectF(0, 0, self.rel_width / 2, 3)) left_p.setGeometry(QRectF(0, 0, 0, 0)) right_p.setGeometry(QRectF(0, 0, 0, 0)) left_p.widget().setFixedWidth(43) right_p.widget().setFixedWidth(43) rel_name.setPos(x + self.rel_width / 4, self.level - rel_name.widget().height() / 2) left_p.setPos(x - left_p.widget().width(), self.level - left_p.widget().height()) right_p.setPos(x + self.rel_width, self.level - right_p.widget().height()) rel_name.widget().setText(r.name) left_p.widget().setText(r.p_ratio1) right_p.widget().setText(r.p_ratio2) rel_name.widget().editingFinished.connect( partial(self.mod, "n", r, rel_name.widget())) left_p.widget().editingFinished.connect( partial(self.mod, "l", r, left_p.widget())) right_p.widget().editingFinished.connect( partial(self.mod, "r", r, right_p.widget())) atr_step = ((self.rel_width - 2 * right_p.widget().width() - 10) / (len(r.attrib_list) - 1)) if len(r.attrib_list) > 1 else 0 ten = (Qpoints[0].y() - Qpoints[3].y()) / (Qpoints[0].x() - Qpoints[3].x()) for i in range(len(r.attrib_list)): first_pt = QPointF( Qpoints[0].x() + i * atr_step + right_p.widget().width() + 10, self.get_y_line( Qpoints[0].x() + i * atr_step + right_p.widget().width() + 10, Qpoints[0], ten)) if (first_pt.x() > Qpoints[3].x()): first_pt.setY( self.get_y_line(first_pt.x(), Qpoints[3], -1 * ten)) atr_line = self.scene.addLine( first_pt.x(), first_pt.y(), first_pt.x(), Qpoints[3].y() - self.r_atr_line - i * self.r_atr_h) elip_pt = QPointF(first_pt.x() - self.r_atr_w / 2, atr_line.line().y2() - self.r_atr_h) atr_elipse = self.scene.addEllipse( QRectF(0, 0, self.r_atr_w, self.r_atr_h), self.rel_pen, self.rel_Brush) txt = [] txt.append(self.scene.addWidget(QLineEdit(r.attrib_list[i].name))) atr_elipse.setPos(elip_pt) txt[-1].setPos(elip_pt.x() + self.rel_width * 0.25, elip_pt.y() + self.r_atr_h * 0.125) txt[-1].widget().setFixedWidth(self.r_atr_w * 0.5) txt[-1].widget().setFixedHeight(self.r_atr_h * 0.75) txt[-1].widget().editingFinished.connect( partial(self.mod, "c", r, txt[-1].widget(), i))
def mouseReleaseEvent(self, event): if not self._photo.isUnderMouse(): return if self.box_creation_mode and self.box_start_point is not None: photo_click_point = self.mapToScene(event.pos()).toPoint() polygon_coords = [ QPointF(self.box_start_point.x(), self.box_start_point.y()), QPointF(self.box_start_point.x(), photo_click_point.y()), QPointF(photo_click_point.x(), photo_click_point.y()), QPointF(photo_click_point.x(), self.box_start_point.y()) ] selection_polygon = SelectionPolygon(polygon_coords, self) self.add_selection_polygon(selection_polygon) self.scene.removeItem(self._box_graphic) self.box_creation_mode = False self.box_start_point = None self._box_graphic = None self.setDragMode(QtWidgets.QGraphicsView.ScrollHandDrag) elif self.line_selection_mode and self.start_line_select is not None: # line select self.deselect_all() photo_click_point = self.mapToScene(event.pos()).toPoint() self.scene.removeItem(self.line_graphic) for polygon in self.selection_polygons: line = [ np.array([photo_click_point.x(), photo_click_point.y()]), np.array([ self.start_line_select.x(), self.start_line_select.y() ]) ] centroid = polygon.centroid() # max node dist from centroid, used for approximations max_dist = 0.0 for point in polygon.polygon_points: # todo manhattan length is a bad approx of euclid. dist, maybe its not worth the inaccuracy dist = (point - centroid).manhattanLength() if dist > max_dist: max_dist = dist np_centroid = np.array([centroid.x(), centroid.y()]) distance_from_line = np.abs( np.cross(line[1] - line[0], line[0] - np_centroid)) / norm(line[0] - line[1]) if distance_from_line <= max_dist: min_x = min(photo_click_point.x(), self.start_line_select.x()) * .95 max_x = max(photo_click_point.x(), self.start_line_select.x()) * 1.05 min_y = min(photo_click_point.y(), self.start_line_select.y()) * .95 max_y = max(photo_click_point.y(), self.start_line_select.x()) * 1.05 if min_x < centroid.x() < max_x and min_y < centroid.y( ) < max_y: polygon.select() self.start_line_select = None self.line_graphic = None else: super(PhotoViewer, self).mouseReleaseEvent(event)
def move(self, x, y): delta = QPointF(x, y) for p in self._midPoints: p += delta
class DataModel(QGraphicsScene): WIDTH = 800 HEIGHT = 800 WALL_THICKNESS = 5 ALLOWED_AREA = QRectF(QPointF(-WIDTH / 2, -HEIGHT / 2), QPointF(WIDTH / 2, HEIGHT / 2)) START_POINT = QPointF(0, HEIGHT / 2 - 20) GOAL_POINT = QPointF(0, -HEIGHT / 2 + 20) GOAL_TOLERANCE = 50 # walls around the allowed area WALLS_SURROUNDING = [] # left WALLS_SURROUNDING.append( QRectF( QPointF(ALLOWED_AREA.left() - WALL_THICKNESS, ALLOWED_AREA.top() - WALL_THICKNESS), QPointF(ALLOWED_AREA.left(), ALLOWED_AREA.bottom() + WALL_THICKNESS))) # right WALLS_SURROUNDING.append( QRectF( QPointF(ALLOWED_AREA.right(), ALLOWED_AREA.top() - WALL_THICKNESS), QPointF(ALLOWED_AREA.right() + WALL_THICKNESS, ALLOWED_AREA.bottom() + WALL_THICKNESS))) # top WALLS_SURROUNDING.append( QRectF( QPointF(ALLOWED_AREA.left() - WALL_THICKNESS, ALLOWED_AREA.top() - WALL_THICKNESS), QPointF(ALLOWED_AREA.right() + WALL_THICKNESS, ALLOWED_AREA.top()))) # bottom WALLS_SURROUNDING.append( QRectF( QPointF(ALLOWED_AREA.left() - WALL_THICKNESS, ALLOWED_AREA.bottom()), QPointF(ALLOWED_AREA.right() + WALL_THICKNESS, ALLOWED_AREA.bottom() + WALL_THICKNESS))) # custom walls WALLS_CUSTOM = [] WALLS_CUSTOM.append( QRectF( QPointF(ALLOWED_AREA.left() - WALL_THICKNESS, HEIGHT / 4), QPointF(ALLOWED_AREA.left() + WIDTH - 100, HEIGHT / 4 + WALL_THICKNESS))) WALLS_CUSTOM.append( QRectF(QPointF(ALLOWED_AREA.left() + 100, 0), QPointF(ALLOWED_AREA.right() + WALL_THICKNESS, WALL_THICKNESS))) VISIBILITY_GRAPH = VisibilityGraph(START_POINT, GOAL_POINT, WALLS_CUSTOM + WALLS_SURROUNDING, ALLOWED_AREA) ################################################################################ def __init__(self): """ """ super().__init__() self.setSceneRect(self.ALLOWED_AREA) self._population = Population(self) self._generationCountItem = self.addSimpleText( 'gen: ' + str(self._population.generationCount)) self._generationCountItem.setPos( QPointF(-self.WIDTH / 2 + 20, -self.HEIGHT / 2 + 20)) self._wonCountItem = self.addSimpleText('won: ' + str(self._population.wonCount)) self._wonCountItem.setPos( QPointF(-self.WIDTH / 2 + 20, -self.HEIGHT / 2 + 40)) self._exhaustedCountItem = self.addSimpleText( 'exh: ' + str(self._population.exhaustedCount)) self._exhaustedCountItem.setPos( QPointF(-self.WIDTH / 2 + 20, -self.HEIGHT / 2 + 60)) self._deadCountItem = self.addSimpleText( 'ded: ' + str(self._population.deadCount)) self._deadCountItem.setPos( QPointF(-self.WIDTH / 2 + 20, -self.HEIGHT / 2 + 80)) self._population.updateCounters.connect(self._updateCounters) self._ctrlFlag = False ################################################################################ def _updateCounters(self): """ """ self._generationCountItem.setText( 'gen: ' + str(self._population.generationCount)) self._wonCountItem.setText('won: ' + str(self._population.wonCount)) self._exhaustedCountItem.setText('exh: ' + str(self._population.exhaustedCount)) self._deadCountItem.setText('ded: ' + str(self._population.deadCount)) ################################################################################ def mousePressEvent(self, event): """ """ self._population.start() super().mousePressEvent(event) ################################################################################ def keyPressEvent(self, event): """ """ key = event.key() if key == Qt.Key_Control: self._ctrlFlag = True self.update() super().keyPressEvent(event) ################################################################################ def keyReleaseEvent(self, event): """ """ key = event.key() if key == Qt.Key_Control: self._ctrlFlag = False self.update() super().keyReleaseEvent(event) ################################################################################ def drawBackground(self, painter, rect): """ """ painter.setPen(Qt.gray) painter.setBrush(Qt.gray) painter.drawRect(rect) painter.setBrush(Qt.white) painter.drawRect(self.ALLOWED_AREA) painter.setPen(Qt.blue) painter.setBrush(Qt.blue) painter.drawEllipse(self.START_POINT, 5, 5) painter.setPen(Qt.green) painter.setBrush(Qt.green) painter.drawEllipse(self.GOAL_POINT, self.GOAL_TOLERANCE, self.GOAL_TOLERANCE) painter.setPen(Qt.black) super().drawBackground(painter, rect) ################################################################################ def drawForeground(self, painter, rect): """ """ painter.setPen(QPen(Qt.red, 1, join=Qt.MiterJoin)) painter.setBrush(Qt.red) for rect in self.WALLS_SURROUNDING: painter.drawRect(rect) for rect in self.WALLS_CUSTOM: painter.drawRect(rect) if self._ctrlFlag: painter.setPen(Qt.green) for edge in self.VISIBILITY_GRAPH.shortestRouteEdges: painter.drawLine(edge) else: painter.setPen(Qt.black) for edge in self.VISIBILITY_GRAPH.edges: painter.drawLine(edge) super().drawForeground(painter, rect)
def paintEvent(self, event): ''' if self.point == 'Yes': print("DIO") self.painter = QPainter(self) #self.painter.begin(self) self.painter.setPen(QPen(Qt.red, 5)) for i in range(len(x_points)): self.painter.drawPoint(X + x_points[i],\ Y + y_points[i]) print("DIO1") self.painter.end() self.point = None ''' self.painter = QPainter(self) if (self.square and self.triangle and len(x_points) > 2): points_x = [ self.x1_circle, self.x2_circle, self.x3_circle, self.x_result_circle_centre + self.result_radius, self.x_result_circle_centre - self.result_radius ] points_y = [ self.y1_circle, self.y2_circle, self.y3_circle, self.y_result_circle_centre + self.result_radius, self.y_result_circle_centre - self.result_radius ] self.find_scale(points_x, x_triangle_points, points_y, y_triangle_points) self.painter.setPen(QPen(Qt.black, 1)) # Треугольник(основной) self.painter.drawPolygon\ (QPointF(X + self.convert_x(x_triangle_points[0]), Y + self.convert_y(y_triangle_points[0])),\ QPointF(X + self.convert_x(x_triangle_points[1]), Y + self.convert_y(y_triangle_points[1])),\ QPointF(X + self.convert_x(x_triangle_points[2]), Y + self.convert_y(y_triangle_points[2]))) # Его точки с подписями self.painter.setPen(QPen(Qt.red, 3)) self.painter.drawPoint(X + self.convert_x(x_triangle_points[0]), Y + self.convert_y(y_triangle_points[0])) self.painter.drawPoint(X + self.convert_x(x_triangle_points[1]), Y + self.convert_y(y_triangle_points[1])) self.painter.drawPoint(X + self.convert_x(x_triangle_points[2]), Y + self.convert_y(y_triangle_points[2])) self.painter.setPen(QPen(Qt.black, 3)) text = '(' + str(x_triangle_points[0]) + ', ' + str( y_triangle_points[0]) + ')' self.painter.drawText(X + self.convert_x(x_triangle_points[0]), Y + self.convert_y(y_triangle_points[0]), text) text = '(' + str(x_triangle_points[1]) + ', ' + str( y_triangle_points[1]) + ')' self.painter.drawText(X + self.convert_x(x_triangle_points[1]), Y + self.convert_y(y_triangle_points[1]), text) text = '(' + str(x_triangle_points[2]) + ', ' + str( y_triangle_points[2]) + ')' self.painter.drawText(X + self.convert_x(x_triangle_points[2]), Y + self.convert_y(y_triangle_points[2]), text) ''' #self.dot_lbl_1.move(X + x_triangle_points[0], Y + y_triangle_points[0]) self.dot_lbl_1.setGeometry(QtCore.QRect(X + self.convert_x(x_triangle_points[0]),\ Y + self.convert_y(y_triangle_points[0]), 160, 21)) text = '(' + str(x_triangle_points[0]) + ', ' + str(y_triangle_points[0]) + ')' self.dot_lbl_1.setText(text) #self.dot_lbl_2.move(X + x_triangle_points[1], Y + y_triangle_points[1]) self.dot_lbl_2.setGeometry(QtCore.QRect(X + self.convert_x(x_triangle_points[1]),\ Y + self.convert_y(y_triangle_points[1]), 160, 21)) self.dot_lbl_2.setText('(' + str(x_triangle_points[1]) + ', ' + str(y_triangle_points[1]) + ')') #self.dot_lbl_3.move(X + x_triangle_points[2], Y + y_triangle_points[2]) self.dot_lbl_3.setGeometry(QtCore.QRect(X + self.convert_x(x_triangle_points[2]),\ Y + self.convert_y(y_triangle_points[2]), 160, 21)) self.dot_lbl_3.setText('(' + str(x_triangle_points[2]) + ', ' + str(y_triangle_points[2]) + ')') ''' # Центр треугольника self.painter.setPen(QPen(Qt.red, 3)) ''' self.triangle_centre(X + self.convert_x(x_triangle_points[0]), Y + self.convert_y(y_triangle_points[0]),\ X + self.convert_x(x_triangle_points[1]), Y + self.convert_y(y_triangle_points[1]),\ X + self.convert_x(x_triangle_points[2]), Y + self.convert_y(y_triangle_points[2])) ''' self.triangle_centre(x_triangle_points[0], y_triangle_points[0],\ x_triangle_points[1], y_triangle_points[1],\ x_triangle_points[2], y_triangle_points[2]) self.painter.drawPoint(X + self.convert_x(self.x_triangle_centre), Y + self.convert_y(self.y_triangle_centre)) #self.dot_lbl_4.move(self.x_triangle_centre, self.y_triangle_centre) #self.dot_lbl_4.setText('(' + str(self.x_triangle_centre - X) + ', ' + str(self.y_triangle_centre - Y) + ')') # Окружность self.painter.setPen(QPen(Qt.black, 1)) self.painter.drawEllipse(QPointF(self.convert_x(self.x_result_circle_centre) + X,\ self.convert_y(self.y_result_circle_centre) + Y),\ self.scale * self.result_radius, self.scale * self.result_radius) self.painter.setPen(QPen(Qt.red, 3)) self.painter.drawPoint( self.convert_x(self.x1_circle) + X, self.convert_y(self.y1_circle) + Y) self.painter.drawPoint( self.convert_x(self.x2_circle) + X, self.convert_y(self.y2_circle) + Y) self.painter.drawPoint( self.convert_x(self.x3_circle) + X, self.convert_y(self.y3_circle) + Y) ''' self.dot_lbl_7.setGeometry(QtCore.QRect(X + self.convert_x(self.x1_circle), Y + self.convert_y(self.y1_circle), 160, 21)) self.dot_lbl_7.setText('(' + str(self.x1_circle) + ', ' + str(self.y1_circle) + ')') self.painter.drawPoint(self.convert_x(self.x1_circle) + X, self.convert_y(self.y1_circle) + Y) self.dot_lbl_8.setGeometry(QtCore.QRect(X + self.convert_x(self.x2_circle), Y + self.convert_y(self.y2_circle), 160, 21)) self.dot_lbl_8.setText('(' + str(self.x2_circle) + ', ' + str(self.y2_circle) + ')') self.painter.drawPoint(self.convert_x(self.x2_circle) + X, self.convert_y(self.y2_circle) + Y) self.dot_lbl_9.setGeometry(QtCore.QRect(X + self.convert_x(self.x3_circle), Y + self.convert_y(self.y3_circle), 160, 21)) self.dot_lbl_9.setText('(' + str(self.x3_circle) + ', ' + str(self.y3_circle) + ')') ''' self.painter.setPen(QPen(Qt.black, 3)) text = '(' + str(self.x1_circle) + ', ' + str(self.y1_circle) + ')' self.painter.drawText( self.convert_x(self.x1_circle) + X, self.convert_y(self.y1_circle) + Y, text) text = '(' + str(self.x2_circle) + ', ' + str(self.y2_circle) + ')' self.painter.drawText( self.convert_x(self.x2_circle) + X, self.convert_y(self.y2_circle) + Y, text) text = '(' + str(self.x3_circle) + ', ' + str(self.y3_circle) + ')' self.painter.drawText( self.convert_x(self.x3_circle) + X, self.convert_y(self.y3_circle) + Y, text) self.painter.setPen(QPen(Qt.red, 3)) # Её центр self.painter.setPen(QPen(Qt.red, 3)) self.painter.drawPoint(self.convert_x(self.x_result_circle_centre) + X, \ self.convert_y(self.y_result_circle_centre) + Y) #self.dot_lbl_5.move(self.x_result_circle_centre + X, self.y_result_circle_centre + Y) #self.dot_lbl_5.setText('(' + str(self.x_result_circle_centre) + ', ' + str(self.н_result_circle_centre) + ')') # Точка касательной self.painter.drawPoint(self.convert_x(self.x_result_tangent_point) + X,\ self.convert_y(self.y_result_tangent_point) + Y) #self.dot_lbl_6.move(self.x_result_tangent_point + X, self.y_result_tangent_point + Y) #self.dot_lbl_6.setText('(' + str(self.x_result_tangent_point) + ', ' + str(self.y_result_tangent_point) + ')') # Треугольник искомый ''' self.painter.setPen(QPen(Qt.blue, 2)) self.painter.drawLine(X + self.convert_x(self.x_triangle_centre),\ Y + self.convert_y(self.y_triangle_centre), self.convert_x(self.x_result_tangent_point) + X,\ self.convert_y(self.y_result_tangent_point) + Y) self.painter.drawLine(X + self.convert_x(self.x_triangle_centre),\ Y + self.convert_y(self.y_triangle_centre), self.convert_x(self.x_result_circle_centre) + X,\ self.convert_y(self.y_result_circle_centre) + Y) self.painter.drawLine(self.convert_x(self.x_result_tangent_point) + X,\ self.convert_y(self.y_result_tangent_point) + Y, self.convert_x(self.x_result_circle_centre) + X,\ self.convert_y(self.y_result_circle_centre) + Y) ''' self.painter.setPen(QPen(Qt.blue, 3)) brush = QBrush(Qt.SolidPattern) brush.setStyle(Qt.BDiagPattern) self.painter.setBrush(brush) self.painter.drawPolygon(QPointF(X + self.convert_x(self.x_triangle_centre),\ Y + self.convert_y(self.y_triangle_centre)),\ QPointF(self.convert_x(self.x_result_tangent_point) + X,\ self.convert_y(self.y_result_tangent_point) + Y),\ QPointF(self.convert_x(self.x_result_circle_centre) + X,\ self.convert_y(self.y_result_circle_centre) + Y)) #self.square = 0 self.update() self.painter.end()
def makeEv(delta): return QWheelEvent(QPointF(10, 10), QPointF(webView.mapToGlobal(QPoint(10, 10))), QPoint(0, 0), QPoint(0, delta), delta, Qt.Horizontal, Qt.NoButton, Qt.ControlModifier)
def __init__(self, group_id, group_name, icon, parent=None): QGraphicsItem.__init__(self) self.setParentItem(parent) # Save Variables, useful for later self.m_group_id = group_id self.m_group_name = group_name # plugin Id, < 0 if invalid self.m_plugin_id = -1 self.m_plugin_ui = False self.m_plugin_inline = self.INLINE_DISPLAY_DISABLED # Base Variables self.p_width = 50 self.p_width_in = 0 self.p_width_out = 0 self.p_height = canvas.theme.box_header_height + canvas.theme.box_header_spacing + 1 self.m_last_pos = QPointF() self.m_splitted = False self.m_splitted_mode = PORT_MODE_NULL self.m_cursor_moving = False self.m_forced_split = False self.m_mouse_down = False self.m_inline_image = None self.m_inline_scaling = 1.0 self.m_port_list_ids = [] self.m_connection_lines = [] # Set Font self.m_font_name = QFont() self.m_font_name.setFamily(canvas.theme.box_font_name) self.m_font_name.setPixelSize(canvas.theme.box_font_size) self.m_font_name.setWeight(canvas.theme.box_font_state) self.m_font_port = QFont() self.m_font_port.setFamily(canvas.theme.port_font_name) self.m_font_port.setPixelSize(canvas.theme.port_font_size) self.m_font_port.setWeight(canvas.theme.port_font_state) # Icon if canvas.theme.box_use_icon: self.icon_svg = CanvasIcon(icon, self.m_group_name, self) else: self.icon_svg = None # Shadow # FIXME FX on top of graphic items make them lose high-dpi # See https://bugreports.qt.io/browse/QTBUG-65035 # FIXME Random crashes while using Qt's drop shadow, let's just disable it if False and options.eyecandy and canvas.scene.getDevicePixelRatioF( ) == 1.0: self.shadow = CanvasBoxShadow(self.toGraphicsObject()) self.shadow.setFakeParent(self) self.setGraphicsEffect(self.shadow) else: self.shadow = None # Final touches self.setFlags(QGraphicsItem.ItemIsFocusable | QGraphicsItem.ItemIsMovable | QGraphicsItem.ItemIsSelectable) # Wait for at least 1 port if options.auto_hide_groups: self.setVisible(False) if options.auto_select_items: self.setAcceptHoverEvents(True) self.updatePositions() canvas.scene.addItem(self) QTimer.singleShot(0, self.fixPos)
def setUp(self): """ """ # --left --right # ' ' # I | II | III # ------+==========+------ --top # VIII | IX (in) | IV # ------+==========+------ --bottom # VII | VI | V self._offset = 10 self._rect = QRectF(QPointF(-20, -10), QPointF(20, 10)) self._pointI = QPointF(self._rect.left()-self._offset, self._rect.top()-self._offset) self._pointII = QPointF(self._rect.center().x(), self._rect.top()-self._offset) self._pointIII = QPointF(self._rect.right()+ self._offset, self._rect.top()- self._offset) self._pointIV = QPointF(self._rect.right()+self._offset, self._rect.center().y()) self._pointV = QPointF(self._rect.right()+self._offset, self._rect.bottom()+self._offset) self._pointVI = QPointF(self._rect.center().x(), self._rect.bottom()+self._offset) self._pointVII = QPointF(self._rect.left()-self._offset, self._rect.bottom()+self._offset) self._pointVIII = QPointF(self._rect.left()-self._offset, self._rect.center().y()) self._pointIX = self._rect.center() self._lineI_VII = QLineF(self._pointI, self._pointVII) self._lineI_V = QLineF(self._pointI, self._pointV) self._lineII = QLineF(self._pointII, QPointF(self._rect.center().x(), self._rect.top())) self._lineII_IV = QLineF(QPointF(self._rect.right()-self._offset, self._rect.top()-self._offset), QPointF(self._rect.right()+self._offset, self._rect.top()+self._offset))
# States. rootState = QState() ellipseState = QState(rootState) figure8State = QState(rootState) randomState = QState(rootState) tiledState = QState(rootState) centeredState = QState(rootState) # Values. for i, item in enumerate(items): # Ellipse. ellipseState.assignProperty( item, 'pos', QPointF( math.cos((i / 63.0) * 6.28) * 250, math.sin((i / 63.0) * 6.28) * 250)) # Figure 8. figure8State.assignProperty( item, 'pos', QPointF( math.sin((i / 63.0) * 6.28) * 250, math.sin(((i * 2) / 63.0) * 6.28) * 250)) # Random. #qrand()返回0-randMax之间的数值 qrand()%500 将随机数限制在0-499 randomState.assignProperty( item, 'pos', QPointF(-250 + qrand() % 500, -250 + qrand() % 500)) # Tiled.
def testIntersects(self): """ """ rect = QRectF(QPointF(-50, -10), QPointF(50, 10)) # line completely outside of the rectangle self.assertFalse(PathFinding.intersects(rect, QLineF(QPointF(-100, -50), QPointF(-100, 50)))) # the line is a top side of the rectangle self.assertFalse(PathFinding.intersects(rect, QLineF(rect.topLeft(), rect.topRight()))) # the line starts at the left corner of the rectangle and is not perpendicular to any of the rectangle sides; # the line ends outside of the rectangle, not going through it self.assertFalse(PathFinding.intersects(rect, QLineF(rect.topLeft(), QPointF(-100, -100)))) # the line starts at the left corner of the rectangle and is perpendicular to the top side of the rectangle; # the line ends outside of the rectangle, not going through it self.assertFalse(PathFinding.intersects(rect, QLineF(rect.topLeft(), QPointF(rect.left(), rect.top() - 100)))) # the line is horizontal and goes straight through the center of the rectangle self.assertTrue(PathFinding.intersects(rect, QLineF(QPointF(-100, 0), QPointF(100, 0)))) # the line is vertical and goes straight through the center of the rectangle self.assertTrue(PathFinding.intersects(rect, QLineF(QPointF(0, -100), QPointF(0, 100)))) # the line is vertical and goes up from the bottom right corner of the rectangle self.assertFalse(PathFinding.intersects(rect, QLineF(rect.bottomRight(), QPointF(rect.right(), rect.top()-100)))) # the line is diagonal of the rectangle self.assertTrue(PathFinding.intersects(rect, QLineF(rect.topLeft(), rect.bottomRight())))
def create_path(self, start_point, end_point, directed): """Creeaza path-ul muchiei Path-ul muchiei este o curba Bezier. In cazul in care nici-un nod nu se intersecteaza cu path-ul direct dintre noduri, punctele de control ale curbei vor fi la centrul de greutate al dreptei date de cele 2 noduri, astfel creeandu-se o linie dreapta. In caz contrar, daca un nod se intersecteaza cu path-ul direct, pucntele de control ale curbei se vor situa pe dreapta perpendiculara pe path-ul direct, ce trece centrul de greutate al acestuia (dat de punctul de control initial) la o distanta egala dublul razei nodului. Aceste pucnte se pot situa in 2 pozitii, una la 'stanga' path-ului, iar cealalta la 'dreaptea' acestuia. Pozitia finala a punctului de control se determina 'trasand' 2 linii de la nodul care se intersecteaza la cele 2 posibile puncte de control. Verificand lungimea celor 2 linii se alege locatia punctului de control. panta dreptei : m = (y2 - y1) / (x2 - x1) ecuatia dreptei : y - y1 = m(x - x1) panta drepntei perpendiculare pe o dreapta : m' = -1 / m lungimea unei drepte : AB ^ 2 = (x2 - x1) ^ 2 + (y2 - y1) ^ 2 => primul pas pentru a afla pucntele de control in cazul unei intersectii este: de a calula panta dreptei perpendiculara pe path-ul direct => m' = -1 / (node2.y - node1.y) / (node2.x - node1.x) => m' = -1 * (node2.x - node1.x) / (node2.y - node1.y) => cel de-al doilea pas este calcularea ecuatiei dreptei de panta m' ce trece prin pucntul de control (not G) => y - G.y = m'(x - G.x) => y = m'(x - G.x) + G.y => cel de-al treilea pas este inlocuirea lui y in lungimea dreptei ( lungimea dreptei dorita este dublul razei nodului) pentru a afla cele 2 coordonate x posibile (la 'stanga' si la 'dreapta' path-ului direct) => (x2 - G.x) ^ 2 + (m'(x2 - G.x) + G.y - G.y) ^ 2 = (2raza) ^ 2 => x2 ^ 2 - 2 x2 G.x + G.x ^ 2 + (m' x2) ^ 2 - 2 (m' ^ 2) x2 G.x + (m' G.x) ^ 2 - (2raza) ^ 2 = 0 => (x2 ^ 2)(1 + m' ^ 2) + x2(2 G.x (1 + m' ^ 2)) + (G.x ^ 2)(1 + m' ^ 2) - (2raza) ^ 2 = 0 => cele 2 coordonate pe Ox ale punctului de control, prentu a afla cele 2 coordonate pe Oy se inlocuiesc valorie obtinute in ecuatia dreptei. Parametrii ---------- start_point : QPointF punctul de start al path-ului end_point : QPointF punctul de final al path-ului directed : bool orientarea grafului Returneaza ---------- path : QPainterPath path-ul final al muchiei """ # Centrul de greutate al dreptei formata de cele 2 noduri control_point = QPointF((start_point.x() + end_point.x()) / 2, (start_point.y() + end_point.y()) / 2) path = QPainterPath(start_point) node_radius = self.engine.node_radius point1 = point2 = None # Creearea path-ului direct _path = QPainterPath(start_point) _path.lineTo(end_point) self.direct_path.setPath(_path) # Verificarea pentru intersectii cu path-ul direct intersecting_items = self.engine.view.scene.collidingItems( self.direct_path) intersecting_items.remove(self.node1) intersecting_items.remove(self.node2) # Calcularea coordonatelor pe Ox a punctelor de control in cazul unei intersectii try: m = -1 * (self.node2.x() - self.node1.x()) / (self.node2.y() - self.node1.y()) agent = 1 + (m**2) factors = [ agent, -2 * control_point.x() * agent, (control_point.x()**2) * agent - (node_radius * 2)**2 ] roots = np.roots(factors) # In cazul in care nodurile au acceleasi coordonate pe Ox sau Oy panta # dreptei nu exista. Atunci se va trata cazul de ZeroDivisionError except ZeroDivisionError: point1 = control_point + QPointF(0, node_radius * 2) point2 = control_point - QPointF(0, node_radius * 2) for item in intersecting_items: if isinstance(item, Node): # Daca exista o intersectie si exista si panta dreptei atunci se calculeaza # si coordonatele pe Oy ale posibilelor puncte de control if (point1 and point2) is None: point1 = QPointF( roots[0], m * (roots[0] - control_point.x()) + control_point.y()) point2 = QPointF( roots[1], m * (roots[1] - control_point.x()) + control_point.y()) # Cele 2 linii de la nod la posibilele puncte de control line1 = QLineF(item.pos(), point1) line2 = QLineF(item.pos(), point2) # Daca lungimea primei linii este mai mica decat lungimea celei de-a doua linie # inseamna ca nodul este mai aproape de prima linie deci path-ul va trebui sa se # curbeze in partea opusa => se alege cel de-al doilea punct control_point = point2 if line1.length() <= line2.length( ) else point1 break # Creearea curbei Bezier path.cubicTo(control_point, control_point, end_point) # Daca graful este orientat se adauga la capatul muchiei o sageata pentru # a reprezenta orientarea acestuia if directed: pos = path.currentPosition() dx, dy, angle = self.engine.get_angle(control_point, end_point) path.lineTo( QPointF(pos.x() + self.arrow_length * math.cos(angle + 60), pos.y() + self.arrow_length * math.sin(angle + 60))) path.moveTo(end_point) path.lineTo( QPointF(pos.x() + self.arrow_length * math.cos(angle - 60), pos.y() + self.arrow_length * math.sin(angle - 60))) # In cazul in care muchia are un cost acesta va fi afisat la mijlocul muchiei font_metrics = QFontMetrics(TEXT_FONT) font_offset = QPointF(font_metrics.height(), font_metrics.horizontalAdvance(self.cost)) path.addText(control_point - font_offset / 2, TEXT_FONT, self.cost) return path
test = Rect2D(0, 0, 100, 100) rect = QRectF(0,0, 125,256) print(rect.x()) print(rect.y()) print(rect.width()) print(rect.height()) rect.translate(10,20) # ça marche print(rect) (test.x(), test.y(), test.width(), test.height()) print(test.contains(QPointF(50, 50))) print(test.contains(QPointF(-1, -1))) print(test.contains(QPointF(0, 0))) print(test.contains(QPointF(100, 100))) print(test.contains(QPointF(100, 100.1))) point = QPointF(50, 50) point.x() # p1 = test.p1() # print(p1.x(), p1.y()) # p2 = test.p2() # print(p2.x(), p2.y()) # print(test.arrow) # print(test.length()) # sqrt 2 --> 141 # # if it's an arrow I can add easily all the stuff I need
def pixmapForLegendNode(legend_node): # handles only symbol nodes if not isinstance(legend_node, QgsSymbolLegendNode): return # If size is default, use default implementation size = iface.layerTreeView().iconSize() if size.width() in (-1, 16): size = QSize(18, 18) symbol = legend_node.symbol() if not symbol: return # Compute minimum width model = iface.layerTreeView().layerTreeModel() if not legend_node.layerNode(): return text = legend_node.textOnSymbolLabel() minimum_width = max( max( l_node.minimumIconSize().width() + (8 if text else 0) for l_node in model.layerLegendNodes(legend_node.layerNode()) if isinstance(l_node, QgsSymbolLegendNode) ), size.width(), ) symbol_size = QSize(minimum_width, size.height()) context = QgsRenderContext.fromMapSettings(iface.mapCanvas().mapSettings()) pixmap = QgsSymbolLayerUtils.symbolPreviewPixmap(symbol, symbol_size, 0, context) if text: painter = QPainter(pixmap) text_format = legend_node.textOnSymbolTextFormat() try: text_context = createTemporaryRenderContext() if text_context: painter.setRenderHint(QPainter.Antialiasing) text_context.setPainter(painter) font_metrics = QFontMetricsF(text_format.scaledFont(context)) y_baseline_v_center = ( symbol_size.height() + font_metrics.ascent() - font_metrics.descent() ) / 2 QgsTextRenderer.drawText( QPointF(symbol_size.width() / 2, y_baseline_v_center), 0, QgsTextRenderer.AlignCenter, [text], text_context, text_format, ) text_context.setPainter(None) except Exception as e: QgsMessageLog.logMessage(str(e)) return pixmap
def get_P1(self): return QPointF(self.x(), self.y())
def showWedge(self, angle, color, extended=False, rev_gradient=False, outline_only=False): """Summary Args: angle (TYPE): Description color (TYPE): Description extended (bool, optional): Description rev_gradient (bool, optional): Description outline_only (bool, optional): Description """ # Hack to keep wedge in front # self.setRotation(self.pre_xover_item_group.rotation()) self._last_params = (angle, color, extended, rev_gradient, outline_only) radius = self._radius span = self.pre_xover_item_group.partCrossoverSpanAngle() / 2 radius_adjusted = radius + (_WEDGE_RECT_GAIN / 2) tip = QPointF(radius_adjusted, radius_adjusted) EXT = 1.35 if extended else 1.0 # print("wtf", tip, pos) base_p2 = QPointF(1, 1) line0 = QLineF(tip, QPointF(base_p2)) line1 = QLineF(tip, QPointF(base_p2)) line2 = QLineF(tip, QPointF(base_p2)) quad_scale = 1 + (.22*(span - 5) / 55) # lo+(hi-lo)*(val-min)/(max-min) line0.setLength(radius_adjusted * EXT*quad_scale) # for quadTo control point line1.setLength(radius_adjusted * EXT) line2.setLength(radius_adjusted * EXT) line0.setAngle(angle) line1.setAngle(angle - span) line2.setAngle(angle + span) path = QPainterPath() if outline_only: self.setPen(getPenObj(color, 0.5, alpha=128, capstyle=Qt.RoundCap)) path.moveTo(line1.p2()) path.quadTo(line0.p2(), line2.p2()) else: gradient = QRadialGradient(tip, radius_adjusted * EXT) color1 = getColorObj(color, alpha=80) color2 = getColorObj(color, alpha=0) if rev_gradient: color1, color2 = color2, color1 if extended: gradient.setColorAt(0, color1) gradient.setColorAt(radius_adjusted / (radius_adjusted * EXT), color1) gradient.setColorAt(radius_adjusted / (radius_adjusted * EXT) + 0.01, color2) gradient.setColorAt(1, color2) else: gradient.setColorAt(0, getColorObj(color, alpha=50)) brush = QBrush(gradient) self.setBrush(brush) path.moveTo(line1.p1()) path.lineTo(line1.p2()) path.quadTo(line0.p2(), line2.p2()) path.lineTo(line2.p1()) self.setPath(path) self.show()
def onMouseMove_drag(self, imageview, event): imageview._deltaPan = QPointF(event.pos() - imageview._lastPanPoint) imageview._panning() imageview._lastPanPoint = event.pos()
def updateFloatPath(self, point=None): """ Draws a quad curve from the edge of the fromBase to the top or bottom of the toBase (q5), and finally to the center of the toBase (toBaseEndpoint). If floatPos!=None, this is a floatingXover and floatPos is the destination point (where the mouse is) while toHelix, toIndex are potentially None and represent the base at floatPos. """ node3 = self._node3 node5 = self._node5 bw = _BASE_WIDTH vhi5 = self._virtual_helix_item part_item = vhi5.partItem() pt5 = vhi5.mapToItem(part_item, *node5.floatPoint()) five_is_top = node5.isOnTop() five_is_5_to_3 = node5.isDrawn5to3() # Enter/exit are relative to the direction that the path travels # overall. five_enter_pt = pt5 + QPointF(0 if five_is_5_to_3 else 1, .5) * bw five_center_pt = pt5 + QPointF(.5, .5) * bw five_exit_pt = pt5 + QPointF(.5, 0 if five_is_top else 1) * bw vhi3 = node3.virtualHelixItem() if point: pt3 = point three_is_top = True three_is_5_to_3 = True same_strand = False same_parity = False three_enter_pt = three_center_pt = three_exit_pt = pt3 else: pt3 = vhi3.mapToItem(part_item, *node3.point()) three_is_top = node3.isOnTop() three_is_5_to_3 = node3.isDrawn5to3() same_strand = (node5.strandType() == node3.strandType()) and vhi3 == vhi5 same_parity = five_is_5_to_3 == three_is_5_to_3 three_enter_pt = pt3 + QPointF(.5, 0 if three_is_top else 1) * bw three_center_pt = pt3 + QPointF(.5, .5) * bw three_exit_pt = pt3 + QPointF(1 if three_is_5_to_3 else 0, .5) * bw c1 = QPointF() # case 1: same strand if same_strand: dx = abs(three_enter_pt.x() - five_exit_pt.x()) c1.setX(0.5 * (five_exit_pt.x() + three_enter_pt.x())) if five_is_top: c1.setY(five_exit_pt.y() - _yScale * dx) else: c1.setY(five_exit_pt.y() + _yScale * dx) # case 2: same parity elif same_parity: dy = abs(three_enter_pt.y() - five_exit_pt.y()) c1.setX(five_exit_pt.x() + _xScale * dy) c1.setY(0.5 * (five_exit_pt.y() + three_enter_pt.y())) # case 3: different parity else: if five_is_top and five_is_5_to_3: c1.setX(five_exit_pt.x() - _xScale *\ abs(three_enter_pt.y() - five_exit_pt.y())) else: c1.setX(five_exit_pt.x() + _xScale *\ abs(three_enter_pt.y() - five_exit_pt.y())) c1.setY(0.5 * (five_exit_pt.y() + three_enter_pt.y())) # Construct painter path painterpath = QPainterPath() painterpath.moveTo(five_enter_pt) painterpath.lineTo(five_center_pt) painterpath.lineTo(five_exit_pt) painterpath.quadTo(c1, three_enter_pt) painterpath.lineTo(three_center_pt) painterpath.lineTo(three_exit_pt) self.setPath(painterpath) self._updateFloatPen()
def dropEvent(self, ev): item = None origin = None path = None self.clearSelection() if ev.mimeData().hasText(): text = ev.mimeData().text() origin, path = text.split(',') path = Path(path) if ev.mimeData().hasImage(): pixmap = ev.mimeData().imageData() # If origin != BACKGROUND, we scale item to fit. parent = self.__background_item if origin != BACKGROUND else None item = CustomPixmapItem(pixmap, parent=parent) item.setFlags(QGraphicsPixmapItem.ItemIsMovable | QGraphicsPixmapItem.ItemIsSelectable | QGraphicsPixmapItem.ItemSendsGeometryChanges) if origin == BACKGROUND: item.setZValue(-1) if origin != BACKGROUND: # Scale to fit the scene. scene_rect = self.sceneRect() item_rect = item.boundingRect() scene_width = scene_rect.width() scene_height = scene_rect.height() item_width = item_rect.width() item_height = item_rect.height() if scene_width >= scene_height: factor = scene_height / (2 * item_height) else: factor = scene_width / (2 * item_width) item.setScale(factor) dx = item.boundingRect().width() * factor / 2 dy = item.boundingRect().height() * factor / 2 scene_pos = ev.scenePos() item.setPos(QPointF(abs(scene_pos.x() - dx), abs(scene_pos.y() - dy))) else: # Modify the background aspect ratio in order to match the aspect ratio for # the desired size. desired_size_width = settings.adaptive_resize_width desired_size_height = settings.adaptive_resize_height if not (desired_size_height == 0 or desired_size_width == 0): ratio = desired_size_width / desired_size_height with Image(filename=str(path)) as original_background: r = Rectangle(original_background.width, original_background.height) r_resize = min_resize(r, ratio) original_background.liquid_rescale(int(r_resize.width), int(r_resize.height)) root_dir = Path(settings.output_path) backgrounds_dir = root_dir.joinpath(BACKGROUND) backgrounds_dir.mkdir(exist_ok=True) name = path.name.replace(path.suffix, f".fixed{ path.suffix}") path = backgrounds_dir.joinpath(name) original_background.save(filename=str(path)) self.addItem(item) if origin == BACKGROUND: self.__background_item = item self.setSceneRect(item.boundingRect()) self.parent().fitInView(self.sceneRect(), Qt.KeepAspectRatio) if origin == BACKGROUND: # We need to show the grid AFTER the background has been scaled to # fit the scene. self.show_grid() self.process_dropped_data(item, origin=origin, path=path)
def screenToTileCoords(self, x, y): p = RenderParams(self.map()) if (p.staggerX): if p.staggerEven: x -= p.tileWidth else: x -= p.sideOffsetX else: if p.staggerEven: y -= p.tileHeight else: y -= p.sideOffsetY # Start with the coordinates of a grid-aligned tile lenx = p.tileWidth + p.sideLengthX leny = p.tileHeight + p.sideLengthY referencePoint = QPoint(math.floor(x / lenx), math.floor(y / leny)) # Relative x and y position on the base square of the grid-aligned tile rel = QVector2D(x - referencePoint.x() * lenx, y - referencePoint.y() * leny) # Adjust the reference point to the correct tile coordinates if p.staggerX: staggerAxisIndex = referencePoint.x() else: staggerAxisIndex = referencePoint.y() staggerAxisIndex *= 2 if (p.staggerEven): staggerAxisIndex += 1 if p.staggerX: referencePoint.setX(staggerAxisIndex) else: referencePoint.setY(staggerAxisIndex) # Determine the nearest hexagon tile by the distance to the center centers = [0, 0, 0, 0] if (p.staggerX): left = int(p.sideLengthX / 2) centerX = left + p.columnWidth centerY = int(p.tileHeight / 2) centers[0] = QVector2D(left, centerY) centers[1] = QVector2D(centerX, centerY - p.rowHeight) centers[2] = QVector2D(centerX, centerY + p.rowHeight) centers[3] = QVector2D(centerX + p.columnWidth, centerY) else: top = int(p.sideLengthY / 2) centerX = int(p.tileWidth / 2) centerY = top + p.rowHeight centers[0] = QVector2D(centerX, top) centers[1] = QVector2D(centerX - p.columnWidth, centerY) centers[2] = QVector2D(centerX + p.columnWidth, centerY) centers[3] = QVector2D(centerX, centerY + p.rowHeight) nearest = 0 minDist = 1.7976931348623157e+308 for i in range(4): center = centers[i] dc = (center - rel).lengthSquared() if (dc < minDist): minDist = dc nearest = i offsetsStaggerX = [ QPoint(0, 0), QPoint(+1, -1), QPoint(+1, 0), QPoint(+2, 0), ] offsetsStaggerY = [ QPoint(0, 0), QPoint(-1, +1), QPoint(0, +1), QPoint(0, +2), ] if p.staggerX: offsets = offsetsStaggerX else: offsets = offsetsStaggerY return QPointF(referencePoint + offsets[nearest])
def paint(self, painter, option, widget): painter.save() painter.setRenderHint(QPainter.Antialiasing, bool(options.antialiasing == ANTIALIASING_FULL)) rect = QRectF(0, 0, self.p_width, self.p_height) # Draw rectangle pen = QPen(canvas.theme.box_pen_sel if self.isSelected() else canvas. theme.box_pen) pen.setWidthF(pen.widthF() + 0.00001) painter.setPen(pen) lineHinting = pen.widthF() / 2 if canvas.theme.box_bg_type == Theme.THEME_BG_GRADIENT: box_gradient = QLinearGradient(0, 0, 0, self.p_height) box_gradient.setColorAt(0, canvas.theme.box_bg_1) box_gradient.setColorAt(1, canvas.theme.box_bg_2) painter.setBrush(box_gradient) else: painter.setBrush(canvas.theme.box_bg_1) rect.adjust(lineHinting, lineHinting, -lineHinting, -lineHinting) painter.drawRect(rect) # Draw plugin inline display if supported self.paintInlineDisplay(painter) # Draw pixmap header rect.setHeight(canvas.theme.box_header_height) if canvas.theme.box_header_pixmap: painter.setPen(Qt.NoPen) painter.setBrush(canvas.theme.box_bg_2) # outline rect.adjust(lineHinting, lineHinting, -lineHinting, -lineHinting) painter.drawRect(rect) rect.adjust(1, 1, -1, 0) painter.drawTiledPixmap(rect, canvas.theme.box_header_pixmap, rect.topLeft()) # Draw text painter.setFont(self.m_font_name) if self.isSelected(): painter.setPen(canvas.theme.box_text_sel) else: painter.setPen(canvas.theme.box_text) if canvas.theme.box_use_icon: textPos = QPointF(25, canvas.theme.box_text_ypos) else: appNameSize = fontHorizontalAdvance(self.m_font_name, self.m_group_name) rem = self.p_width - appNameSize textPos = QPointF(rem / 2, canvas.theme.box_text_ypos) painter.drawText(textPos, self.m_group_name) self.repaintLines() painter.restore()
def pointInLine(qPointF, qLineF): from sympy import Point, Line, Segment, Rational p1 = Point(qPointF.x(), qPointF.y()) l = Line(Point(qLineF.x1(), qLineF.y1()), Point(qLineF.x2(), qLineF.y2())) point2d = l.projection(p1) return QPointF(point2d[0], point2d[1])
def itemChange(self, change, value): # TODO : here to merge segments when moving blockitems if (self.parent.parent.parent().moveDirectPorts and hasattr(self.parent, "heatExchangers") and change == self.ItemPositionChange): if not self.savePos is None: self.logger.debug("val is " + str(value)) value.setY(max(value.y(), 0)) value.setY(min(value.y(), self.parent.h)) return QPointF(self.savePos.x(), value.y()) if change == self.ItemScenePositionHasChanged and self.parent.parent.parent( ).editorMode == 0: self.logger.debug("editor mode = 0") for conn in self.connectionList: conn.positionLabel() if conn.fromPort is self: # self.logger.debug("This port is the starting port of connection") # nextNodeInConn = conn.startNode.nextN() # self.logger.debug("Type of parent is " + str(type(nextNodeInConn.parent))) e = conn.segments[0] e.setLine(self.scenePos().x(), self.scenePos().y(), e.line().p2().x(), e.line().p2().y()) if conn.toPort is self: # self.logger.debug("This port is the ending port of connection") # nextNodeInConn = conn.endNode.prevN() # self.logger.debug("nextnodeinconn is " + str(conn.endNode.prevN())) # self.logger.debug("nextNode is " + str(nextNodeInConn)) # self.logger.debug("Type of parent is " + str(type(nextNodeInConn.parent))) # New e = conn.segments[-1] e.setLine(e.line().p1().x(), e.line().p1().y(), self.scenePos().x(), self.scenePos().y()) for s in conn.segments: s.updateGrad() if change == self.ItemScenePositionHasChanged and self.parent.parent.parent( ).editorMode == 1: for conn in self.connectionList: # Update position of connection label conn.positionLabel() if conn.fromPort is self: if (self.createdAtSide != 1 and self.createdAtSide != 3 ) or not conn.segments[0].isVertical(): if len(conn.getCorners()) > 0 and len( conn.segments) > 0: self.logger.debug("inside here") cor = conn.getCorners()[0] cor.setPos(cor.pos().x(), self.scenePos().y()) seg = conn.segments[0] # first segment seg.setLine(self.scenePos().x(), self.scenePos().y(), cor.scenePos().x() + 0.6, cor.scenePos().y()) if len(conn.segments) > 2: verSeg = conn.segments[1] nextSeg = conn.segments[2] if nextSeg.isHorizontal() and seg.isHorizontal( ): if (int(seg.endNode.parent.pos().y() - 0) <= int(nextSeg.line().p2().y()) <= int(seg.endNode.parent.pos().y() + 0)): self.logger.debug( "both segments are horizontal from fromport" ) # verSeg.deleteSegment() self.hideCorners(conn) verSeg.setVisible(False) else: self.showCorners(conn) verSeg.setVisible(True) else: self.logger.debug("inside else") if len(conn.getCorners()) > 0 and len( conn.segments) > 0: cor = conn.getCorners()[0] cor.setPos(self.scenePos().x(), cor.pos().y()) seg = conn.segments[0] # first segment seg.setLine(self.scenePos().x(), self.scenePos().y(), cor.scenePos().x(), cor.scenePos().y()) elif conn.toPort is self: if (conn.fromPort.createdAtSide != 1 and conn.fromPort.createdAtSide != 3 ) or not conn.segments[0].isVertical(): if len(conn.getCorners()) > 0 and len( conn.segments) > 0: cor = conn.getCorners()[-1] cor.setPos(cor.pos().x(), self.scenePos().y()) seg = conn.segments[-1] seg.setLine( self.scenePos().x(), self.scenePos().y(), cor.scenePos().x() + 0.6, cor.scenePos().y() + 0.6, ) if len(conn.segments) > 2: verSeg = conn.segments[-2] nextSeg = conn.segments[-3] if nextSeg.isHorizontal() and seg.isHorizontal( ): if (int(nextSeg.endNode.parent.pos().y() - 0) <= int(seg.line().p2().y()) <= int(nextSeg.endNode.parent.pos().y( ) + 0)): self.logger.debug( "both segments are horizontal from toport" ) self.hideCorners(conn) verSeg.setVisible(False) else: self.showCorners(conn) verSeg.setVisible(True) else: if len(conn.getCorners()) == 1 and len( conn.segments) > 0: cor = conn.getCorners()[-1] cor.setPos(cor.pos().x(), self.scenePos().y()) self.logger.debug("Inside 2nd") seg = conn.segments[-1] # last segment seg.setLine(self.scenePos().x(), self.scenePos().y(), cor.scenePos().x(), cor.scenePos().y()) elif len(conn.getCorners()) == 2 and len( conn.segments) > 0: cor = conn.getCorners()[-1] cor.setPos(self.scenePos().x(), cor.pos().y()) self.logger.debug("Inside 3rd") seg = conn.segments[-1] # last segment seg.setLine(self.scenePos().x(), self.scenePos().y(), cor.scenePos().x(), cor.scenePos().y()) else: self.logger.debug( "Error: In Mode 1, moving a portItem, portItem is neither from nor toPort" ) if change == self.ItemScenePositionHasChanged: for cb in self.posCallbacks: cb(value) return value return super().itemChange(change, value)