class HistoryChart(QChart): """ Base class for the charts used within the program. """ BAR_CHART = 0 PERCENT_CHART = 1 def __init__(self): super(HistoryChart, self).__init__() self.pen = QColor(Qt.black) self.categories = ["'" + str(i) for i in range(82, 90)] font = QFont() font.setPixelSize(10) self.axisX = QBarCategoryAxis() self.axisX.setLabelsFont(font) self.axisX.append(self.categories) self.addAxis(self.axisX, Qt.AlignBottom) self.legend().setVisible(False) self.layout().setContentsMargins(0, 0, 0, 0) self.setMargins(QMargins(5, 5, 5, 5)) self.setBackgroundRoundness(0)
class QtHistogram(QChartView): def __init__(self, spec): super().__init__(None) self.spec = spec self.chart = QChart() self.chart.setTitle(self.spec.variable) self.chart.legend().hide() self.mainset = QBarSet("") self.mainset.append([0] * len(spec.bins)) self.mainset.setColor( QColor(spec.color[0], spec.color[1], spec.color[2])) self.series = QBarSeries() self.series.append(self.mainset) self.setMinimumWidth(400) self.setMinimumHeight(230) self.y_ranges = [0, 1, 5, 10, 25, 50, 100, 250, 500, 1000] self.max_y = 1000 self.max_y_range = 1000 self.lookback = 30 self.recent_max_y = deque([self.max_y_range] * self.lookback) font = QtGui.QFont() font.setPixelSize(10) self.axis_x = QBarCategoryAxis() self.axis_x.setLabelsAngle(-90) self.axis_x.setLabelsFont(font) self.axis_y = QValueAxis() self.axis_y.setRange(0, self.max_y) self.axis_x.append(map(str, spec.bins)) self.chart.addSeries(self.series) self.chart.setAxisX(self.axis_x, self.series) self.chart.setAxisY(self.axis_y, self.series) self.setChart(self.chart) self.setRenderHint(QPainter.Antialiasing) self._updates_per_second = 10 self._dataset = [] def clear(self): self._dataset = [] def update_data(self, dataset): data = [] for d in dataset: data.append(d) self._dataset = data def redraw(self): if len(self._dataset) > 0: for i in range(len(self._dataset)): self.mainset.replace(i, self._dataset[i]) # Calculate max of current values max_y_range = max(self._dataset) # Store max value self.recent_max_y.appendleft(max_y_range) if len(self.recent_max_y) > self.lookback: self.recent_max_y.pop() # Set max based on the last 30 max values, # to avoid flickering self.max_y_range = max(self.recent_max_y) y_range = bisect.bisect_left(self.y_ranges, self.max_y_range) if y_range < len(self.y_ranges): self.max_y = self.y_ranges[y_range] elif max_y_range > self.max_y: self.max_y += self.max_y elif max_y_range < self.max_y / 2: self.max_y = self.max_y / 2 self.axis_y.setRange(0, self.max_y)
class LastMonthsHistogram(QChartView): """ Chart that displays the balance from the whole portfolio from the last months """ def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.chart = QChart() def setupChartWithData(self): """ Chart gets updated displaying the new data. Data has to be expressed on a dictionary form: - keys are timestamps - values are total balance for that timestamp """ self.chart = QChart() self.chart.setTheme(QChart.ChartThemeDark) self.chart.setAnimationOptions(QChart.SeriesAnimations) self.chart.setBackgroundBrush(QBrush(QColor("transparent"))) # Series self.barseries = QBarSeries() currentyear, currentmonth = datetime.today().year, datetime.today( ).month dates, amounts = [], [] # Get 5 previous month numbers for _ in range(5): dates.append((currentmonth, currentyear)) currentmonth -= 1 if currentmonth == 0: currentmonth = 12 currentyear -= 1 # Get amounts for each month for d in dates: month, year = d amounts.append( dbhandler.get_total_wealth_on_month(month, year=year)) # Iterate months and amount and insert them into the histogram appropiately barset = QBarSet('Total wealth') labelsfont = QFont() labelsfont.setFamily('Inter') labelsfont.setBold(True) barset.setLabelFont(labelsfont) barset.setColor(QColor("#D3EABD")) x_values = [] for d, a in zip(reversed(dates), reversed(amounts)): if a > 0: barset.append(int(a)) x_values.append(calendar.month_name[d[0]]) self.barseries.append(barset) self.barseries.setName("Last Months") self.barseries.setLabelsVisible(True) self.barseries.setBarWidth(0.2) self.barseries.setLabelsPosition(QAbstractBarSeries.LabelsOutsideEnd) self.chart.addSeries(self.barseries) # Axis X (Dates) self.x_axis = QBarCategoryAxis() self.x_axis.setTitleText(self.tr('Date')) labelsfont = QFont() labelsfont.setFamily('Roboto') labelsfont.setLetterSpacing(QFont.AbsoluteSpacing, 1) labelsfont.setWeight(QFont.Light) labelsfont.setPointSize(9) self.x_axis.setLabelsFont(labelsfont) self.x_axis.setGridLineVisible(False) self.x_axis.setLineVisible(False) self.x_axis.setLinePenColor(QColor("#D3EABD")) self.x_axis.setTitleVisible(False) self.x_axis.append(x_values) self.chart.addAxis(self.x_axis, Qt.AlignBottom) # Axis Y (Balances) self.y_axis = QValueAxis() self.y_axis.setMax(max(amounts) * 1.3) self.y_axis.setMin(min(amounts) * 0.95) self.y_axis.hide() labelsfont = QFont() labelsfont.setPointSize(4) self.y_axis.setLabelsFont(labelsfont) self.chart.addAxis(self.y_axis, Qt.AlignLeft) # Attach axis to series self.barseries.attachAxis(self.x_axis) self.barseries.attachAxis(self.y_axis) # Legend self.chart.legend().hide() # Set up chart on ChartView self.setChart(self.chart) self.setRenderHint(QPainter.Antialiasing) self.setStyleSheet("border: 0px; background-color: rgba(0,0,0,0)")