File indexing completed on 2024-03-24 05:49:22
0001 // SPDX-FileCopyrightText: 2020 Simon Persson <simon.persson@mykolab.com> 0002 // 0003 // SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0004 0005 #include "driveselectiondelegate.h" 0006 #include "driveselection.h" 0007 0008 #include <QApplication> 0009 #include <QIcon> 0010 #include <QPainter> 0011 #include <QStyle> 0012 0013 #include <KCapacityBar> 0014 #include <KFormat> 0015 #include <KIO/Global> 0016 #include <KLocalizedString> 0017 0018 static const int cMargin = 6; 0019 0020 DriveSelectionDelegate::DriveSelectionDelegate(QListView *pParent) 0021 : QStyledItemDelegate(pParent), 0022 mCapacityBar(new KCapacityBar(KCapacityBar::DrawTextInline)), 0023 mListView(pParent) 0024 {} 0025 0026 DriveSelectionDelegate::~DriveSelectionDelegate() 0027 { 0028 delete mCapacityBar; 0029 } 0030 0031 void DriveSelectionDelegate::paint(QPainter* pPainter, const QStyleOptionViewItem& pOption, 0032 const QModelIndex& pIndex) const { 0033 pPainter->save(); 0034 pPainter->setRenderHint(QPainter::Antialiasing); 0035 QApplication::style()->drawPrimitive(QStyle::PE_PanelItemViewItem, &pOption, pPainter); 0036 0037 auto lTotalSize = pIndex.data(DriveSelection::TotalSpace).toULongLong(); 0038 auto lUsedSize = pIndex.data(DriveSelection::UsedSpace).toULongLong(); 0039 bool lIsDisconnected = pIndex.data(DriveSelection::UDI).toString().isEmpty(); 0040 0041 auto lFontMetrics = mListView->fontMetrics(); 0042 0043 if(lTotalSize == 0 || lIsDisconnected) { 0044 mCapacityBar->setValue(0); 0045 } else { 0046 mCapacityBar->setValue(static_cast<int>((lUsedSize * 100) / lTotalSize)); 0047 } 0048 mCapacityBar->drawCapacityBar( 0049 pPainter, 0050 pOption.rect.adjusted( 0051 cMargin, 0052 cMargin+lFontMetrics.height()+cMargin, 0053 -cMargin, 0054 4*cMargin + lFontMetrics.height() - pOption.rect.height())); 0055 0056 if (pOption.state & QStyle::State_HasFocus) 0057 pPainter->setPen(pOption.palette.color(QPalette::HighlightedText)); 0058 else 0059 pPainter->setPen(pOption.palette.color(QPalette::Text)); 0060 0061 KFormat lFormat; 0062 QString lDisplayLabel, lPartitionLabel, lDisconnectedLabel; 0063 int lTextEnd = pOption.rect.right() - cMargin; 0064 if(lIsDisconnected) { 0065 lDisconnectedLabel = xi18nc("@item:inlistbox this text is added if selected drive is disconnected", " (disconnected)"); 0066 } else { 0067 lDisconnectedLabel = QString(); 0068 if(lTotalSize > 0) { 0069 QString lFreeSpace = xi18nc("@label %1 is amount of free storage space of hard drive","%1 free", 0070 lFormat.formatByteSize(lTotalSize - lUsedSize)); 0071 int lTextWidth = lFontMetrics.horizontalAdvance(lFreeSpace); 0072 lTextEnd -= lTextWidth + cMargin; 0073 QPoint lOffset = QPoint(-cMargin - lTextWidth, cMargin + lFontMetrics.height()); 0074 pPainter->drawText(pOption.rect.topRight() + lOffset, lFreeSpace); 0075 } 0076 } 0077 0078 QString lDeviceDescription = pIndex.data(DriveSelection::DeviceDescription).toString(); 0079 QString lLabel = pIndex.data(DriveSelection::Label).toString(); 0080 int lPartitionNumber = pIndex.data(DriveSelection::PartitionNumber).toInt(); 0081 if(lLabel.isEmpty() || lLabel == lDeviceDescription) { 0082 if(pIndex.data(DriveSelection::PartitionsOnDrive).toInt() > 1) { 0083 lPartitionLabel = xi18nc("@item:inlistbox used for unnamed filesystems, more than one filesystem on device. %1 is partition number, %2 is device description, %3 is either empty or the \" (disconnected)\" text", 0084 "Partition %1 on %2%3", lPartitionNumber, lDeviceDescription, lDisconnectedLabel); 0085 } else { 0086 lPartitionLabel = xi18nc("@item:inlistbox used when there is only one unnamed filesystem on device. %1 is device description, %2 is either empty or the \" (disconnected)\" text", 0087 "%1%2", lDeviceDescription, lDisconnectedLabel); 0088 } 0089 } else { 0090 lPartitionLabel = xi18nc("@item:inlistbox %1 is filesystem label, %2 is the device description, %3 is either empty or the \" (disconnected)\" text", 0091 "%1 on %2%3", lLabel, lDeviceDescription, lDisconnectedLabel); 0092 } 0093 0094 if(lTotalSize == 0) { 0095 lDisplayLabel = lPartitionLabel; 0096 } else { 0097 lDisplayLabel = xi18nc("@item:inlistbox %1 is drive(partition) label, %2 is storage capacity", 0098 "%1: %2 total capacity", lPartitionLabel, lFormat.formatByteSize(lTotalSize)); 0099 } 0100 lDisplayLabel = lFontMetrics.elidedText(lDisplayLabel, Qt::ElideMiddle, lTextEnd - pOption.rect.left() - cMargin); 0101 pPainter->drawText(pOption.rect.topLeft() + QPoint(cMargin, cMargin+lFontMetrics.height()), lDisplayLabel); 0102 0103 int lIconSize = 48; 0104 QRect lWarningRect = warningRect(pOption.rect.adjusted(lIconSize + cMargin, 0, 0, 0), pIndex); 0105 if(!lWarningRect.isEmpty()) { 0106 QIcon lIcon = QIcon::fromTheme(QStringLiteral("dialog-warning")); 0107 lIcon.paint(pPainter, lWarningRect.left() - cMargin - lIconSize, lWarningRect.top(), lIconSize, lIconSize); 0108 pPainter->drawText(lWarningRect, Qt::AlignVCenter | Qt::TextWordWrap, warningText(pIndex)); 0109 } 0110 0111 pPainter->restore(); 0112 } 0113 0114 QSize DriveSelectionDelegate::sizeHint(const QStyleOptionViewItem& pOption, const QModelIndex& pIndex) const { 0115 Q_UNUSED(pOption) 0116 auto lFontMetrics = mListView->fontMetrics(); 0117 QSize lSize; 0118 lSize.setWidth(cMargin*2 + lFontMetrics.horizontalAdvance(pIndex.data().toString())); 0119 lSize.setHeight(cMargin*5 + lFontMetrics.height()); 0120 int lIconSize = 48; 0121 QRect lWarningRect = warningRect(mListView->rect().adjusted(lIconSize + cMargin, 0, 0, 0), pIndex); 0122 if(!lWarningRect.isEmpty()) { 0123 lSize.setHeight(lSize.height() + 2*cMargin + lWarningRect.height()); 0124 } 0125 return lSize; 0126 } 0127 0128 QRect DriveSelectionDelegate::warningRect(const QRect &pRect, const QModelIndex &pIndex) const { 0129 auto lFontMetrics = mListView->fontMetrics(); 0130 QRect lTextLocation = pRect.adjusted(cMargin, 5*cMargin + lFontMetrics.height(), -cMargin, -cMargin); 0131 QString lWarningText = warningText(pIndex); 0132 if(lWarningText.isEmpty()) { 0133 return {}; 0134 } 0135 QRect lTextBoundary = lFontMetrics.boundingRect(lTextLocation, Qt::TextWordWrap, lWarningText); 0136 int lIconSize = 48; 0137 if(lTextBoundary.height() < lIconSize) { 0138 lTextBoundary.setHeight(lIconSize); 0139 } 0140 return lTextBoundary; 0141 } 0142 0143 QString DriveSelectionDelegate::warningText(const QModelIndex &pIndex) { 0144 bool lPermissionWarning = pIndex.data(DriveSelection::PermissionLossWarning).toBool(); 0145 bool lSymlinkWarning = pIndex.data(DriveSelection::SymlinkLossWarning).toBool(); 0146 if(lPermissionWarning && lSymlinkWarning) { 0147 return xi18nc("@item:inlistbox", "Warning: Symbolic links and file permissions can not be saved " 0148 "to this file system. File permissions only matters if there is more than one " 0149 "user of this computer or if you are backing up executable program files."); 0150 } 0151 if(lPermissionWarning) { 0152 return xi18nc("@item:inlistbox", "Warning: File permissions can not be saved to this file " 0153 "system. File permissions only matters if there is more than one " 0154 "user of this computer or if you are backing up executable program files."); 0155 } 0156 return {}; 0157 }