french -> French
[kdepim.git] / knode / treewidget.cpp
blob0fdb3d4198f89d83e816adedff718bd0f694ed53
1 /******************************************************************************
3 * This file is part of libkdepim.
5 * Copyright (C) 2008 Szymon Tomasz Stefanek <pragma@kvirc.net>
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public License
18 * along with this library; see the file COPYING.LIB. If not, write to
19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
22 *****************************************************************************/
24 #include "treewidget.h"
26 #include <KMenu>
27 #include <KConfig>
28 #include <KConfigGroup>
29 #include <KLocale>
31 #include <QHeaderView>
32 #include <QVector>
33 #include <QEvent>
35 namespace KPIM {
37 #define KPIM_TREEWIDGET_DEFAULT_CONFIG_KEY "TreeWidgetLayout"
39 TreeWidget::TreeWidget( QWidget * parent, const char * name )
40 : QTreeWidget( parent )
42 setObjectName( name );
43 setColumnCount( 0 );
45 header()->setMovable( true );
47 setManualColumnHidingEnabled( true );
49 // At the moment of writing (25.11.2008) there is a bug in Qt
50 // which causes an assertion failure in animated views when
51 // the animated item is deleted. The bug notification has been
52 // sent to qt-bugs. For the moment we keep animations explicitly disabled.
53 // FIXME: Re-enable animations once the qt bug is fixed.
54 setAnimated( false );
57 void TreeWidget::changeEvent( QEvent *e )
59 QTreeWidget::changeEvent( e );
61 if ( e->type() == QEvent::StyleChange )
63 // At the moment of writing (25.11.2008) there is a bug in Qt
64 // which causes an assertion failure in animated views when
65 // the animated item is deleted. The bug notification has been
66 // sent to qt-bugs. For the moment we keep animations explicitly disabled.
67 // FIXME: Re-enable animations once the qt bug is fixed.
68 setAnimated( false );
72 bool TreeWidget::saveLayout( KConfigGroup &group, const QString &keyName ) const
74 group.writeEntry(
75 keyName.isEmpty() ? QString( KPIM_TREEWIDGET_DEFAULT_CONFIG_KEY ) : keyName,
76 QVariant( header()->saveState().toHex() )
79 return true;
82 bool TreeWidget::saveLayout( KConfig * config, const QString &groupName, const QString &keyName ) const
84 if( !config || groupName.isEmpty() )
85 return false;
87 KConfigGroup group( config, groupName );
88 return saveLayout( group, keyName );
91 bool TreeWidget::restoreLayout( KConfigGroup &group, const QString &keyName )
93 // Restore the view column order, width and visibility
94 QByteArray state = group.readEntry(
95 keyName.isEmpty() ? QString( KPIM_TREEWIDGET_DEFAULT_CONFIG_KEY ) : keyName,
96 QVariant( QVariant::ByteArray )
97 ).toByteArray();
98 state = QByteArray::fromHex( state );
100 if( state.isEmpty() )
101 return false;
103 int cc = header()->count();
105 // Qt writes also some options that can be set only
106 // programmatically. This can drive you crazy if you
107 // first setup the view and then restore the layout:
108 // it will overwrite your previous settings...
110 bool sectionsWereClickable = header()->isClickable();
111 bool sectionsWereMovable = header()->isMovable();
112 bool sortIndicatorWasShown = header()->isSortIndicatorShown();
113 Qt::Alignment originalDefaultAlignment = header()->defaultAlignment();
114 //int defaultSectionSize = header()->defaultSectionSize();
115 int minimumSectionSize = header()->minimumSectionSize();
116 bool cascadingSectionResizes = header()->cascadingSectionResizes();
117 QVector<QHeaderView::ResizeMode> resizeModes( cc );
118 for ( int i = 0 ; i < cc ; ++i ) {
119 resizeModes[ i ] = header()->resizeMode( i );
122 // Qt (4.4) will perform a layout based on the stored column sizes
123 // when restoreState() is called. However, there is an issue
124 // related to the last section: the restoreState() call will
125 // preserve the _current_ (pre-restoreState()-call) width
126 // of the last section if that is actually greater than the stored
127 // value. This is very likely to throw the last section out of
128 // the view and cause a horizontal scroll bar to appear even
129 // if it wasn't present when saveState() was called.
130 // This seems to be a Qt buggie and we workaround it by
131 // setting all the sections sizes to something very small
132 // just before calling restoreState().
134 // we also need to save the current sections sizes in order to remain
135 // consistent if restoreState() fails for some reason.
136 QVector<int> savedSizes( cc );
137 for ( int i = 0 ; i < cc ; ++i )
139 savedSizes[ i ] = header()->sectionSize( i );
140 header()->resizeSection( i , 10 );
143 if ( !header()->restoreState( state ) )
145 // failed: be consistent and restore the section sizes before returning
146 for ( int c = 0 ; c < cc ; ++c )
147 header()->resizeSection( c , savedSizes[ c ] );
148 return false;
151 header()->setClickable( sectionsWereClickable );
152 header()->setMovable( sectionsWereMovable );
153 header()->setSortIndicatorShown( sortIndicatorWasShown );
154 header()->setDefaultAlignment( originalDefaultAlignment );
155 header()->setMinimumSectionSize( minimumSectionSize );
156 header()->setCascadingSectionResizes( cascadingSectionResizes );
157 for ( int i = 0 ; i < cc ; ++i ) {
158 header()->setResizeMode( i, resizeModes[ i ] );
161 // FIXME: This would cause the sections to be resized and thus
162 // can't be reliably reset after the configuration
163 // has been read. Can do nothing about that except warning
164 // the user in the docs.
165 //header()->setDefaultSectionSize( defaultSectionSize );
167 return true;
170 bool TreeWidget::restoreLayout( KConfig * config, const QString &groupName, const QString &keyName )
172 if( !config || groupName.isEmpty() )
173 return false;
175 if ( !config->hasGroup( groupName ) )
176 return false;
178 KConfigGroup group( config, groupName );
179 return restoreLayout( group, keyName );
182 void TreeWidget::setManualColumnHidingEnabled( bool enable )
184 if( enable )
186 header()->setContextMenuPolicy( Qt::CustomContextMenu ); // make sure it's true
187 QObject::connect( header(), SIGNAL(customContextMenuRequested(QPoint)),
188 this, SLOT(slotHeaderContextMenuRequested(QPoint)) );
189 } else {
190 if ( mEnableManualColumnHiding )
191 QObject::disconnect( header(), SIGNAL(customContextMenuRequested(QPoint)),
192 this, SLOT(slotHeaderContextMenuRequested(QPoint)) );
195 mEnableManualColumnHiding = enable;
198 void TreeWidget::setColumnHidden( int logicalIndex, bool hide )
200 if ( header()->isSectionHidden( logicalIndex ) == hide )
201 return;
202 header()->setSectionHidden( logicalIndex, hide );
204 emit columnVisibilityChanged( logicalIndex );
207 bool TreeWidget::isColumnHidden( int logicalIndex ) const
209 return header()->isSectionHidden( logicalIndex );
212 bool TreeWidget::fillHeaderContextMenu( KMenu * menu, const QPoint & )
214 if ( !menu || !mEnableManualColumnHiding )
215 return false;
217 menu->addTitle( i18n("View Columns") );
219 QTreeWidgetItem * hitem = headerItem();
220 if ( !hitem )
221 return false; // oops..
223 // Dynamically build the menu and check the items for visible columns
224 int cc = hitem->columnCount();
225 if ( cc < 1 )
226 return false;
228 for ( int i = 1 ; i < cc; ++i )
230 QAction * act = menu->addAction( hitem->text( i ) );
231 act->setCheckable( true );
232 if ( !header()->isSectionHidden( i ) )
233 act->setChecked( true );
234 act->setData( QVariant( i ) );
236 connect(
237 act, SIGNAL(triggered(bool)),
238 this, SLOT(slotToggleColumnActionTriggered(bool)) );
241 return true;
244 void TreeWidget::toggleColumn( int logicalIndex )
246 setColumnHidden( logicalIndex, !header()->isSectionHidden( logicalIndex ) );
250 void TreeWidget::slotToggleColumnActionTriggered( bool )
252 QAction *act = dynamic_cast< QAction * >( sender() );
253 if ( !act )
254 return;
256 QVariant data = act->data();
258 bool ok;
259 int id = data.toInt( &ok );
260 if ( !ok )
261 return;
263 if ( id > columnCount() )
264 return;
266 setColumnHidden( id, !act->isChecked() );
269 void TreeWidget::slotHeaderContextMenuRequested( const QPoint &clickPoint )
271 KMenu menu( this );
273 if ( !fillHeaderContextMenu( &menu, clickPoint ) )
274 return;
276 menu.exec( header()->mapToGlobal( clickPoint ) );
279 int TreeWidget::addColumn( const QString &label, int headerAlignment )
281 QTreeWidgetItem * hitem = headerItem();
282 if ( !hitem )
284 // In fact this seems to never happen
285 hitem = new QTreeWidgetItem( this );
286 hitem->setText( 0, label );
287 hitem->setTextAlignment( 0, headerAlignment );
288 setHeaderItem( hitem ); // will set column count to 1
289 return 0;
292 int cc = columnCount();
294 setColumnCount( cc + 1 );
295 hitem->setText( cc, label );
296 hitem->setTextAlignment( cc, headerAlignment );
297 return cc;
300 bool TreeWidget::setColumnText( int columnIndex, const QString &label )
302 if ( columnIndex >= columnCount() )
303 return false;
304 QTreeWidgetItem * hitem = headerItem();
305 if ( !hitem )
306 return false;
307 hitem->setText( columnIndex, label );
308 return true;
311 QTreeWidgetItem * TreeWidget::firstItem() const
313 if ( topLevelItemCount() < 1 )
314 return 0;
315 return topLevelItem( 0 );
318 QTreeWidgetItem * TreeWidget::lastItem() const
320 QTreeWidgetItem *it = 0;
321 int cc = topLevelItemCount();
322 if ( cc < 1 )
323 return 0;
324 it = topLevelItem( cc - 1 );
325 if ( !it )
326 return 0; // sanity check
327 cc = it->childCount();
328 while ( cc > 0 )
330 it = it->child( cc - 1 );
331 if ( !it )
332 return 0; // aaaaaargh: something is really wrong :D
333 cc = it->childCount();
335 return it;