我已经开始扩展qGetDownloadManager
以发出 a 的进度TransferItem
,以便我可以连接到它。我将进度数据插入TableView
模型的单元格中以显示Delegate
,最后代表绘制进度条。这在理论上可行,但我遇到了以下问题
问题:当有多个并行下载时,我会从两个信号中获取进度更新到两个单元格中!
两个进度条都显示进度数据,但信号有点混合,不是当前索引 ( QModelIndex index
/ index.row()
) 独有的。
(请忽略 UserRoles 之间的小转换问题(单击下载按钮后显示“ActionCell”然后“安装”,在“ProgressBar”出现之前。)。这不是这里的主要问题。我的问题是关于索引问题。)文本“112”和“113”是 int index.row
。
问题:
- 如何使用多个 ProgressBars 的进度数据更新 TableView?
- 我必须更改哪些内容才能为每次下载呈现进度条?
来源
发出下载进度
我添加了以下内容以通过类重新发出信号,直到它冒泡到顶部,在那里它可以从 GUI 连接。
从
QNetworkReply
-downloadProgress(qint64,qint64)
到TransferItem
-的连接updateDownloadProgress(qint64,qint64)
void TransferItem::startRequest() { reply = nam.get(request); connect(reply, SIGNAL(readyRead()), this, SLOT(readyRead())); connect(reply, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(updateDownloadProgress(qint64,qint64))); connect(reply, SIGNAL(finished()), this, SLOT(finished())); timer.start(); }
SLOT 函数
TransferItem
-updateDownloadProgress(qint64,qint64)
接收方计算进度并将其存储在progress
(QMap<QString, QVariant>
) 中。计算后downloadProgress(this)
发出信号。// SLOT void TransferItem::updateDownloadProgress(qint64 bytesReceived, qint64 bytesTotal) { progress["bytesReceived"] = QString::number(bytesReceived); progress["bytesTotal"] = QString::number(bytesTotal); progress["size"] = getSizeHumanReadable(outputFile->size()); progress["speed"] = QString::number((double)outputFile->size()/timer.elapsed(),'f',0).append(" KB/s"); progress["time"] = QString::number((double)timer.elapsed()/1000,'f',2).append("s"); progress["percentage"] = (bytesTotal > 0) ? QString::number(bytesReceived*100/bytesTotal).append("%") : "0 %"; emit downloadProgress(this); } QString TransferItem::getSizeHumanReadable(qint64 bytes) { float num = bytes; QStringList list; list << "KB" << "MB" << "GB" << "TB"; QStringListIterator i(list); QString unit("bytes"); while(num >= 1024.0 && i.hasNext()) { unit = i.next(); num /= 1024.0; } return QString::fromLatin1("%1 %2").arg(num, 3, 'f', 1).arg(unit); }
当新的下载入队时,我将发射连接
downloadProgress(this)
到 SlotDownloadManager
-downloadProgress(TransferItem*)
。(dl
是DownloadItem
扩展TransferItem
)。void DownloadManager::get(const QNetworkRequest &request) { DownloadItem *dl = new DownloadItem(request, nam); transfers.append(dl); FilesToDownloadCounter = transfers.count(); connect(dl, SIGNAL(downloadProgress(TransferItem*)), SLOT(downloadProgress(TransferItem*))); connect(dl, SIGNAL(downloadFinished(TransferItem*)), SLOT(downloadFinished(TransferItem*))); }
最后,我再次发送下载进度:
void DownloadManager::downloadProgress(TransferItem *item) { emit signalProgress(item->progress); }
现在带有 Delegate、doDownload(index) 和 ProgressBarUpdater 的 TableView
QTableView
- 添加
QSortFilterProxyModel
(不区分大小写) 添加了
ColumnDelegate
,它根据自定义 UserRoles 呈现 DownloadButton 和 ProgressBar。委托处理按钮单击:downloadButtonClicked(index)
从editorEvent(event, model, option, index)
方法发出信号。actionDelegate = new Updater::ActionColumnItemDelegate; ui->tableView->setItemDelegateForColumn(Columns::Action, actionDelegate); connect(actionDelegate, SIGNAL(downloadButtonClicked(QModelIndex)), this, SLOT(doDownload(QModelIndex)));
该
doDownload
方法接收index
并从模型中获取下载 URL。然后将 URL 添加到 DownloadManager 中,我正在设置 ProgressBarUpdater 对象以将进度数据设置为给定索引处的模型。最后,我连接downloadManager::signalProgress
并progressBar::updateProgress
调用downloadManager::checkForAllDone
以开始下载处理。void UpdaterDialog::doDownload(const QModelIndex &index) { QUrl downloadURL = getDownloadUrl(index); if (!validateURL(downloadURL)) return; QNetworkRequest request(downloadURL); downloadManager.get(request); // QueueMode is Parallel by default ProgressBarUpdater *progressBar = new ProgressBarUpdater(this, index.row()); progressBar->setObjectName("ProgressBar_in_Row_" + QString::number(index.row()) ); connect(&downloadManager, SIGNAL(signalProgress(QMap<QString, QVariant>)), progressBar, SLOT(updateProgress(QMap<QString, QVariant>))); QMetaObject::invokeMethod(&downloadManager, "checkForAllDone", Qt::QueuedConnection); }
模型更新部分:ProgressBarUpdater 获取索引和进度,并应在给定索引处更新模型。
ProgressBarUpdater::ProgressBarUpdater(UpdaterDialog *parent, int currentIndexRow) : QObject(parent), currentIndexRow(currentIndexRow) { model = parent->ui->tableView_1->model(); } void ProgressBarUpdater::updateProgress(QMap<QString, QVariant> progress) { QModelIndex actionIndex = model->index(currentIndexRow, UpdaterDialog::Columns::Action); // set progress to model model->setData(actionIndex, progress, ActionColumnItemDelegate::DownloadProgressBarRole); model->dataChanged(actionIndex, actionIndex); }
渲染部分:我正在渲染来自委托的假 ProgressBar;使用 获取进度数据
index.model()->data(index, DownloadProgressBarRole)
。void ActionColumnItemDelegate::drawDownloadProgressBar(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { QStyleOptionProgressBarV2 opt; opt.initFrom(bar); opt.rect = option.rect; opt.rect.adjust(3,3,-3,-3); opt.textVisible = true; opt.textAlignment = Qt::AlignCenter; opt.state = QStyle::State_Enabled | QStyle::State_Active; // get progress from model QMap<QString, QVariant> progress = index.model()->data(index, DownloadProgressBarRole).toMap(); QString text = QString::fromLatin1(" %1 %2 %3 %4 %5 ") .arg(QString::number(index.row())) .arg(progress["percentage"].toString()) .arg(progress["size"].toString()) .arg(progress["speed"].toString()) .arg(progress["time"].toString()); opt.minimum = 0; opt.maximum = progress["bytesTotal"].toFloat(); opt.progress = progress["bytesReceived"].toFloat(); opt.text = text; bar->style()->drawControl(QStyle::CE_ProgressBar,&opt,painter,bar); }
我已添加QString::number(index.row()
到进度条文本,以便每个 ProgressBar 都呈现其行号。换句话说:渲染对于行来说是唯一的,但是传入的进度数据以某种方式混合在一起。
我在索引问题上停留了一段时间。预先感谢您的帮助。
更新:问题已解决!
非常感谢ddriver!!我遵循了您的建议并修复了它: