b0436f0e1e2e6d783bdac00e82a76d423b65b4db
[vlc.git] / modules / gui / qt4 / components / playlist / playlist_item.cpp
1 /*****************************************************************************
2  * playlist_item.cpp : Manage playlist item
3  ****************************************************************************
4  * Copyright © 2006-2008 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Clément Stenac <zorglub@videolan.org>
8  *          Jean-Baptiste Kempf <jb@videolan.org>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23  *****************************************************************************/
24
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #include <assert.h>
30
31 #include "qt4.hpp"
32 #include "components/playlist/playlist_model.hpp"
33 #include <vlc_intf_strings.h>
34
35 #include <QSettings>
36
37 #include "sorting.h"
38
39 /*************************************************************************
40  * Playlist item implementation
41  *************************************************************************/
42
43 /*
44    Playlist item is just a wrapper, an abstraction of the playlist_item
45    in order to be managed by PLModel
46
47    PLItem have a parent, and id and a input Id
48 */
49
50
51 void PLItem::init( int _i_id, int _i_input_id, bool _is_node, PLItem *parent, PLModel *m, QSettings *settings )
52 {
53     parentItem = parent;          /* Can be NULL, but only for the rootItem */
54     i_id       = _i_id;           /* Playlist item specific id */
55     i_input_id = _i_input_id;     /* Identifier of the input */
56     model      = m;               /* PLModel (QAbsmodel) */
57     i_type     = -1;              /* Item type - Avoid segfault */
58     b_current  = false;           /* Is the item the current Item or not */
59     b_is_node = _is_node;
60
61     assert( model );              /* We need a model */
62
63     /* No parent, should be the 2 main ones */
64     if( parentItem == NULL )
65     {
66         if( model->i_depth == DEPTH_SEL )  /* Selector Panel */
67         {
68             i_showflags = 0;
69             item_col_strings.append( "" );
70         }
71         else
72         {
73             i_showflags = settings->value( "qt-pl-showflags", COLUMN_DEFAULT ).toInt();
74             if( i_showflags < 1)
75                 i_showflags = COLUMN_DEFAULT; /* reasonable default to show something; */
76             else if ( i_showflags >= COLUMN_END )
77                 i_showflags = COLUMN_END - 1; /* show everything */
78
79             updateColumnHeaders();
80         }
81     }
82     else
83     {
84         i_showflags = parentItem->i_showflags;
85         //Add empty string and update() handles data appending
86         item_col_strings.append( "" );
87     }
88 }
89
90 /*
91    Constructors
92    Call the above function init
93    So far the first constructor isn't used...
94    */
95 PLItem::PLItem( int _i_id, int _i_input_id, bool _is_node, PLItem *parent, PLModel *m )
96 {
97     init( _i_id, _i_input_id, _is_node, parent, m, NULL );
98 }
99
100 PLItem::PLItem( playlist_item_t * p_item, PLItem *parent, PLModel *m )
101 {
102     init( p_item->i_id, p_item->p_input->i_id, p_item->i_children > -1,
103         parent, m, NULL );
104 }
105
106 PLItem::PLItem( playlist_item_t * p_item, QSettings *settings, PLModel *m )
107 {
108     init( p_item->i_id, p_item->p_input->i_id, p_item->i_children > -1,
109         NULL, m, settings );
110 }
111
112 PLItem::~PLItem()
113 {
114     qDeleteAll( children );
115     children.clear();
116 }
117
118 /* Column manager */
119 void PLItem::updateColumnHeaders()
120 {
121     item_col_strings.clear();
122
123     assert( i_showflags < COLUMN_END );
124
125     for( uint32_t i_index=1; i_index < COLUMN_END; i_index <<= 1 )
126     {
127         if( i_showflags & i_index )
128             item_col_strings.append( qfu( psz_column_title( i_index ) ) );
129     }
130 }
131
132 /* So far signal is always true.
133    Using signal false would not call PLModel... Why ?
134  */
135 void PLItem::insertChild( PLItem *item, int i_pos, bool signal )
136 {
137     if( signal )
138         model->beginInsertRows( model->index( this , 0 ), i_pos, i_pos );
139     children.insert( i_pos, item );
140     if( signal )
141         model->endInsertRows();
142 }
143
144 void PLItem::remove( PLItem *removed )
145 {
146     if( model->i_depth == DEPTH_SEL || parentItem )
147     {
148         int i_index = parentItem->children.indexOf( removed );
149         model->beginRemoveRows( model->index( parentItem, 0 ),
150                                 i_index, i_index );
151         parentItem->children.removeAt( i_index );
152         model->endRemoveRows();
153     }
154 }
155
156 /* This function is used to get one's parent's row number in the model */
157 int PLItem::row() const
158 {
159     if( parentItem )
160         return parentItem->children.indexOf( const_cast<PLItem*>(this) );
161        // We don't ever inherit PLItem, yet, but it might come :D
162     return 0;
163 }
164
165 /* update the PL Item, get the good names and so on */
166 /* This function may not be the best way to do it
167    It destroys everything and gets everything again instead of just
168    building the necessary columns.
169    This does extra work if you re-display the same column. Slower...
170    On the other hand, this way saves memory.
171    There must be a more clever way.
172    */
173 void PLItem::update( playlist_item_t *p_item, bool iscurrent )
174 {
175     assert( p_item->p_input->i_id == i_input_id );
176
177     /* Useful for the model */
178     i_type = p_item->p_input->i_type;
179     b_current = iscurrent;
180     b_is_node = p_item->i_children > -1;
181
182     item_col_strings.clear();
183
184     if( model->i_depth == 1 )  /* Selector Panel */
185     {
186         item_col_strings.append( qfu( p_item->p_input->psz_name ) );
187         return;
188     }
189
190     i_showflags = parentItem ? parentItem->i_showflags : i_showflags;
191
192     /* Meta: ID */
193     if( i_showflags & COLUMN_NUMBER )
194     {
195         QModelIndex idx = model->index( this, 0 );
196         item_col_strings.append( QString::number( idx.row() + 1 ) );
197     }
198     /* Other meta informations */
199     for( uint32_t i_index=2; i_index < COLUMN_END; i_index <<= 1 )
200     {
201         if( i_showflags & i_index )
202         {
203             char *psz = psz_column_meta( p_item->p_input, i_index );
204             item_col_strings.append( qfu( psz ) );
205             free( psz );
206         }
207     }
208 }
209