• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdepim API Reference
  • KDE Home
  • Contact Us
 

akregator

  • sources
  • kde-4.14
  • kdepim
  • akregator
  • src
subscriptionlistview.cpp
Go to the documentation of this file.
1 /*
2  This file is part of Akregator.
3 
4  Copyright (C) 2007 Frank Osterfeld <frank.osterfeld@kdemail.net>
5 
6  This program is free software; you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or
9  (at your option) any later version.
10 
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with this program; if not, write to the Free Software
18  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 
20  As a special exception, permission is given to link this program
21  with any edition of Qt, and distribute the resulting executable,
22  without including the source code for Qt in the source distribution.
23 */
24 
25 #include "subscriptionlistview.h"
26 #include "subscriptionlistmodel.h"
27 #include "subscriptionlistdelegate.h"
28 #include "akregatorconfig.h"
29 
30 #include <QHeaderView>
31 #include <QStack>
32 #include <QPointer>
33 
34 #include <KMenu>
35 #include <KLocalizedString>
36 #include <KDebug>
37 #include <KConfigGroup>
38 
39 #include <cassert>
40 
41 using namespace Akregator;
42 
43 static QModelIndex prevIndex( const QModelIndex& idx )
44 {
45  if ( !idx.isValid() )
46  return QModelIndex();
47  const QAbstractItemModel* const model = idx.model();
48  assert( model );
49 
50  if ( idx.row() > 0 )
51  {
52  QModelIndex i = idx.sibling( idx.row() - 1, idx.column() );
53  while ( model->hasChildren( i ) )
54  i = i.child( model->rowCount( i ) - 1, i.column() );
55  return i;
56  }
57  else
58  return idx.parent();
59 }
60 
61 
62 static QModelIndex prevFeedIndex( const QModelIndex& idx, bool allowPassed = false )
63 {
64  QModelIndex prev = allowPassed ? idx : prevIndex( idx );
65  while ( prev.isValid() && prev.data( SubscriptionListModel::IsAggregationRole ).toBool() )
66  prev = prevIndex( prev );
67  return prev;
68 }
69 
70 static QModelIndex prevUnreadFeedIndex( const QModelIndex& idx, bool allowPassed = false )
71 {
72  QModelIndex prev = allowPassed ? idx : prevIndex( idx );
73  while ( prev.isValid() && ( prev.data( SubscriptionListModel::IsAggregationRole ).toBool() || prev.sibling( prev.row(), SubscriptionListModel::UnreadCountColumn ).data().toInt() == 0 ) )
74  prev = prevIndex( prev );
75  return prev;
76 }
77 
78 static QModelIndex lastLeaveChild( const QAbstractItemModel* const model )
79 {
80  assert( model );
81  if ( model->rowCount() == 0 )
82  return QModelIndex();
83  QModelIndex idx = model->index( model->rowCount() - 1, 0 );
84  while ( model->hasChildren( idx ) )
85  idx = idx.child( model->rowCount( idx ) - 1, idx.column() );
86  return idx;
87 }
88 
89 static QModelIndex nextIndex( const QModelIndex& idx )
90 {
91  if ( !idx.isValid() )
92  return QModelIndex();
93  const QAbstractItemModel* const model = idx.model();
94  assert( model );
95  if ( model->hasChildren( idx ) )
96  return idx.child( 0, idx.column() );
97  QModelIndex i = idx;
98  while ( true )
99  {
100  if ( !i.isValid() )
101  return i;
102  const int siblings = model->rowCount( i.parent() );
103  if ( i.row() + 1 < siblings )
104  return i.sibling( i.row() + 1, i.column() );
105  i = i.parent();
106  }
107 }
108 
109 static QModelIndex nextFeedIndex( const QModelIndex& idx )
110 {
111  QModelIndex next = nextIndex( idx );
112  while ( next.isValid() && next.data( SubscriptionListModel::IsAggregationRole ).toBool() )
113  next = nextIndex( next );
114  return next;
115 }
116 
117 static QModelIndex nextUnreadFeedIndex( const QModelIndex& idx )
118 {
119  QModelIndex next = nextIndex( idx );
120  while ( next.isValid() && ( next.data( SubscriptionListModel::IsAggregationRole ).toBool() || next.sibling( next.row(), SubscriptionListModel::UnreadCountColumn ).data().toInt() == 0 ) )
121  next = nextIndex( next );
122  return next;
123 }
124 
125 Akregator::SubscriptionListView::SubscriptionListView( QWidget* parent ) : QTreeView( parent )
126 {
127  setFocusPolicy( Qt::NoFocus );
128  setSelectionMode( QAbstractItemView::SingleSelection );
129  setRootIsDecorated( false );
130  setAlternatingRowColors( true );
131  setContextMenuPolicy( Qt::CustomContextMenu );
132  setDragDropMode( QAbstractItemView::DragDrop );
133  setDropIndicatorShown( true );
134  setAcceptDrops( true );
135  setUniformRowHeights( true );
136  setItemDelegate( new SubscriptionListDelegate( this ) );
137  connect( header(), SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showHeaderMenu(QPoint)) );
138 
139  loadHeaderSettings();
140 }
141 
142 Akregator::SubscriptionListView::~SubscriptionListView()
143 {
144  saveHeaderSettings();
145 }
146 
147 void Akregator::SubscriptionListView::setModel( QAbstractItemModel* m )
148 {
149  Q_ASSERT( m );
150 
151  if ( model() )
152  m_headerState = header()->saveState();
153 
154  QTreeView::setModel( m );
155 
156  restoreHeaderState();
157 
158  QStack<QModelIndex> stack;
159  stack.push( rootIndex() );
160  while ( !stack.isEmpty() )
161  {
162  const QModelIndex i = stack.pop();
163  const int childCount = m->rowCount( i );
164  for ( int j = 0; j < childCount; ++j )
165  {
166  const QModelIndex child = m->index( j, 0, i );
167  if ( child.isValid() )
168  stack.push( child );
169  }
170  setExpanded( i, i.data( Akregator::SubscriptionListModel::IsOpenRole ).toBool() );
171  }
172 
173  header()->setContextMenuPolicy( Qt::CustomContextMenu );
174 }
175 
176 void Akregator::SubscriptionListView::showHeaderMenu( const QPoint& pos )
177 {
178  if( ! model() )
179  return;
180 
181  QPointer<KMenu> menu = new KMenu( this );
182  menu->addTitle( i18n( "Columns" ) );
183  menu->setAttribute( Qt::WA_DeleteOnClose );
184  connect(menu, SIGNAL(triggered(QAction*)), this, SLOT(headerMenuItemTriggered(QAction*)) );
185 
186  for (int i = 0; i < model()->columnCount(); ++i)
187  {
188  if ( SubscriptionListModel::TitleColumn == i ) {
189  continue;
190  }
191  QString col = model()->headerData( i, Qt::Horizontal, Qt::DisplayRole ).toString();
192  QAction* act = menu->addAction( col );
193  act->setCheckable( true );
194  act->setChecked( !header()->isSectionHidden( i ) );
195  act->setData( i );
196  }
197 
198  menu->popup( header()->mapToGlobal( pos ) );
199 }
200 
201 void Akregator::SubscriptionListView::headerMenuItemTriggered( QAction* act )
202 {
203  assert( act );
204  const int col = act->data().toInt();
205  if ( act->isChecked() )
206  header()->showSection( col );
207  else
208  header()->hideSection( col );
209 }
210 
211 void Akregator::SubscriptionListView::saveHeaderSettings()
212 {
213  if ( model() )
214  m_headerState = header()->saveState();
215  KConfigGroup conf( Settings::self()->config(), "General" );
216  conf.writeEntry( "SubscriptionListHeaders", m_headerState.toBase64() );
217 }
218 
219 void Akregator::SubscriptionListView::loadHeaderSettings()
220 {
221  const KConfigGroup conf( Settings::self()->config(), "General" );
222  m_headerState = QByteArray::fromBase64( conf.readEntry( "SubscriptionListHeaders" ).toLatin1() );
223  restoreHeaderState();
224 }
225 
226 void Akregator::SubscriptionListView::restoreHeaderState()
227 {
228  header()->restoreState( m_headerState ); // needed, even with Qt 4.5
229  // Always shows the title column
230  header()->showSection( SubscriptionListModel::TitleColumn );
231  if ( m_headerState.isEmpty() )
232  {
233  // Default configuration: only show the title column
234  header()->hideSection( SubscriptionListModel::UnreadCountColumn );
235  header()->hideSection( SubscriptionListModel::TotalCountColumn );
236  }
237 }
238 
239 void Akregator::SubscriptionListView::slotPrevFeed()
240 {
241  if ( !model() )
242  return;
243  const QModelIndex current = currentIndex();
244  QModelIndex prev = prevFeedIndex( current );
245  if ( !prev.isValid() )
246  {
247  prev = prevFeedIndex( lastLeaveChild( model() ), true );
248  }
249  if ( prev.isValid() )
250  setCurrentIndex( prev );
251 
252 }
253 
254 void Akregator::SubscriptionListView::slotNextFeed()
255 {
256  if ( !model() )
257  return;
258  emit userActionTakingPlace();
259  const QModelIndex current = currentIndex();
260  QModelIndex next = nextFeedIndex( current );
261  if ( !next.isValid() )
262  next = nextFeedIndex( model()->index( 0, 0 ) );
263  if ( next.isValid() )
264  setCurrentIndex( next );
265 }
266 
267 void Akregator::SubscriptionListView::slotPrevUnreadFeed()
268 {
269  if ( !model() )
270  return;
271  emit userActionTakingPlace();
272  const QModelIndex current = currentIndex();
273  QModelIndex prev = prevUnreadFeedIndex( current );
274  if ( !prev.isValid() )
275  prev = prevUnreadFeedIndex( lastLeaveChild( model() ), true );
276  if ( prev.isValid() )
277  setCurrentIndex( prev );
278 }
279 
280 void Akregator::SubscriptionListView::slotNextUnreadFeed()
281 {
282  if ( !model() )
283  return;
284  emit userActionTakingPlace();
285  const QModelIndex current = currentIndex();
286  QModelIndex next = nextUnreadFeedIndex( current );
287  if ( !next.isValid() )
288  next = nextUnreadFeedIndex( model()->index( 0, 0 ) );
289  if ( next.isValid() )
290  setCurrentIndex( next );
291 }
292 
293 void SubscriptionListView::slotItemBegin()
294 {
295  if ( !model() )
296  return;
297  emit userActionTakingPlace();
298  setCurrentIndex( nextFeedIndex( model()->index( 0, 0 ) ) );
299 }
300 
301 void SubscriptionListView::slotItemEnd()
302 {
303  if ( !model() )
304  return;
305  emit userActionTakingPlace();
306  setCurrentIndex( lastLeaveChild( model() ) );
307 }
308 
309 void SubscriptionListView::slotItemLeft()
310 {
311  if ( !model() )
312  return;
313  emit userActionTakingPlace();
314  const QModelIndex current = currentIndex();
315  if ( !current.isValid() ) {
316  setCurrentIndex( nextFeedIndex( model()->index( 0, 0 ) ) );
317  return;
318  }
319  if ( current.parent().isValid() )
320  setCurrentIndex( current.parent() );
321 }
322 
323 void SubscriptionListView::slotItemRight()
324 {
325  if ( !model() )
326  return;
327  emit userActionTakingPlace();
328  const QModelIndex current = currentIndex();
329  if ( !current.isValid() ) {
330  setCurrentIndex( nextFeedIndex( model()->index( 0, 0 ) ) );
331  return;
332  }
333  if ( model()->rowCount( current ) > 0 )
334  setCurrentIndex( current.child( 0, 0 ) );
335 }
336 
337 void SubscriptionListView::slotItemUp()
338 {
339  if ( !model() )
340  return;
341  emit userActionTakingPlace();
342  const QModelIndex current = currentIndex();
343  QModelIndex prev = current.row() > 0 ? current.sibling( current.row() - 1, current.column() ) : current.parent();
344  if ( !prev.isValid() )
345  prev = lastLeaveChild( model() );
346  if ( prev.isValid() )
347  setCurrentIndex( prev );
348 }
349 
350 void SubscriptionListView::slotItemDown()
351 {
352  if ( !model() )
353  return;
354  emit userActionTakingPlace();
355  const QModelIndex current = currentIndex();
356  if ( current.row() >= model()->rowCount( current.parent() ) )
357  return;
358  setCurrentIndex( current.sibling( current.row() + 1, current.column() ) );
359 }
360 
361 
362 void Akregator::SubscriptionListView::ensureNodeVisible( Akregator::TreeNode* )
363 {
364 }
365 
366 void Akregator::SubscriptionListView::startNodeRenaming( Akregator::TreeNode* node )
367 {
368  Q_UNUSED( node );
369  const QModelIndex current = currentIndex();
370  if ( !current.isValid() )
371  return;
372  edit( current );
373 }
374 
QWidget::customContextMenuRequested
void customContextMenuRequested(const QPoint &pos)
QModelIndex
nextFeedIndex
static QModelIndex nextFeedIndex(const QModelIndex &idx)
Definition: subscriptionlistview.cpp:109
QWidget
QAbstractItemModel::rowCount
virtual int rowCount(const QModelIndex &parent) const =0
Akregator::SubscriptionListView::setModel
void setModel(QAbstractItemModel *model)
Definition: subscriptionlistview.cpp:147
QAbstractItemModel::index
virtual QModelIndex index(int row, int column, const QModelIndex &parent) const =0
QAbstractItemView::setAlternatingRowColors
void setAlternatingRowColors(bool enable)
Akregator::SubscriptionListModel::UnreadCountColumn
Definition: subscriptionlistmodel.h:60
QAbstractItemView::setCurrentIndex
void setCurrentIndex(const QModelIndex &index)
QAbstractItemView::setSelectionMode
void setSelectionMode(QAbstractItemView::SelectionMode mode)
QStack::pop
T pop()
Akregator::SubscriptionListView::slotNextFeed
void slotNextFeed()
Definition: subscriptionlistview.cpp:254
subscriptionlistdelegate.h
Akregator::SubscriptionListView::slotPrevUnreadFeed
void slotPrevUnreadFeed()
Definition: subscriptionlistview.cpp:267
QWidget::setFocusPolicy
void setFocusPolicy(Qt::FocusPolicy policy)
QAction::setChecked
void setChecked(bool)
QAction::data
QVariant data() const
QStack::push
void push(const T &t)
Akregator::SubscriptionListView::slotItemEnd
void slotItemEnd()
Definition: subscriptionlistview.cpp:301
QPointer
QAbstractItemView::setDragDropMode
void setDragDropMode(DragDropMode behavior)
Akregator::SubscriptionListView::slotPrevFeed
void slotPrevFeed()
Definition: subscriptionlistview.cpp:239
nextUnreadFeedIndex
static QModelIndex nextUnreadFeedIndex(const QModelIndex &idx)
Definition: subscriptionlistview.cpp:117
QTreeView::setUniformRowHeights
void setUniformRowHeights(bool uniform)
Akregator::SubscriptionListView::slotItemRight
void slotItemRight()
Definition: subscriptionlistview.cpp:323
nextIndex
static QModelIndex nextIndex(const QModelIndex &idx)
Definition: subscriptionlistview.cpp:89
QPoint
Akregator::SubscriptionListView::~SubscriptionListView
~SubscriptionListView()
Definition: subscriptionlistview.cpp:142
QModelIndex::isValid
bool isValid() const
QVariant::toInt
int toInt(bool *ok) const
prevIndex
static QModelIndex prevIndex(const QModelIndex &idx)
Definition: subscriptionlistview.cpp:43
QAbstractItemView::setItemDelegate
void setItemDelegate(QAbstractItemDelegate *delegate)
Akregator::SubscriptionListView::slotNextUnreadFeed
void slotNextUnreadFeed()
Definition: subscriptionlistview.cpp:280
QModelIndex::row
int row() const
subscriptionlistview.h
QString
Akregator::SubscriptionListView::SubscriptionListView
SubscriptionListView(QWidget *parent=0)
Definition: subscriptionlistview.cpp:125
QModelIndex::parent
QModelIndex parent() const
Akregator::SubscriptionListModel::IsOpenRole
Definition: subscriptionlistmodel.h:54
lastLeaveChild
static QModelIndex lastLeaveChild(const QAbstractItemModel *const model)
Definition: subscriptionlistview.cpp:78
Akregator::SubscriptionListView::ensureNodeVisible
void ensureNodeVisible(TreeNode *node)
Definition: subscriptionlistview.cpp:362
QWidget::setAcceptDrops
void setAcceptDrops(bool on)
QAction::setData
void setData(const QVariant &userData)
QWidget::setContextMenuPolicy
void setContextMenuPolicy(Qt::ContextMenuPolicy policy)
QAction::setCheckable
void setCheckable(bool)
QModelIndex::child
QModelIndex child(int row, int column) const
Akregator::SubscriptionListView::startNodeRenaming
void startNodeRenaming(TreeNode *node)
Definition: subscriptionlistview.cpp:366
prevFeedIndex
static QModelIndex prevFeedIndex(const QModelIndex &idx, bool allowPassed=false)
Definition: subscriptionlistview.cpp:62
Akregator::SubscriptionListView::slotItemBegin
void slotItemBegin()
Definition: subscriptionlistview.cpp:293
QModelIndex::model
const QAbstractItemModel * model() const
prevUnreadFeedIndex
static QModelIndex prevUnreadFeedIndex(const QModelIndex &idx, bool allowPassed=false)
Definition: subscriptionlistview.cpp:70
Akregator::SubscriptionListView::slotItemUp
void slotItemUp()
Definition: subscriptionlistview.cpp:337
QModelIndex::data
QVariant data(int role) const
Akregator::SubscriptionListView::userActionTakingPlace
void userActionTakingPlace()
QTreeView
QByteArray::fromBase64
QByteArray fromBase64(const QByteArray &base64)
QAbstractItemModel::hasChildren
virtual bool hasChildren(const QModelIndex &parent) const
QVector::isEmpty
bool isEmpty() const
Akregator::SubscriptionListView::slotItemDown
void slotItemDown()
Definition: subscriptionlistview.cpp:350
QModelIndex::sibling
QModelIndex sibling(int row, int column) const
QTreeView::setModel
virtual void setModel(QAbstractItemModel *model)
QAction
QModelIndex::column
int column() const
QVariant::toBool
bool toBool() const
QAbstractItemModel
QTreeView::header
QHeaderView * header() const
QAbstractItemView::model
QAbstractItemModel * model() const
QAbstractItemView::currentIndex
QModelIndex currentIndex() const
QTreeView::setRootIsDecorated
void setRootIsDecorated(bool show)
QObject::connect
bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
subscriptionlistmodel.h
Akregator::TreeNode
Abstract base class for all kind of elements in the feed tree, like feeds and feed groups (and search...
Definition: treenode.h:58
Akregator::SubscriptionListModel::TitleColumn
Definition: subscriptionlistmodel.h:59
Akregator::SubscriptionListDelegate
Definition: subscriptionlistdelegate.h:34
Akregator::SubscriptionListModel::IsAggregationRole
Definition: subscriptionlistmodel.h:51
Akregator::SubscriptionListView::slotItemLeft
void slotItemLeft()
Definition: subscriptionlistview.cpp:309
QStack
QAbstractItemView::setDropIndicatorShown
void setDropIndicatorShown(bool enable)
Akregator::SubscriptionListModel::TotalCountColumn
Definition: subscriptionlistmodel.h:61
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:34:00 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

akregator

Skip menu "akregator"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members

kdepim API Reference

Skip menu "kdepim API Reference"
  • akonadi_next
  • akregator
  • blogilo
  • calendarsupport
  • console
  •   kabcclient
  •   konsolekalendar
  • kaddressbook
  • kalarm
  •   lib
  • kdgantt2
  • kjots
  • kleopatra
  • kmail
  • knode
  • knotes
  • kontact
  • korgac
  • korganizer
  • ktimetracker
  • libkdepim
  • libkleo
  • libkpgp
  • mailcommon
  • messagelist
  • messageviewer
  • pimprint

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal