1 /*****************************************************************************
2 * bookmarks.cpp : Bookmarks
3 ****************************************************************************
4 * Copyright (C) 2007-2008 the VideoLAN team
6 * Authors: Antoine Lejeune <phytos@via.ecp.fr>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21 *****************************************************************************/
27 #include "dialogs/bookmarks.hpp"
28 #include "input_manager.hpp"
30 #include <QHBoxLayout>
31 #include <QSpacerItem>
32 #include <QPushButton>
33 #include <QDialogButtonBox>
34 #include <QModelIndexList>
36 BookmarksDialog::BookmarksDialog( intf_thread_t *_p_intf ):QVLCFrame( _p_intf )
38 b_ignore_updates = false;
39 setWindowFlags( Qt::Tool );
40 setWindowOpacity( var_InheritFloat( p_intf, "qt-opacity" ) );
41 setWindowTitle( qtr( "Edit Bookmarks" ) );
42 setWindowRole( "vlc-bookmarks" );
44 QHBoxLayout *layout = new QHBoxLayout( this );
46 QDialogButtonBox *buttonsBox = new QDialogButtonBox( Qt::Vertical );
47 QPushButton *addButton = new QPushButton( qtr( "Create" ) );
48 addButton->setToolTip( qtr( "Create a new bookmark" ) );
49 buttonsBox->addButton( addButton, QDialogButtonBox::ActionRole );
50 delButton = new QPushButton( qtr( "Delete" ) );
51 delButton->setToolTip( qtr( "Delete the selected item" ) );
52 buttonsBox->addButton( delButton, QDialogButtonBox::ActionRole );
53 clearButton = new QPushButton( qtr( "Clear" ) );
54 clearButton->setToolTip( qtr( "Delete all the bookmarks" ) );
55 buttonsBox->addButton( clearButton, QDialogButtonBox::ResetRole );
57 QPushButton *extractButton = new QPushButton( qtr( "Extract" ) );
58 extractButton->setToolTip( qtr() );
59 buttonsBox->addButton( extractButton, QDialogButtonBox::ActionRole );
61 /* ?? Feels strange as Qt guidelines will put reject on top */
62 buttonsBox->addButton( new QPushButton( qtr( "&Close" ) ),
63 QDialogButtonBox::RejectRole);
65 bookmarksList = new QTreeWidget( this );
66 bookmarksList->setRootIsDecorated( false );
67 bookmarksList->setAlternatingRowColors( true );
68 bookmarksList->setSelectionMode( QAbstractItemView::ExtendedSelection );
69 bookmarksList->setSelectionBehavior( QAbstractItemView::SelectRows );
70 bookmarksList->setEditTriggers( QAbstractItemView::SelectedClicked );
71 bookmarksList->setColumnCount( 3 );
72 bookmarksList->resize( sizeHint() );
74 QStringList headerLabels;
75 headerLabels << qtr( "Description" );
76 headerLabels << qtr( "Bytes" );
77 headerLabels << qtr( "Time" );
78 bookmarksList->setHeaderLabels( headerLabels );
80 layout->addWidget( buttonsBox );
81 layout->addWidget( bookmarksList );
83 CONNECT( THEMIM->getIM(), bookmarksChanged(),
86 CONNECT( bookmarksList, activated( QModelIndex ), this,
87 activateItem( QModelIndex ) );
88 CONNECT( bookmarksList, itemChanged( QTreeWidgetItem*, int ),
89 this, edit( QTreeWidgetItem*, int ) );
90 CONNECT( bookmarksList->model(), rowsInserted( const QModelIndex &, int, int ),
91 this, updateButtons() );
92 CONNECT( bookmarksList->model(), rowsRemoved( const QModelIndex &, int, int ),
93 this, updateButtons() );
94 CONNECT( bookmarksList->selectionModel(), selectionChanged( const QItemSelection &, const QItemSelection & ),
95 this, updateButtons() );
96 BUTTONACT( addButton, add() );
97 BUTTONACT( delButton, del() );
98 BUTTONACT( clearButton, clear() );
101 BUTTONACT( extractButton, extract() );
103 CONNECT( buttonsBox, rejected(), this, close() );
106 restoreWidgetPosition( "Bookmarks", QSize( 435, 280 ) );
110 BookmarksDialog::~BookmarksDialog()
112 saveWidgetPosition( "Bookmarks" );
115 void BookmarksDialog::updateButtons()
117 clearButton->setEnabled( bookmarksList->model()->rowCount() > 0 );
118 delButton->setEnabled( bookmarksList->selectionModel()->hasSelection() );
121 void BookmarksDialog::update()
123 if ( b_ignore_updates ) return;
124 input_thread_t *p_input = THEMIM->getInput();
125 if( !p_input ) return;
127 seekpoint_t **pp_bookmarks;
130 if( bookmarksList->topLevelItemCount() > 0 )
132 bookmarksList->model()->removeRows( 0, bookmarksList->topLevelItemCount() );
135 if( input_Control( p_input, INPUT_GET_BOOKMARKS, &pp_bookmarks,
136 &i_bookmarks ) != VLC_SUCCESS )
139 for( int i = 0; i < i_bookmarks; i++ )
141 // List with the differents elements of the row
143 row << QString( qfu( pp_bookmarks[i]->psz_name ) );
145 int total = pp_bookmarks[i]->i_time_offset/ 1000000;
146 int hour = total / (60*60);
147 int min = (total - hour*60*60) / 60;
148 int sec = total - hour*60*60 - min*60;
150 row << str.sprintf("%02d:%02d:%02d", hour, min, sec );
151 QTreeWidgetItem *item = new QTreeWidgetItem( bookmarksList, row );
152 item->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEditable |
153 Qt::ItemIsUserCheckable | Qt::ItemIsEnabled);
154 bookmarksList->insertTopLevelItem( i, item );
155 vlc_seekpoint_Delete( pp_bookmarks[i] );
157 free( pp_bookmarks );
160 void BookmarksDialog::add()
162 input_thread_t *p_input = THEMIM->getInput();
163 if( !p_input ) return;
165 seekpoint_t bookmark;
167 if( !input_Control( p_input, INPUT_GET_BOOKMARK, &bookmark ) )
169 QString name = THEMIM->getIM()->getName() + " #"
170 + QString::number( bookmarksList->topLevelItemCount() );
171 bookmark.psz_name = const_cast<char *>qtu( name );
173 input_Control( p_input, INPUT_ADD_BOOKMARK, &bookmark );
177 void BookmarksDialog::del()
179 input_thread_t *p_input = THEMIM->getInput();
180 if( !p_input ) return;
182 QModelIndexList selected = bookmarksList->selectionModel()->selectedRows();
183 if ( !selected.empty() )
185 b_ignore_updates = true;
186 /* Sort needed to make sure that selected elements are deleted in descending
187 order, otherwise the indexes might change and wrong bookmarks are deleted. */
188 qSort( selected.begin(), selected.end() );
189 QModelIndexList::Iterator it = selected.end();
190 for( --it; it != selected.begin(); it-- )
192 input_Control( p_input, INPUT_DEL_BOOKMARK, (*it).row() );
194 input_Control( p_input, INPUT_DEL_BOOKMARK, (*it).row() );
195 b_ignore_updates = false;
200 void BookmarksDialog::clear()
202 input_thread_t *p_input = THEMIM->getInput();
203 if( !p_input ) return;
205 input_Control( p_input, INPUT_CLEAR_BOOKMARKS );
208 void BookmarksDialog::edit( QTreeWidgetItem *item, int column )
211 // We can only edit a item if it is the last item selected
212 if( bookmarksList->selectedItems().isEmpty() ||
213 bookmarksList->selectedItems().last() != item )
216 input_thread_t *p_input = THEMIM->getInput();
220 // We get the row number of the item
221 int i_edit = bookmarksList->indexOfTopLevelItem( item );
223 // We get the bookmarks list
224 seekpoint_t** pp_bookmarks;
225 seekpoint_t* p_seekpoint = NULL;
228 if( input_Control( p_input, INPUT_GET_BOOKMARKS, &pp_bookmarks,
229 &i_bookmarks ) != VLC_SUCCESS )
232 if( i_edit >= i_bookmarks )
235 // We modify the seekpoint
236 p_seekpoint = pp_bookmarks[i_edit];
239 free( p_seekpoint->psz_name );
240 p_seekpoint->psz_name = strdup( qtu( item->text( column ) ) );
242 else if( column == 2 )
244 fields = item->text( column ).split( ":", QString::SkipEmptyParts );
245 if( fields.count() == 1 )
246 p_seekpoint->i_time_offset = 1000000 * ( fields[0].toInt() );
247 else if( fields.count() == 2 )
248 p_seekpoint->i_time_offset = 1000000 * ( fields[0].toInt() * 60 + fields[1].toInt() );
249 else if( fields.count() == 3 )
250 p_seekpoint->i_time_offset = 1000000 * ( fields[0].toInt() * 3600 + fields[1].toInt() * 60 + fields[2].toInt() );
253 msg_Err( p_intf, "Invalid string format for time" );
258 // Send the modification
259 input_Control( p_input, INPUT_CHANGE_BOOKMARK, p_seekpoint, i_edit );
262 // Clear the bookmark list
263 for( int i = 0; i < i_bookmarks; i++)
264 vlc_seekpoint_Delete( pp_bookmarks[i] );
265 free( pp_bookmarks );
268 void BookmarksDialog::extract()
273 void BookmarksDialog::activateItem( QModelIndex index )
275 input_thread_t *p_input = THEMIM->getInput();
276 if( !p_input ) return;
278 input_Control( p_input, INPUT_SET_BOOKMARK, index.row() );
281 void BookmarksDialog::toggleVisible()
283 /* Update, to show existing bookmarks in case a new playlist
289 QVLCFrame::toggleVisible();