save column width of feed view and make it changeable

This commit is contained in:
Martin Rotter 2025-05-22 13:23:38 +02:00
parent 9f70325177
commit 2ed50e55f9
12 changed files with 59 additions and 82 deletions

View file

@ -19,7 +19,7 @@ using RootItemPtr = RootItem*;
FeedsProxyModel::FeedsProxyModel(FeedsModel* source_model, QObject* parent)
: QSortFilterProxyModel(parent), m_sourceModel(source_model), m_view(nullptr), m_selectedItem(nullptr),
m_showUnreadOnly(false), m_sortAlphabetically(false), m_filter(FeedListFilter::NoFiltering) {
m_sortAlphabetically(false), m_filter(FeedListFilter::NoFiltering) {
setObjectName(QSL("FeedsProxyModel"));
initializeFilters();
@ -513,29 +513,6 @@ void FeedsProxyModel::setSelectedItem(const RootItem* selected_item) {
m_selectedItem = selected_item;
}
bool FeedsProxyModel::showUnreadOnly() const {
return m_showUnreadOnly;
}
void FeedsProxyModel::invalidateReadFeedsFilter(bool set_new_value, bool show_unread_only) {
if (set_new_value) {
setShowUnreadOnly(show_unread_only);
}
QTimer::singleShot(0,
this,
#if QT_VERSION_MAJOR == 5
&FeedsProxyModel::invalidateFilter);
#else
&FeedsProxyModel::invalidateRowsFilter);
#endif
}
void FeedsProxyModel::setShowUnreadOnly(bool show_unread_only) {
m_showUnreadOnly = show_unread_only;
qApp->settings()->setValue(GROUP(Feeds), Feeds::ShowOnlyUnreadFeeds, show_unread_only);
}
void FeedsProxyModel::setSortAlphabetically(bool sort_alphabetically) {
if (sort_alphabetically != m_sortAlphabetically) {
m_sortAlphabetically = sort_alphabetically;

View file

@ -57,9 +57,6 @@ class FeedsProxyModel : public QSortFilterProxyModel {
// Maps list of indexes.
QModelIndexList mapListToSource(const QModelIndexList& indexes) const;
bool showUnreadOnly() const;
void setShowUnreadOnly(bool show_unread_only);
const RootItem* selectedItem() const;
void setSelectedItem(const RootItem* selected_item);
@ -68,9 +65,6 @@ class FeedsProxyModel : public QSortFilterProxyModel {
bool sortAlphabetically() const;
void setSortAlphabetically(bool sort_alphabetically);
public slots:
void invalidateReadFeedsFilter(bool set_new_value = false, bool show_unread_only = false);
signals:
void indexNotFilteredOutAnymore(QModelIndex source_idx) const;
@ -90,7 +84,6 @@ class FeedsProxyModel : public QSortFilterProxyModel {
FeedsModel* m_sourceModel;
FeedsView* m_view;
const RootItem* m_selectedItem;
bool m_showUnreadOnly;
bool m_sortAlphabetically;
bool m_showNodeUnread;
bool m_showNodeProbes;

View file

@ -196,7 +196,6 @@ QList<QAction*> FormMain::allActions() const {
actions << m_ui->m_actionClearSelectedItems;
actions << m_ui->m_actionPurgeSelectedItems;
actions << m_ui->m_actionClearAllItems;
actions << m_ui->m_actionShowOnlyUnreadItems;
actions << m_ui->m_actionSortFeedsAlphabetically;
actions << m_ui->m_actionShowTreeBranches;
actions << m_ui->m_actionAutoExpandItemsWhenSelected;
@ -635,7 +634,6 @@ void FormMain::setupIcons() {
m_ui->m_actionSelectPreviousMessage->setIcon(icon_theme_factory->fromTheme(QSL("arrow-up")));
m_ui->m_actionSelectNextUnreadMessage->setIcon(icon_theme_factory->fromTheme(QSL("mail-mark-unread")));
m_ui->m_actionSortFeedsAlphabetically->setIcon(icon_theme_factory->fromTheme(QSL("format-text-bold")));
m_ui->m_actionShowOnlyUnreadItems->setIcon(icon_theme_factory->fromTheme(QSL("mail-mark-unread")));
m_ui->m_actionExpandCollapseItem->setIcon(icon_theme_factory->fromTheme(QSL("format-indent-more")));
m_ui->m_actionExpandCollapseItemRecursively->setIcon(icon_theme_factory->fromTheme(QSL("format-indent-more")));
m_ui->m_actionRestoreSelectedMessages->setIcon(icon_theme_factory->fromTheme(QSL("view-refresh")));
@ -721,8 +719,6 @@ void FormMain::loadSize() {
// Other startup GUI-related or misc settings.
m_ui->m_actionSortFeedsAlphabetically
->setChecked(settings->value(GROUP(Feeds), SETTING(Feeds::SortAlphabetically)).toBool());
m_ui->m_actionShowOnlyUnreadItems
->setChecked(settings->value(GROUP(Feeds), SETTING(Feeds::ShowOnlyUnreadFeeds)).toBool());
m_ui->m_actionShowTreeBranches->setChecked(settings->value(GROUP(Feeds), SETTING(Feeds::ShowTreeBranches)).toBool());
m_ui->m_actionAutoExpandItemsWhenSelected
->setChecked(settings->value(GROUP(Feeds), SETTING(Feeds::AutoExpandOnSelection)).toBool());
@ -1022,10 +1018,6 @@ void FormMain::createConnections() {
&QAction::triggered,
tabWidget()->feedMessageViewer(),
&FeedMessageViewer::switchMessageSplitterOrientation);
connect(m_ui->m_actionShowOnlyUnreadItems,
&QAction::toggled,
tabWidget()->feedMessageViewer(),
&FeedMessageViewer::toggleShowOnlyUnreadFeeds);
connect(m_ui->m_actionSortFeedsAlphabetically,
&QAction::toggled,
tabWidget()->feedMessageViewer()->feedsView(),

View file

@ -136,7 +136,6 @@
<addaction name="m_actionRearrangeCategories"/>
<addaction name="m_actionRearrangeFeeds"/>
<addaction name="separator"/>
<addaction name="m_actionShowOnlyUnreadItems"/>
<addaction name="m_actionAutoExpandItemsWhenSelected"/>
<addaction name="m_actionShowTreeBranches"/>
<addaction name="m_actionExpandCollapseItem"/>
@ -647,17 +646,6 @@
<string notr="true">Ctrl+Shift+Del</string>
</property>
</action>
<action name="m_actionShowOnlyUnreadItems">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Show unread items only</string>
</property>
<property name="shortcut">
<string notr="true">U</string>
</property>
</action>
<action name="m_actionExpandCollapseItem">
<property name="text">
<string>&amp;Expand/collapse selected item</string>

View file

@ -64,6 +64,7 @@ FeedsToolBar* FeedMessageViewer::feedsToolBar() const {
void FeedMessageViewer::saveSize() {
Settings* settings = qApp->settings();
settings->setValue(GROUP(GUI), GUI::FeedViewState, QString(m_feedsView->saveHeaderState().toBase64()));
settings->setValue(GROUP(GUI), GUI::MessageViewState, QString(m_messagesView->saveHeaderState().toBase64()));
// Store "visibility" of toolbars and list headers.
@ -84,6 +85,12 @@ void FeedMessageViewer::loadSize() {
switchMessageSplitterOrientation();
}
QString settings_feed_header = settings->value(GROUP(GUI), SETTING(GUI::FeedViewState)).toString();
if (!settings_feed_header.isEmpty()) {
m_feedsView->restoreHeaderState(QByteArray::fromBase64(settings_feed_header.toLocal8Bit()));
}
QString settings_msg_header = settings->value(GROUP(GUI), SETTING(GUI::MessageViewState)).toString();
if (!settings_msg_header.isEmpty()) {
@ -190,17 +197,6 @@ void FeedMessageViewer::changeFeedFilter(FeedsProxyModel::FeedListFilter filter)
m_feedsView->changeFilter(filter);
}
void FeedMessageViewer::toggleShowOnlyUnreadFeeds() {
const QAction* origin = qobject_cast<QAction*>(sender());
if (origin == nullptr) {
m_feedsView->invalidateReadFeedsFilter(true, false);
}
else {
m_feedsView->invalidateReadFeedsFilter(true, origin->isChecked());
}
}
void FeedMessageViewer::toggleShowFeedTreeBranches() {
const QAction* origin = qobject_cast<QAction*>(sender());

View file

@ -65,7 +65,6 @@ class RSSGUARD_DLLSPEC FeedMessageViewer : public TabContent {
void changeMessageFilter(MessagesProxyModel::MessageListFilter filter);
void changeFeedFilter(FeedsProxyModel::FeedListFilter filter);
void toggleShowOnlyUnreadFeeds();
void toggleShowFeedTreeBranches();
void toggleItemsAutoExpandingOnSelection();
void alternateRowColorsInLists();

View file

@ -1123,11 +1123,49 @@ QMenu* FeedsView::initializeContextMenuProbe(RootItem* clicked_item) {
return m_contextMenuProbe;
}
QByteArray FeedsView::saveHeaderState() const {
QJsonObject obj;
obj[QSL("header_count")] = header()->count();
// Store column attributes.
for (int i = 0; i < header()->count(); i++) {
obj[QSL("header_%1_size").arg(i)] = header()->sectionSize(i);
}
return QJsonDocument(obj).toJson(QJsonDocument::JsonFormat::Compact);
}
void FeedsView::restoreHeaderState(const QByteArray& dta) {
QJsonObject obj = QJsonDocument::fromJson(dta).object();
int saved_header_count = obj[QSL("header_count")].toInt();
if (saved_header_count < header()->count()) {
qWarningNN << LOGSEC_GUI << "Detected invalid state for feed list.";
return;
}
// Restore column attributes.
for (int i = 0; i < saved_header_count && i < header()->count(); i++) {
int ss = obj[QSL("header_%1_size").arg(i)].toInt();
header()->resizeSection(i, ss);
}
// All columns are resizeable but last one is set to auto-stretch to fill remaining
// space. Sometimes this column is saved as too wide and causes
// horizontal scrollbar to appear. Therefore downsize it.
header()->resizeSection(header()->logicalIndex(header()->count() - 1), 1);
}
void FeedsView::setupAppearance() {
// Setup column resize strategies.
header()->setSectionResizeMode(FDS_MODEL_TITLE_INDEX, QHeaderView::ResizeMode::Stretch);
header()->setSectionResizeMode(FDS_MODEL_COUNTS_INDEX, QHeaderView::ResizeMode::ResizeToContents);
header()->setStretchLastSection(false);
for (int i = 0; i < header()->count(); i++) {
header()->setSectionResizeMode(i, QHeaderView::ResizeMode::Interactive);
}
header()->setStretchLastSection(true);
header()->setSectionsMovable(false);
setUniformRowHeights(true);
setAnimated(true);
@ -1152,10 +1190,6 @@ void FeedsView::setupAppearance() {
this));
}
void FeedsView::invalidateReadFeedsFilter(bool set_new_value, bool show_unread_only) {
m_proxyModel->invalidateReadFeedsFilter(set_new_value, show_unread_only);
}
void FeedsView::selectionChanged(const QItemSelection& selected, const QItemSelection& deselected) {
RootItem* selected_item = selectedItem();
@ -1163,8 +1197,6 @@ void FeedsView::selectionChanged(const QItemSelection& selected, const QItemSele
QTreeView::selectionChanged(selected, deselected);
emit itemSelected(selected_item);
invalidateReadFeedsFilter();
if (!selectedIndexes().isEmpty() &&
qApp->settings()->value(GROUP(Feeds), SETTING(Feeds::AutoExpandOnSelection)).toBool()) {
expand(selectedIndexes().constFirst());

View file

@ -42,6 +42,9 @@ class RSSGUARD_DLLSPEC FeedsView : public BaseTreeView {
void saveAllExpandStates();
void loadAllExpandStates();
QByteArray saveHeaderState() const;
void restoreHeaderState(const QByteArray& dta);
public slots:
void copyUrlOfSelectedFeeds() const;
void sortByColumn(int column, Qt::SortOrder order);
@ -87,13 +90,11 @@ class RSSGUARD_DLLSPEC FeedsView : public BaseTreeView {
void switchVisibility();
void changeFilter(FeedsProxyModel::FeedListFilter filter);
void filterItems(SearchLineEdit::SearchMode mode,
Qt::CaseSensitivity sensitivity,
int custom_criteria,
const QString& phrase);
void toggleFeedSortingMode(bool sort_alphabetically);
void invalidateReadFeedsFilter(bool set_new_value = false, bool show_unread_only = false);
signals:
void itemSelected(RootItem* item);

View file

@ -98,7 +98,7 @@ void MessagesView::restoreHeaderState(const QByteArray& dta) {
int saved_header_count = obj[QSL("header_count")].toInt();
if (saved_header_count < header()->count()) {
qWarningNN << LOGSEC_GUI << "Detected invalid state for list view.";
qWarningNN << LOGSEC_GUI << "Detected invalid state for article list.";
return;
}

View file

@ -124,9 +124,6 @@ DVALUE(bool) Feeds::FeedsUpdateOnStartupDef = false;
DKEY Feeds::FeedsUpdateStartupDelay = "feeds_update_on_startup_delay";
DVALUE(double) Feeds::FeedsUpdateStartupDelayDef = STARTUP_UPDATE_DELAY;
DKEY Feeds::ShowOnlyUnreadFeeds = "show_only_unread_feeds";
DVALUE(bool) Feeds::ShowOnlyUnreadFeedsDef = false;
DKEY Feeds::SortAlphabetically = "sort_alphabetically";
DVALUE(bool) Feeds::SortAlphabeticallyDef = false;
@ -269,6 +266,9 @@ DVALUE(bool) CustomSkinColors::EnabledDef = false;
// GUI.
DKEY GUI::ID = "gui";
DKEY GUI::FeedViewState = "feed_view_state";
DVALUE(QString) GUI::FeedViewStateDef = QString();
DKEY GUI::MessageViewState = "msg_view_state";
DVALUE(QString) GUI::MessageViewStateDef = QString();

View file

@ -122,9 +122,6 @@ namespace Feeds {
KEY FeedsUpdateStartupDelay;
VALUE(double) FeedsUpdateStartupDelayDef;
KEY ShowOnlyUnreadFeeds;
VALUE(bool) ShowOnlyUnreadFeedsDef;
KEY SortAlphabetically;
VALUE(bool) SortAlphabeticallyDef;
@ -296,6 +293,9 @@ namespace GUI {
KEY ToastNotificationsWidth;
VALUE(int) ToastNotificationsWidthDef;
KEY FeedViewState;
VALUE(QString) FeedViewStateDef;
KEY MessageViewState;
VALUE(QString) MessageViewStateDef;

View file

@ -62,7 +62,6 @@ class RSSGUARD_DLLSPEC RootItem : public QObject {
explicit RootItem(const RootItem& other);
virtual ~RootItem();
// Determines if this item should be kept always in the beginning of feeds list.
virtual QString hashCode() const;
virtual QString additionalTooltip() const;