Improve displaying downloads
This commit is contained in:
parent
d863858bff
commit
a4259223e0
|
@ -102,7 +102,7 @@ bool SyncthingDir::assignStatus(DirStatus newStatus, DateTime time)
|
|||
|
||||
SyncthingItemDownloadProgress::SyncthingItemDownloadProgress(const QString &containingDirPath, const QString &relativeItemPath, const QJsonObject &values) :
|
||||
relativePath(relativeItemPath),
|
||||
fileInfo(containingDirPath % QChar('/') % relativeItemPath),
|
||||
fileInfo(containingDirPath % QChar('/') % QString(relativeItemPath).replace(QChar('\\'), QChar('/'))),
|
||||
blocksCurrentlyDownloading(values.value(QStringLiteral("Pulling")).toInt()),
|
||||
blocksAlreadyDownloaded(values.value(QStringLiteral("Pulled")).toInt()),
|
||||
totalNumberOfBlocks(values.value(QStringLiteral("Total")).toInt()),
|
||||
|
@ -681,7 +681,7 @@ void SyncthingConnection::readConfig()
|
|||
void SyncthingConnection::readDirs(const QJsonArray &dirs)
|
||||
{
|
||||
m_dirs.clear();
|
||||
m_dirs.reserve(dirs.size());
|
||||
m_dirs.reserve(static_cast<size_t>(dirs.size()));
|
||||
for(const QJsonValue &dirVal : dirs) {
|
||||
const QJsonObject dirObj(dirVal.toObject());
|
||||
SyncthingDir dirItem;
|
||||
|
@ -712,7 +712,7 @@ void SyncthingConnection::readDirs(const QJsonArray &dirs)
|
|||
void SyncthingConnection::readDevs(const QJsonArray &devs)
|
||||
{
|
||||
m_devs.clear();
|
||||
m_devs.reserve(devs.size());
|
||||
m_devs.reserve(static_cast<size_t>(devs.size()));
|
||||
for(const QJsonValue &devVal: devs) {
|
||||
const QJsonObject devObj(devVal.toObject());
|
||||
SyncthingDev devItem;
|
||||
|
@ -1121,7 +1121,6 @@ void SyncthingConnection::readStatusChangedEvent(DateTime eventTime, const QJson
|
|||
|
||||
/*!
|
||||
* \brief Reads results of requestEvents().
|
||||
* \remarks TODO
|
||||
*/
|
||||
void SyncthingConnection::readDownloadProgressEvent(DateTime eventTime, const QJsonObject &eventData)
|
||||
{
|
||||
|
|
|
@ -13,7 +13,8 @@ SyncthingDownloadModel::SyncthingDownloadModel(SyncthingConnection &connection,
|
|||
m_connection(connection),
|
||||
m_dirs(connection.dirInfo()),
|
||||
m_unknownIcon(QIcon::fromTheme(QStringLiteral("text-x-generic"), QIcon(QStringLiteral(":/icons/hicolor/scalable/mimetypes/text-x-generic.svg")))),
|
||||
m_pendingDirs(0)
|
||||
m_pendingDirs(0),
|
||||
m_singleColumnMode(true)
|
||||
{
|
||||
connect(&m_connection, &SyncthingConnection::newConfig, this, &SyncthingDownloadModel::newConfig);
|
||||
connect(&m_connection, &SyncthingConnection::newDirs, this, &SyncthingDownloadModel::newDirs);
|
||||
|
@ -112,6 +113,8 @@ QVariant SyncthingDownloadModel::data(const QModelIndex &index, int role) const
|
|||
break;
|
||||
case ItemPercentage:
|
||||
return progress.downloadPercentage;
|
||||
case ItemProgressLabel:
|
||||
return progress.label;
|
||||
default:
|
||||
;
|
||||
}
|
||||
|
@ -136,6 +139,8 @@ QVariant SyncthingDownloadModel::data(const QModelIndex &index, int role) const
|
|||
break;
|
||||
case ItemPercentage:
|
||||
return dir.downloadPercentage;
|
||||
case ItemProgressLabel:
|
||||
return dir.downloadLabel;
|
||||
default:
|
||||
;
|
||||
}
|
||||
|
@ -164,9 +169,9 @@ int SyncthingDownloadModel::rowCount(const QModelIndex &parent) const
|
|||
int SyncthingDownloadModel::columnCount(const QModelIndex &parent) const
|
||||
{
|
||||
if(!parent.isValid()) {
|
||||
return 2; // label/ID, status/progress
|
||||
return singleColumnMode() ? 1 : 2; // label/ID, status/progress
|
||||
} else if(!parent.parent().isValid()) {
|
||||
return 2; // file, progress
|
||||
return singleColumnMode() ? 1 : 2; // file, progress
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
@ -210,4 +215,19 @@ void SyncthingDownloadModel::downloadProgressChanged()
|
|||
}
|
||||
}
|
||||
|
||||
void SyncthingDownloadModel::setSingleColumnMode(bool singleColumnModeEnabled)
|
||||
{
|
||||
if(m_singleColumnMode != singleColumnModeEnabled) {
|
||||
if(m_singleColumnMode) {
|
||||
beginInsertColumns(QModelIndex(), 1, 1);
|
||||
m_singleColumnMode = true;
|
||||
endInsertColumns();
|
||||
} else {
|
||||
beginRemoveColumns(QModelIndex(), 1, 1);
|
||||
m_singleColumnMode = false;
|
||||
endRemoveColumns();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Data
|
||||
|
|
|
@ -17,12 +17,14 @@ class SyncthingDownloadModel : public QAbstractItemModel
|
|||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(unsigned int pendingDownloads READ pendingDownloads NOTIFY pendingDownloadsChanged)
|
||||
Q_PROPERTY(bool singleColumnMode READ singleColumnMode WRITE setSingleColumnMode)
|
||||
public:
|
||||
explicit SyncthingDownloadModel(SyncthingConnection &connection, QObject *parent = nullptr);
|
||||
|
||||
enum SyncthingDownloadModelRole
|
||||
{
|
||||
ItemPercentage = Qt::UserRole + 1
|
||||
ItemPercentage = Qt::UserRole + 1,
|
||||
ItemProgressLabel
|
||||
};
|
||||
|
||||
public Q_SLOTS:
|
||||
|
@ -36,6 +38,8 @@ public Q_SLOTS:
|
|||
const SyncthingDir *dirInfo(const QModelIndex &index) const;
|
||||
const SyncthingItemDownloadProgress *progressInfo(const QModelIndex &index) const;
|
||||
unsigned int pendingDownloads() const;
|
||||
bool singleColumnMode() const;
|
||||
void setSingleColumnMode(bool singleColumnModeEnabled);
|
||||
|
||||
Q_SIGNALS:
|
||||
void pendingDownloadsChanged(unsigned int pendingDownloads);
|
||||
|
@ -52,6 +56,7 @@ private:
|
|||
const QFileIconProvider m_fileIconProvider;
|
||||
std::vector<const SyncthingDir *> m_pendingDirs;
|
||||
unsigned int m_pendingDownloads;
|
||||
bool m_singleColumnMode;
|
||||
};
|
||||
|
||||
inline unsigned int SyncthingDownloadModel::pendingDownloads() const
|
||||
|
@ -59,6 +64,11 @@ inline unsigned int SyncthingDownloadModel::pendingDownloads() const
|
|||
return m_pendingDownloads;
|
||||
}
|
||||
|
||||
inline bool SyncthingDownloadModel::singleColumnMode() const
|
||||
{
|
||||
return m_singleColumnMode;
|
||||
}
|
||||
|
||||
} // namespace Data
|
||||
|
||||
#endif // DATA_SYNCTHINGDOWNLOADMODEL_H
|
||||
|
|
|
@ -10,7 +10,11 @@
|
|||
#include <QStyleOptionViewItem>
|
||||
#include <QBrush>
|
||||
#include <QPalette>
|
||||
#include <QFontMetrics>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
using namespace Data;
|
||||
|
||||
namespace QtGui {
|
||||
|
@ -27,37 +31,66 @@ DownloadItemDelegate::DownloadItemDelegate(QObject* parent) :
|
|||
|
||||
void DownloadItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||
{
|
||||
// use the customization only on top-level rows
|
||||
//if(!index.parent().isValid()) {
|
||||
// QStyledItemDelegate::paint(painter, option, index);
|
||||
//} else {
|
||||
// init style options to use drawControl(), except for the text
|
||||
QStyleOptionViewItem opt = option;
|
||||
initStyleOption(&opt, index);
|
||||
opt.text.clear();
|
||||
opt.features = QStyleOptionViewItem::None;
|
||||
QApplication::style()->drawControl(QStyle::CE_ItemViewItem, &opt, painter);
|
||||
// init style options to use drawControl(), except for the text
|
||||
QStyleOptionViewItem opt = option;
|
||||
initStyleOption(&opt, index);
|
||||
opt.textElideMode = Qt::ElideNone; // elide manually
|
||||
opt.features = QStyleOptionViewItem::None;
|
||||
if(index.parent().isValid()) {
|
||||
opt.displayAlignment = Qt::AlignTop | Qt::AlignLeft;
|
||||
opt.decorationSize = QSize(option.rect.height(), option.rect.height());
|
||||
opt.features |= QStyleOptionViewItem::HasDecoration;
|
||||
opt.text = option.fontMetrics.elidedText(opt.text, Qt::ElideMiddle, opt.rect.width() - opt.rect.height() - 26);
|
||||
} else {
|
||||
opt.text = option.fontMetrics.elidedText(opt.text, Qt::ElideMiddle, opt.rect.width() / 2 - 4);
|
||||
}
|
||||
QApplication::style()->drawControl(QStyle::CE_ItemViewItem, &opt, painter);
|
||||
|
||||
// draw progress bar
|
||||
const QAbstractItemModel *model = index.model();
|
||||
QStyleOptionProgressBar progressBarOption;
|
||||
progressBarOption.state = QStyle::State_Enabled;
|
||||
progressBarOption.direction = QApplication::layoutDirection();
|
||||
progressBarOption.rect = option.rect;
|
||||
progressBarOption.rect.setWidth(option.rect.width() - 20);
|
||||
progressBarOption.textAlignment = Qt::AlignCenter;
|
||||
progressBarOption.textVisible = true;
|
||||
progressBarOption.progress = model->data(index, SyncthingDownloadModel::ItemPercentage).toInt();
|
||||
progressBarOption.minimum = 0;
|
||||
progressBarOption.maximum = 100;
|
||||
progressBarOption.text = model->data(index, Qt::DisplayRole).toString();
|
||||
QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progressBarOption, painter);
|
||||
// draw progress bar
|
||||
const QAbstractItemModel *model = index.model();
|
||||
QStyleOptionProgressBar progressBarOption;
|
||||
progressBarOption.state = option.state;
|
||||
progressBarOption.direction = option.direction;
|
||||
progressBarOption.rect = option.rect;
|
||||
if(index.parent().isValid()) {
|
||||
progressBarOption.rect.setX(opt.rect.x() + opt.rect.height() + 4);
|
||||
progressBarOption.rect.setY(opt.rect.y() + opt.rect.height() / 2);
|
||||
} else {
|
||||
progressBarOption.rect.setX(opt.rect.x() + opt.fontMetrics.width(opt.text) + 6);
|
||||
progressBarOption.rect.setWidth(progressBarOption.rect.width() - 18);
|
||||
}
|
||||
progressBarOption.textAlignment = Qt::AlignCenter;
|
||||
progressBarOption.textVisible = true;
|
||||
if(option.state & QStyle::State_Selected) {
|
||||
progressBarOption.palette.setBrush(QPalette::Foreground, option.palette.brush(QPalette::HighlightedText));
|
||||
}
|
||||
progressBarOption.progress = model->data(index, SyncthingDownloadModel::ItemPercentage).toInt();
|
||||
progressBarOption.minimum = 0;
|
||||
progressBarOption.maximum = 100;
|
||||
progressBarOption.text = model->data(index, SyncthingDownloadModel::ItemProgressLabel).toString();
|
||||
QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progressBarOption, painter);
|
||||
|
||||
// draw buttons
|
||||
const int buttonY = option.rect.y() + centerObj(option.rect.height(), 16);
|
||||
painter->drawPixmap(option.rect.right() - 16, buttonY, 16, 16, m_folderIcon);
|
||||
//}
|
||||
// draw buttons
|
||||
int buttonY = option.rect.y();
|
||||
if(!index.parent().isValid()) {
|
||||
buttonY += centerObj(progressBarOption.rect.height(), 16);
|
||||
}
|
||||
painter->drawPixmap(option.rect.right() - 16, buttonY, 16, 16, m_folderIcon);
|
||||
|
||||
// draw file icon
|
||||
if(index.parent().isValid()) {
|
||||
const int fileIconHeight = option.rect.height() - 2;
|
||||
painter->drawPixmap(option.rect.left(), option.rect.y() + 1, fileIconHeight, fileIconHeight, model->data(index, Qt::DecorationRole).value<QIcon>().pixmap(fileIconHeight));
|
||||
}
|
||||
}
|
||||
|
||||
QSize DownloadItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
|
||||
{
|
||||
QSize defaultSize(QStyledItemDelegate::sizeHint(option, index));
|
||||
if(index.parent().isValid()) {
|
||||
defaultSize.setHeight(defaultSize.height() + defaultSize.height() - 12);
|
||||
}
|
||||
return defaultSize;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ public:
|
|||
DownloadItemDelegate(QObject *parent);
|
||||
|
||||
void paint(QPainter *, const QStyleOptionViewItem &, const QModelIndex &) const;
|
||||
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const;
|
||||
|
||||
private:
|
||||
const QPixmap m_folderIcon;
|
||||
|
|
|
@ -19,7 +19,7 @@ DownloadView::DownloadView(QWidget *parent) :
|
|||
{
|
||||
header()->setSectionResizeMode(QHeaderView::ResizeToContents);
|
||||
header()->hide();
|
||||
setItemDelegateForColumn(1, new DownloadItemDelegate(this));
|
||||
setItemDelegateForColumn(0, new DownloadItemDelegate(this));
|
||||
setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(this, &DownloadView::customContextMenuRequested, this, &DownloadView::showContextMenu);
|
||||
}
|
||||
|
@ -30,12 +30,14 @@ void DownloadView::mouseReleaseEvent(QMouseEvent *event)
|
|||
if(const SyncthingDownloadModel *dlModel = qobject_cast<SyncthingDownloadModel *>(model())) {
|
||||
const QPoint pos(event->pos());
|
||||
const QModelIndex clickedIndex(indexAt(event->pos()));
|
||||
if(clickedIndex.isValid() && clickedIndex.column() == 1) {
|
||||
if(clickedIndex.isValid() && clickedIndex.column() == 0) {
|
||||
const QRect itemRect(visualRect(clickedIndex));
|
||||
if(pos.x() > itemRect.right() - 17) {
|
||||
if(clickedIndex.parent().isValid()) {
|
||||
if(const SyncthingItemDownloadProgress *progress = dlModel->progressInfo(clickedIndex)) {
|
||||
emit openItemDir(*progress);
|
||||
if(pos.y() < itemRect.y() + itemRect.height() / 2) {
|
||||
if(const SyncthingItemDownloadProgress *progress = dlModel->progressInfo(clickedIndex)) {
|
||||
emit openItemDir(*progress);
|
||||
}
|
||||
}
|
||||
} else if(const SyncthingDir *dir = dlModel->dirInfo(clickedIndex)) {
|
||||
emit openDir(*dir);
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
"BytesTotal": 104792064,
|
||||
"BytesDone": 87883776
|
||||
},
|
||||
"dir\\file4": {
|
||||
"directory1\\directory\\directory3\\directory4\\directory5\\directory3\\directory4\\directory5\\file4": {
|
||||
"Total": 80,
|
||||
"Pulling": 2,
|
||||
"CopiedFromOrigin": 0,
|
||||
|
|
Loading…
Reference in New Issue