2018-02-27 18:06:05 +01:00
/*
* Strawberry Music Player
* This file was part of Clementine .
* Copyright 2010 , David Sansome < me @ davidsansome . com >
2021-03-20 21:14:47 +01:00
* Copyright 2018 - 2021 , Jonas Kvinge < jonas @ jkvinge . net >
2018-02-27 18:06:05 +01:00
*
* Strawberry is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
* Strawberry is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with Strawberry . If not , see < http : //www.gnu.org/licenses/>.
2018-08-09 18:39:44 +02:00
*
2018-02-27 18:06:05 +01:00
*/
# include "config.h"
# include <memory>
2018-05-01 00:41:33 +02:00
# include <QtGlobal>
2018-02-27 18:06:05 +01:00
# include <QApplication>
2018-05-01 00:41:33 +02:00
# include <QObject>
# include <QWidget>
# include <QAbstractItemView>
# include <QSortFilterProxyModel>
# include <QItemSelectionModel>
# include <QStyleOptionViewItem>
# include <QMimeData>
# include <QAction>
# include <QVariant>
# include <QUrl>
# include <QFont>
# include <QFontMetrics>
# include <QString>
# include <QStringList>
# include <QPixmap>
2018-02-27 18:06:05 +01:00
# include <QPainter>
2018-05-01 00:41:33 +02:00
# include <QPalette>
# include <QRect>
# include <QStyle>
# include <QMenu>
# include <QFlags>
2018-02-27 18:06:05 +01:00
# include <QPushButton>
2018-05-01 00:41:33 +02:00
# include <QMessageBox>
# include <QtEvents>
2018-02-27 18:06:05 +01:00
2018-05-01 00:41:33 +02:00
# include "core/iconloader.h"
2018-02-27 18:06:05 +01:00
# include "core/application.h"
# include "core/deletefiles.h"
# include "core/mergedproxymodel.h"
# include "core/mimedata.h"
2018-05-01 00:41:33 +02:00
# include "core/musicstorage.h"
2020-04-27 00:22:46 +02:00
# include "core/utilities.h"
2020-08-04 21:18:14 +02:00
# include "organize/organizedialog.h"
# include "organize/organizeerrordialog.h"
2018-02-27 18:06:05 +01:00
# include "collection/collectiondirectorymodel.h"
# include "collection/collectionmodel.h"
2019-05-27 21:10:37 +02:00
# include "collection/collectionitemdelegate.h"
2018-05-01 00:41:33 +02:00
# include "connecteddevice.h"
# include "devicelister.h"
# include "devicemanager.h"
# include "deviceproperties.h"
# include "deviceview.h"
2018-02-27 18:06:05 +01:00
const int DeviceItemDelegate : : kIconPadding = 6 ;
2018-09-30 00:08:09 +02:00
DeviceItemDelegate : : DeviceItemDelegate ( QObject * parent ) : CollectionItemDelegate ( parent ) { }
2018-02-27 18:06:05 +01:00
2021-01-26 16:48:04 +01:00
void DeviceItemDelegate : : paint ( QPainter * painter , const QStyleOptionViewItem & option , const QModelIndex & idx ) const {
2018-02-27 18:06:05 +01:00
// Is it a device or a collection item?
2021-01-26 16:48:04 +01:00
if ( idx . data ( DeviceManager : : Role : : Role_State ) . isNull ( ) ) {
CollectionItemDelegate : : paint ( painter , option , idx ) ;
2018-02-27 18:06:05 +01:00
return ;
}
// Draw the background
2018-11-28 17:45:50 +01:00
const QWidget * widget = option . widget ;
2018-02-27 18:06:05 +01:00
QStyle * style = widget - > style ( ) ? widget - > style ( ) : QApplication : : style ( ) ;
2018-11-28 17:45:50 +01:00
style - > drawPrimitive ( QStyle : : PE_PanelItemViewItem , & option , painter , widget ) ;
2018-02-27 18:06:05 +01:00
2018-11-28 17:45:50 +01:00
painter - > save ( ) ;
2018-02-27 18:06:05 +01:00
// Font for the status line
2018-11-28 17:45:50 +01:00
QFont status_font ( option . font ) ;
2018-02-27 18:06:05 +01:00
# ifdef Q_OS_WIN32
status_font . setPointSize ( status_font . pointSize ( ) - 1 ) ;
# else
status_font . setPointSize ( status_font . pointSize ( ) - 2 ) ;
# endif
2018-11-28 17:45:50 +01:00
const int text_height = QFontMetrics ( option . font ) . height ( ) + QFontMetrics ( status_font ) . height ( ) ;
2018-02-27 18:06:05 +01:00
2018-11-28 17:45:50 +01:00
QRect line1 ( option . rect ) ;
QRect line2 ( option . rect ) ;
line1 . setTop ( line1 . top ( ) + ( option . rect . height ( ) - text_height ) / 2 ) ;
line2 . setTop ( line1 . top ( ) + QFontMetrics ( option . font ) . height ( ) ) ;
2018-02-27 18:06:05 +01:00
line1 . setLeft ( line1 . left ( ) + DeviceManager : : kDeviceIconSize + kIconPadding ) ;
line2 . setLeft ( line2 . left ( ) + DeviceManager : : kDeviceIconSize + kIconPadding ) ;
// Change the color for selected items
2018-11-28 17:45:50 +01:00
if ( option . state & QStyle : : State_Selected ) {
painter - > setPen ( option . palette . color ( QPalette : : HighlightedText ) ) ;
2018-02-27 18:06:05 +01:00
}
// Draw the icon
2021-01-26 16:48:04 +01:00
painter - > drawPixmap ( option . rect . topLeft ( ) , idx . data ( Qt : : DecorationRole ) . value < QPixmap > ( ) ) ;
2018-02-27 18:06:05 +01:00
// Draw the first line (device name)
2021-01-26 16:48:04 +01:00
painter - > drawText ( line1 , Qt : : AlignLeft | Qt : : AlignTop , idx . data ( ) . toString ( ) ) ;
2018-02-27 18:06:05 +01:00
// Draw the second line (status)
2021-01-26 16:48:04 +01:00
DeviceManager : : State state = static_cast < DeviceManager : : State > ( idx . data ( DeviceManager : : Role_State ) . toInt ( ) ) ;
QVariant progress = idx . data ( DeviceManager : : Role_UpdatingPercentage ) ;
2018-02-27 18:06:05 +01:00
QString status_text ;
if ( progress . isValid ( ) ) {
status_text = tr ( " Updating %1%... " ) . arg ( progress . toInt ( ) ) ;
}
else {
switch ( state ) {
case DeviceManager : : State_Remembered :
status_text = tr ( " Not connected " ) ;
break ;
case DeviceManager : : State_NotMounted :
status_text = tr ( " Not mounted - double click to mount " ) ;
break ;
case DeviceManager : : State_NotConnected :
status_text = tr ( " Double click to open " ) ;
break ;
case DeviceManager : : State_Connected : {
2021-01-26 16:48:04 +01:00
QVariant song_count = idx . data ( DeviceManager : : Role_SongCount ) ;
2018-02-27 18:06:05 +01:00
if ( song_count . isValid ( ) ) {
int count = song_count . toInt ( ) ;
2019-01-06 17:41:56 +01:00
status_text = tr ( " %1 song%2 " ) . arg ( count ) . arg ( count = = 1 ? " " : " s " ) ;
2018-02-27 18:06:05 +01:00
}
else {
2021-01-26 16:48:04 +01:00
status_text = idx . data ( DeviceManager : : Role_MountPath ) . toString ( ) ;
2018-02-27 18:06:05 +01:00
}
break ;
}
}
}
2020-04-27 00:22:46 +02:00
if ( option . state & QStyle : : State_Selected ) {
2018-11-28 17:45:50 +01:00
painter - > setPen ( option . palette . color ( QPalette : : HighlightedText ) ) ;
2020-04-27 00:22:46 +02:00
}
else {
if ( Utilities : : IsColorDark ( option . palette . color ( QPalette : : Window ) ) ) {
painter - > setPen ( option . palette . color ( QPalette : : Midlight ) . lighter ( ) . lighter ( ) ) ;
}
else {
painter - > setPen ( option . palette . color ( QPalette : : Dark ) ) ;
}
}
2018-02-27 18:06:05 +01:00
2018-11-28 17:45:50 +01:00
painter - > setFont ( status_font ) ;
painter - > drawText ( line2 , Qt : : AlignLeft | Qt : : AlignTop , status_text ) ;
painter - > restore ( ) ;
2018-03-10 13:02:56 +01:00
2018-02-27 18:06:05 +01:00
}
DeviceView : : DeviceView ( QWidget * parent )
: AutoExpandingTreeView ( parent ) ,
app_ ( nullptr ) ,
merged_model_ ( nullptr ) ,
sort_model_ ( nullptr ) ,
properties_dialog_ ( new DeviceProperties ) ,
device_menu_ ( nullptr ) ,
2021-06-20 23:53:28 +02:00
eject_action_ ( nullptr ) ,
forget_action_ ( nullptr ) ,
properties_action_ ( nullptr ) ,
collection_menu_ ( nullptr ) ,
load_action_ ( nullptr ) ,
add_to_playlist_action_ ( nullptr ) ,
open_in_new_playlist_ ( nullptr ) ,
organize_action_ ( nullptr ) ,
delete_action_ ( nullptr ) {
2018-02-27 18:06:05 +01:00
setItemDelegate ( new DeviceItemDelegate ( this ) ) ;
SetExpandOnReset ( false ) ;
setAttribute ( Qt : : WA_MacShowFocusRect , false ) ;
setHeaderHidden ( true ) ;
setAllColumnsShowFocus ( true ) ;
setDragEnabled ( true ) ;
setDragDropMode ( QAbstractItemView : : DragOnly ) ;
setSelectionMode ( QAbstractItemView : : ExtendedSelection ) ;
}
2020-06-15 21:55:05 +02:00
DeviceView : : ~ DeviceView ( ) = default ;
2018-02-27 18:06:05 +01:00
void DeviceView : : SetApplication ( Application * app ) {
Q_ASSERT ( app_ = = nullptr ) ;
app_ = app ;
2021-01-26 16:48:04 +01:00
QObject : : connect ( app_ - > device_manager ( ) , & DeviceManager : : DeviceConnected , this , & DeviceView : : DeviceConnected ) ;
QObject : : connect ( app_ - > device_manager ( ) , & DeviceManager : : DeviceDisconnected , this , & DeviceView : : DeviceDisconnected ) ;
2018-02-27 18:06:05 +01:00
sort_model_ = new QSortFilterProxyModel ( this ) ;
sort_model_ - > setSourceModel ( app_ - > device_manager ( ) ) ;
sort_model_ - > setDynamicSortFilter ( true ) ;
sort_model_ - > setSortCaseSensitivity ( Qt : : CaseInsensitive ) ;
sort_model_ - > sort ( 0 ) ;
merged_model_ = new MergedProxyModel ( this ) ;
merged_model_ - > setSourceModel ( sort_model_ ) ;
2018-09-14 23:05:58 +02:00
setModel ( merged_model_ ) ;
2018-02-27 18:06:05 +01:00
2021-01-26 16:48:04 +01:00
QObject : : connect ( merged_model_ , & MergedProxyModel : : SubModelReset , this , & AutoExpandingTreeView : : RecursivelyExpandSlot ) ;
2018-02-27 18:06:05 +01:00
properties_dialog_ - > SetDeviceManager ( app_ - > device_manager ( ) ) ;
2020-08-04 21:18:14 +02:00
organize_dialog_ . reset ( new OrganizeDialog ( app_ - > task_manager ( ) , nullptr , this ) ) ;
organize_dialog_ - > SetDestinationModel ( app_ - > collection_model ( ) - > directory_model ( ) ) ;
2018-02-27 18:06:05 +01:00
}
void DeviceView : : contextMenuEvent ( QContextMenuEvent * e ) {
if ( ! device_menu_ ) {
device_menu_ = new QMenu ( this ) ;
collection_menu_ = new QMenu ( this ) ;
// Device menu
2021-01-26 16:48:04 +01:00
eject_action_ = device_menu_ - > addAction ( IconLoader : : Load ( " media-eject " ) , tr ( " Safely remove device " ) , this , & DeviceView : : Unmount ) ;
forget_action_ = device_menu_ - > addAction ( IconLoader : : Load ( " list-remove " ) , tr ( " Forget device " ) , this , & DeviceView : : Forget ) ;
2018-02-27 18:06:05 +01:00
device_menu_ - > addSeparator ( ) ;
2021-01-26 16:48:04 +01:00
properties_action_ = device_menu_ - > addAction ( IconLoader : : Load ( " configure " ) , tr ( " Device properties... " ) , this , & DeviceView : : Properties ) ;
2018-02-27 18:06:05 +01:00
// Collection menu
2021-01-26 16:48:04 +01:00
add_to_playlist_action_ = collection_menu_ - > addAction ( IconLoader : : Load ( " media-playback-start " ) , tr ( " Append to current playlist " ) , this , & DeviceView : : AddToPlaylist ) ;
load_action_ = collection_menu_ - > addAction ( IconLoader : : Load ( " media-playback-start " ) , tr ( " Replace current playlist " ) , this , & DeviceView : : Load ) ;
open_in_new_playlist_ = collection_menu_ - > addAction ( IconLoader : : Load ( " document-new " ) , tr ( " Open in new playlist " ) , this , & DeviceView : : OpenInNewPlaylist ) ;
2018-02-27 18:06:05 +01:00
collection_menu_ - > addSeparator ( ) ;
2021-01-26 16:48:04 +01:00
organize_action_ = collection_menu_ - > addAction ( IconLoader : : Load ( " edit-copy " ) , tr ( " Copy to collection... " ) , this , & DeviceView : : Organize ) ;
delete_action_ = collection_menu_ - > addAction ( IconLoader : : Load ( " edit-delete " ) , tr ( " Delete from device... " ) , this , & DeviceView : : Delete ) ;
2018-02-27 18:06:05 +01:00
}
menu_index_ = currentIndex ( ) ;
const QModelIndex device_index = MapToDevice ( menu_index_ ) ;
const QModelIndex collection_index = MapToCollection ( menu_index_ ) ;
if ( device_index . isValid ( ) ) {
2019-01-21 17:44:37 +01:00
const bool is_plugged_in = app_ - > device_manager ( ) - > GetLister ( device_index ) ;
const bool is_remembered = app_ - > device_manager ( ) - > GetDatabaseId ( device_index ) ! = - 1 ;
2018-02-27 18:06:05 +01:00
forget_action_ - > setEnabled ( is_remembered ) ;
eject_action_ - > setEnabled ( is_plugged_in ) ;
device_menu_ - > popup ( e - > globalPos ( ) ) ;
2018-03-10 13:02:56 +01:00
}
else if ( collection_index . isValid ( ) ) {
2018-02-27 18:06:05 +01:00
const QModelIndex parent_device_index = FindParentDevice ( menu_index_ ) ;
bool is_filesystem_device = false ;
if ( parent_device_index . isValid ( ) ) {
2019-01-21 17:44:37 +01:00
std : : shared_ptr < ConnectedDevice > device = app_ - > device_manager ( ) - > GetConnectedDevice ( parent_device_index ) ;
2018-02-27 18:06:05 +01:00
if ( device & & ! device - > LocalPath ( ) . isEmpty ( ) ) is_filesystem_device = true ;
}
2020-08-04 21:18:14 +02:00
organize_action_ - > setEnabled ( is_filesystem_device ) ;
2018-02-27 18:06:05 +01:00
collection_menu_ - > popup ( e - > globalPos ( ) ) ;
}
}
QModelIndex DeviceView : : MapToDevice ( const QModelIndex & merged_model_index ) const {
QModelIndex sort_model_index = merged_model_ - > mapToSource ( merged_model_index ) ;
2018-09-14 23:05:58 +02:00
if ( sort_model_index . model ( ) ! = sort_model_ ) return QModelIndex ( ) ;
2018-02-27 18:06:05 +01:00
return sort_model_ - > mapToSource ( sort_model_index ) ;
}
QModelIndex DeviceView : : FindParentDevice ( const QModelIndex & merged_model_index ) const {
2021-01-26 16:48:04 +01:00
QModelIndex idx = merged_model_ - > FindSourceParent ( merged_model_index ) ;
if ( idx . model ( ) ! = sort_model_ ) return QModelIndex ( ) ;
return sort_model_ - > mapToSource ( idx ) ;
2018-02-27 18:06:05 +01:00
}
QModelIndex DeviceView : : MapToCollection ( const QModelIndex & merged_model_index ) const {
QModelIndex sort_model_index = merged_model_ - > mapToSource ( merged_model_index ) ;
if ( const QSortFilterProxyModel * sort_model = qobject_cast < const QSortFilterProxyModel * > ( sort_model_index . model ( ) ) ) {
return sort_model - > mapToSource ( sort_model_index ) ;
}
return QModelIndex ( ) ;
}
void DeviceView : : Connect ( ) {
QModelIndex device_idx = MapToDevice ( menu_index_ ) ;
app_ - > device_manager ( ) - > data ( device_idx , MusicStorage : : Role_StorageForceConnect ) ;
}
2021-06-20 19:04:08 +02:00
void DeviceView : : DeviceConnected ( const QModelIndex & idx ) {
2018-02-27 18:06:05 +01:00
2019-01-21 17:44:37 +01:00
if ( ! idx . isValid ( ) ) return ;
std : : shared_ptr < ConnectedDevice > device = app_ - > device_manager ( ) - > GetConnectedDevice ( idx ) ;
2018-02-27 18:06:05 +01:00
if ( ! device ) return ;
2019-01-21 17:44:37 +01:00
QModelIndex sort_idx = sort_model_ - > mapFromSource ( idx ) ;
2019-01-05 23:17:20 +01:00
if ( ! sort_idx . isValid ( ) ) return ;
2018-02-27 18:06:05 +01:00
QSortFilterProxyModel * sort_model = new QSortFilterProxyModel ( device - > model ( ) ) ;
sort_model - > setSourceModel ( device - > model ( ) ) ;
sort_model - > setSortRole ( CollectionModel : : Role_SortText ) ;
sort_model - > setDynamicSortFilter ( true ) ;
sort_model - > sort ( 0 ) ;
merged_model_ - > AddSubModel ( sort_idx , sort_model ) ;
expand ( menu_index_ ) ;
2018-03-10 13:02:56 +01:00
2018-02-27 18:06:05 +01:00
}
2021-06-20 19:04:08 +02:00
void DeviceView : : DeviceDisconnected ( const QModelIndex & idx ) {
2019-01-21 17:44:37 +01:00
if ( ! idx . isValid ( ) ) return ;
merged_model_ - > RemoveSubModel ( sort_model_ - > mapFromSource ( idx ) ) ;
2018-02-27 18:06:05 +01:00
}
void DeviceView : : Forget ( ) {
QModelIndex device_idx = MapToDevice ( menu_index_ ) ;
QString unique_id = app_ - > device_manager ( ) - > data ( device_idx , DeviceManager : : Role_UniqueId ) . toString ( ) ;
2019-01-21 17:44:37 +01:00
if ( app_ - > device_manager ( ) - > GetLister ( device_idx ) & & app_ - > device_manager ( ) - > GetLister ( device_idx ) - > AskForScan ( unique_id ) ) {
2018-02-27 18:06:05 +01:00
std : : unique_ptr < QMessageBox > dialog ( new QMessageBox (
QMessageBox : : Question , tr ( " Forget device " ) ,
tr ( " Forgetting a device will remove it from this list and Strawberry will have to rescan all the songs again next time you connect it. " ) ,
QMessageBox : : Cancel , this ) ) ;
QPushButton * forget = dialog - > addButton ( tr ( " Forget device " ) , QMessageBox : : DestructiveRole ) ;
dialog - > exec ( ) ;
if ( dialog - > clickedButton ( ) ! = forget ) return ;
}
2019-01-21 17:44:37 +01:00
app_ - > device_manager ( ) - > Forget ( device_idx ) ;
2018-02-27 18:06:05 +01:00
}
void DeviceView : : Properties ( ) {
2019-01-21 17:44:37 +01:00
properties_dialog_ - > ShowDevice ( MapToDevice ( menu_index_ ) ) ;
2018-02-27 18:06:05 +01:00
}
2021-01-26 16:48:04 +01:00
void DeviceView : : mouseDoubleClickEvent ( QMouseEvent * e ) {
2018-02-27 18:06:05 +01:00
2021-01-26 16:48:04 +01:00
AutoExpandingTreeView : : mouseDoubleClickEvent ( e ) ;
2018-02-27 18:06:05 +01:00
2021-01-26 16:48:04 +01:00
QModelIndex merged_index = indexAt ( e - > pos ( ) ) ;
2018-02-27 18:06:05 +01:00
QModelIndex device_index = MapToDevice ( merged_index ) ;
if ( device_index . isValid ( ) ) {
2019-01-21 17:44:37 +01:00
if ( ! app_ - > device_manager ( ) - > GetConnectedDevice ( device_index ) ) {
2018-02-27 18:06:05 +01:00
menu_index_ = merged_index ;
Connect ( ) ;
}
}
}
SongList DeviceView : : GetSelectedSongs ( ) const {
QModelIndexList selected_merged_indexes = selectionModel ( ) - > selectedRows ( ) ;
SongList songs ;
for ( const QModelIndex & merged_index : selected_merged_indexes ) {
QModelIndex collection_index = MapToCollection ( merged_index ) ;
if ( ! collection_index . isValid ( ) ) continue ;
const CollectionModel * collection = qobject_cast < const CollectionModel * > ( collection_index . model ( ) ) ;
if ( ! collection ) continue ;
songs < < collection - > GetChildSongs ( collection_index ) ;
}
return songs ;
}
void DeviceView : : Load ( ) {
2020-04-23 21:08:28 +02:00
QMimeData * q_mimedata = model ( ) - > mimeData ( selectedIndexes ( ) ) ;
if ( MimeData * mimedata = qobject_cast < MimeData * > ( q_mimedata ) ) {
mimedata - > clear_first_ = true ;
2018-02-27 18:06:05 +01:00
}
2020-04-23 21:08:28 +02:00
emit AddToPlaylistSignal ( q_mimedata ) ;
2018-02-27 18:06:05 +01:00
}
void DeviceView : : AddToPlaylist ( ) {
emit AddToPlaylistSignal ( model ( ) - > mimeData ( selectedIndexes ( ) ) ) ;
}
void DeviceView : : OpenInNewPlaylist ( ) {
2020-04-23 21:08:28 +02:00
QMimeData * q_mimedata = model ( ) - > mimeData ( selectedIndexes ( ) ) ;
if ( MimeData * mimedata = qobject_cast < MimeData * > ( q_mimedata ) ) {
mimedata - > open_in_new_playlist_ = true ;
2018-02-27 18:06:05 +01:00
}
2020-04-23 21:08:28 +02:00
emit AddToPlaylistSignal ( q_mimedata ) ;
2018-02-27 18:06:05 +01:00
}
void DeviceView : : Delete ( ) {
2021-03-21 04:47:11 +01:00
QModelIndexList selected_indexes = selectedIndexes ( ) ;
if ( selected_indexes . isEmpty ( ) ) return ;
2018-02-27 18:06:05 +01:00
// Take the device of the first selected item
2021-03-21 04:47:11 +01:00
QModelIndex device_index = FindParentDevice ( selected_indexes [ 0 ] ) ;
2018-02-27 18:06:05 +01:00
if ( ! device_index . isValid ( ) ) return ;
2021-03-21 04:47:11 +01:00
if ( QMessageBox : : question ( this , tr ( " Delete files " ) , tr ( " These files will be deleted from the device, are you sure you want to continue? " ) , QMessageBox : : Yes , QMessageBox : : Cancel ) ! = QMessageBox : : Yes ) {
2018-02-27 18:06:05 +01:00
return ;
2021-03-21 04:47:11 +01:00
}
2018-02-27 18:06:05 +01:00
std : : shared_ptr < MusicStorage > storage = device_index . data ( MusicStorage : : Role_Storage ) . value < std : : shared_ptr < MusicStorage > > ( ) ;
2020-08-19 22:02:35 +02:00
DeleteFiles * delete_files = new DeleteFiles ( app_ - > task_manager ( ) , storage , false ) ;
2021-01-26 16:48:04 +01:00
QObject : : connect ( delete_files , & DeleteFiles : : Finished , this , & DeviceView : : DeleteFinished ) ;
2018-02-27 18:06:05 +01:00
delete_files - > Start ( GetSelectedSongs ( ) ) ;
}
2020-08-04 21:18:14 +02:00
void DeviceView : : Organize ( ) {
2018-02-27 18:06:05 +01:00
2021-06-20 19:04:08 +02:00
const SongList songs = GetSelectedSongs ( ) ;
2018-02-27 18:06:05 +01:00
QStringList filenames ;
2021-06-20 19:04:08 +02:00
filenames . reserve ( songs . count ( ) ) ;
2018-02-27 18:06:05 +01:00
for ( const Song & song : songs ) {
filenames < < song . url ( ) . toLocalFile ( ) ;
}
2020-08-04 21:18:14 +02:00
organize_dialog_ - > SetCopy ( true ) ;
organize_dialog_ - > SetFilenames ( filenames ) ;
organize_dialog_ - > show ( ) ;
2018-02-27 18:06:05 +01:00
}
void DeviceView : : Unmount ( ) {
QModelIndex device_idx = MapToDevice ( menu_index_ ) ;
2019-01-21 17:44:37 +01:00
app_ - > device_manager ( ) - > Unmount ( device_idx ) ;
2018-02-27 18:06:05 +01:00
}
void DeviceView : : DeleteFinished ( const SongList & songs_with_errors ) {
if ( songs_with_errors . isEmpty ( ) ) return ;
2020-08-04 21:18:14 +02:00
OrganizeErrorDialog * dialog = new OrganizeErrorDialog ( this ) ;
dialog - > Show ( OrganizeErrorDialog : : Type_Delete , songs_with_errors ) ;
2018-02-27 18:06:05 +01:00
// It deletes itself when the user closes it
}
2020-06-14 18:58:24 +02:00
bool DeviceView : : CanRecursivelyExpand ( const QModelIndex & idx ) const {
2018-02-27 18:06:05 +01:00
// Never expand devices
2020-06-14 18:58:24 +02:00
return idx . parent ( ) . isValid ( ) ;
2018-02-27 18:06:05 +01:00
}