File indexing completed on 2024-05-05 04:51:37
0001 /* 0002 SPDX-FileCopyrightText: 2003-2008 Sebastian Trueg <trueg@k3b.org> 0003 SPDX-FileCopyrightText: 2010-2011 Michal Malek <michalm@jabster.pl> 0004 SPDX-FileCopyrightText: 1998-2008 Sebastian Trueg <trueg@k3b.org> 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 0009 #include "k3bdevicewidget.h" 0010 #include "k3bdevicemanager.h" 0011 #include "k3bdevice.h" 0012 #include "k3bdeviceglobals.h" 0013 0014 #include <KAuth/Action> 0015 #include <KAuth/ExecuteJob> 0016 #include <KConfig> 0017 #include <KLocalizedString> 0018 #include <KIO/Global> 0019 #include <KMessageWidget> 0020 0021 #include <QFileInfo> 0022 #include <QColor> 0023 #include <QIcon> 0024 #include <QAction> 0025 #include <QGridLayout> 0026 #include <QGroupBox> 0027 #include <QHBoxLayout> 0028 #include <QHeaderView> 0029 #include <QLayout> 0030 #include <QList> 0031 #include <QPushButton> 0032 #include <QString> 0033 #include <QToolTip> 0034 #include <QTreeWidget> 0035 #include <QVariant> 0036 #include <QVBoxLayout> 0037 0038 #include <grp.h> 0039 #include <unistd.h> 0040 #include <pwd.h> 0041 0042 0043 K3b::DeviceWidget::DeviceWidget( K3b::Device::DeviceManager* manager, QWidget *parent ) 0044 : QWidget( parent ), 0045 m_deviceManager( manager ), 0046 m_writerParentViewItem( 0 ), 0047 m_readerParentViewItem( 0 ) 0048 { 0049 // message widget 0050 m_messageWidget = new KMessageWidget( this ); 0051 m_messageWidget->hide(); 0052 m_messageWidget->setWordWrap( true ); 0053 m_addToGroupAction = new QAction( QIcon::fromTheme("dialog-password"), QString(), this ); 0054 0055 // buttons 0056 // ------------------------------------------------ 0057 QPushButton* buttonRefreshDevices = new QPushButton( QIcon::fromTheme( "view-refresh" ), i18n( "Refresh" ), this ); 0058 buttonRefreshDevices->setToolTip( i18n( "Rescan the devices" ) ); 0059 QHBoxLayout* refreshButtonGrid = new QHBoxLayout; 0060 refreshButtonGrid->setContentsMargins( 0, 0, 0, 0 ); 0061 refreshButtonGrid->addStretch(); 0062 refreshButtonGrid->addWidget( buttonRefreshDevices ); 0063 // ------------------------------------------------ 0064 0065 // Devices view 0066 // ------------------------------------------------ 0067 m_viewDevices = new QTreeWidget( this ); 0068 m_viewDevices->setAllColumnsShowFocus( true ); 0069 m_viewDevices->setHeaderHidden( true ); 0070 m_viewDevices->setColumnCount( 2 ); 0071 m_viewDevices->setSelectionMode( QAbstractItemView::NoSelection ); 0072 m_viewDevices->setItemsExpandable( false ); 0073 m_viewDevices->setRootIsDecorated( false ); 0074 m_viewDevices->header()->setSectionResizeMode( 0, QHeaderView::ResizeToContents ); 0075 m_viewDevices->setFocusPolicy( Qt::NoFocus ); 0076 m_viewDevices->setVerticalScrollMode( QAbstractItemView::ScrollPerPixel ); 0077 // ------------------------------------------------ 0078 0079 QVBoxLayout* frameLayout = new QVBoxLayout( this ); 0080 frameLayout->setContentsMargins( 0, 0, 0, 0 ); 0081 frameLayout->addWidget( m_messageWidget, 0 ); 0082 frameLayout->addWidget( m_viewDevices, 1 ); 0083 frameLayout->addLayout( refreshButtonGrid, 0 ); 0084 // ------------------------------------------------ 0085 0086 // connections 0087 // ------------------------------------------------ 0088 connect( buttonRefreshDevices, SIGNAL(clicked()), SIGNAL(refreshButtonClicked()) ); 0089 connect( m_deviceManager, SIGNAL(changed()), SLOT(init()) ); 0090 connect( m_addToGroupAction, SIGNAL(triggered(bool)), SLOT(addUserToGroup()) ); 0091 // ------------------------------------------------ 0092 } 0093 0094 0095 K3b::DeviceWidget::~DeviceWidget() 0096 { 0097 } 0098 0099 0100 void K3b::DeviceWidget::init() 0101 { 0102 updateDeviceListViews(); 0103 } 0104 0105 0106 void K3b::DeviceWidget::updateDeviceListViews() 0107 { 0108 QColor disabledTextColor = palette().color( QPalette::Disabled, QPalette::Text ); 0109 0110 m_viewDevices->clear(); 0111 0112 // create the parent view items 0113 // ----------------------------------------- 0114 m_writerParentViewItem = new QTreeWidgetItem( m_viewDevices, QStringList() << i18n("Writer Drives") ); 0115 m_writerParentViewItem->setIcon( 0, QIcon::fromTheme( "media-optical-recordable" ) ); 0116 // spacer item 0117 QTreeWidgetItem* spacer = new QTreeWidgetItem( m_viewDevices ); 0118 spacer->setFlags( Qt::NoItemFlags ); 0119 m_readerParentViewItem = new QTreeWidgetItem( m_viewDevices, QStringList() << i18n("Read-only Drives") ); 0120 m_readerParentViewItem->setIcon( 0, QIcon::fromTheme( "media-optical" ) ); 0121 // ----------------------------------------- 0122 0123 QFont fBold( m_viewDevices->font() ); 0124 fBold.setBold(true); 0125 QFont fItalic( m_viewDevices->font() ); 0126 fItalic.setItalic(true); 0127 0128 foreach( Device::Device* dev, m_deviceManager->allDevices() ) { 0129 // create the root device item 0130 QTreeWidgetItem* devRoot = new QTreeWidgetItem( (dev->burner() ? m_writerParentViewItem : m_readerParentViewItem), 0131 QStringList() << ( dev->vendor() + ' ' + dev->description() ) ); 0132 devRoot->setFont( 0, fBold ); 0133 0134 // create the read-only info items 0135 QTreeWidgetItem* systemDeviceItem = new QTreeWidgetItem( devRoot, QStringList() << i18n("System device name:") ); 0136 systemDeviceItem->setText( 1, dev->blockDeviceName() ); 0137 systemDeviceItem->setForeground( 0, disabledTextColor ); 0138 systemDeviceItem->setTextAlignment( 0, Qt::AlignRight ); 0139 0140 QTreeWidgetItem* vendorItem = new QTreeWidgetItem( devRoot, systemDeviceItem ); 0141 vendorItem->setText( 0, i18n("Vendor:") ); 0142 vendorItem->setText( 1, dev->vendor() ); 0143 vendorItem->setForeground( 0, disabledTextColor ); 0144 vendorItem->setTextAlignment( 0, Qt::AlignRight ); 0145 0146 QTreeWidgetItem* modelItem = new QTreeWidgetItem( devRoot, vendorItem ); 0147 modelItem->setText( 0, i18n("Description:") ); 0148 modelItem->setText( 1, dev->description() ); 0149 modelItem->setForeground( 0, disabledTextColor ); 0150 modelItem->setTextAlignment( 0, Qt::AlignRight ); 0151 0152 QTreeWidgetItem* versionItem = new QTreeWidgetItem( devRoot, modelItem ); 0153 versionItem->setText( 0, i18n("Firmware:") ); 0154 versionItem->setText( 1, dev->version() ); 0155 versionItem->setForeground( 0, disabledTextColor ); 0156 versionItem->setTextAlignment( 0, Qt::AlignRight ); 0157 0158 0159 // drive type 0160 // -------------------------------- 0161 QTreeWidgetItem* typeItem = new QTreeWidgetItem( devRoot, versionItem ); 0162 typeItem->setText( 0, i18n("Write Capabilities:") ); 0163 typeItem->setText( 1, K3b::Device::mediaTypeString( dev->writeCapabilities(), true ) ); 0164 typeItem->setToolTip( 1, typeItem->text(1) ); 0165 typeItem->setForeground( 0, disabledTextColor ); 0166 typeItem->setTextAlignment( 0, Qt::AlignRight ); 0167 0168 typeItem = new QTreeWidgetItem( devRoot, typeItem ); 0169 typeItem->setText( 0, i18n("Read Capabilities:") ); 0170 typeItem->setText( 1, K3b::Device::mediaTypeString( dev->readCapabilities(), true ) ); 0171 typeItem->setToolTip( 1, typeItem->text(1) ); 0172 typeItem->setForeground( 0, disabledTextColor ); 0173 typeItem->setTextAlignment( 0, Qt::AlignRight ); 0174 // -------------------------------- 0175 0176 0177 // now add the reader (both interfaces) items 0178 if( dev->bufferSize() > 0 ) { 0179 typeItem = new QTreeWidgetItem( devRoot, typeItem ); 0180 typeItem->setText( 0, i18n("Buffer Size:") ); 0181 typeItem->setText( 1, KIO::convertSizeFromKiB(dev->bufferSize()) ); 0182 typeItem->setForeground( 0, disabledTextColor ); 0183 typeItem->setTextAlignment( 0, Qt::AlignRight ); 0184 } 0185 0186 0187 // now add the writer specific items 0188 if( dev->burner() ) { 0189 typeItem = new QTreeWidgetItem( devRoot, typeItem ); 0190 typeItem->setText( 0, i18n("Supports Burnfree:") ); 0191 typeItem->setText( 1, dev->burnfree() ? i18n("yes") : i18n("no") ); 0192 typeItem->setForeground( 0, disabledTextColor ); 0193 typeItem->setTextAlignment( 0, Qt::AlignRight ); 0194 0195 // and at last the write modes 0196 typeItem = new QTreeWidgetItem( devRoot, typeItem ); 0197 typeItem->setText( 0, i18n("Write modes:") ); 0198 typeItem->setText( 1, K3b::Device::writingModeString(dev->writingModes()) ); 0199 typeItem->setToolTip( 1, typeItem->text(1) ); 0200 typeItem->setForeground( 0, disabledTextColor ); 0201 typeItem->setTextAlignment( 0, Qt::AlignRight ); 0202 } 0203 } 0204 0205 // create empty items 0206 if( m_writerParentViewItem->childCount() == 0 ) { 0207 QTreeWidgetItem* item = new QTreeWidgetItem( m_writerParentViewItem ); 0208 item->setText( 0, i18n("none") ); 0209 item->setFont( 0, fItalic ); 0210 } 0211 if( m_readerParentViewItem->childCount() == 0 ) { 0212 QTreeWidgetItem* item = new QTreeWidgetItem( m_readerParentViewItem ); 0213 item->setText( 0, i18n("none") ); 0214 item->setFont( 0, fItalic ); 0215 } 0216 0217 m_viewDevices->expandAll(); 0218 0219 // Show warning message if the current user does not belong to 0220 // the group device belongs to 0221 QList<Device::Device*> devices = m_deviceManager->allDevices(); 0222 if( !devices.empty() ) { 0223 QFileInfo fileInfo( devices.front()->blockDeviceName() ); 0224 m_deviceGroup = fileInfo.group(); 0225 0226 if( m_deviceGroup != "root" ) { 0227 QVector<gid_t> gids(::getgroups(0, 0)); 0228 ::getgroups(gids.size(), gids.data()); 0229 0230 QSet<QString> groupNames; 0231 Q_FOREACH( gid_t gid, gids ) { 0232 if( ::group* g = ::getgrgid( gid ) ) { 0233 groupNames.insert( QString::fromLocal8Bit( g->gr_name ) ); 0234 } 0235 } 0236 0237 if (!groupNames.contains(m_deviceGroup)) { 0238 QString messageText = i18n("In order to give K3b full access to the writer device the current user needs be added to a group <em>%1</em>.", m_deviceGroup); 0239 m_messageWidget->setMessageType(KMessageWidget::Warning); 0240 m_messageWidget->setText(messageText); 0241 m_messageWidget->addAction(m_addToGroupAction); 0242 m_addToGroupAction->setText(i18n("Add")); 0243 m_messageWidget->animatedShow(); 0244 } 0245 } 0246 } 0247 } 0248 0249 void K3b::DeviceWidget::addUserToGroup() 0250 { 0251 QVariantMap args; 0252 args["groupName"] = m_deviceGroup; 0253 args["userName"] = QString::fromLocal8Bit(getpwuid(getuid())->pw_name); 0254 0255 KAuth::Action action("org.kde.k3b.addtogroup"); 0256 action.setHelperId("org.kde.k3b"); 0257 #if QT_VERSION_MAJOR == 5 0258 action.setParentWidget(this); 0259 #else 0260 action.setParentWindow(window()->windowHandle()); 0261 #endif 0262 action.setArguments(args); 0263 0264 KAuth::ExecuteJob* job = action.execute(); 0265 connect( job, &KAuth::ExecuteJob::result, [this, job]() 0266 { 0267 if( job->error() == KJob::NoError ) { 0268 m_messageWidget->removeAction(m_addToGroupAction); 0269 m_messageWidget->setMessageType(KMessageWidget::Information); 0270 m_messageWidget->setText(i18n("Please relogin to apply the changes.")); 0271 } else { 0272 m_messageWidget->setMessageType(KMessageWidget::Error); 0273 m_messageWidget->setText(i18n("Unable to execute the action: %1 (Error code: %2)", job->errorString(), job->error())); 0274 m_addToGroupAction->setText(i18n("Retry")); 0275 } 0276 } ); 0277 job->start(); 0278 } 0279 0280 #include "moc_k3bdevicewidget.cpp"