diff --git a/src/core/musicstorage.h b/src/core/musicstorage.h index 072572992..4706622a0 100644 --- a/src/core/musicstorage.h +++ b/src/core/musicstorage.h @@ -26,7 +26,11 @@ public: MusicStorage(); virtual ~MusicStorage() {} - static const int kStorageRole = Qt::UserRole + 100; + enum Role { + Role_Storage = Qt::UserRole + 100, + Role_Capacity, + Role_FreeSpace, + }; virtual QString LocalPath() const { return QString(); } diff --git a/src/core/utilities.cpp b/src/core/utilities.cpp index 7dbb93ed1..9c5b88fad 100644 --- a/src/core/utilities.cpp +++ b/src/core/utilities.cpp @@ -19,6 +19,8 @@ #include #include +#include + namespace Utilities { static QString tr(const char* str) { @@ -72,4 +74,20 @@ QString PrettySize(quint64 bytes) { return ret; } +quint64 FileSystemCapacity(const QString& path) { + struct statvfs fs_info; + if (statvfs(path.toLocal8Bit().constData(), &fs_info) == 0) + return fs_info.f_blocks * fs_info.f_bsize; + + return 0; +} + +quint64 FileSystemFreeSpace(const QString& path) { + struct statvfs fs_info; + if (statvfs(path.toLocal8Bit().constData(), &fs_info) == 0) + return fs_info.f_bavail * fs_info.f_bsize; + + return 0; +} + } // namespace diff --git a/src/core/utilities.h b/src/core/utilities.h index 6b9725760..42df881eb 100644 --- a/src/core/utilities.h +++ b/src/core/utilities.h @@ -23,6 +23,9 @@ namespace Utilities { QString PrettyTime(int seconds); QString PrettySize(quint64 bytes); QString WordyTime(quint64 seconds); + + quint64 FileSystemCapacity(const QString& path); + quint64 FileSystemFreeSpace(const QString& path); } #endif // UTILITIES_H diff --git a/src/devices/devicekitlister.cpp b/src/devices/devicekitlister.cpp index 86fc5d1e9..b5d3b84a7 100644 --- a/src/devices/devicekitlister.cpp +++ b/src/devices/devicekitlister.cpp @@ -17,6 +17,7 @@ #include "config.h" #include "devicekitlister.h" #include "filesystemdevice.h" +#include "core/utilities.h" #include "dbus/udisks.h" #include "dbus/udisksdevice.h" @@ -178,12 +179,8 @@ DeviceKitLister::DeviceData DeviceKitLister::ReadDeviceData( ret.device_mount_paths = device.deviceMountPaths(); // Get free space info - if (!ret.device_mount_paths.isEmpty()) { - struct statvfs fs_info; - if (statvfs(ret.device_mount_paths[0].toLocal8Bit().constData(), &fs_info) == 0) { - ret.free_space = fs_info.f_bavail * fs_info.f_bsize; - } - } + if (!ret.device_mount_paths.isEmpty()) + ret.free_space = Utilities::FileSystemFreeSpace(ret.device_mount_paths[0]); return ret; } diff --git a/src/devices/devicemanager.cpp b/src/devices/devicemanager.cpp index f0b53751f..2f893e280 100644 --- a/src/devices/devicemanager.cpp +++ b/src/devices/devicemanager.cpp @@ -217,9 +217,11 @@ QVariant DeviceManager::data(const QModelIndex& index, int role) const { return info.icon_name_; case Role_Capacity: + case MusicStorage::Role_Capacity: return info.size_; case Role_FreeSpace: + case MusicStorage::Role_FreeSpace: return info.BestBackend()->lister_ ? info.BestBackend()->lister_->DeviceFreeSpace(info.BestBackend()->unique_id_) : QVariant(); @@ -236,7 +238,7 @@ QVariant DeviceManager::data(const QModelIndex& index, int role) const { return QVariant(); return info.task_percentage_; - case MusicStorage::kStorageRole: + case MusicStorage::Role_Storage: if (!info.device_) const_cast(this)->Connect(index.row()); if (!info.device_) diff --git a/src/library/librarydirectorymodel.cpp b/src/library/librarydirectorymodel.cpp index 60cdf5be4..313ff28c6 100644 --- a/src/library/librarydirectorymodel.cpp +++ b/src/library/librarydirectorymodel.cpp @@ -18,6 +18,7 @@ #include "librarybackend.h" #include "core/filesystemmusicstorage.h" #include "core/musicstorage.h" +#include "core/utilities.h" #include "ui/iconloader.h" LibraryDirectoryModel::LibraryDirectoryModel(LibraryBackend* backend, QObject* parent) @@ -70,9 +71,17 @@ void LibraryDirectoryModel::RemoveDirectory(const QModelIndex& index) { } QVariant LibraryDirectoryModel::data(const QModelIndex &index, int role) const { - if (role == MusicStorage::kStorageRole) { + switch (role) { + case MusicStorage::Role_Storage: return QVariant::fromValue(storage_[index.row()]); - } - return QStandardItemModel::data(index, role); + case MusicStorage::Role_FreeSpace: + return Utilities::FileSystemFreeSpace(data(index, Qt::DisplayRole).toString()); + + case MusicStorage::Role_Capacity: + return Utilities::FileSystemCapacity(data(index, Qt::DisplayRole).toString()); + + default: + return QStandardItemModel::data(index, role); + } } diff --git a/src/library/libraryview.cpp b/src/library/libraryview.cpp index 9e1880c38..87f938528 100644 --- a/src/library/libraryview.cpp +++ b/src/library/libraryview.cpp @@ -250,24 +250,30 @@ void LibraryView::scrollTo(const QModelIndex &index, ScrollHint hint) { QTreeView::scrollTo(index, hint); } -QStringList LibraryView::GetSelectedFilenames() const { +void LibraryView::GetSelectedFileInfo( + QStringList *filenames, quint64 *size) const { QModelIndexList selected_indexes = qobject_cast(model())->mapSelectionToSource( selectionModel()->selection()).indexes(); SongList songs = library_->GetChildSongs(selected_indexes); - QStringList ret; + *size = 0; foreach (const Song& song, songs) { - ret << song.filename(); - } + *filenames << song.filename(); - return ret; + if (song.filesize() >= 0) + *size += song.filesize(); + } } void LibraryView::Organise() { + QStringList filenames; + quint64 size = 0; + GetSelectedFileInfo(&filenames, &size); + organise_dialog_->SetDestinationModel(library_->directory_model()); organise_dialog_->SetCopy(false); - organise_dialog_->SetFilenames(GetSelectedFilenames()); + organise_dialog_->SetFilenames(filenames, size); organise_dialog_->show(); } @@ -276,8 +282,12 @@ void LibraryView::Delete() { } void LibraryView::CopyToDevice() { + QStringList filenames; + quint64 size = 0; + GetSelectedFileInfo(&filenames, &size); + organise_dialog_->SetDestinationModel(devices_->connected_devices_model(), true); organise_dialog_->SetCopy(true); - organise_dialog_->SetFilenames(GetSelectedFilenames()); + organise_dialog_->SetFilenames(filenames, size); organise_dialog_->show(); } diff --git a/src/library/libraryview.h b/src/library/libraryview.h index 5be9b73bc..96493d16d 100644 --- a/src/library/libraryview.h +++ b/src/library/libraryview.h @@ -78,7 +78,7 @@ class LibraryView : public AutoExpandingTreeView { private: void RecheckIsEmpty(); void ShowInVarious(bool on); - QStringList GetSelectedFilenames() const; + void GetSelectedFileInfo(QStringList* filenames, quint64* size) const; private: LibraryModel* library_; diff --git a/src/ui/organisedialog.cpp b/src/ui/organisedialog.cpp index 46b41e657..34e3a6554 100644 --- a/src/ui/organisedialog.cpp +++ b/src/ui/organisedialog.cpp @@ -97,7 +97,7 @@ void OrganiseDialog::SetDestinationModel(QAbstractItemModel *model, bool devices ui_->eject_after->setVisible(devices); } -void OrganiseDialog::SetUrls(const QList &urls) { +void OrganiseDialog::SetUrls(const QList &urls, quint64 total_size) { QStringList filenames; // Only add file:// URLs @@ -107,10 +107,10 @@ void OrganiseDialog::SetUrls(const QList &urls) { filenames << url.toLocalFile(); } - SetFilenames(filenames); + SetFilenames(filenames, total_size); } -void OrganiseDialog::SetFilenames(const QStringList& filenames) { +void OrganiseDialog::SetFilenames(const QStringList& filenames, quint64 total_size) { filenames_ = filenames; preview_songs_.clear(); @@ -120,6 +120,9 @@ void OrganiseDialog::SetFilenames(const QStringList& filenames) { LoadPreviewSongs(filenames_[i]); } + ui_->free_space->set_additional_bytes(total_size); + qDebug() << "Total bytes" << total_size; + UpdatePreviews(); } @@ -158,7 +161,7 @@ void OrganiseDialog::UpdatePreviews() { bool has_local_destination = false; if (destination.isValid()) { - storage = destination.data(MusicStorage::kStorageRole).value(); + storage = destination.data(MusicStorage::Role_Storage).value(); has_local_destination = !storage->LocalPath().isEmpty(); } @@ -173,6 +176,18 @@ void OrganiseDialog::UpdatePreviews() { if (!format_valid) return; + // Update the free space bar + quint64 capacity = destination.data(MusicStorage::Role_Capacity).toLongLong(); + quint64 free = destination.data(MusicStorage::Role_FreeSpace).toLongLong(); + + if (!capacity) { + ui_->free_space->hide(); + } else { + ui_->free_space->show(); + ui_->free_space->set_free_bytes(free); + ui_->free_space->set_total_bytes(capacity); + } + // Update the previews ui_->preview->clear(); ui_->preview_group->setVisible(has_local_destination); @@ -232,7 +247,7 @@ void OrganiseDialog::accept() { const QModelIndex destination = ui_->destination->model()->index( ui_->destination->currentIndex(), 0); MusicStorage* storage = - destination.data(MusicStorage::kStorageRole).value(); + destination.data(MusicStorage::Role_Storage).value(); // It deletes itself when it's finished. const bool copy = ui_->aftercopying->currentIndex() == 0; diff --git a/src/ui/organisedialog.h b/src/ui/organisedialog.h index 4e1283901..bb7156222 100644 --- a/src/ui/organisedialog.h +++ b/src/ui/organisedialog.h @@ -47,8 +47,8 @@ public: void SetDestinationModel(QAbstractItemModel* model, bool devices = false); - void SetUrls(const QList& urls); - void SetFilenames(const QStringList& filenames); + void SetUrls(const QList& urls, quint64 total_size = 0); + void SetFilenames(const QStringList& filenames, quint64 total_size = 0); void SetCopy(bool copy); public slots: diff --git a/src/ui/organisedialog.ui b/src/ui/organisedialog.ui index 47c86a740..b78f2e6b7 100644 --- a/src/ui/organisedialog.ui +++ b/src/ui/organisedialog.ui @@ -7,7 +7,7 @@ 0 0 588 - 497 + 525 @@ -53,6 +53,9 @@ + + + @@ -151,6 +154,12 @@ + + FreeSpaceBar + QWidget +
widgets/freespacebar.h
+ 1 +
LineTextEdit QTextEdit diff --git a/src/widgets/freespacebar.cpp b/src/widgets/freespacebar.cpp index e405c8a88..98a7589f9 100644 --- a/src/widgets/freespacebar.cpp +++ b/src/widgets/freespacebar.cpp @@ -25,6 +25,8 @@ const int FreeSpaceBar::kMarkerSpacing = 32; const QRgb FreeSpaceBar::kColorBg1 = qRgb(214, 207, 200); const QRgb FreeSpaceBar::kColorBg2 = qRgb(234, 226, 218); +const QRgb FreeSpaceBar::kColorAdd1 = qRgb(250, 182, 134); +const QRgb FreeSpaceBar::kColorAdd2 = qRgb(229, 157, 105); const QRgb FreeSpaceBar::kColorBar1 = qRgb(250, 148, 76); const QRgb FreeSpaceBar::kColorBar2 = qRgb(214, 102, 24); const QRgb FreeSpaceBar::kColorBorder = qRgb(174, 168, 162); @@ -32,7 +34,8 @@ const QRgb FreeSpaceBar::kColorBorder = qRgb(174, 168, 162); FreeSpaceBar::FreeSpaceBar(QWidget *parent) : QWidget(parent), - free_(33), + free_(100), + additional_(0), total_(100) { setMinimumHeight(kBarHeight); @@ -43,6 +46,11 @@ void FreeSpaceBar::set_free_bytes(quint64 bytes) { update(); } +void FreeSpaceBar::set_additional_bytes(quint64 bytes) { + additional_ = bytes; + update(); +} + void FreeSpaceBar::set_total_bytes(quint64 bytes) { total_ = bytes; update(); @@ -74,6 +82,20 @@ void FreeSpaceBar::paintEvent(QPaintEvent*) { p.setBrush(background_gradient); p.drawRoundedRect(background_rect, kBarBorderRadius, kBarBorderRadius); + // Draw any additional space + if (additional_) { + QRect additional_rect(bar_rect); + additional_rect.setWidth(float(background_rect.width()) * ( + float(qMin(total_, total_ - free_ + additional_)) / total_)); + + QLinearGradient additional_gradient(additional_rect.topLeft(), additional_rect.bottomLeft()); + additional_gradient.setColorAt(0, kColorAdd1); + additional_gradient.setColorAt(1, kColorAdd2); + + p.setBrush(additional_gradient); + p.drawRoundedRect(additional_rect, kBarBorderRadius, kBarBorderRadius); + } + // Draw the bar foreground p.setBrush(bar_gradient); p.drawRoundedRect(bar_rect, kBarBorderRadius, kBarBorderRadius); diff --git a/src/widgets/freespacebar.h b/src/widgets/freespacebar.h index eae0dcb64..ac139e066 100644 --- a/src/widgets/freespacebar.h +++ b/src/widgets/freespacebar.h @@ -22,6 +22,7 @@ class FreeSpaceBar : public QWidget { Q_OBJECT Q_PROPERTY(quint64 free READ free_bytes WRITE set_free_bytes); + Q_PROPERTY(quint64 additional READ additional_bytes WRITE set_additional_bytes); Q_PROPERTY(quint64 total READ total_bytes WRITE set_total_bytes); public: @@ -33,13 +34,17 @@ public: static const QRgb kColorBg1; static const QRgb kColorBg2; + static const QRgb kColorAdd1; + static const QRgb kColorAdd2; static const QRgb kColorBar1; static const QRgb kColorBar2; static const QRgb kColorBorder; quint64 free_bytes() const { return free_; } + quint64 additional_bytes() const { return additional_; } quint64 total_bytes() const { return total_; } void set_free_bytes(quint64 bytes); + void set_additional_bytes(quint64 bytes); void set_total_bytes(quint64 bytes); QSize sizeHint() const; @@ -49,6 +54,7 @@ protected: private: quint64 free_; + quint64 additional_; quint64 total_; };