mirror of
https://github.com/clementine-player/Clementine
synced 2025-02-02 04:16:47 +01:00
Show a free space bar in the organise dialog, and also show how much space would be taken up after copying files.
This commit is contained in:
parent
3ad30d14a8
commit
6f259d4ecc
@ -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(); }
|
||||
|
||||
|
@ -19,6 +19,8 @@
|
||||
#include <QCoreApplication>
|
||||
#include <QStringList>
|
||||
|
||||
#include <sys/statvfs.h>
|
||||
|
||||
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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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<DeviceManager*>(this)->Connect(index.row());
|
||||
if (!info.device_)
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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<QSortFilterProxyModel*>(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();
|
||||
}
|
||||
|
@ -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_;
|
||||
|
@ -97,7 +97,7 @@ void OrganiseDialog::SetDestinationModel(QAbstractItemModel *model, bool devices
|
||||
ui_->eject_after->setVisible(devices);
|
||||
}
|
||||
|
||||
void OrganiseDialog::SetUrls(const QList<QUrl> &urls) {
|
||||
void OrganiseDialog::SetUrls(const QList<QUrl> &urls, quint64 total_size) {
|
||||
QStringList filenames;
|
||||
|
||||
// Only add file:// URLs
|
||||
@ -107,10 +107,10 @@ void OrganiseDialog::SetUrls(const QList<QUrl> &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<MusicStorage*>();
|
||||
storage = destination.data(MusicStorage::Role_Storage).value<MusicStorage*>();
|
||||
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<MusicStorage*>();
|
||||
destination.data(MusicStorage::Role_Storage).value<MusicStorage*>();
|
||||
|
||||
// It deletes itself when it's finished.
|
||||
const bool copy = ui_->aftercopying->currentIndex() == 0;
|
||||
|
@ -47,8 +47,8 @@ public:
|
||||
|
||||
void SetDestinationModel(QAbstractItemModel* model, bool devices = false);
|
||||
|
||||
void SetUrls(const QList<QUrl>& urls);
|
||||
void SetFilenames(const QStringList& filenames);
|
||||
void SetUrls(const QList<QUrl>& urls, quint64 total_size = 0);
|
||||
void SetFilenames(const QStringList& filenames, quint64 total_size = 0);
|
||||
void SetCopy(bool copy);
|
||||
|
||||
public slots:
|
||||
|
@ -7,7 +7,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>588</width>
|
||||
<height>497</height>
|
||||
<height>525</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@ -53,6 +53,9 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="FreeSpaceBar" name="free_space" native="true"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="eject_after">
|
||||
<property name="text">
|
||||
@ -151,6 +154,12 @@
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>FreeSpaceBar</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>widgets/freespacebar.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>LineTextEdit</class>
|
||||
<extends>QTextEdit</extends>
|
||||
|
@ -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);
|
||||
|
@ -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_;
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user