'Updates the plot layout.
This function recalculates the position of titles, axes, the legend and the main plot area.
It does not update the curve or the other plot items.'

def update_layout(self):

    if (not self.isVisible()):
        return
    graph_rect = QRectF(self.contentsRect())
    self.centerOn(graph_rect.center())
    m = self.graph_margin
    graph_rect.adjust(m, m, (- m), (- m))
    if (self.showMainTitle and self.mainTitle):
        if self.title_item:
            self.scene().remove_item(self.title_item)
            del self.title_item
        self.title_item = QGraphicsTextItem(self.mainTitle, scene=self.scene())
        title_size = self.title_item.boundingRect().size()
        self.title_item.setPos(((graph_rect.width() / 2) - (title_size.width() / 2)), ((self.title_margin / 2) - (title_size.height() / 2)))
        graph_rect.setTop((graph_rect.top() + self.title_margin))
    if self.show_legend:
        self._legend_outside_area = QRectF(graph_rect)
        self._legend.max_size = self._legend_outside_area.size()
        r = self._legend_margin
        graph_rect.adjust(r.left(), r.top(), (- r.right()), (- r.bottom()))
    self._legend.update_items()
    axis_rects = dict()
    base_margin = min(self.axis_margin, (graph_rect.height() / 4), (graph_rect.height() / 4))
    if ((xBottom in self.axes) and self.axes[xBottom].isVisible()):
        margin = base_margin
        if self.axes[xBottom].should_be_expanded():
            margin += min(20, (graph_rect.height() / 8), (graph_rect.width() / 8))
        bottom_rect = QRectF(graph_rect)
        bottom_rect.setTop((bottom_rect.bottom() - margin))
        axis_rects[xBottom] = bottom_rect
        graph_rect.setBottom((graph_rect.bottom() - margin))
    if ((xTop in self.axes) and self.axes[xTop].isVisible()):
        margin = base_margin
        if self.axes[xTop].should_be_expanded():
            margin += min(20, (graph_rect.height() / 8), (graph_rect.width() / 8))
        top_rect = QRectF(graph_rect)
        top_rect.setBottom((top_rect.top() + margin))
        axis_rects[xTop] = top_rect
        graph_rect.setTop((graph_rect.top() + margin))
    if ((yLeft in self.axes) and self.axes[yLeft].isVisible()):
        margin = base_margin
        if self.axes[yLeft].should_be_expanded():
            margin += min(20, (graph_rect.height() / 8), (graph_rect.width() / 8))
        left_rect = QRectF(graph_rect)
        left = ((graph_rect.left() + margin) + self.y_axis_extra_margin)
        left_rect.setRight(left)
        graph_rect.setLeft(left)
        axis_rects[yLeft] = left_rect
        if (xBottom in axis_rects):
            axis_rects[xBottom].setLeft(left)
        if (xTop in axis_rects):
            axis_rects[xTop].setLeft(left)
    if ((yRight in self.axes) and self.axes[yRight].isVisible()):
        margin = base_margin
        if self.axes[yRight].should_be_expanded():
            margin += min(20, (graph_rect.height() / 8), (graph_rect.width() / 8))
        right_rect = QRectF(graph_rect)
        right = ((graph_rect.right() - margin) - self.y_axis_extra_margin)
        right_rect.setLeft(right)
        graph_rect.setRight(right)
        axis_rects[yRight] = right_rect
        if (xBottom in axis_rects):
            axis_rects[xBottom].setRight(right)
        if (xTop in axis_rects):
            axis_rects[xTop].setRight(right)
    if (self.graph_area != graph_rect):
        self.graph_area = QRectF(graph_rect)
        self.set_graph_rect(self.graph_area)
        self._transform_cache = {}
        if self._zoom_rect:
            data_zoom_rect = self.map_transform.inverted()[0].mapRect(self._zoom_rect)
            self.map_transform = self.transform_for_axes()
            self.set_zoom_rect(self.map_transform.mapRect(data_zoom_rect))
    self.map_transform = self.transform_for_axes()
    for c in self.plot_items():
        (x, y) = c.axes()
        c.set_graph_transform(self.transform_for_axes(x, y))
        c.update_properties()
