From e5c97384f4fb1d6b5278c50aac52c5c60f948fda Mon Sep 17 00:00:00 2001 From: BluABK Date: Sat, 20 Apr 2019 17:24:48 +0200 Subject: [PATCH 01/22] Change VideoTileLabel font handling from plaintext to QFont.fromString. Also changed start with stored videos to True by default. --- config.ini.sample | 8 +++++++- .../gui/views/grid_view/labels/channel_label.py | 10 +++++++--- .../gui/views/grid_view/labels/date_label.py | 11 +++++++---- .../gui/views/grid_view/labels/title_label.py | 12 +++++++----- sane_yt_subfeed/handlers/config_handler.py | 8 +++++++- 5 files changed, 35 insertions(+), 14 deletions(-) diff --git a/config.ini.sample b/config.ini.sample index 385a990..0cd2baa 100644 --- a/config.ini.sample +++ b/config.ini.sample @@ -12,7 +12,7 @@ filter_videos_days_old = -1 [Debug] debug = False cached_subs = True -start_with_stored_videos = False +start_with_stored_videos = True channels_limit = -1 use_playlistitems = True disable_tooltips = False @@ -43,6 +43,12 @@ toolbar_icon_size_modifier = 1 last_style = last_theme = +[Fonts] +video_title_font = Helvetica,12,-1,0,75,0,0,0,0,0,Bold +video_channel_font = Helvetica,12,-1,0,50,0,0,0,0,0,Regular +video_time_font = Helvetica,12,-1,0,50,0,0,0,0,0,Regular +video_thumbnail_overlay_font = Helvetica,10,-1,0,50,0,0,0,0,0,Regular + [GridView] show_watched = False show_dismissed = False diff --git a/sane_yt_subfeed/gui/views/grid_view/labels/channel_label.py b/sane_yt_subfeed/gui/views/grid_view/labels/channel_label.py index 88175b2..a8976a0 100644 --- a/sane_yt_subfeed/gui/views/grid_view/labels/channel_label.py +++ b/sane_yt_subfeed/gui/views/grid_view/labels/channel_label.py @@ -1,12 +1,16 @@ -from sane_yt_subfeed.gui.views.grid_view.labels.video_tile_label import VideoTileLabel +from sane_yt_subfeed.gui.views.grid_view.labels.elided_label import ElidedLabel +from sane_yt_subfeed.handlers.config_handler import read_config +from PyQt5.QtGui import QFont CFG_LINES_ENTRY = ['GridView', 'tile_channel_lines'] CFG_ELIDED_MOD_ENTRY = ['GridView', 'elided_text_modifier_channel'] -class ChannelLabel(VideoTileLabel): +class ChannelLabel(ElidedLabel): def __init__(self, text, parent): - VideoTileLabel.__init__(self, text, parent, CFG_LINES_ENTRY, CFG_ELIDED_MOD_ENTRY) + font = QFont() + font.fromString(read_config("Fonts", "video_channel_font")) + ElidedLabel.__init__(self, text, parent, font, CFG_LINES_ENTRY, CFG_ELIDED_MOD_ENTRY) diff --git a/sane_yt_subfeed/gui/views/grid_view/labels/date_label.py b/sane_yt_subfeed/gui/views/grid_view/labels/date_label.py index 0d777f6..ae54852 100644 --- a/sane_yt_subfeed/gui/views/grid_view/labels/date_label.py +++ b/sane_yt_subfeed/gui/views/grid_view/labels/date_label.py @@ -1,11 +1,14 @@ -from sane_yt_subfeed.gui.views.grid_view.labels.video_tile_label import VideoTileLabel +from sane_yt_subfeed.gui.views.grid_view.labels.elided_label import ElidedLabel +from sane_yt_subfeed.handlers.config_handler import read_config +from PyQt5.QtGui import QFont CFG_LINES_ENTRY = ['GridView', 'tile_date_lines'] CFG_ELIDED_MOD_ENTRY = ['GridView', 'elided_text_modifier_date'] -class DateLabel(VideoTileLabel): +class DateLabel(ElidedLabel): def __init__(self, text, parent): - VideoTileLabel.__init__(self, text, parent, CFG_LINES_ENTRY, CFG_ELIDED_MOD_ENTRY) - + font = QFont() + font.fromString(read_config("Fonts", "video_time_font")) + ElidedLabel.__init__(self, text, parent, font, CFG_LINES_ENTRY, CFG_ELIDED_MOD_ENTRY) diff --git a/sane_yt_subfeed/gui/views/grid_view/labels/title_label.py b/sane_yt_subfeed/gui/views/grid_view/labels/title_label.py index a770f4c..e6e1eee 100644 --- a/sane_yt_subfeed/gui/views/grid_view/labels/title_label.py +++ b/sane_yt_subfeed/gui/views/grid_view/labels/title_label.py @@ -1,12 +1,14 @@ -from sane_yt_subfeed.gui.views.grid_view.labels.video_tile_label import VideoTileLabel +from sane_yt_subfeed.gui.views.grid_view.labels.elided_label import ElidedLabel +from sane_yt_subfeed.handlers.config_handler import read_config +from PyQt5.QtGui import QFont CFG_LINES_ENTRY = ['GridView', 'tile_title_lines'] CFG_ELIDED_MOD_ENTRY = ['GridView', 'elided_text_modifier_title'] -CFG_FONT_WEIGHT = ['GridView', 'title_tile_font_weight'] -class TitleLabel(VideoTileLabel): +class TitleLabel(ElidedLabel): def __init__(self, text, parent): - VideoTileLabel.__init__(self, text, parent, CFG_LINES_ENTRY, CFG_ELIDED_MOD_ENTRY, - cfg_font_weight=CFG_FONT_WEIGHT) + font = QFont() + font.fromString(read_config("Fonts", "video_title_font")) + ElidedLabel.__init__(self, text, parent, font, CFG_LINES_ENTRY, CFG_ELIDED_MOD_ENTRY) diff --git a/sane_yt_subfeed/handlers/config_handler.py b/sane_yt_subfeed/handlers/config_handler.py index b6914f4..f7f7c97 100644 --- a/sane_yt_subfeed/handlers/config_handler.py +++ b/sane_yt_subfeed/handlers/config_handler.py @@ -28,7 +28,7 @@ 'Debug': { 'debug': 'False', 'cached_subs': 'True', - 'start_with_stored_videos': 'False', + 'start_with_stored_videos': 'True', 'channels_limit': '-1', 'use_playlistitems': 'True', 'disable_tooltips': 'False', @@ -59,6 +59,12 @@ 'last_style': "", 'last_theme': "" }, + 'Fonts': { + 'video_title_font': 'Helvetica,12,-1,0,75,0,0,0,0,0,Bold', + 'video_channel_font': 'Helvetica,12,-1,0,50,0,0,0,0,0,Regular', + 'video_time_font': 'Helvetica,12,-1,0,50,0,0,0,0,0,Regular', + 'video_thumbnail_overlay_font': 'Helvetica,10,-1,0,50,0,0,0,0,0,Regular' + }, 'GridView': { 'show_watched': 'False', 'show_dismissed': 'False', From 499f022bbc9d0ef5b73eb58f948a63835ce91be5 Mon Sep 17 00:00:00 2001 From: BluABK Date: Sat, 20 Apr 2019 17:26:10 +0200 Subject: [PATCH 02/22] Refactor renamed (and moved) VideoTileLabel to ElidedLabel. --- .../{video_tile_label.py => elided_label.py} | 22 +++++-------------- 1 file changed, 6 insertions(+), 16 deletions(-) rename sane_yt_subfeed/gui/views/grid_view/labels/{video_tile_label.py => elided_label.py} (77%) diff --git a/sane_yt_subfeed/gui/views/grid_view/labels/video_tile_label.py b/sane_yt_subfeed/gui/views/grid_view/labels/elided_label.py similarity index 77% rename from sane_yt_subfeed/gui/views/grid_view/labels/video_tile_label.py rename to sane_yt_subfeed/gui/views/grid_view/labels/elided_label.py index 64c1aff..fa3be7e 100644 --- a/sane_yt_subfeed/gui/views/grid_view/labels/video_tile_label.py +++ b/sane_yt_subfeed/gui/views/grid_view/labels/elided_label.py @@ -5,27 +5,24 @@ from sane_yt_subfeed.handlers.config_handler import read_config from sane_yt_subfeed.utils import get_unicode_weight -from sane_yt_subfeed.gui.views.config_view.config_item_types import TILE_TITLE_FONT_WEIGHTS_MAP -class VideoTileLabel(QLabel): +class ElidedLabel(QLabel): - def __init__(self, text, parent, cfg_lines_entry, cfg_elided_mod_entry, cfg_font_weight=None): + def __init__(self, text, parent, font, cfg_lines_entry, cfg_elided_mod_entry): """ - Video tile label (superclass). + Elided label (superclass). :param text: String to put on QLabel. :param parent: Parent ptr. - :param cfg_lines_entry: Config [section, option] entry for lines of text to show. - :param cfg_elided_mod_entry: Config [section, option] entry for elided text modifier. - :param cfg_font_weight: Config [section, option] entry for font weight (optional). + :param cfg_lines_entry: QFont font to use. """ QLabel.__init__(self, text) self.parent = parent + self.setFont(font) # Set label type independent config entries self.cfg_lines_entry: list = cfg_lines_entry self.cfg_elided_mod_entry: list = cfg_elided_mod_entry - self.cfg_font_weight: list = cfg_font_weight # Elided overwrites the original, so we need to keep a copy. self.original_text = text @@ -33,13 +30,6 @@ def __init__(self, text, parent, cfg_lines_entry, cfg_elided_mod_entry, cfg_font # Get font metrics/info. metrics = QFontMetrics(self.font()) - # Set up font. - t_font: QFont = self.font() - t_font.setStyleHint(QFont.Helvetica) # FIXME: Make font configurable - if cfg_font_weight: - t_font.setWeight(TILE_TITLE_FONT_WEIGHTS_MAP[read_config(*cfg_font_weight)]) - t_font.setFixedPitch(True) - # Lines of text to show (determines height of title text item). lines = read_config(*self.cfg_lines_entry) @@ -57,7 +47,7 @@ def __init__(self, text, parent, cfg_lines_entry, cfg_elided_mod_entry, cfg_font self.setWordWrap(True) # Apply modified font. - self.setFont(t_font) + # self.setFont(t_font) # Finally, set the text string. self.setText(text, elided=True) From a00fc49d2411a19e7170c476c87642939bcef12c Mon Sep 17 00:00:00 2001 From: BluABK Date: Sat, 20 Apr 2019 17:29:40 +0200 Subject: [PATCH 03/22] Changed ThumbnailTile sizing from fixed size to minimum width (scaled). --- .../gui/views/grid_view/thumbnail_tile.py | 77 +++++++++++++++---- 1 file changed, 63 insertions(+), 14 deletions(-) diff --git a/sane_yt_subfeed/gui/views/grid_view/thumbnail_tile.py b/sane_yt_subfeed/gui/views/grid_view/thumbnail_tile.py index 58700fa..3c14970 100644 --- a/sane_yt_subfeed/gui/views/grid_view/thumbnail_tile.py +++ b/sane_yt_subfeed/gui/views/grid_view/thumbnail_tile.py @@ -1,5 +1,5 @@ from PyQt5.QtCore import Qt, QSize, QPoint, QRect -from PyQt5.QtGui import QPainter, QPixmap, QBrush, QColor, QPen, QFont +from PyQt5.QtGui import QPainter, QPixmap, QBrush, QColor, QPen, QFont, QFontMetrics from PyQt5.QtWidgets import QLabel from sane_yt_subfeed.absolute_paths import THUMBNAIL_NA_PATH @@ -14,8 +14,7 @@ def __init__(self, parent): self.parent = parent self.logger = create_logger(__name__ + ".ThumbnailTitle") - margins = self.parent.layout.getContentsMargins() - self.setFixedSize(self.parent.width() - margins[0] - margins[2], (self.parent.height() - 4 * margins[3]) * 0.6) + self.setMinimumWidth(self.parent.width()) def setPixmap(self, p): """ @@ -37,38 +36,88 @@ def paintEvent(self, event): painter = QPainter(self) if read_config('Gui', 'keep_thumb_ar'): - thumb = self.p.scaled(self.width(), self.height(), Qt.KeepAspectRatio, Qt.SmoothTransformation) + thumb = self.p.scaledToWidth(self.width(), Qt.SmoothTransformation) + self.setMinimumHeight(thumb.height()) painter.drawPixmap(0, 0, thumb) else: thumb = self painter.drawPixmap(thumb.rect(), thumb.p) # Overlay video duration on thumbnail + font = QFont() + font.fromString(read_config("Fonts", "video_thumbnail_overlay_font")) + pen = QPen(Qt.white) painter.setPen(pen) - point = QPoint(thumb.width() * 0.70, thumb.height() * 0.85) - rect = QRect(point, QSize(thumb.width() * 0.28, thumb.height() * 0.12)) + painter.setFont(font) + + duration_right_padding = 4 + duration_bottom_padding = 8 + + point = QPoint( + thumb.width() - duration_right_padding, + thumb.height() - duration_bottom_padding + ) + metrics = QFontMetrics(font) + duration_string = format(self.parent.video.duration) + # Find out the width of the text + text_width = metrics.width(duration_string) + # Work out the max height the text can be + text_height = metrics.descent() + metrics.ascent() + # Add a padding of 8px (4px on left, 4px on right) for width + rect_width = text_width + 8 + # Add a padding of 4px (2px on top, 2px on bottom) for height + rect_height = text_height + 4 + # Create a rectangle + # point starts at the bottom right so we need to use negative sizes + # because we need to move closer to 0,0 again + rect = QRect(point, QSize(-rect_width, -rect_height)) painter.fillRect(rect, QBrush(QColor(0, 0, 0, 180))) - painter.drawText(rect, Qt.AlignCenter, format(self.parent.video.duration)) + painter.drawText(rect, Qt.AlignCenter, duration_string) # Overlay captions (if any) on thumbnail # FIXME: Replace with something better like a small icon if self.parent.video.has_caption: pen = QPen(Qt.white) painter.setPen(pen) - point = QPoint(thumb.width() * 0.03, thumb.height() * 0.85) - rect = QRect(point, QSize(thumb.width() * 0.28, thumb.height() * 0.12)) + painter.setFont(font) + + captions_left_padding = 4 + captions_bottom_padding = 8 + + point = QPoint( + captions_left_padding, + thumb.height() - captions_bottom_padding + ) + metrics = QFontMetrics(font) + text_width = metrics.width("captions") + text_height = metrics.descent() + metrics.ascent() + rect_width = text_width + 8 + rect_height = text_height + 4 + + rect = QRect(point, QSize(rect_width, -rect_height)) painter.fillRect(rect, QBrush(QColor(0, 0, 0, 180))) painter.drawText(rect, Qt.AlignCenter, "captions") if self.parent.video.definition == "sd": pen = QPen(Qt.red) painter.setPen(pen) - point = QPoint(thumb.width() * 0.02, thumb.height() * 0.02) - rect = QRect(point, QSize(thumb.width() * 0.16, thumb.height() * 0.20)) + painter.setFont(font) + + sd_left_padding = 4 + sd_top_padding = 4 + + point = QPoint( + sd_left_padding, + sd_top_padding + ) + metrics = QFontMetrics(font) + text_width = metrics.width("SD") + text_height = metrics.descent() + metrics.ascent() + rect_width = text_width + 4 + rect_height = text_height + 4 + + rect = QRect(point, QSize(rect_width, rect_height)) painter.fillRect(rect, QBrush(QColor(0, 0, 0, 180))) - enlarged_font = QFont(painter.font()) - enlarged_font.setPointSize(14) - painter.setFont(enlarged_font) painter.drawText(rect, Qt.AlignCenter, "SD") self.add_overlay(painter, thumb) From a5741fb8006be3289fa595d11a047c06f959b624 Mon Sep 17 00:00:00 2001 From: BluABK Date: Sat, 20 Apr 2019 17:38:22 +0200 Subject: [PATCH 04/22] VideoTile: sizing logic change and made all but thumb optional. - Changed VideoTile sizing from fixed size to fixed width and max height. - Made Title, Channel and Date text fields optional if cfg lines == 0. --- .../gui/views/grid_view/video_tile.py | 44 ++++++++++++------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/sane_yt_subfeed/gui/views/grid_view/video_tile.py b/sane_yt_subfeed/gui/views/grid_view/video_tile.py index a3628bf..4cef1b9 100644 --- a/sane_yt_subfeed/gui/views/grid_view/video_tile.py +++ b/sane_yt_subfeed/gui/views/grid_view/video_tile.py @@ -42,18 +42,28 @@ def __init__(self, parent, video, vid_id, clipboard, status_bar): self.pref_height = read_config('Gui', 'tile_pref_height') self.pref_width = read_config('Gui', 'tile_pref_width') - self.setFixedSize(self.pref_width, self.pref_height) self.layout = QGridLayout() self.layout.setSpacing(0) # Don't use Qt's "global padding" spacing. self.layout.setAlignment(Qt.AlignTop) # Make sure layout items don't overlap self.layout.setContentsMargins(0, 0, 0, 0) - + + total_height = 0 self.thumbnail_label = self.init_thumbnail_tile() - self.title_label = TitleLabel(video.title, self) - self.channel_label = ChannelLabel(video.channel_title, self) - self.date_label = DateLabel('', self) + total_height += self.thumbnail_label.height() + if read_config('GridView', 'tile_title_lines') != 0: + self.title_label = TitleLabel(video.title, self) + total_height += self.title_label.height() + if read_config('GridView', 'tile_channel_lines') != 0: + self.channel_label = ChannelLabel(video.channel_title, self) + total_height += self.channel_label.height() + if read_config('GridView', 'tile_date_lines') != 0: + self.date_label = DateLabel('', self) + total_height += self.date_label.height() + + self.setFixedWidth(self.pref_width) + self.setMaximumHeight(max(self.pref_height, total_height)) # Use a blank QLabel as spacer item for increased control of spacing (avoids global padding). spacer_label = QLabel() @@ -61,11 +71,14 @@ def __init__(self, parent, video, vid_id, clipboard, status_bar): # Add labels to layout self.layout.addWidget(self.thumbnail_label) - self.layout.addWidget(self.title_label) - self.layout.addWidget(spacer_label) - self.layout.addWidget(self.channel_label) - self.layout.addWidget(spacer_label) - self.layout.addWidget(self.date_label) + if read_config('GridView', 'tile_title_lines') != 0: + self.layout.addWidget(self.title_label) + self.layout.addWidget(spacer_label) + if read_config('GridView', 'tile_channel_lines') != 0: + self.layout.addWidget(self.channel_label) + self.layout.addWidget(spacer_label) + if read_config('GridView', 'tile_date_lines') != 0: + self.layout.addWidget(self.date_label) self.setLayout(self.layout) @@ -77,7 +90,8 @@ def __init__(self, parent, video, vid_id, clipboard, status_bar): self.thumbnail_label.setStyleSheet("QLabel { background-color : darkMagenta}") self.title_label.setStyleSheet("QLabel { background-color : crimson}") self.channel_label.setStyleSheet("QLabel { background-color : darkGreen}") - self.date_label.setStyleSheet("QLabel { background-color : gray}") + if read_config('GridView', 'tile_date_lines') != 0: + self.date_label.setStyleSheet("QLabel { background-color : gray}") def init_thumbnail_tile(self): raise ValueError("ThumbnailTile initialised from VideoTile, not subclass!") @@ -94,9 +108,10 @@ def set_video(self, video): self.video = video self.set_tool_tip() - self.channel_label.setText(self.video.channel_title) - - self.date_label.setText(self.strf_delta(self.video.date_published)) + if read_config('GridView', 'tile_channel_lines') != 0: + self.channel_label.setText(self.video.channel_title) + if read_config('GridView', 'tile_date_lines') != 0: + self.date_label.setText(self.strf_delta(self.video.date_published)) self.color_old_video(self.video.date_published) self.color_live_video() @@ -234,7 +249,6 @@ def strf_delta(date_published, fmt=None): def color_palette(self, color, role=QPalette.Window, log_facility=None, log_msg=""): """ Colors a given palette. - :param palette: :param color: A Qt color integer :param role: Which QPalette role to apply color to (default: background) :param log_facility: if set, log to this facility From 571a5f5236fb76f001b745621c066bfe9fcb3788 Mon Sep 17 00:00:00 2001 From: BluABK Date: Sat, 20 Apr 2019 18:33:41 +0200 Subject: [PATCH 05/22] Removed maximum height sizing logic from VideoTile. --- sane_yt_subfeed/gui/views/grid_view/video_tile.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/sane_yt_subfeed/gui/views/grid_view/video_tile.py b/sane_yt_subfeed/gui/views/grid_view/video_tile.py index 4cef1b9..84e3fc2 100644 --- a/sane_yt_subfeed/gui/views/grid_view/video_tile.py +++ b/sane_yt_subfeed/gui/views/grid_view/video_tile.py @@ -49,21 +49,15 @@ def __init__(self, parent, video, vid_id, clipboard, status_bar): # Make sure layout items don't overlap self.layout.setContentsMargins(0, 0, 0, 0) - total_height = 0 self.thumbnail_label = self.init_thumbnail_tile() - total_height += self.thumbnail_label.height() if read_config('GridView', 'tile_title_lines') != 0: self.title_label = TitleLabel(video.title, self) - total_height += self.title_label.height() if read_config('GridView', 'tile_channel_lines') != 0: self.channel_label = ChannelLabel(video.channel_title, self) - total_height += self.channel_label.height() if read_config('GridView', 'tile_date_lines') != 0: self.date_label = DateLabel('', self) - total_height += self.date_label.height() self.setFixedWidth(self.pref_width) - self.setMaximumHeight(max(self.pref_height, total_height)) # Use a blank QLabel as spacer item for increased control of spacing (avoids global padding). spacer_label = QLabel() From a79ff11389b872a364181edd759848334292354e Mon Sep 17 00:00:00 2001 From: BluABK Date: Sat, 20 Apr 2019 18:41:13 +0200 Subject: [PATCH 06/22] Removed redundant (and also problematic) layout alignments. --- sane_yt_subfeed/gui/views/grid_view/labels/elided_label.py | 1 - sane_yt_subfeed/gui/views/grid_view/video_tile.py | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/sane_yt_subfeed/gui/views/grid_view/labels/elided_label.py b/sane_yt_subfeed/gui/views/grid_view/labels/elided_label.py index fa3be7e..79e1a89 100644 --- a/sane_yt_subfeed/gui/views/grid_view/labels/elided_label.py +++ b/sane_yt_subfeed/gui/views/grid_view/labels/elided_label.py @@ -43,7 +43,6 @@ def __init__(self, text, parent, font, cfg_lines_entry, cfg_elided_mod_entry): self.setFixedHeight((metrics.height() * lines) + (unicode_height_offset * lines)) # Set alignment and enable word wrapping so the text newlines instead of continuing OOB - self.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop) self.setWordWrap(True) # Apply modified font. diff --git a/sane_yt_subfeed/gui/views/grid_view/video_tile.py b/sane_yt_subfeed/gui/views/grid_view/video_tile.py index 84e3fc2..77610ac 100644 --- a/sane_yt_subfeed/gui/views/grid_view/video_tile.py +++ b/sane_yt_subfeed/gui/views/grid_view/video_tile.py @@ -45,7 +45,7 @@ def __init__(self, parent, video, vid_id, clipboard, status_bar): self.layout = QGridLayout() self.layout.setSpacing(0) # Don't use Qt's "global padding" spacing. - self.layout.setAlignment(Qt.AlignTop) + # Make sure layout items don't overlap self.layout.setContentsMargins(0, 0, 0, 0) From a9c620a91b8c560a3861c315d017f298088a38fb Mon Sep 17 00:00:00 2001 From: BluABK Date: Sat, 20 Apr 2019 19:09:54 +0200 Subject: [PATCH 07/22] ElidedLabel aligned to top and add spacer between thumb and title. Aligned to top so it *only* bleeds oob downwards (it's a sorta progress) --- sane_yt_subfeed/gui/views/grid_view/labels/elided_label.py | 1 + sane_yt_subfeed/gui/views/grid_view/video_tile.py | 1 + 2 files changed, 2 insertions(+) diff --git a/sane_yt_subfeed/gui/views/grid_view/labels/elided_label.py b/sane_yt_subfeed/gui/views/grid_view/labels/elided_label.py index 79e1a89..ae88acf 100644 --- a/sane_yt_subfeed/gui/views/grid_view/labels/elided_label.py +++ b/sane_yt_subfeed/gui/views/grid_view/labels/elided_label.py @@ -43,6 +43,7 @@ def __init__(self, text, parent, font, cfg_lines_entry, cfg_elided_mod_entry): self.setFixedHeight((metrics.height() * lines) + (unicode_height_offset * lines)) # Set alignment and enable word wrapping so the text newlines instead of continuing OOB + self.setAlignment(QtCore.Qt.AlignTop) self.setWordWrap(True) # Apply modified font. diff --git a/sane_yt_subfeed/gui/views/grid_view/video_tile.py b/sane_yt_subfeed/gui/views/grid_view/video_tile.py index 77610ac..439a4dc 100644 --- a/sane_yt_subfeed/gui/views/grid_view/video_tile.py +++ b/sane_yt_subfeed/gui/views/grid_view/video_tile.py @@ -65,6 +65,7 @@ def __init__(self, parent, video, vid_id, clipboard, status_bar): # Add labels to layout self.layout.addWidget(self.thumbnail_label) + self.layout.addWidget(spacer_label) if read_config('GridView', 'tile_title_lines') != 0: self.layout.addWidget(self.title_label) self.layout.addWidget(spacer_label) From 11fb2838a3a70498c069b30d42f629ad31db1dad Mon Sep 17 00:00:00 2001 From: BluABK Date: Sat, 20 Apr 2019 19:20:56 +0200 Subject: [PATCH 08/22] Add branch issues listing reasons why this branch is not yet mergable. --- BRANCH_ISSUES.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 BRANCH_ISSUES.md diff --git a/BRANCH_ISSUES.md b/BRANCH_ISSUES.md new file mode 100644 index 0000000..e0a6ab5 --- /dev/null +++ b/BRANCH_ISSUES.md @@ -0,0 +1,6 @@ +This branch (kitteh_changes) cannot be merged to master due to the following unresolved issues: + +- Text ellision breaks; It only reacts to UTF-8 titles... +- UTF-8 text isn't displayed in line with ASCII (a bit lower than ASCII "top"). +- Issue with font being somewhat condensed and less readable. +- VideoTile label text bleeds onto n+1 line (if you limit title box height then UTF-8 ones break). \ No newline at end of file From b5122a3883cd6bdbaae2b4f85e60f26e3ef6c8a2 Mon Sep 17 00:00:00 2001 From: BluABK Date: Thu, 25 Apr 2019 18:13:02 +0200 Subject: [PATCH 09/22] Add some if coverage in dbg tile colouring. --- .../gui/views/grid_view/video_tile.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/sane_yt_subfeed/gui/views/grid_view/video_tile.py b/sane_yt_subfeed/gui/views/grid_view/video_tile.py index 439a4dc..708555a 100644 --- a/sane_yt_subfeed/gui/views/grid_view/video_tile.py +++ b/sane_yt_subfeed/gui/views/grid_view/video_tile.py @@ -63,6 +63,17 @@ def __init__(self, parent, video, vid_id, clipboard, status_bar): spacer_label = QLabel() spacer_label.setFixedHeight(read_config('GridView', 'tile_line_spacing')) + if read_config('Debug', 'color_tile_elements'): + self.color_palette(Qt.green) + self.thumbnail_label.setStyleSheet("QLabel { background-color : darkMagenta}") + # spacer_label.setStyleSheet("QLabel { background-color : cyan}") + if read_config('GridView', 'tile_channel_lines') != 0: + self.title_label.setStyleSheet("QLabel { background-color : crimson}") + if read_config('GridView', 'tile_title_lines') != 0: + self.channel_label.setStyleSheet("QLabel { background-color : darkGreen}") + if read_config('GridView', 'tile_date_lines') != 0: + self.date_label.setStyleSheet("QLabel { background-color : gray}") + # Add labels to layout self.layout.addWidget(self.thumbnail_label) self.layout.addWidget(spacer_label) @@ -80,14 +91,6 @@ def __init__(self, parent, video, vid_id, clipboard, status_bar): # Add video on the layout/tile. self.set_video(video) - if read_config('Debug', 'color_tile_elements'): - self.color_palette(Qt.green) - self.thumbnail_label.setStyleSheet("QLabel { background-color : darkMagenta}") - self.title_label.setStyleSheet("QLabel { background-color : crimson}") - self.channel_label.setStyleSheet("QLabel { background-color : darkGreen}") - if read_config('GridView', 'tile_date_lines') != 0: - self.date_label.setStyleSheet("QLabel { background-color : gray}") - def init_thumbnail_tile(self): raise ValueError("ThumbnailTile initialised from VideoTile, not subclass!") From 285a1de0dd95948529386634b89bcdac7b3fbbd7 Mon Sep 17 00:00:00 2001 From: BluABK Date: Thu, 25 Apr 2019 18:14:23 +0200 Subject: [PATCH 10/22] Remove size limit from TextPickleType due to lack of support. PostgreSQL doesn't seem to support strings with any length limit at all. --- sane_yt_subfeed/database/decorators.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/sane_yt_subfeed/database/decorators.py b/sane_yt_subfeed/database/decorators.py index 65edaa5..652ce0d 100644 --- a/sane_yt_subfeed/database/decorators.py +++ b/sane_yt_subfeed/database/decorators.py @@ -3,11 +3,8 @@ import sqlalchemy from sqlalchemy import TypeDecorator -SIZE = 256 - - class TextPickleType(TypeDecorator): - impl = sqlalchemy.Text(SIZE) + impl = sqlalchemy.Text() def process_bind_param(self, value, dialect): if value is not None: From 0e2daacc4b46d039fad3ca62d91d3fbe22377861 Mon Sep 17 00:00:00 2001 From: BluABK Date: Fri, 26 Apr 2019 16:23:57 +0200 Subject: [PATCH 11/22] Added utils function for checking if a string contains unicode. --- sane_yt_subfeed/utils.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/sane_yt_subfeed/utils.py b/sane_yt_subfeed/utils.py index 1de9cfd..7a0594a 100644 --- a/sane_yt_subfeed/utils.py +++ b/sane_yt_subfeed/utils.py @@ -15,3 +15,16 @@ def get_unicode_weight(text, unicode_weight_modifier): unicode_weight += unicode_weight_modifier return unicode_weight + + +def text_has_unicode(text): + """ + Determine if a text contains unicode characters. + :param text: + :return: + """ + for c in text: + if ord(c) > 128: + return True + + return False From 319b2626dd20b1c5a3230cdccb2c3ade83a3ba33 Mon Sep 17 00:00:00 2001 From: BluABK Date: Fri, 26 Apr 2019 16:35:37 +0200 Subject: [PATCH 12/22] Made all font read_config entries non-literal eval. i.e. read as string. Also video_time_font is mid-rename in this one. --- .../gui/views/grid_view/labels/channel_label.py | 3 ++- sane_yt_subfeed/gui/views/grid_view/labels/date_label.py | 3 ++- .../gui/views/grid_view/labels/elided_label.py | 9 +++------ .../gui/views/grid_view/labels/title_label.py | 3 ++- sane_yt_subfeed/gui/views/grid_view/thumbnail_tile.py | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/sane_yt_subfeed/gui/views/grid_view/labels/channel_label.py b/sane_yt_subfeed/gui/views/grid_view/labels/channel_label.py index a8976a0..b849a13 100644 --- a/sane_yt_subfeed/gui/views/grid_view/labels/channel_label.py +++ b/sane_yt_subfeed/gui/views/grid_view/labels/channel_label.py @@ -10,7 +10,8 @@ class ChannelLabel(ElidedLabel): def __init__(self, text, parent): font = QFont() - font.fromString(read_config("Fonts", "video_channel_font")) + font.fromString(read_config("Fonts", "video_channel_font", literal_eval=False)) + ElidedLabel.__init__(self, text, parent, font, CFG_LINES_ENTRY, CFG_ELIDED_MOD_ENTRY) diff --git a/sane_yt_subfeed/gui/views/grid_view/labels/date_label.py b/sane_yt_subfeed/gui/views/grid_view/labels/date_label.py index ae54852..c70800a 100644 --- a/sane_yt_subfeed/gui/views/grid_view/labels/date_label.py +++ b/sane_yt_subfeed/gui/views/grid_view/labels/date_label.py @@ -10,5 +10,6 @@ class DateLabel(ElidedLabel): def __init__(self, text, parent): font = QFont() - font.fromString(read_config("Fonts", "video_time_font")) + font.fromString(read_config("Fonts", "video_date_font", literal_eval=False)) + ElidedLabel.__init__(self, text, parent, font, CFG_LINES_ENTRY, CFG_ELIDED_MOD_ENTRY) diff --git a/sane_yt_subfeed/gui/views/grid_view/labels/elided_label.py b/sane_yt_subfeed/gui/views/grid_view/labels/elided_label.py index ae88acf..54b74dd 100644 --- a/sane_yt_subfeed/gui/views/grid_view/labels/elided_label.py +++ b/sane_yt_subfeed/gui/views/grid_view/labels/elided_label.py @@ -9,7 +9,7 @@ class ElidedLabel(QLabel): - def __init__(self, text, parent, font, cfg_lines_entry, cfg_elided_mod_entry): + def __init__(self, text, parent, font: QFont, cfg_lines_entry, cfg_elided_mod_entry): """ Elided label (superclass). :param text: String to put on QLabel. @@ -37,18 +37,15 @@ def __init__(self, text, parent, font, cfg_lines_entry, cfg_elided_mod_entry): # # If set to 2 there will be 1px clearing beneath unicode, # but ASCII will show 1px of its supposedly cut-off next line. - unicode_height_offset = read_config('GridView', 'tile_unicode_line_height_offset') # = 1.99 + unicode_height_offset = read_config('GridView', 'tile_unicode_line_height_offset') # Set height equal to lines and add some newline spacing for unicode. self.setFixedHeight((metrics.height() * lines) + (unicode_height_offset * lines)) # Set alignment and enable word wrapping so the text newlines instead of continuing OOB - self.setAlignment(QtCore.Qt.AlignTop) + self.setAlignment(QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop) self.setWordWrap(True) - # Apply modified font. - # self.setFont(t_font) - # Finally, set the text string. self.setText(text, elided=True) diff --git a/sane_yt_subfeed/gui/views/grid_view/labels/title_label.py b/sane_yt_subfeed/gui/views/grid_view/labels/title_label.py index e6e1eee..41ffb13 100644 --- a/sane_yt_subfeed/gui/views/grid_view/labels/title_label.py +++ b/sane_yt_subfeed/gui/views/grid_view/labels/title_label.py @@ -10,5 +10,6 @@ class TitleLabel(ElidedLabel): def __init__(self, text, parent): font = QFont() - font.fromString(read_config("Fonts", "video_title_font")) + font.fromString(read_config("Fonts", "video_title_font", literal_eval=False)) + ElidedLabel.__init__(self, text, parent, font, CFG_LINES_ENTRY, CFG_ELIDED_MOD_ENTRY) diff --git a/sane_yt_subfeed/gui/views/grid_view/thumbnail_tile.py b/sane_yt_subfeed/gui/views/grid_view/thumbnail_tile.py index 3c14970..f328270 100644 --- a/sane_yt_subfeed/gui/views/grid_view/thumbnail_tile.py +++ b/sane_yt_subfeed/gui/views/grid_view/thumbnail_tile.py @@ -45,7 +45,7 @@ def paintEvent(self, event): # Overlay video duration on thumbnail font = QFont() - font.fromString(read_config("Fonts", "video_thumbnail_overlay_font")) + font.fromString(read_config("Fonts", "video_thumbnail_overlay_font", literal_eval=False)) pen = QPen(Qt.white) painter.setPen(pen) From 074ca59b2dc372d93a76c4d41e1d8c382ec37b09 Mon Sep 17 00:00:00 2001 From: BluABK Date: Fri, 26 Apr 2019 16:37:42 +0200 Subject: [PATCH 13/22] Changed default Fonts from Helvetica to Noto Sans (likely the same font). video_time_font still mid-rename. --- config.ini.sample | 8 ++++---- sane_yt_subfeed/handlers/config_handler.py | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/config.ini.sample b/config.ini.sample index 0cd2baa..788adba 100644 --- a/config.ini.sample +++ b/config.ini.sample @@ -44,10 +44,10 @@ last_style = last_theme = [Fonts] -video_title_font = Helvetica,12,-1,0,75,0,0,0,0,0,Bold -video_channel_font = Helvetica,12,-1,0,50,0,0,0,0,0,Regular -video_time_font = Helvetica,12,-1,0,50,0,0,0,0,0,Regular -video_thumbnail_overlay_font = Helvetica,10,-1,0,50,0,0,0,0,0,Regular +video_title_font = Noto Sans,10,-1,0,75,0,0,0,0,0,Bold +video_channel_font = Noto Sans,10,-1,0,50,0,0,0,0,0,Regular +video_date_font = Noto Sans,10,-1,0,50,0,0,0,0,0,Regular +video_thumbnail_overlay_font = Noto Sans,10,-1,0,50,0,0,0,0,0,Regular [GridView] show_watched = False diff --git a/sane_yt_subfeed/handlers/config_handler.py b/sane_yt_subfeed/handlers/config_handler.py index f7f7c97..1407175 100644 --- a/sane_yt_subfeed/handlers/config_handler.py +++ b/sane_yt_subfeed/handlers/config_handler.py @@ -60,10 +60,10 @@ 'last_theme': "" }, 'Fonts': { - 'video_title_font': 'Helvetica,12,-1,0,75,0,0,0,0,0,Bold', - 'video_channel_font': 'Helvetica,12,-1,0,50,0,0,0,0,0,Regular', - 'video_time_font': 'Helvetica,12,-1,0,50,0,0,0,0,0,Regular', - 'video_thumbnail_overlay_font': 'Helvetica,10,-1,0,50,0,0,0,0,0,Regular' + 'video_title_font': 'Noto Sans,10,-1,0,75,0,0,0,0,0,Bold', + 'video_channel_font': 'Noto Sans,10,-1,0,50,0,0,0,0,0,Regular', + 'video_date_font': 'Noto Sans,10,-1,0,50,0,0,0,0,0,Regular', + 'video_thumbnail_overlay_font': 'Noto Sans,10,-1,0,50,0,0,0,0,0,Regular' }, 'GridView': { 'show_watched': 'False', From c70e63a0d5aa377a15d7520fb1a859f97c2e7512 Mon Sep 17 00:00:00 2001 From: BluABK Date: Fri, 26 Apr 2019 16:39:57 +0200 Subject: [PATCH 14/22] Created a FontPickerButton which lets users pick fonts and ... ... displays the current font in a human readable format on the button. Also created add_option_fontpicker and updated ConfigView accordingly. --- .../config_items/font_picker_button.py | 161 ++++++++++++++++++ .../gui/views/config_view/input_super.py | 31 +++- .../views/config_view/views/config_view.py | 6 +- 3 files changed, 194 insertions(+), 4 deletions(-) create mode 100644 sane_yt_subfeed/gui/views/config_view/config_items/font_picker_button.py diff --git a/sane_yt_subfeed/gui/views/config_view/config_items/font_picker_button.py b/sane_yt_subfeed/gui/views/config_view/config_items/font_picker_button.py new file mode 100644 index 0000000..0933460 --- /dev/null +++ b/sane_yt_subfeed/gui/views/config_view/config_items/font_picker_button.py @@ -0,0 +1,161 @@ +from PyQt5.QtGui import QFont +from PyQt5.QtWidgets import QPushButton, QFontDialog + +from sane_yt_subfeed import create_logger +from sane_yt_subfeed.handlers.config_handler import read_config, set_config + +FONT_WEIGHT_MAP = {'0': 'Thin', '12': 'ExtraLight', '18': 'Thi', '25': 'Light', '50': 'Regular', '54': 'Medium', + '62': 'ExtraCondensed', '63': 'DemiBold', '75': 'Bold', '81': 'ExtraBold', '87': 'Black'} +HUMAN_READABLE_KEYS = {'underline': 'Underline', 'strikeout': 'Strike out', 'fixed_pitch': 'Fixed pitch', + 'raw_mode': 'RAW mode'} + + +class FontPickerButton(QPushButton): + def __init__(self, parent, cfg_section, cfg_option, tooltip=None, actions=None, actions_kwargs=None): + """ + A custom QPushButton that launches a QFontDialog. + :param parent: Parent ptr. + :param cfg_section: Config section. + :param cfg_option: Config Option. + :param tooltip: String to show on tooltip. + :param actions: Function to call when font is selected. + :param actions_kwargs: Keyword arguments (dict) to send in checked action calls. + """ + super(QPushButton, self).__init__(parent=parent) + self.parent = parent + self.logger = create_logger(__name__) + self.tooltip = tooltip + self.cfg_section = cfg_section + self.cfg_option = cfg_option + self.current_font = QFont() + self.current_font.fromString(read_config(self.cfg_section, self.cfg_option, literal_eval=False)) + self.update_info() + + self.clicked.connect(self.open_font_dialog) + + def weight_map_lookup(self, weight): + """ + Checks if a weight exists in the font weight map, + if not then it reports it and returns a fallback string. + :param weight: + :return: + """ + if str(weight) in FONT_WEIGHT_MAP: + return FONT_WEIGHT_MAP[str(weight)] + else: + self.logger.error("Umatched font weight: {}!".format(weight)) + return "UNDEFINED({})".format(weight) + + def map_font_str(self, font_str): + """ + Maps a comma separated QFont.toString to a much more sensible dict, which it then returns. + + QFont.toString composition (comma separated, always in the following order): + Family: Font family name. + Point size: Point size of the font. + -1 if the font size was specified in pixels. + Pixel size: Pixel size of the font if it was set with pixel size. + -1 if the size was set with point size. + Style hint: Affects the {QFont}{font matching} algorithm. See QFont.StyleHint and QFont constants. + Style hints are used by the {QFont}{font matching} algorithm to find an appropriate default family + if a selected font family is not available. + + AnyStyle leaves the font matching algorithm to choose the family. This is the default. + + 0 seems to be equivalent to Helvetica and 5 is AnyStyle. + Weight: Weight of the font (0-99), usually it's a predefined enum. + Qt uses a weighting scale from 0 to 99 similar to, but not the same as, the scales used in Windows or + CSS. A weight of 0 is ultralight, whilst 99 will be an extremely black. + Style: Style of the font (enum of the different styles of glyphs that are used to display text). + Only covers the following types: Normal = 0, Italic = 1, Oblique = 2 + Underline: Self-explanatory. + 0 if False, 1 if True. + Strikeout: Self-explanatory. + 0 if False, 1 if True. + Fixed pitch: Fixed pitch value of the matched window system font. + 0 if False, 1 if True. + + Useful url: + shorthand: https://bit.ly/2XIjI5B + raw (with linebreaks): https://cep.xray.aps.anl.gov/software/qt4-x11-4.2.2-browser/ + d7/da1/class_q_font.html#5ab046d742a8538c2e2e50c2e03733ea + + :param font_str: A string in the form of QFont.toString(). + :return: + """ + font_info = font_str.split(',') + font_info_map = {'family': str(font_info[0]), 'point_size': int(font_info[1]), + 'pixel_size': float(font_info[2]), 'style_hint': int(font_info[3]), + 'weight': self.weight_map_lookup(font_info[4]), 'style': int(font_info[5]), + 'underline': bool(int(font_info[6])), 'strikeout': bool(int(font_info[7])), + 'fixed_pitch': bool(int(font_info[8])), 'raw_mode': bool(int(font_info[9])), + 'font_style': str(font_info[10])} + + return font_info_map + + def format_qfont_str(self, font_str): + """ + Formats a QFont.toString to a more human readable string. + :param font_str: + :return: + """ + # Map the string to a font info map/dict. + f: dict = self.map_font_str(font_str) + + # Make a list of enabled setting keys. + enabled_bools = [] + for key, value in f.items(): + if value is True: + enabled_bools.append(HUMAN_READABLE_KEYS[key]) + + # It is guaranteed to be either pt or px, so ternary works fine for this. + pt_or_px = "{}pt.".format(f['point_size']) if f['point_size'] != -1 else "{}px.".format(f['pixel_size']) + + # Determine the enabled (boolean) settings: + bools = [] + for boolean in enabled_bools: + bools.append(boolean) + bools.append(", ") + + if len(bools) > 0: + # Strip trailing runaway comma-space delimiter + bools = bools[:-1] + + # Wrap in parenthesis + bools.insert(0, '(') + bools.append(')') + + # Retval for weight (optional): " (" + f['weight'] + ")" if f['weight'] != f['font_style'] else "", + + return "{} ({}) {} {}".format(f['family'], f['font_style'], pt_or_px, + "".join(bools) if not len(bools) == 0 else "") + + def update_info(self): + """ + Update info (various text/labels etc). + :return: + """ + self.setText(self.format_qfont_str(self.current_font.toString())) + if self.tooltip: + self.setToolTip(self.tooltip) + + def open_font_dialog(self): + """ + Opens a QFontDialog and updates current font and config with the choice (if any). + :return: + """ + font = QFont() + font.fromString(read_config(self.cfg_section, self.cfg_option, literal_eval=False)) + font, ok = QFontDialog.getFont() + + # If user selected a font. + if ok: + # Update current font ref. + self.current_font = font + + # Save selected font to config. + set_config(self.cfg_section, self.cfg_option, font.toString()) + + # Make button text reflect changes. + self.update_info() + diff --git a/sane_yt_subfeed/gui/views/config_view/input_super.py b/sane_yt_subfeed/gui/views/config_view/input_super.py index 6edbb6d..e9d74cc 100644 --- a/sane_yt_subfeed/gui/views/config_view/input_super.py +++ b/sane_yt_subfeed/gui/views/config_view/input_super.py @@ -1,7 +1,8 @@ from PyQt5.QtCore import Qt from PyQt5.QtGui import QFont -from PyQt5.QtWidgets import QWidget, QGridLayout, QLabel +from PyQt5.QtWidgets import QWidget, QGridLayout, QLabel, QFontDialog +from sane_yt_subfeed.gui.views.config_view.config_items.font_picker_button import FontPickerButton from sane_yt_subfeed.handlers.config_handler import read_config, set_config from sane_yt_subfeed.gui.views.config_view.config_items.button import GenericConfigPushButton from sane_yt_subfeed.gui.views.config_view.config_items.checkbox import GenericConfigCheckBox @@ -104,7 +105,7 @@ def add_option_line_edit(self, description, cfg_section, cfg_option, cfg_validat :param cfg_section: :param description: :param actions: Function to call when line gets edited. - :param actions_kwargs Keyword arguments (dict) to send in checked action calls. + :param actions_kwargs: Keyword arguments (dict) to send in checked action calls. :return: """ if restart_check and actions is None: @@ -120,6 +121,32 @@ def add_option_line_edit(self, description, cfg_section, cfg_option, cfg_validat return value # Needed for connected listeners etc + def add_option_fontpicker(self, description, cfg_section, cfg_option, disabled=False, tooltip=None, + actions=None, actions_kwargs=None, restart_check=True): + """ + Add an option w/ value to the ConfigView layout and increment the grid offset. + :param description: Description of the option. + :param cfg_section: Config section. + :param cfg_option: Config option. + :param disabled: Sets disabled status if True. + :param tooltip: String to show on tooltip. + :param actions: Function to call when font is selected. + :param actions_kwargs: Keyword arguments (dict) to send in checked action calls. + :param restart_check: If set to false, don't check if a restart (may) be required for this option. + :return: + """ + if restart_check and actions is None: + description = "{} {}".format(description, RESTART_REQUIRED_SIGNIFIER) + option = QLabel(description) + value = FontPickerButton(self, cfg_section, cfg_option, tooltip=tooltip, actions=actions, + actions_kwargs=actions_kwargs) + + if disabled: + value.setDisabled(True) + self.layout.addWidget(option, self.offset, 0) + self.layout.addWidget(value, self.offset, 1) + self.offset += 1 + def add_option_inactive(self, description, cfg_section, cfg_option): """ Add an option w/ UNEDITABLE value to the ConfigView layout and increment the grid offset. diff --git a/sane_yt_subfeed/gui/views/config_view/views/config_view.py b/sane_yt_subfeed/gui/views/config_view/views/config_view.py index f858ac2..eca87f9 100644 --- a/sane_yt_subfeed/gui/views/config_view/views/config_view.py +++ b/sane_yt_subfeed/gui/views/config_view/views/config_view.py @@ -115,18 +115,20 @@ def add_config_tab_views(self): self.root.del_central_widget_download, self.root.setup_views], unchecked_kwargs=[{'tab': 'Download'}, None, None, None, None]) + self.add_option_fontpicker('Thumbnail overlay font', 'Fonts', 'video_thumbnail_overlay_font') + self.add_option_fontpicker('Title font', 'Fonts', 'video_title_font') self.add_option_line_edit('Title elided text multiplier', 'GridView', 'elided_text_modifier_title', cfg_validator=QDoubleValidator()) self.add_option_line_edit('Title lines to display', 'GridView', 'tile_title_lines', cfg_validator=QIntValidator()) - self.add_option_combobox('Title text font weight', 'GridView', 'title_tile_font_weight', - TILE_TITLE_FONT_WEIGHTS) self.add_option_info(None, None) # Line spacer + self.add_option_fontpicker('Channel font', 'Fonts', 'video_channel_font') self.add_option_line_edit('Channel elided text multiplier', 'GridView', 'elided_text_modifier_channel', cfg_validator=QDoubleValidator()) self.add_option_line_edit('Channel Title lines to display', 'GridView', 'tile_channel_lines', cfg_validator=QIntValidator()) self.add_option_info(None, None) # Line spacer + self.add_option_fontpicker('Date font', 'Fonts', 'video_date_font') self.add_option_line_edit('Date elided text multiplier', 'GridView', 'elided_text_modifier_date', cfg_validator=QDoubleValidator()) self.add_option_line_edit('Date lines to display', 'GridView', 'tile_date_lines', From c96c2970f8f433c6d15671fae7e0332455dca1d0 Mon Sep 17 00:00:00 2001 From: BluABK Date: Fri, 26 Apr 2019 16:49:29 +0200 Subject: [PATCH 15/22] Updated CHANGELOG and deleted resolved BRANCH_ISSUES.md --- BRANCH_ISSUES.md | 6 ------ CHANGELOG | 25 +++++++++++++++++++++++++ 2 files changed, 25 insertions(+), 6 deletions(-) delete mode 100644 BRANCH_ISSUES.md diff --git a/BRANCH_ISSUES.md b/BRANCH_ISSUES.md deleted file mode 100644 index e0a6ab5..0000000 --- a/BRANCH_ISSUES.md +++ /dev/null @@ -1,6 +0,0 @@ -This branch (kitteh_changes) cannot be merged to master due to the following unresolved issues: - -- Text ellision breaks; It only reacts to UTF-8 titles... -- UTF-8 text isn't displayed in line with ASCII (a bit lower than ASCII "top"). -- Issue with font being somewhat condensed and less readable. -- VideoTile label text bleeds onto n+1 line (if you limit title box height then UTF-8 ones break). \ No newline at end of file diff --git a/CHANGELOG b/CHANGELOG index 53dada5..eff033c 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,4 +1,29 @@ Current +- Created (and added to UI) a FontPickerButton which lets users pick fonts and displays the current font in a + human readable format on the button. +- Changed default Fonts from Helvetica to Noto Sans (likely the same font) +- Made all font read_config entries non-literal eval (i.e. read as string). +- Added utils function for checking if a string contains unicode. +- Removed size limit from TextPickleType due to lack of support. + - PostgreSQL doesn't seem to support strings with any length limit at all. +- Added some if coverage in debug tile colouring. +- ElidedLabel is now aligned to top and added spacer between thumb and title. +- Removed redundant (and also problematic) layout alignments. +- Removed maximum height sizing logic from VideoTile. +- Made Title, Channel and Date text fields optional if cfg lines == 0. +- Changed VideoTile sizing from fixed size to fixed width and max height. +- Changed ThumbnailTile sizing from fixed size to minimum width (scaled). +- Refactor renamed (and moved) VideoTileLabel to ElidedLabel. +- Changed start with stored videos to True by default. +- Changed VideoTileLabel font handling from plaintext to QFont.fromString. +- Added accidentally omitted config hotkey to defaults and sample config. +- Fixed critical DB creation failure bug introduced in commit 2da05b2 (Caused by IDE refactor move). +- Made PyYAML dependency in requirements.txt >= instead of ==. +- Made sample cfg/hotkeys if not exist use the new create_config_file function. +- Replaced copyfile(sample, cfg) with func that uses DEFAULTS dict directly. +- Made log_handler automatically create missing dirs and files. +- Made PyQt5 pip requirements >= instead of forcing specific version. +- Renamed subs list reload item, so it's harder to confuse with subfeed refresh. - Hotfix: disabled elision by default and instead explicitly using it during init only, due to VideoTileLabel.width() changing drastically later on. - Deleted deprecated debug_functions and cli arg --debug_open_1k_fds that was used for "too many file descriptors" From 6ef63ce0d19e4f55becdcb276987aa2daf36cb3f Mon Sep 17 00:00:00 2001 From: BluABK Date: Fri, 26 Apr 2019 17:10:32 +0200 Subject: [PATCH 16/22] Made config.ini only contain overrides instead of mirroring all defaults. --- CHANGELOG | 1 + sane_yt_subfeed/handlers/config_handler.py | 11 ----------- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index eff033c..eabaa9b 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,4 +1,5 @@ Current +- Made config.ini only contain overrides instead of mirroring all defaults. - Created (and added to UI) a FontPickerButton which lets users pick fonts and displays the current font in a human readable format on the button. - Changed default Fonts from Helvetica to Noto Sans (likely the same font) diff --git a/sane_yt_subfeed/handlers/config_handler.py b/sane_yt_subfeed/handlers/config_handler.py index 1407175..419f114 100644 --- a/sane_yt_subfeed/handlers/config_handler.py +++ b/sane_yt_subfeed/handlers/config_handler.py @@ -2,8 +2,6 @@ import copy import os from configparser import ConfigParser, NoSectionError, NoOptionError -from shutil import copyfile - from sane_yt_subfeed.absolute_paths import CONFIG_PATH, SAMPLE_PATH, CONFIG_HOTKEYS_PATH, \ SAMPLE_HOTKEYS_PATH, DATABASE_PATH @@ -250,25 +248,18 @@ def read_config(section, option, literal_eval=True, custom_ini=None): :param custom_ini: if set, use given custom config :return: """ - config_path = CONFIG_PATH - sample_path = SAMPLE_PATH defaults = DEFAULTS parser = default_parser # Support multiple configs if custom_ini is not None: # logger.debug("Reading custom config: {}".format(custom_ini)) if custom_ini == "hotkeys": - config_path = CONFIG_HOTKEYS_PATH - sample_path = SAMPLE_HOTKEYS_PATH defaults = DEFAULTS_HOTKEYS parser = hotkeys_parser else: - # logger.critical("Custom config '{}' is not defined in handler!!".format(custom_ini)) raise ValueError("Custom config '{}' is not defined in handler!!".format(custom_ini)) if literal_eval: - if not os.path.exists(config_path): - create_config_file(config_path, DEFAULTS) try: value = parser.get(section, option) except (NoSectionError, NoOptionError): @@ -281,8 +272,6 @@ def read_config(section, option, literal_eval=True, custom_ini=None): else: return ast.literal_eval(defaults[section][option]) else: - if not os.path.exists(config_path): - create_config_file(config_path, DEFAULTS) try: value = parser.get(section, option) except (NoSectionError, NoOptionError): From 3e56256cc0d42d4f206b5980e467e585c52744af Mon Sep 17 00:00:00 2001 From: BluABK Date: Fri, 26 Apr 2019 17:17:28 +0200 Subject: [PATCH 17/22] Update text ellision values to work with the VideoTile redesign. --- CHANGELOG | 1 + sane_yt_subfeed/handlers/config_handler.py | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index eabaa9b..b05171d 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,4 +1,5 @@ Current +- Update text ellision values to work with the VideoTile redesign. - Made config.ini only contain overrides instead of mirroring all defaults. - Created (and added to UI) a FontPickerButton which lets users pick fonts and displays the current font in a human readable format on the button. diff --git a/sane_yt_subfeed/handlers/config_handler.py b/sane_yt_subfeed/handlers/config_handler.py index 419f114..2d3adc0 100644 --- a/sane_yt_subfeed/handlers/config_handler.py +++ b/sane_yt_subfeed/handlers/config_handler.py @@ -66,19 +66,19 @@ 'GridView': { 'show_watched': 'False', 'show_dismissed': 'False', - 'elided_text_modifier_title': '0.28', - 'elided_text_modifier_channel': '0.28', - 'elided_text_modifier_date': '0.28', + 'elided_text_modifier_title': '1', + 'elided_text_modifier_channel': '1', + 'elided_text_modifier_date': '1', 'elided_text_unicode_weight_modifier': '0.0075', 'tile_unicode_line_height_offset': '1.99', - 'tile_line_spacing': '7', + 'tile_line_spacing': '5', 'tile_title_lines': '2', 'tile_channel_lines': '1', 'tile_date_lines': '1', 'title_tile_font_weight': 'Bold', 'timedelta_format': '$HH:$MM:$SS ago', 'timedelta_format_days': '$d days, $HH:$MM:$SS ago', - 'timedelta_format_months': '$m months, $d d, $HH:$MM:$SS ago', + 'timedelta_format_months': '$m months, ${d}d, $HH:$MM:$SS ago', 'timedelta_format_years': '${yd}y, ${m}m, ${d}d, $HH:$MM:$SS ago', 'timedelta_format_decades': '${decades}dc, ${yd}y, ${m}m, ${d}d, $HH:$MM:$SS ago' }, From ebe239817f12fa98e7714ab0fb33b75cd2e187af Mon Sep 17 00:00:00 2001 From: BluABK Date: Fri, 26 Apr 2019 17:23:27 +0200 Subject: [PATCH 18/22] Moved datestamp settings to its own Time & Date tab. --- CHANGELOG | 1 + .../gui/views/config_view/config_view_tabs.py | 2 +- .../views/config_view/views/config_view.py | 62 ++++++++++--------- 3 files changed, 35 insertions(+), 30 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index b05171d..7d0575f 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,4 +1,5 @@ Current +- Moved datestamp settings to its own Time & Date tab. - Update text ellision values to work with the VideoTile redesign. - Made config.ini only contain overrides instead of mirroring all defaults. - Created (and added to UI) a FontPickerButton which lets users pick fonts and displays the current font in a diff --git a/sane_yt_subfeed/gui/views/config_view/config_view_tabs.py b/sane_yt_subfeed/gui/views/config_view/config_view_tabs.py index 2a39213..a2222e4 100644 --- a/sane_yt_subfeed/gui/views/config_view/config_view_tabs.py +++ b/sane_yt_subfeed/gui/views/config_view/config_view_tabs.py @@ -7,7 +7,7 @@ from sane_yt_subfeed.gui.views.config_view.views.config_view import ConfigViewWidget CONFIG_TABS = ["GUI", "Views", "Model", "Requests", "Thumbnails", "Threading", "Download", "Media player", - "Default Application", "Logging", "Debug", "Advanced"] + "Default Application", "Logging", "Debug", "Advanced", "Time && Date"] class ConfigViewTabs(QTabWidget): diff --git a/sane_yt_subfeed/gui/views/config_view/views/config_view.py b/sane_yt_subfeed/gui/views/config_view/views/config_view.py index eca87f9..c9a375c 100644 --- a/sane_yt_subfeed/gui/views/config_view/views/config_view.py +++ b/sane_yt_subfeed/gui/views/config_view/views/config_view.py @@ -52,6 +52,8 @@ def __init__(self, config_view_tabs, parent, root, tab_id): self.add_config_tab_mediaplayer() elif self.tab_id == 'Default Application': self.add_config_tab_default_apps() + elif self.tab_id == "Time && Date": + self.add_config_tab_datetime() elif self.tab_id == 'Logging': self.add_config_tab_logging() elif self.tab_id == 'Advanced': @@ -143,35 +145,6 @@ def add_config_tab_views(self): '(Set this to 0 if using phantomstyle)', 'GridView', 'elided_text_unicode_weight_modifier', cfg_validator=QDoubleValidator()) self.add_option_info(None, None) # Line spacer - self.add_option_line_edit('Date format for: videos uploaded' - ' less than a day ago', 'GridView', 'timedelta_format') - self.add_option_line_edit('Date format for: videos uploaded' - ' a day ago', 'GridView', 'timedelta_format_days') - self.add_option_line_edit('Date format for: videos uploaded' - ' a month ago', 'GridView', 'timedelta_format_months') - self.add_option_line_edit('Date format for: videos uploaded' - ' a year ago', 'GridView', 'timedelta_format_years') - self.add_option_line_edit('Date format for: videos uploaded' - ' a decade ago', 'GridView', 'timedelta_format_decades') - - self.add_option_info('$decadesdecades', 'Decades as a zero-padded decimal number.') - self.add_option_info('$decades', 'Decades as a decimal number.') - self.add_option_info('$ydyd', 'Yearsdelta as a zero-padded decimal number.') - self.add_option_info('$yd', 'Yearsdelta as a decimal number.') - self.add_option_info('$mm', 'Months as a zero-padded decimal number.') - self.add_option_info('$m', 'Months as a decimal number.') - self.add_option_info('$dd', 'Days of the month as a zero-padded decimal number.') - self.add_option_info('$d', 'Days of the month as a decimal number.') - self.add_option_info('$HH', 'Hours (24-hour clock) as a zero-padded decimal number.') - self.add_option_info('$H', 'Hours (24-hour clock) as a decimal number.') - self.add_option_info('$MM', 'Minutes as a zero-padded decimal number.') - self.add_option_info('$M', 'Minutes as a decimal number.') - self.add_option_info('$SS', 'Seconds as a zero-padded decimal number.') - self.add_option_info('$S', 'Seconds as a decimal number.') - self.add_option_info('$f', 'Microseconds as a decimal number, zero-padded on the left.') - self.add_option_info('$%', 'A literal \'%\' character.') - self.add_option_info('', '') - self.add_option_info('Valid delimters:', '$, ${}') # Section [SubFeed] self.add_section('{}Subscription feed{}'.format(self.deco_l, self.deco_r)) @@ -293,6 +266,37 @@ def add_config_tab_mediaplayer(self): def add_config_tab_default_apps(self): self.add_option_line_edit('Image viewer', 'DefaultApp', 'Image', restart_check=False) + def add_config_tab_datetime(self): + self.add_option_line_edit('Date format for: videos uploaded' + ' less than a day ago', 'GridView', 'timedelta_format') + self.add_option_line_edit('Date format for: videos uploaded' + ' a day ago', 'GridView', 'timedelta_format_days') + self.add_option_line_edit('Date format for: videos uploaded' + ' a month ago', 'GridView', 'timedelta_format_months') + self.add_option_line_edit('Date format for: videos uploaded' + ' a year ago', 'GridView', 'timedelta_format_years') + self.add_option_line_edit('Date format for: videos uploaded' + ' a decade ago', 'GridView', 'timedelta_format_decades') + + self.add_option_info('$decadesdecades', 'Decades as a zero-padded decimal number.') + self.add_option_info('$decades', 'Decades as a decimal number.') + self.add_option_info('$ydyd', 'Yearsdelta as a zero-padded decimal number.') + self.add_option_info('$yd', 'Yearsdelta as a decimal number.') + self.add_option_info('$mm', 'Months as a zero-padded decimal number.') + self.add_option_info('$m', 'Months as a decimal number.') + self.add_option_info('$dd', 'Days of the month as a zero-padded decimal number.') + self.add_option_info('$d', 'Days of the month as a decimal number.') + self.add_option_info('$HH', 'Hours (24-hour clock) as a zero-padded decimal number.') + self.add_option_info('$H', 'Hours (24-hour clock) as a decimal number.') + self.add_option_info('$MM', 'Minutes as a zero-padded decimal number.') + self.add_option_info('$M', 'Minutes as a decimal number.') + self.add_option_info('$SS', 'Seconds as a zero-padded decimal number.') + self.add_option_info('$S', 'Seconds as a decimal number.') + self.add_option_info('$f', 'Microseconds as a decimal number, zero-padded on the left.') + self.add_option_info('$%', 'A literal \'%\' character.') + self.add_option_info('', '') + self.add_option_info('Valid delimters:', '$, ${}') + def add_config_tab_logging(self): self.add_option_checkbox('Use socket instead of file', 'Logging', 'use_socket_log') self.add_option_info('Value\t Level', None) From 1e81035361068f06113e0cd3fb2ff7d7a700bb02 Mon Sep 17 00:00:00 2001 From: BluABK Date: Fri, 26 Apr 2019 17:39:02 +0200 Subject: [PATCH 19/22] Shuffled around various settings to lessen a wasteful amount of tabs. --- CHANGELOG | 1 + .../gui/views/config_view/config_view_tabs.py | 3 +- .../views/config_view/views/config_view.py | 91 ++++++++----------- 3 files changed, 41 insertions(+), 54 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 7d0575f..f0adbba 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,4 +1,5 @@ Current +- Shuffled around various settings to lessen a wasteful amount of tabs. - Moved datestamp settings to its own Time & Date tab. - Update text ellision values to work with the VideoTile redesign. - Made config.ini only contain overrides instead of mirroring all defaults. diff --git a/sane_yt_subfeed/gui/views/config_view/config_view_tabs.py b/sane_yt_subfeed/gui/views/config_view/config_view_tabs.py index a2222e4..d1d578b 100644 --- a/sane_yt_subfeed/gui/views/config_view/config_view_tabs.py +++ b/sane_yt_subfeed/gui/views/config_view/config_view_tabs.py @@ -6,8 +6,7 @@ from sane_yt_subfeed.gui.views.config_view.config_scroll_area import ConfigScrollArea from sane_yt_subfeed.gui.views.config_view.views.config_view import ConfigViewWidget -CONFIG_TABS = ["GUI", "Views", "Model", "Requests", "Thumbnails", "Threading", "Download", "Media player", - "Default Application", "Logging", "Debug", "Advanced", "Time && Date"] +CONFIG_TABS = ["GUI", "Views", "Download", "Apps && Players", "Time && Date", "Logging", "Advanced", "Debug"] class ConfigViewTabs(QTabWidget): diff --git a/sane_yt_subfeed/gui/views/config_view/views/config_view.py b/sane_yt_subfeed/gui/views/config_view/views/config_view.py index c9a375c..cfe39f9 100644 --- a/sane_yt_subfeed/gui/views/config_view/views/config_view.py +++ b/sane_yt_subfeed/gui/views/config_view/views/config_view.py @@ -38,20 +38,10 @@ def __init__(self, config_view_tabs, parent, root, tab_id): self.add_config_tab_views() elif self.tab_id == 'Debug' and read_config('Debug', 'debug'): self.add_config_tab_debug() - elif self.tab_id == 'Model': - self.add_config_tab_model() - elif self.tab_id == 'Requests': - self.add_config_tab_requests() - elif self.tab_id == 'Thumbnails': - self.add_config_tab_thumbnails() - elif self.tab_id == 'Threading': - self.add_config_tab_threading() elif self.tab_id == 'Download' and read_config('Play', 'enabled'): self.add_config_tab_download() - elif self.tab_id == 'Media player': - self.add_config_tab_mediaplayer() - elif self.tab_id == 'Default Application': - self.add_config_tab_default_apps() + elif self.tab_id == 'Apps && Players': + self.add_config_tab_apps() elif self.tab_id == "Time && Date": self.add_config_tab_datetime() elif self.tab_id == 'Logging': @@ -69,6 +59,8 @@ def init_ui(self): self.logger.info("Initializing UI: ConfigViewWidget: {}".format(self.tab_id)) def add_config_tab_gui(self): + self.add_option_line_edit('Videos to load by default', 'Model', 'loaded_videos', + cfg_validator=QIntValidator()) self.add_option_checkbox('Grey background on old (1d+) videos', 'Gui', 'grey_old_videos') self.add_option_line_edit('Grid tile height (px)', 'Gui', 'tile_pref_height', cfg_validator=QIntValidator()) self.add_option_line_edit('Grid tile width (px)', 'Gui', 'tile_pref_width', cfg_validator=QIntValidator()) @@ -168,8 +160,6 @@ def add_config_tab_views(self): # Section [Play] if read_config('Play', 'enabled'): self.add_section('{}Playback feed{}'.format(self.deco_l, self.deco_r)) - self.add_option_line_edit('YouTube video directory', 'Play', 'yt_file_path', restart_check=False) - self.add_option_checkbox('Disable directory listener (inotify)', 'Play', 'disable_dir_listener') self.add_option_line_edit('Default watch priority', 'Play', 'default_watch_prio', cfg_validator=QIntValidator(), restart_check=False) # Section [PlaySort] @@ -184,38 +174,6 @@ def add_config_tab_debug(self): self.add_option_checkbox('Color video tile elements', 'Debug', 'color_tile_elements') self.add_option_info_restart_required() - def add_config_tab_model(self): - self.add_option_line_edit('Videos to load by default', 'Model', 'loaded_videos', - cfg_validator=QIntValidator()) - self.add_option_info_restart_required() - - def add_config_tab_requests(self): - self.add_option_checkbox('Use tests', 'Requests', 'use_tests', restart_check=False) - self.add_option_line_edit('Missed video limit', 'Requests', 'miss_limit', - cfg_validator=QIntValidator(), restart_check=False) - self.add_option_line_edit('Test pages', 'Requests', 'test_pages', - cfg_validator=QIntValidator(), restart_check=False) - self.add_option_line_edit('Additional list pages', 'Requests', 'extra_list_pages', - cfg_validator=QIntValidator(), restart_check=False) - self.add_option_line_edit('Deep search API quota limit per request (in K)', 'Requests', - 'deep_search_quota_k', - cfg_validator=QIntValidator(), restart_check=False) - self.add_option_line_edit('Filter videos older than (days)', 'Requests', 'filter_videos_days_old', - cfg_validator=QIntValidator(), restart_check=False) - - def add_config_tab_thumbnails(self): - self.add_option_checkbox('Force download best quality, based on prioritised list', - 'Thumbnails', 'force_download_best', restart_check=False) - self.add_option_combobox('1. Priority', 'Thumbnails', '0', THUMBNAIL_QUALITIES, restart_check=False) - self.add_option_combobox('2. Priority', 'Thumbnails', '1', THUMBNAIL_QUALITIES, restart_check=False) - self.add_option_combobox('3. Priority', 'Thumbnails', '2', THUMBNAIL_QUALITIES, restart_check=False) - self.add_option_combobox('4. Priority', 'Thumbnails', '3', THUMBNAIL_QUALITIES, restart_check=False) - self.add_option_combobox('5. Priority', 'Thumbnails', '4', THUMBNAIL_QUALITIES, restart_check=False) - - def add_config_tab_threading(self): - self.add_option_line_edit('Image/thumbnail download thread limit', 'Threading', 'img_threads', - cfg_validator=QIntValidator(), restart_check=False) - def add_config_tab_download(self): # Section [Youtube-dl] if 'youtube_dl' in sys.modules: @@ -247,12 +205,12 @@ def add_config_tab_download(self): if 'youtube_dl' not in sys.modules: self.add_option_info_restart_required() - def add_config_tab_mediaplayer(self): - # Section [Player] + self.add_option_line_edit('YouTube video directory', 'Play', 'yt_file_path', restart_check=False) + self.add_option_checkbox('Disable directory listener (inotify)', 'Play', 'disable_dir_listener') + + def add_config_tab_apps(self): + self.add_section('{}Media Players{}'.format(self.deco_l, self.deco_r)) self.add_option_line_edit('Default Media Player', 'Player', 'default_player', restart_check=False) - self.add_option_line_edit('Default Web Browser
' - '(Uses system default if none specified)', 'Player', 'url_player', - restart_check=False) _counter = 1 for alt_player in get_options('Player'): # if _counter == 1: # Skip default player @@ -263,7 +221,10 @@ def add_config_tab_mediaplayer(self): restart_check=False) _counter += 1 - def add_config_tab_default_apps(self): + self.add_section('{}Default Applications{}'.format(self.deco_l, self.deco_r)) + self.add_option_line_edit('Default Web Browser
' + '(Uses system default if none specified)', 'Player', 'url_player', + restart_check=False) self.add_option_line_edit('Image viewer', 'DefaultApp', 'Image', restart_check=False) def add_config_tab_datetime(self): @@ -330,4 +291,30 @@ def add_config_tab_advanced(self): self.add_option_line_edit('Grid view X', 'Gui', 'grid_view_x', cfg_validator=QIntValidator()) self.add_option_line_edit('Grid view Y', 'Gui', 'grid_view_y', cfg_validator=QIntValidator()) self.add_option_line_edit('Database URL', 'Database', 'url') + + self.add_section('{}Thumbnails{}'.format(self.deco_l, self.deco_r)) + self.add_option_checkbox('Force download best quality, based on prioritised list', + 'Thumbnails', 'force_download_best', restart_check=False) + self.add_option_combobox('1. Priority', 'Thumbnails', '0', THUMBNAIL_QUALITIES, restart_check=False) + self.add_option_combobox('2. Priority', 'Thumbnails', '1', THUMBNAIL_QUALITIES, restart_check=False) + self.add_option_combobox('3. Priority', 'Thumbnails', '2', THUMBNAIL_QUALITIES, restart_check=False) + self.add_option_combobox('4. Priority', 'Thumbnails', '3', THUMBNAIL_QUALITIES, restart_check=False) + self.add_option_combobox('5. Priority', 'Thumbnails', '4', THUMBNAIL_QUALITIES, restart_check=False) + self.add_option_line_edit('Image/thumbnail download thread limit', 'Threading', 'img_threads', + cfg_validator=QIntValidator(), restart_check=False) + + self.add_section('{}YouTube requests{}'.format(self.deco_l, self.deco_r)) + self.add_option_checkbox('Use tests', 'Requests', 'use_tests', restart_check=False) + self.add_option_line_edit('Missed video limit', 'Requests', 'miss_limit', + cfg_validator=QIntValidator(), restart_check=False) + self.add_option_line_edit('Test pages', 'Requests', 'test_pages', + cfg_validator=QIntValidator(), restart_check=False) + self.add_option_line_edit('Additional list pages', 'Requests', 'extra_list_pages', + cfg_validator=QIntValidator(), restart_check=False) + self.add_option_line_edit('Deep search API quota limit per request (in K)', 'Requests', + 'deep_search_quota_k', + cfg_validator=QIntValidator(), restart_check=False) + self.add_option_line_edit('Filter videos older than (days)', 'Requests', 'filter_videos_days_old', + cfg_validator=QIntValidator(), restart_check=False) + self.add_option_info_restart_required() From 297e19ab1249a2700dd93323e297de6eb43ed0b0 Mon Sep 17 00:00:00 2001 From: BluABK Date: Fri, 26 Apr 2019 17:43:45 +0200 Subject: [PATCH 20/22] Changed Function menu alt-key from F to u (overlapped with File menu). --- CHANGELOG | 1 + .../gui/main_window/main_window.py | 26 +++++++++---------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index f0adbba..664e212 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,4 +1,5 @@ Current +- Changed Function menu alt-key from F to u (overlapped with File menu). - Shuffled around various settings to lessen a wasteful amount of tabs. - Moved datestamp settings to its own Time & Date tab. - Update text ellision values to work with the VideoTile redesign. diff --git a/sane_yt_subfeed/gui/main_window/main_window.py b/sane_yt_subfeed/gui/main_window/main_window.py index f6767ca..0ca7b26 100644 --- a/sane_yt_subfeed/gui/main_window/main_window.py +++ b/sane_yt_subfeed/gui/main_window/main_window.py @@ -599,16 +599,16 @@ def add_menu_function(self, menubar): :param menubar: :return: """ - self.add_menu(menubar, '&Function') + self.add_menu(menubar, 'F&unction') # Set function menu triggers - self.add_submenu('&Function', 'Copy all URLs', self.clipboard_copy_urls, + self.add_submenu('F&unction', 'Copy all URLs', self.clipboard_copy_urls, shortcut=read_config('Global', 'copy_all_urls', custom_ini=HOTKEYS_INI, literal_eval=HOTKEYS_EVAL), tooltip='Copy URLs of all currently visible videos to clipboard', icon=COPY_ALL_URLS_ICON) # refresh_list - self.toolbar_items['RefreshSubFeed'] = self.add_submenu('&Function', 'Refresh Feed', + self.toolbar_items['RefreshSubFeed'] = self.add_submenu('F&unction', 'Refresh Feed', self.emit_signal_with_set_args, shortcut=read_config('Global', 'refresh_feed', custom_ini=HOTKEYS_INI, @@ -618,53 +618,53 @@ def add_menu_function(self, menubar): signal=self.main_model.main_window_listener.refreshVideos, args=(LISTENER_SIGNAL_NORMAL_REFRESH,)) - self.add_submenu('&Function', 'Fetch &List of Subscribed Channels', + self.add_submenu('F&unction', 'Fetch &List of Subscribed Channels', self.main_model.main_window_listener.refreshSubs.emit, shortcut=read_config('Global', 'reload_subslist', custom_ini=HOTKEYS_INI, literal_eval=HOTKEYS_EVAL), tooltip='Fetch a new subscriptions list', icon=RELOAD_SUBS_LIST_ICON) # FIXME: icon, shortcut(alt/shift as extra modifier to the normal refresh shortcut?) - self.add_submenu('&Function', 'Deep refresh of feed', self.emit_signal_with_set_args, + self.add_submenu('F&unction', 'Deep refresh of feed', self.emit_signal_with_set_args, shortcut=read_config('Global', 'refresh_feed_deep', custom_ini=HOTKEYS_INI, literal_eval=HOTKEYS_EVAL), tooltip='Deep refresh the subscription feed', icon=REFRESH_SUBFEED_DEEP_ICON, signal=self.main_model.main_window_listener.refreshVideos, args=(LISTENER_SIGNAL_DEEP_REFRESH,)) - self.add_submenu('&Function', 'Test Channels', self.main_model.main_window_listener.testChannels.emit, + self.add_submenu('F&unction', 'Test Channels', self.main_model.main_window_listener.testChannels.emit, tooltip='Tests the test_pages and miss_limit of channels', icon=RERUN_TEST_ICON) if self.main_model.yt_dir_listener is not None: - self.add_submenu('&Function', 'Manual dir search', self.main_model.yt_dir_listener.manualCheck.emit, + self.add_submenu('F&unction', 'Manual dir search', self.main_model.yt_dir_listener.manualCheck.emit, tooltip='Starts a manual search for new videos in youtube directory', icon=MANUAL_DIR_SEARCH_ICON) thumb_tooltip = 'Starts a manual download of thumbnails for videos currently in play view and sub feed' - self.add_submenu('&Function', 'Manual thumbnail download', + self.add_submenu('F&unction', 'Manual thumbnail download', self.download_thumbnails_manually, tooltip=thumb_tooltip, icon=MANUAL_THUMBS_DOWNLOAD_ICON) - self.add_submenu('&Function', 'Manual DB grab', self.update_from_db, + self.add_submenu('F&unction', 'Manual DB grab', self.update_from_db, tooltip='Starts a manual grab of data for the model', icon=DATABASE_ICON, shortcut=read_config('Global', 'manual_db_grab', custom_ini=HOTKEYS_INI, literal_eval=HOTKEYS_EVAL)) # FIXME: icon, look more related to action - self.add_submenu('&Function', 'Toggle sort-by: ascending date', self.toggle_sort_by_ascending, + self.add_submenu('F&unction', 'Toggle sort-by: ascending date', self.toggle_sort_by_ascending, tooltip='Toggles the ascending date config option, and does a manual re-grab', icon=SORT_BY_ASC_DATE_ICON, shortcut=read_config('Playback', 'ascending_sort_toggle', custom_ini=HOTKEYS_INI, literal_eval=HOTKEYS_EVAL)) - self.add_submenu('&Function', 'Toggle sort-by: channel', self.toggle_sort_by_channel, + self.add_submenu('F&unction', 'Toggle sort-by: channel', self.toggle_sort_by_channel, tooltip='Toggles the ascending date config option, and does a manual re-grab', icon=SORT_BY_CHANNEL_ICON, shortcut=read_config('Playback', 'by_channel_sort_toggle', custom_ini=HOTKEYS_INI, literal_eval=HOTKEYS_EVAL)) - self.add_submenu('&Function', 'Log History 2.0', self.history_log, + self.add_submenu('F&unction', 'Log History 2.0', self.history_log, tooltip='Send entire history to logger') - self.add_submenu('&Function', 'Undo', self.history_undo, + self.add_submenu('F&unction', 'Undo', self.history_undo, tooltip='Undo previous action (if possible)', icon=UNDO_ICON, shortcut=read_config('Global', 'history_undo_action', custom_ini=HOTKEYS_INI, literal_eval=HOTKEYS_EVAL)) From d5dd4de05b72599aa342373ab9deb1f9d6589b47 Mon Sep 17 00:00:00 2001 From: BluABK Date: Fri, 26 Apr 2019 17:51:26 +0200 Subject: [PATCH 21/22] Made sd warn and has-captions overlays optional. sd warn now disabled by default due to recently unreliable API data. --- CHANGELOG | 1 + sane_yt_subfeed/gui/views/config_view/views/config_view.py | 3 +++ sane_yt_subfeed/gui/views/grid_view/thumbnail_tile.py | 4 ++-- sane_yt_subfeed/handlers/config_handler.py | 2 ++ 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 664e212..8a1133a 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,4 +1,5 @@ Current +- Made sd warn and has-captions overlays optional (and made sd warning False by default due to recently buggy API data). - Changed Function menu alt-key from F to u (overlapped with File menu). - Shuffled around various settings to lessen a wasteful amount of tabs. - Moved datestamp settings to its own Time & Date tab. diff --git a/sane_yt_subfeed/gui/views/config_view/views/config_view.py b/sane_yt_subfeed/gui/views/config_view/views/config_view.py index cfe39f9..95e53d9 100644 --- a/sane_yt_subfeed/gui/views/config_view/views/config_view.py +++ b/sane_yt_subfeed/gui/views/config_view/views/config_view.py @@ -96,6 +96,9 @@ def add_config_tab_views(self): self.add_section('{}Grid Views{}'.format(self.deco_l, self.deco_r)) self.add_option_checkbox('Show watched videos', 'GridView', 'show_watched') self.add_option_checkbox('Show dismissed videos', 'GridView', 'show_dismissed') + self.add_option_checkbox('Warn if video is SD quality', 'GridView', 'show_sd_warning', restart_check=False) + self.add_option_checkbox('Show if video has captions available', 'GridView', 'show_has_captions', + restart_check=False) self.add_option_checkbox('Enable Playback view (and download support)', 'Play', 'enabled', checked_actions=[self.config_view_tabs.add_tab, self.root.respawn_menubar_and_toolbar, diff --git a/sane_yt_subfeed/gui/views/grid_view/thumbnail_tile.py b/sane_yt_subfeed/gui/views/grid_view/thumbnail_tile.py index f328270..6cb3bc0 100644 --- a/sane_yt_subfeed/gui/views/grid_view/thumbnail_tile.py +++ b/sane_yt_subfeed/gui/views/grid_view/thumbnail_tile.py @@ -76,7 +76,7 @@ def paintEvent(self, event): painter.drawText(rect, Qt.AlignCenter, duration_string) # Overlay captions (if any) on thumbnail # FIXME: Replace with something better like a small icon - if self.parent.video.has_caption: + if self.parent.video.has_caption and read_config('GridView', 'show_has_captions'): pen = QPen(Qt.white) painter.setPen(pen) painter.setFont(font) @@ -98,7 +98,7 @@ def paintEvent(self, event): painter.fillRect(rect, QBrush(QColor(0, 0, 0, 180))) painter.drawText(rect, Qt.AlignCenter, "captions") - if self.parent.video.definition == "sd": + if self.parent.video.definition == "sd" and read_config('GridView', 'show_sd_warning'): pen = QPen(Qt.red) painter.setPen(pen) painter.setFont(font) diff --git a/sane_yt_subfeed/handlers/config_handler.py b/sane_yt_subfeed/handlers/config_handler.py index 2d3adc0..d2adda2 100644 --- a/sane_yt_subfeed/handlers/config_handler.py +++ b/sane_yt_subfeed/handlers/config_handler.py @@ -66,6 +66,8 @@ 'GridView': { 'show_watched': 'False', 'show_dismissed': 'False', + 'show_sd_warning': 'False', + 'show_has_captions': 'True', 'elided_text_modifier_title': '1', 'elided_text_modifier_channel': '1', 'elided_text_modifier_date': '1', From 4ac5ae20a65b563bba6d39950896ffeb1c53e8bf Mon Sep 17 00:00:00 2001 From: BluABK Date: Fri, 26 Apr 2019 17:52:14 +0200 Subject: [PATCH 22/22] Bump to v0.6.2 --- CHANGELOG | 2 +- VERSION | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 8a1133a..13857ec 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,4 +1,4 @@ -Current +v0.6.2 - Made sd warn and has-captions overlays optional (and made sd warning False by default due to recently buggy API data). - Changed Function menu alt-key from F to u (overlapped with File menu). - Shuffled around various settings to lessen a wasteful amount of tabs. diff --git a/VERSION b/VERSION index 7ceb040..b1d7abc 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.6.1 \ No newline at end of file +0.6.2 \ No newline at end of file